- Initial commit from WCF/LGPL SVN-Repository, skipped history
authorAlexander Ebert <ebert@woltlab.com>
Thu, 14 Jul 2011 16:49:20 +0000 (18:49 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 14 Jul 2011 16:49:20 +0000 (18:49 +0200)
666 files changed:
com.woltlab.wcf/acpmenu.xml [new file with mode: 0644]
com.woltlab.wcf/coreobject.xml [new file with mode: 0644]
com.woltlab.wcf/cronjobs.xml [new file with mode: 0644]
com.woltlab.wcf/eventlistener.xml [new file with mode: 0644]
com.woltlab.wcf/groupoptions.xml [new file with mode: 0644]
com.woltlab.wcf/options.xml [new file with mode: 0644]
com.woltlab.wcf/package.xml [new file with mode: 0644]
com.woltlab.wcf/pip.xml [new file with mode: 0644]
com.woltlab.wcf/styleattributes.xml [new file with mode: 0644]
com.woltlab.wcf/templates/documentHeader.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/footer.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/footerMenu.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/headInclude.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/header.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/headerMenu.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/imageViewer.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeBoolean.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeDate.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeMultiselect.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeRadiobuttons.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeSelect.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeText.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/optionTypeTextarea.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/permissionDenied.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/redirect.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/userException.tpl [new file with mode: 0644]
com.woltlab.wcf/useroptions.xml [new file with mode: 0644]
com.woltlab.wcf/woltlab-basic-style.tar [new file with mode: 0644]
wcfsetup/install.php [new file with mode: 0644]
wcfsetup/install/files/acp/dereferrer.php [new file with mode: 0644]
wcfsetup/install/files/acp/global.php [new file with mode: 0644]
wcfsetup/install/files/acp/images/acpLogo.png [new file with mode: 0644]
wcfsetup/install/files/acp/index.php [new file with mode: 0644]
wcfsetup/install/files/acp/install.php [new file with mode: 0644]
wcfsetup/install/files/acp/js/WCF.ACP.js [new file with mode: 0644]
wcfsetup/install/files/acp/style/extra/setupStyle-rtl.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/extra/setupStyle.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/extra/setupWindowStyle-rtl.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/extra/setupWindowStyle.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/style.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/testing-reset.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/testing.css [new file with mode: 0644]
wcfsetup/install/files/acp/style/wcfAcp.css [new file with mode: 0644]
wcfsetup/install/files/acp/templates/.htaccess [new file with mode: 0644]
wcfsetup/install/files/acp/templates/acpSessionLog.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/acpSessionLogList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/ajaxException.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/cacheList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/cronjobAdd.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/cronjobList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/cronjobLogList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/footer.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/header.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/imageViewer.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/index.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/languageServerAdd.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/languageServerList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/login.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/masterPassword.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/masterPasswordInit.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/option.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionFieldList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionImport.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeBoolean.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeCustomselect.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeDate.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeMultiselect.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeRadiobuttons.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeSelect.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeText.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/optionTypeTextarea.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageAutoUpdateList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageInstallationConfirm.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageInstallationSetup.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageInstallationStepPrepare.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageStartInstall.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageUninstallationDependencies.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageUninstallationStepPrepare.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageUpdate.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageUpdateAuth.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageUpdateSearch.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageUpdateSearchResult.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/packageView.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/permissionDenied.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/setupFooter.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/setupHeader.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/setupWindowFooter.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/setupWindowHeader.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/success.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/updateServerAdd.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/updateServerList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userAdd.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userAssignToGroup.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userEmailAddressExport.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userException.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userGroupAdd.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userGroupList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userList.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userMail.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/userSearch.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/usersMassProcessing.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/worker.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/workerException.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/workerFinish.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/workerNext.tpl [new file with mode: 0644]
wcfsetup/install/files/cache/.htaccess [new file with mode: 0644]
wcfsetup/install/files/cache/templateListener/.htaccess [new file with mode: 0644]
wcfsetup/install/files/global.php [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/closeHoverM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/closeM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/enlargeHoverM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/enlargeM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/nextHoverM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/nextM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/pauseHoverM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/pauseM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/playHoverM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/playM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/previousHoverM.png [new file with mode: 0644]
wcfsetup/install/files/icon/imageViewer/previousM.png [new file with mode: 0644]
wcfsetup/install/files/images/imageViewer/blank.png [new file with mode: 0644]
wcfsetup/install/files/images/imageViewer/menu.png [new file with mode: 0644]
wcfsetup/install/files/images/spinner.gif [new file with mode: 0644]
wcfsetup/install/files/js/3rdParty/jquery-ui.min.js [new file with mode: 0644]
wcfsetup/install/files/js/3rdParty/jquery.min.js [new file with mode: 0644]
wcfsetup/install/files/js/WCF.js [new file with mode: 0644]
wcfsetup/install/files/language/.htaccess [new file with mode: 0644]
wcfsetup/install/files/lib/acp/action/AJAXProxyAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/action/InstallPackageAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/action/LogoutAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/action/OptionExportAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/action/UninstallPackageAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/ACPForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/AbstractOptionListForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/CronjobAddForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/CronjobEditForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/LoginForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/MasterPasswordForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/MasterPasswordInitForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/OptionForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/OptionImportForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/PackageStartInstallForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/PackageUpdateAuthForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/PackageUpdateForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/PackageUpdateSearchForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UpdateServerAddForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UpdateServerEditForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserAddForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserAssignToGroupForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserEditForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserEmailAddressExportForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserGroupAddForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserGroupEditForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserMailForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserOptionListForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserSearchForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UsersMassProcessingForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/ACPSessionLogListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/ACPSessionLogPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/CacheListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/CronjobListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/CronjobLogListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/IndexPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/PackageAutoUpdateListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/PackageListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/PackagePage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/PackageUpdateSearchResultPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/PackageViewPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/UpdateServerListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/UserGroupListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/UserListPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AJAXProxyAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AbstractAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AbstractAjaxAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AbstractDialogAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AbstractSecureAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AbstractSecureObjectAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/Action.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/core.functions.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/DatabaseObject.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/DatabaseObjectAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/DatabaseObjectDecorator.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/DatabaseObjectList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/EditableCachedObject.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/EditableObject.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/StorableObject.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItem.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/ACPSession.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/ACPSessionAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/ACPSessionEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/ACPSessionList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLog.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/data/ACPSessionData.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLog.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/template/ACPTemplate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/template/ACPTemplateAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/template/ACPTemplateEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/template/ACPTemplateList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/Application.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/ApplicationAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/ApplicationEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/ApplicationList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/group/ApplicationGroup.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/group/ApplicationGroupEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/application/group/ApplicationGroupList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cleanup/listener/CleanupListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/core/object/CoreObject.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/core/object/CoreObjectAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/core/object/CoreObjectEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/core/object/CoreObjectList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/Cronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/CronjobAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/CronjobList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/log/CronjobLog.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/log/CronjobLogAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/log/CronjobLogEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/cronjob/log/CronjobLogList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/event/listener/EventListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/event/listener/EventListenerAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/event/listener/EventListenerEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/event/listener/EventListenerList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/Language.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/LanguageAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/LanguageEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/LanguageList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/SetupLanguage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/category/LanguageCategory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/category/LanguageCategoryAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/category/LanguageCategoryEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/category/LanguageCategoryList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/item/LanguageItem.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/item/LanguageItemAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/item/LanguageItemEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/item/LanguageItemList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/server/LanguageServer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/server/LanguageServerAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/server/LanguageServerEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/language/server/LanguageServerList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/Option.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/OptionAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/OptionEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/OptionList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/category/OptionCategory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/category/OptionCategoryAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/category/OptionCategoryEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/option/category/OptionCategoryList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/Package.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/PackageAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/PackageEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/PackageList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueue.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/PackageUpdate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/PackageUpdateAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/PackageUpdateEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/PackageUpdateList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersion.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/location/Location.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/location/PageLocation.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/location/PageLocationAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/location/PageLocationEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/location/PageLocationList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/menu/item/PageMenuItem.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/search/Search.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/search/SearchAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/search/SearchEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/search/SearchList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/Session.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/SessionAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/SessionEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/SessionList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/data/SessionData.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/data/SessionDataAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/data/SessionDataEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/session/data/SessionDataList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/spider/Spider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/spider/SpiderAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/spider/SpiderEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/spider/SpiderList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/style/ActiveStyle.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/style/Style.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/style/StyleAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/style/StyleEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/style/StyleList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/Template.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/TemplateAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/TemplateEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/TemplateList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/group/TemplateGroup.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/group/TemplateGroupAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/group/TemplateGroupEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/group/TemplateGroupList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/listener/TemplateListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/listener/TemplateListenerAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/listener/TemplateListenerEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/template/listener/TemplateListenerList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/User.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/UserAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/UserEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/UserList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/UserGroup.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/UserGroupAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/UserGroupEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/UserGroupList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/UserGroupOption.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/UserOption.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/UserOptionAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/UserOptionEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/UserOptionList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/UserOptionOutput.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/category/UserOptionCategory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/form/AbstractForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/form/AbstractSecureForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/form/Form.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/page/AbstractPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/page/AbstractSecurePage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/page/MultipleLinkPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/page/Page.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/page/SortablePage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/page/util/InlineCalendar.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/SingletonFactory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/WCF.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/WCFACP.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/WCFSetup.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/application/AbstractApplication.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/application/Application.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/application/ApplicationHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/auth/UserAuth.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/auth/UserAuthDefault.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/breadcrumb/Breadcrumb.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/breadcrumb/Breadcrumbs.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderACPMenu.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderApplication.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderCleanupAdapter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderCoreObject.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderCronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderEventListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderIcon.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderLanguage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderOption.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderPackage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderPackageDependency.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderPageMenu.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderSpider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderStyle.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderTemplate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateGroup.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateListenerCode.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderUserGroup.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheBuilderUserGroupPermission.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/CacheHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/SetupCacheHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/source/CacheSource.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/source/DiskCacheSource.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/source/MemcacheAdapter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/source/MemcacheCacheSource.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cleanup/CleanupAdapter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cleanup/CleanupHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/CleanUpCronjobLogCronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/CleanUpSessionLogCronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/CleanupListenerCronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/Cronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/GetUpdateInfoCronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cronjob/RefreshSearchRobotsCronjob.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/Database.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/DatabaseException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/MySQLDatabase.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/PostgreSQLDatabase.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/util/ConditionBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/util/PreparedStatementConditionBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/database/util/SQLParser.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/event/EventHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/event/EventListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/event/listener/SessionAccessLogListener.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/AJAXException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/IllegalLinkException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/NamedUserException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/PermissionDeniedException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/PrintableException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/SystemException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/UserException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/UserInputException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/exception/ValidateActionException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/FormDocument.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/FormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/FormElementContainer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/container/AbstractFormElementContainer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/container/GroupFormElementContainer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/container/MultipleSelectionFormElementContainer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/container/SelectionFormElementContainer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/container/SingleSelectionFormElementContainer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/AbstractFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/AbstractNamedFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/LabelFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/MultipleSelectionFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/PasswordInputFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/SingleSelectionFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/form/element/TextInputFormElement.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/image/Thumbnail.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/FTP.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/File.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/GZipFile.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/RemoteFile.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/Tar.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/TarWriter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/ZipWriter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/language/LanguageFactory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/mail/DebugMailSender.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/mail/Mail.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/mail/MailSender.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/mail/PHPMailSender.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/mail/SMTPMailSender.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/menu/TreeMenu.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/menu/TreeMenuItem.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/menu/acp/ACPMenu.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/menu/page/DefaultPageMenuItemProvider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/menu/page/PageMenu.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/menu/page/PageMenuItemProvider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeBoolean.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeCustomselect.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeDate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeFloat.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeInteger.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeMultiselect.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypePassword.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeRadiobuttons.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeSelect.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeText.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeTextarea.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/OptionTypeTimezone.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/SearchableUserOption.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeBoolean.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeGroups.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInfiniteInteger.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInfiniteInverseInteger.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInteger.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInverseInteger.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeText.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/group/GroupOptionTypeTextarea.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/ACPTemplatesFileHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/FilesFileHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageArchive.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageDependencyHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageInstallationFileHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageInstallationFormManager.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageInstallationNodeBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageInstallationStep.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageUpdateAuthorizationRequiredException.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/TemplatesFileHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/ACPTemplatesPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/AbstractPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/CoreObjectPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/CronjobsPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/FilesPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/GroupOptionsPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/LanguagesPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/OptionsPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/PIPPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/PackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/PageLocationPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/PageMenuPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/ScriptPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/SqlPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/StyleAttributesPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/StylePackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/TemplatesPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/UserOptionsPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/request/LinkHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/request/Request.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/request/RequestHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/session/ACPSessionFactory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/session/AbstractSessionHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/session/SessionFactory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/session/SessionHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/setup/FileHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/setup/Installer.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/setup/Uninstaller.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/storage/StorageHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/style/StyleHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/ACPTemplateEngine.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/SetupTemplate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/SetupTemplateEngine.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplateCompiler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplateEngine.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplatePluginBlock.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplatePluginCompiler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplatePluginFunction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplatePluginModifier.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplatePluginPrefilter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/TemplateScriptingCompiler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginBlockLink.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerAppend.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerAssign.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerFetch.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerIcon.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerImplode.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerLang.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerPrepend.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerStaticlang.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionCounter.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionCycle.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionHtmlcheckboxes.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionHtmloptions.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionPages.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionSmallpages.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierArrayfromlist.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierConcat.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierDate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierDatediff.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierEncodejs.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierFilesize.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierFilesizeBinary.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierPlainTime.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierTime.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierTruncate.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterEvent.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterHascontent.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterIcon.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterLang.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/ArrayUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/BasicFileUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/ClassUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/CronjobUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/DateUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/FileUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/HeaderUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/ImageUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/JSON.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/MathUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/StringStack.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/StringUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/StyleUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/UserUtil.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/XML.class.php [new file with mode: 0644]
wcfsetup/install/files/options.inc.php [new file with mode: 0644]
wcfsetup/install/files/style/buttons.css [new file with mode: 0644]
wcfsetup/install/files/style/colorPicker.css [new file with mode: 0644]
wcfsetup/install/files/style/containers.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/ie6-fix-rtl.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/ie6-fix.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/ie7-fix-rtl.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/ie7-fix.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/ie8-fix-rtl.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/ie8-fix.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/print-rtl.css [new file with mode: 0644]
wcfsetup/install/files/style/extra/print.css [new file with mode: 0644]
wcfsetup/install/files/style/footer.css [new file with mode: 0644]
wcfsetup/install/files/style/forms.css [new file with mode: 0644]
wcfsetup/install/files/style/global.css [new file with mode: 0644]
wcfsetup/install/files/style/header.css [new file with mode: 0644]
wcfsetup/install/files/style/imageViewer.css [new file with mode: 0644]
wcfsetup/install/files/style/inlineCalendar.css [new file with mode: 0644]
wcfsetup/install/files/style/layout.css [new file with mode: 0644]
wcfsetup/install/files/style/messages.css [new file with mode: 0644]
wcfsetup/install/files/style/pageMenu.css [new file with mode: 0644]
wcfsetup/install/files/style/pageNavigation.css [new file with mode: 0644]
wcfsetup/install/files/style/tabbedMenus.css [new file with mode: 0644]
wcfsetup/install/files/style/tables.css [new file with mode: 0644]
wcfsetup/install/files/templates/.htaccess [new file with mode: 0644]
wcfsetup/install/lang/da.xml [new file with mode: 0644]
wcfsetup/install/lang/de-informal.xml [new file with mode: 0644]
wcfsetup/install/lang/de.xml [new file with mode: 0644]
wcfsetup/install/lang/en.xml [new file with mode: 0644]
wcfsetup/install/lang/fr.xml [new file with mode: 0644]
wcfsetup/install/lang/hr.xml [new file with mode: 0644]
wcfsetup/install/lang/it.xml [new file with mode: 0644]
wcfsetup/install/lang/pt-BR.xml [new file with mode: 0644]
wcfsetup/install/lang/sv.xml [new file with mode: 0644]
wcfsetup/install/lang/tr.xml [new file with mode: 0644]
wcfsetup/install/lang/zh-CN.xml [new file with mode: 0644]
wcfsetup/install/lang/zh-TW.xml [new file with mode: 0644]
wcfsetup/setup/db/install.sql [new file with mode: 0644]
wcfsetup/setup/lang/setup_da.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_de-informal.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_de.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_en.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_fr.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_hr.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_it.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_pt-BR.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_sv.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_tr.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_zh-CN.xml [new file with mode: 0644]
wcfsetup/setup/lang/setup_zh-TW.xml [new file with mode: 0644]
wcfsetup/setup/license/license_en.txt [new file with mode: 0644]
wcfsetup/setup/template/footer.tpl [new file with mode: 0644]
wcfsetup/setup/template/header.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepConfigureDB.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepCreateUser.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepInstallPackages.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepNext.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepSearchWcfDir.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepSelectLanguages.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepSelectSetupLanguage.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepShowLicense.tpl [new file with mode: 0644]
wcfsetup/setup/template/stepShowSystemRequirements.tpl [new file with mode: 0644]
wcfsetup/test.php [new file with mode: 0644]

diff --git a/com.woltlab.wcf/acpmenu.xml b/com.woltlab.wcf/acpmenu.xml
new file mode 100644 (file)
index 0000000..20ee7e9
--- /dev/null
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/acpmenu.xsd">\r
+       <import>\r
+               <acpmenuitem name="wcf.acp.menu.link.system">\r
+                       <icon>icon/systemL.png</icon>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <!-- options -->\r
+               <acpmenuitem name="wcf.acp.menu.link.option">\r
+                       <parent>wcf.acp.menu.link.system</parent>\r
+                       <showorder>1</showorder>\r
+                       <permissions>admin.system.canEditOption</permissions>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.option.category">\r
+                       <parent>wcf.acp.menu.link.option</parent>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.option.management">\r
+                       <parent>wcf.acp.menu.link.option</parent>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.option.importAndExport">\r
+                       <parent>wcf.acp.menu.link.option.management</parent>\r
+                       <showorder>1</showorder>\r
+                       <link>index.php?form=OptionImport</link>\r
+               </acpmenuitem>\r
+               <!-- /options -->\r
+               \r
+               <!-- packages -->\r
+               <acpmenuitem name="wcf.acp.menu.link.package">\r
+                       <parent>wcf.acp.menu.link.system</parent>\r
+                       <showorder>2</showorder>\r
+                       <permissions>admin.system.package.canInstallPackage,admin.system.package.canUpdatePackage,admin.system.package.canUninstallPackage,admin.system.package.canEditServer</permissions>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.management">\r
+                       <parent>wcf.acp.menu.link.package</parent>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.view">\r
+                       <icon>icon/packageM.png</icon>\r
+                       <link>index.php?page=PackageList</link>\r
+                       <parent>wcf.acp.menu.link.package.management</parent>\r
+                       <permissions>admin.system.package.canUpdatePackage,admin.system.package.canUninstallPackage</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.install">\r
+                       <link>index.php?form=PackageStartInstall&amp;action=install</link>\r
+                       <parent>wcf.acp.menu.link.package.management</parent>\r
+                       <permissions>admin.system.package.canInstallPackage</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.update">\r
+                       <parent>wcf.acp.menu.link.package</parent>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.autoupdate">\r
+                       <icon>icon/updateM.png</icon>\r
+                       <link>index.php?page=PackageAutoUpdateList</link>\r
+                       <parent>wcf.acp.menu.link.package.update</parent>\r
+                       <permissions>admin.system.package.canUpdatePackage</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.database">\r
+                       <link>index.php?form=PackageUpdateSearch</link>\r
+                       <parent>wcf.acp.menu.link.package.update</parent>\r
+                       <permissions>admin.system.package.canInstallPackage,admin.system.package.canUpdatePackage</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.server">\r
+                       <parent>wcf.acp.menu.link.package</parent>\r
+                       <showorder>3</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.server.view">\r
+                       <icon>icon/updateServerM.png</icon>\r
+                       <link>index.php?page=UpdateServerList</link>\r
+                       <parent>wcf.acp.menu.link.package.server</parent>\r
+                       <permissions>admin.system.package.canEditServer</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.package.server.add">\r
+                       <link>index.php?form=UpdateServerAdd</link>\r
+                       <parent>wcf.acp.menu.link.package.server</parent>\r
+                       <permissions>admin.system.package.canEditServer</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               <!-- /packages -->      \r
+               \r
+               <!-- maintenance -->\r
+               <acpmenuitem name="wcf.acp.menu.link.maintenance">\r
+                       <parent>wcf.acp.menu.link.system</parent>\r
+                       <showorder>3</showorder>\r
+               </acpmenuitem>\r
+               <!-- /maintenance -->\r
+               \r
+               <!-- log -->\r
+               <acpmenuitem name="wcf.acp.menu.link.log">\r
+                       <parent>wcf.acp.menu.link.system</parent>\r
+                       <showorder>4</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.log.system">\r
+                       <parent>wcf.acp.menu.link.log</parent>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.log.additional">\r
+                       <parent>wcf.acp.menu.link.log</parent>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.log.session">\r
+                       <icon>icon/sessionLogM.png</icon>\r
+                       <link>index.php?page=ACPSessionLogList</link>\r
+                       <parent>wcf.acp.menu.link.log.system</parent>\r
+                       <permissions>admin.system.canViewLog</permissions>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.log.cache">\r
+                       <link>index.php?page=CacheList</link>\r
+                       <parent>wcf.acp.menu.link.log.system</parent>\r
+                       <permissions>admin.system.canViewLog</permissions>\r
+               </acpmenuitem>\r
+               <!-- /log -->\r
+               \r
+               <!-- cronjobs -->\r
+               <acpmenuitem name="wcf.acp.menu.link.cronjobs">\r
+                       <parent>wcf.acp.menu.link.maintenance</parent>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.cronjobs.view">\r
+                       <icon>icon/cronjobsM.png</icon>\r
+                       <link>index.php?page=CronjobList</link>\r
+                       <parent>wcf.acp.menu.link.cronjobs</parent>\r
+                       <permissions>admin.system.cronjobs.canEditCronjob,admin.system.cronjobs.canDeleteCronjob,admin.system.cronjobs.canEnableDisableCronjob</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.cronjobs.add">\r
+                       <link>index.php?form=CronjobAdd</link>\r
+                       <parent>wcf.acp.menu.link.cronjobs</parent>\r
+                       <permissions>admin.system.cronjobs.canAddCronjob</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.cronjobs.showLog">\r
+                       <link>index.php?page=CronjobLogList</link>\r
+                       <parent>wcf.acp.menu.link.log.system</parent>\r
+                       <permissions>admin.system.cronjobs.canEditCronjob,admin.system.cronjobs.canDeleteCronjob</permissions>\r
+               </acpmenuitem>\r
+               <!-- /cronjobs -->\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user">\r
+                       <icon>icon/usersL.png</icon>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <!-- users -->\r
+               <acpmenuitem name="wcf.acp.menu.link.user.management">\r
+                       <parent>wcf.acp.menu.link.user</parent>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.management.general">\r
+                       <parent>wcf.acp.menu.link.user.management</parent>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.list">\r
+                       <icon>icon/usersM.png</icon>\r
+                       <link>index.php?page=UserList</link>\r
+                       <parent>wcf.acp.menu.link.user.management.general</parent>\r
+                       <permissions>admin.user.canSearchUser</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.search">\r
+                       <icon>icon/searchM.png</icon>\r
+                       <link>index.php?form=UserSearch</link>\r
+                       <parent>wcf.acp.menu.link.user.management.general</parent>\r
+                       <permissions>admin.user.canSearchUser</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.add">\r
+                       <link>index.php?form=UserAdd</link>\r
+                       <parent>wcf.acp.menu.link.user.management.general</parent>\r
+                       <permissions>admin.user.canAddUser</permissions>\r
+                       <showorder>3</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.management.additional">\r
+                       <parent>wcf.acp.menu.link.user.management</parent>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.massProcessing">\r
+                       <link>index.php?form=UsersMassProcessing</link>\r
+                       <parent>wcf.acp.menu.link.user.management.additional</parent>\r
+                       <permissions>admin.user.canEditUser,admin.user.canDeleteUser,admin.user.canMailUser</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.user.mail">\r
+                       <link>index.php?form=UserMail&amp;action=all</link>\r
+                       <parent>wcf.acp.menu.link.user.management.additional</parent>\r
+                       <permissions>admin.user.canMailUser</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               <!-- /users -->\r
+               \r
+               <!-- user groups -->\r
+               <acpmenuitem name="wcf.acp.menu.link.group">\r
+                       <parent>wcf.acp.menu.link.user</parent>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.group.general">\r
+                       <parent>wcf.acp.menu.link.group</parent>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.group.view">\r
+                       <icon>icon/userGroupM.png</icon>\r
+                       <link>index.php?page=UserGroupList</link>\r
+                       <parent>wcf.acp.menu.link.group.general</parent>\r
+                       <permissions>admin.user.canEditGroup,admin.user.canDeleteGroup</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>  \r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.group.add">\r
+                       <link>index.php?form=UserGroupAdd</link>\r
+                       <parent>wcf.acp.menu.link.group.general</parent>\r
+                       <permissions>admin.user.canAddGroup</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.group.additional">\r
+                       <parent>wcf.acp.menu.link.group</parent>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.group.mail">\r
+                       <icon>icon/emailM.png</icon>\r
+                       <link>index.php?form=UserMail&amp;action=group</link>\r
+                       <parent>wcf.acp.menu.link.group.additional</parent>\r
+                       <permissions>admin.user.canMailUser</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+               <!-- user groups -->\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.display">\r
+                       <icon>icon/displayL.png</icon>\r
+                       <showorder>3</showorder>\r
+               </acpmenuitem>\r
+               \r
+               <!-- language -->\r
+               <acpmenuitem name="wcf.acp.menu.link.language">\r
+                       <parent>wcf.acp.menu.link.display</parent>\r
+               </acpmenuitem>\r
+\r
+               <acpmenuitem name="wcf.acp.menu.link.language.server">\r
+                       <parent>wcf.acp.menu.link.language</parent>\r
+               </acpmenuitem>\r
+\r
+               <acpmenuitem name="wcf.acp.menu.link.language.server.list">\r
+                       <icon>icon/languageServerM.png</icon>\r
+                       <link>index.php?page=LanguageServerList</link>\r
+                       <parent>wcf.acp.menu.link.language.server</parent>\r
+                       <permissions>admin.language.canEditServer</permissions>\r
+                       <showorder>1</showorder>\r
+               </acpmenuitem>\r
+\r
+               <acpmenuitem name="wcf.acp.menu.link.language.server.add">\r
+                       <link>index.php?form=LanguageServerAdd</link>\r
+                       <parent>wcf.acp.menu.link.language.server</parent>\r
+                       <permissions>admin.language.canEditServer</permissions>\r
+                       <showorder>2</showorder>\r
+               </acpmenuitem>\r
+               <!-- /language -->\r
+               \r
+               <acpmenuitem name="wcf.acp.menu.link.content">\r
+                       <icon>icon/contentL.png</icon>\r
+                       <showorder>4</showorder>\r
+               </acpmenuitem>\r
+       </import>\r
+</data>\r
diff --git a/com.woltlab.wcf/coreobject.xml b/com.woltlab.wcf/coreobject.xml
new file mode 100644 (file)
index 0000000..ef99971
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/coreobject.xsd">
+       <import>
+               <coreobject>
+                       <objectname><![CDATA[wcf\system\breadcrumb\Breadcrumbs]]></objectname>
+               </coreobject>
+               <coreobject>
+                       <objectname><![CDATA[wcf\system\request\LinkHandler]]></objectname>
+               </coreobject>
+               <coreobject>
+                       <objectname><![CDATA[wcf\system\menu\page\PageMenu]]></objectname>
+               </coreobject>
+               <coreobject>
+                       <objectname><![CDATA[wcf\system\menu\acp\ACPMenu]]></objectname>
+               </coreobject>
+       </import>
+</data>
diff --git a/com.woltlab.wcf/cronjobs.xml b/com.woltlab.wcf/cronjobs.xml
new file mode 100644 (file)
index 0000000..29284d9
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/cronjobs.xsd">\r
+       <import>\r
+               <cronjob>\r
+                       <classpath>lib/system/cronjob/GetUpdateInfoCronjob.class.php</classpath>\r
+                       <description>Gets update package information</description>\r
+                       <startminute>0</startminute>\r
+                       <starthour>2</starthour>\r
+                       <startdom>*/2</startdom>\r
+                       <startmonth>*</startmonth>\r
+                       <startdow>*</startdow>\r
+                       <active>1</active>\r
+                       <canbeedited>1</canbeedited>\r
+                       <canbedisabled>1</canbedisabled>\r
+               </cronjob>\r
+               \r
+               <cronjob>\r
+                       <classpath>lib/system/cronjob/RefreshSearchRobotsCronjob.class.php</classpath>\r
+                       <description>Refreshes list of search robots</description>\r
+                       <startminute>0</startminute>\r
+                       <starthour>3</starthour>\r
+                       <startdom>1</startdom>\r
+                       <startmonth>*</startmonth>\r
+                       <startdow>*</startdow>\r
+                       <active>1</active>\r
+                       <canbeedited>1</canbeedited>\r
+                       <canbedisabled>1</canbedisabled>\r
+               </cronjob>\r
+               \r
+               <cronjob>\r
+                       <classpath>lib/system/cronjob/CleanUpCronjobLogCronjob.class.php</classpath>\r
+                       <description>Deletes old entries from cronjob log.</description>\r
+                       <startminute>0</startminute>\r
+                       <starthour>12</starthour>\r
+                       <startdom>*</startdom>\r
+                       <startmonth>*</startmonth>\r
+                       <startdow>*</startdow>\r
+                       <active>1</active>\r
+                       <canbeedited>1</canbeedited>\r
+                       <canbedisabled>1</canbedisabled>\r
+               </cronjob>\r
+               \r
+               <cronjob>\r
+                       <classpath>lib/system/cronjob/CleanUpSessionLogCronjob.class.php</classpath>\r
+                       <description>Deletes old entries from session log.</description>\r
+                       <startminute>0</startminute>\r
+                       <starthour>10</starthour>\r
+                       <startdom>*</startdom>\r
+                       <startmonth>*</startmonth>\r
+                       <startdow>*</startdow>\r
+                       <active>1</active>\r
+                       <canbeedited>0</canbeedited>\r
+                       <canbedisabled>0</canbedisabled>\r
+               </cronjob>\r
+               \r
+               <cronjob>\r
+                       <classpath>lib/system/cronjob/CleanupListenerCronjob.class.php</classpath>\r
+                       <description>Executes cleanup system.</description>\r
+                       <startminute>5,20,35,50</startminute>\r
+                       <starthour>*</starthour>\r
+                       <startdom>*</startdom>\r
+                       <startmonth>*</startmonth>\r
+                       <startdow>*</startdow>\r
+                       <active>1</active>\r
+                       <canbeedited>0</canbeedited>\r
+                       <canbedisabled>0</canbedisabled>\r
+               </cronjob>\r
+       </import>\r
+</data>
\ No newline at end of file
diff --git a/com.woltlab.wcf/eventlistener.xml b/com.woltlab.wcf/eventlistener.xml
new file mode 100644 (file)
index 0000000..e1ebdd1
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/eventlistener.xsd">
+       <import>
+               <eventlistener>
+                       <eventclassname>wcf\page\AbstractPage</eventclassname>
+                       <eventname>readParameters</eventname>
+                       <environment>admin</environment>
+                       <inherit>1</inherit>
+                       <listenerclassname>wcf\system\event\listener\SessionAccessLogListener</listenerclassname>
+               </eventlistener>
+               <eventlistener>
+                       <eventclassname>wcf\form\AbstractForm</eventclassname>
+                       <eventname>readParameters</eventname>
+                       <environment>admin</environment>
+                       <inherit>1</inherit>
+                       <listenerclassname>wcf\system\event\listener\SessionAccessLogListener</listenerclassname>
+               </eventlistener>
+               <eventlistener>
+                       <eventclassname>wcf\action\AbstractAction</eventclassname>
+                       <eventname>readParameters</eventname>
+                       <environment>admin</environment>
+                       <inherit>1</inherit>
+                       <listenerclassname>wcf\system\event\listener\SessionAccessLogListener</listenerclassname>
+               </eventlistener>
+       </import>
+</data>
\ No newline at end of file
diff --git a/com.woltlab.wcf/groupoptions.xml b/com.woltlab.wcf/groupoptions.xml
new file mode 100644 (file)
index 0000000..2ae959a
--- /dev/null
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/groupoptions.xsd">\r
+       <import>\r
+               <categories>\r
+                       <category name="user"></category>\r
+                       <category name="mod"></category>\r
+                       <category name="admin"></category>\r
+                       <category name="admin.general">\r
+                               <parent>admin</parent>\r
+                       </category>\r
+                       <category name="admin.system">\r
+                               <parent>admin</parent>\r
+                       </category>\r
+                       <category name="admin.system.cronjobs">\r
+                               <parent>admin.system</parent>\r
+                       </category>\r
+                       <category name="admin.system.package">\r
+                               <parent>admin.system</parent>\r
+                       </category>\r
+                       <category name="admin.maintenance">\r
+                               <parent>admin.system</parent>\r
+                       </category>\r
+                       <category name="admin.user">\r
+                               <parent>admin</parent>\r
+                       </category>\r
+                       <category name="admin.user.user">\r
+                               <parent>admin.user</parent>\r
+                       </category>\r
+                       <category name="admin.user.group">\r
+                               <parent>admin.user</parent>\r
+                       </category>\r
+                       \r
+                       <category name="admin.display">\r
+                               <parent>admin</parent>\r
+                       </category>\r
+                       <category name="admin.content">\r
+                               <parent>admin</parent>\r
+                       </category>\r
+                       <category name="admin.style">\r
+                               <parent>admin.display</parent>\r
+                       </category>\r
+                       <category name="admin.language">\r
+                               <parent>admin.display</parent>\r
+                       </category>\r
+               </categories>\r
+               \r
+               <options>\r
+                       <option name="admin.general.canViewPrivateUserOptions">\r
+                               <categoryname>admin.general</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.canEditOption">\r
+                               <categoryname>admin.system</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.canViewLog">\r
+                               <categoryname>admin.system</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.cronjobs.canAddCronjob">\r
+                               <categoryname>admin.system.cronjobs</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.cronjobs.canEditCronjob">\r
+                               <categoryname>admin.system.cronjobs</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.cronjobs.canDeleteCronjob">\r
+                               <categoryname>admin.system.cronjobs</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.cronjobs.canEnableDisableCronjob">\r
+                               <categoryname>admin.system.cronjobs</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.cronjobs.canDeleteCronjobsLog">\r
+                               <categoryname>admin.system.cronjobs</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.package.canUpdatePackage">\r
+                               <categoryname>admin.system.package</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.package.canUninstallPackage">\r
+                               <categoryname>admin.system.package</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.system.package.canEditServer">\r
+                               <categoryname>admin.system.package</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.accessibleGroups">\r
+                               <categoryname>admin.user.group</categoryname>\r
+                               <optiontype>groups</optiontype>\r
+                               <defaultvalue></defaultvalue>\r
+                               <admindefaultvalue>1,2,3,4,5,6</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canAddUser">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canSearchUser">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canEditUser">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canEditMailAddress">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canEditPassword">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canDeleteUser">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canMailUser">\r
+                               <categoryname>admin.user.user</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canAddGroup">\r
+                               <categoryname>admin.user.group</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.user.canDeleteGroup">\r
+                               <categoryname>admin.user.group</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.style.canUseDisabledStyle">\r
+                               <categoryname>admin.style</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.language.canAddServer">\r
+                               <categoryname>admin.language</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.language.canDeleteServer">\r
+                               <categoryname>admin.language</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+                       <option name="admin.language.canEditServer">\r
+                               <categoryname>admin.language</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                               <admindefaultvalue>1</admindefaultvalue>\r
+                       </option>\r
+               </options>\r
+       </import>\r
+</data>\r
diff --git a/com.woltlab.wcf/options.xml b/com.woltlab.wcf/options.xml
new file mode 100644 (file)
index 0000000..e24eed6
--- /dev/null
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/options.xsd">\r
+       <import>\r
+               <categories>\r
+                       <!-- modules -->\r
+                       <category name="module">\r
+                               <showorder>1</showorder>\r
+                       </category>\r
+                               <category name="module.system">\r
+                                       <parent>module</parent>\r
+                               </category>\r
+                               <category name="module.user">\r
+                                       <parent>module</parent>\r
+                               </category>\r
+                               <category name="module.display">\r
+                                       <parent>module</parent>\r
+                               </category>\r
+                               <category name="module.content">\r
+                                       <parent>module</parent>\r
+                               </category>\r
+                               \r
+                               <category name="message"></category>\r
+                               \r
+                               <category name="message.general">\r
+                                       <parent>message</parent>\r
+                               </category>\r
+                       <!-- /modules -->\r
+                       \r
+                       <!-- general -->\r
+                       <category name="general">\r
+                               <showorder>2</showorder>\r
+                       </category>\r
+                               <category name="general.page">\r
+                                       <parent>general</parent>\r
+                               </category>\r
+                               <category name="general.offline">\r
+                                       <parent>general</parent>\r
+                               </category>\r
+                               <category name="general.http">\r
+                                       <parent>general</parent>\r
+                               </category>\r
+                                       <category name="general.http.cookie">\r
+                                               <parent>general.http</parent>\r
+                                       </category>\r
+                                       <category name="general.http.http">\r
+                                               <parent>general.http</parent>\r
+                                       </category>\r
+                                       <category name="general.http.proxy">\r
+                                               <parent>general.http</parent>\r
+                                       </category>\r
+                               <category name="general.date">\r
+                                       <parent>general</parent>\r
+                               </category>\r
+                               <category name="general.mail">\r
+                                       <parent>general</parent>\r
+                               </category>\r
+                                       <category name="general.mail.general">\r
+                                               <parent>general.mail</parent>\r
+                                       </category>\r
+                                       <category name="general.mail.send">\r
+                                               <parent>general.mail</parent>\r
+                                       </category>\r
+                               <category name="general.cache">\r
+                                       <parent>general</parent>\r
+                               </category>\r
+                                       <category name="general.cache.general">\r
+                                               <parent>general.cache</parent>\r
+                                       </category>\r
+                                       <category name="general.cache.memcache">\r
+                                               <parent>general.cache</parent>\r
+                                       </category>\r
+                       <!-- /general -->\r
+                       \r
+                       <!-- user -->\r
+                       <category name="user">\r
+                               <showorder>3</showorder>\r
+                       </category>\r
+                       <!-- /user -->\r
+                       \r
+                       <!-- security -->\r
+                       <category name="security">\r
+                               <showorder>4</showorder>\r
+                       </category>\r
+                               <category name="security.general">\r
+                                       <parent>security</parent>\r
+                               </category>\r
+                                       <category name="security.general.session">\r
+                                               <parent>security.general</parent>\r
+                                       </category>\r
+                               <category name="security.blacklist">\r
+                                       <parent>security</parent>\r
+                               </category>\r
+                               <category name="security.antispam">\r
+                                       <parent>security</parent>\r
+                               </category>\r
+                               <category name="security.censorship">\r
+                                       <parent>security</parent>\r
+                               </category>\r
+                       <!-- /security -->\r
+               </categories>\r
+               \r
+               <options>\r
+                       <option name="module_master_password">\r
+                               <categoryname>module.system</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                       </option>\r
+                       \r
+                       <!-- general.page -->\r
+                       <option name="page_title">\r
+                               <categoryname>general.page</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="page_description">\r
+                               <categoryname>general.page</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="page_url">\r
+                               <categoryname>general.page</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="page_urls">\r
+                               <categoryname>general.page</categoryname>\r
+                               <optiontype>textarea</optiontype>\r
+                       </option>\r
+                       <option name="meta_keywords">\r
+                               <categoryname>general.page</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="meta_description">\r
+                               <categoryname>general.page</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <!-- /general.page -->\r
+                       \r
+                       <!-- general.http.cookie -->\r
+                       <option name="cookie_prefix">\r
+                               <categoryname>general.http.cookie</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                               <defaultvalue>wcf_</defaultvalue>\r
+                               <validationpattern>.+</validationpattern>\r
+                       </option>\r
+                       <option name="cookie_path">\r
+                               <categoryname>general.http.cookie</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                               <defaultvalue></defaultvalue>\r
+                       </option>\r
+                       <option name="cookie_domain">\r
+                               <categoryname>general.http.cookie</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <!-- /general.http.cookie-->\r
+                       \r
+                       <!-- general.http.http -->\r
+                       <option name="http_enable_no_cache_headers">\r
+                               <categoryname>general.http.http</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>0</defaultvalue>\r
+                       </option>\r
+                       <option name="http_enable_gzip">\r
+                               <categoryname>general.http.http</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>1</defaultvalue>\r
+                               <enableoptions><![CDATA[http_gzip_level]]></enableoptions>\r
+                       </option>\r
+                       <option name="http_gzip_level">\r
+                               <categoryname>general.http.http</categoryname>\r
+                               <optiontype>integer</optiontype>\r
+                               <defaultvalue>1</defaultvalue>\r
+                       </option>\r
+                       <!-- /general.http.http -->\r
+                       \r
+                       <!-- general.http.proxy -->\r
+                       <option name="proxy_server_http">\r
+                               <categoryname>general.http.proxy</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <!-- /general.http.proxy -->\r
+                       \r
+                       <!-- general.session -->\r
+                       <option name="session_timeout">\r
+                               <categoryname>security.general.session</categoryname>\r
+                               <optiontype>integer</optiontype>\r
+                               <defaultvalue>1800</defaultvalue>\r
+                               <validationpattern>^[^0]</validationpattern>\r
+                       </option>\r
+                       <option name="user_online_timeout">\r
+                               <categoryname>security.general.session</categoryname>\r
+                               <optiontype>integer</optiontype>\r
+                               <defaultvalue>900</defaultvalue>\r
+                       </option>\r
+                       <option name="session_validate_ip_address">\r
+                               <categoryname>security.general.session</categoryname>\r
+                               <optiontype>select</optiontype>\r
+                               <selectoptions>0\r
+1\r
+2\r
+3\r
+4</selectoptions>\r
+                               <defaultvalue>2</defaultvalue>\r
+                       </option>\r
+                       <option name="session_validate_user_agent">\r
+                               <categoryname>security.general.session</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                               <defaultvalue>1</defaultvalue>\r
+                       </option>\r
+                       <!-- /general.session -->\r
+                       \r
+                       <!-- security.blacklist -->\r
+                       <option name="blacklist_ip_addresses">\r
+                               <categoryname>security.blacklist</categoryname>\r
+                               <optiontype>textarea</optiontype>\r
+                       </option>\r
+                       <option name="blacklist_user_agents">\r
+                               <categoryname>security.blacklist</categoryname>\r
+                               <optiontype>textarea</optiontype>\r
+                       </option>\r
+                       <option name="blacklist_hostnames">\r
+                               <categoryname>security.blacklist</categoryname>\r
+                               <optiontype>textarea</optiontype>\r
+                       </option>\r
+                       <!-- /security.blacklist -->\r
+                       \r
+                       <!-- general.date -->\r
+                       <option name="timezone">\r
+                               <categoryname>general.date</categoryname>\r
+                               <optiontype>timezone</optiontype>\r
+                               <defaultvalue>Europe/London</defaultvalue>\r
+                       </option>\r
+                       <!-- /general.date -->\r
+                       \r
+                       <!-- mail.general -->\r
+                       <option name="mail_from_name">\r
+                               <categoryname>general.mail.general</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                               <defaultvalue><![CDATA[]]></defaultvalue>\r
+                       </option>\r
+                       <option name="mail_from_address">\r
+                               <categoryname>general.mail.general</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                               <defaultvalue><![CDATA[]]></defaultvalue>\r
+                       </option>\r
+                       <option name="mail_admin_address">\r
+                               <categoryname>general.mail.general</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                               <defaultvalue><![CDATA[]]></defaultvalue>\r
+                       </option>\r
+                       <option name="mail_signature">\r
+                               <categoryname>general.mail.general</categoryname>\r
+                               <optiontype>textarea</optiontype>\r
+                               <defaultvalue><![CDATA[]]></defaultvalue>\r
+                       </option>\r
+                       <!-- /mail.general -->\r
+                       \r
+                       <!-- mail.send -->\r
+                       <option name="mail_send_method">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>radiobuttons</optiontype>\r
+                               <defaultvalue><![CDATA[php]]></defaultvalue>\r
+                               <selectoptions><![CDATA[php:wcf.acp.option.mail_send_method.php\r
+smtp:wcf.acp.option.mail_send_method.smtp\r
+debug:wcf.acp.option.mail_send_method.debug]]></selectoptions>\r
+                               <enableoptions><![CDATA[php:mail_use_f_param,!mail_debug_logfile_path,!mail_smtp_host,!mail_smtp_port,!mail_smtp_user,!mail_smtp_password\r
+smtp:!mail_debug_logfile_path,!mail_use_f_param,mail_smtp_host,mail_smtp_port,mail_smtp_user,mail_smtp_password\r
+debug:mail_debug_logfile_path,!mail_use_f_param,!mail_smtp_host,!mail_smtp_port,!mail_smtp_user,!mail_smtp_password]]></enableoptions>\r
+                       </option>\r
+                       <option name="mail_debug_logfile_path">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="mail_smtp_host">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="mail_smtp_port">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>integer</optiontype>\r
+                               <defaultvalue><![CDATA[25]]></defaultvalue>\r
+                       </option>\r
+                       <option name="mail_smtp_user">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                       </option>\r
+                       <option name="mail_smtp_password">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>password</optiontype>\r
+                       </option>\r
+                       <option name="mail_use_f_param">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                       </option>\r
+                       <option name="mail_use_formatted_address">\r
+                               <categoryname>general.mail.send</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                       </option>\r
+                       <!-- /mail.send -->\r
+                       \r
+                       <!-- general.cache -->\r
+                       <option name="cache_source_type">\r
+                               <categoryname>general.cache.general</categoryname>\r
+                               <optiontype>radiobuttons</optiontype>\r
+                               <defaultvalue><![CDATA[disk]]></defaultvalue>\r
+                               <selectoptions><![CDATA[disk:wcf.acp.option.cache_source_type.disk\r
+memcache:wcf.acp.option.cache_source_type.memcache]]></selectoptions>\r
+                               <enableoptions><![CDATA[disk:!cache_source_memcache_host,!cache_source_memcache_use_pconnect,!enable_session_data_cache\r
+memcache:cache_source_memcache_host,cache_source_memcache_use_pconnect,enable_session_data_cache]]></enableoptions>\r
+                       </option>\r
+                       \r
+                       <option name="enable_session_data_cache">\r
+                               <categoryname>general.cache.general</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                       </option>\r
+                       \r
+                       <option name="cache_source_memcache_host">\r
+                               <categoryname>general.cache.memcache</categoryname>\r
+                               <optiontype>textarea</optiontype>\r
+                       </option>\r
+                       \r
+                       <option name="cache_source_memcache_use_pconnect">\r
+                               <categoryname>general.cache.memcache</categoryname>\r
+                               <optiontype>boolean</optiontype>\r
+                       </option>\r
+                       <!-- /general.cache -->\r
+               </options>\r
+       </import>\r
+</data>
\ No newline at end of file
diff --git a/com.woltlab.wcf/package.xml b/com.woltlab.wcf/package.xml
new file mode 100644 (file)
index 0000000..7fd13fc
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<package name="com.woltlab.wcf" xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/package.xsd">\r
+       <packageinformation>\r
+               <packagename>WoltLab Community Framework</packagename>\r
+               <packagedescription>Free web-framework, designed and developed for complex community applications.</packagedescription>\r
+               <standalone>1</standalone>\r
+               <isunique>1</isunique>\r
+               <version>2.0.0 Alpha 1</version> <!-- codename: maelstrom -->\r
+               <date>2011-05-19</date>\r
+       </packageinformation>\r
+       \r
+       <authorinformation>\r
+               <author>WoltLab GmbH</author>\r
+               <authorurl>http://www.woltlab.com</authorurl>\r
+       </authorinformation>\r
+       \r
+       <instructions type="install">\r
+               <instruction type="packageinstallationplugins">pip.xml</instruction>\r
+               <instruction type="acpmenu">acpmenu.xml</instruction>\r
+               <instruction type="groupoptions">groupoptions.xml</instruction>\r
+               <instruction type="options">options.xml</instruction>\r
+               <instruction type="useroptions">useroptions.xml</instruction>\r
+               <instruction type="templates">templates.tar</instruction>\r
+               <instruction type="eventlistener">eventlistener.xml</instruction>\r
+               <instruction type="script">acp/install.php</instruction>\r
+               <instruction type="cronjobs">cronjobs.xml</instruction>\r
+               <instruction type="coreobject">coreobject.xml</instruction>\r
+       </instructions>\r
+</package>\r
diff --git a/com.woltlab.wcf/pip.xml b/com.woltlab.wcf/pip.xml
new file mode 100644 (file)
index 0000000..c67580c
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/pip.xsd">
+       <import>
+               <pip name="acpmenu">wcf\system\package\plugin\ACPMenuPackageInstallationPlugin</pip>
+               <pip name="acptemplates">wcf\system\package\plugin\ACPTemplatesPackageInstallationPlugin</pip>
+               <pip name="coreobject">wcf\system\package\plugin\CoreObjectPackageInstallationPlugin</pip>
+               <pip name="cronjobs">wcf\system\package\plugin\CronjobsPackageInstallationPlugin</pip>
+               <pip name="eventlistener">wcf\system\package\plugin\EventListenerPackageInstallationPlugin</pip>
+               <pip name="files">wcf\system\package\plugin\FilesPackageInstallationPlugin</pip>
+               <pip name="groupoptions">wcf\system\package\plugin\GroupOptionsPackageInstallationPlugin</pip>
+               <pip name="languages">wcf\system\package\plugin\LanguagesPackageInstallationPlugin</pip>
+               <pip name="options">wcf\system\package\plugin\OptionsPackageInstallationPlugin</pip>
+               <pip name="pagemenu">wcf\system\package\plugin\PageMenuPackageInstallationPlugin</pip>
+               <pip name="script">wcf\system\package\plugin\ScriptPackageInstallationPlugin</pip>
+               <pip name="sql">wcf\system\package\plugin\SqlPackageInstallationPlugin</pip>
+               <pip name="templatelistener">wcf\system\package\plugin\TemplateListenerPackageInstallationPlugin</pip>
+               <pip name="templates">wcf\system\package\plugin\TemplatesPackageInstallationPlugin</pip>
+               <pip name="useroptions">wcf\system\package\plugin\UserOptionsPackageInstallationPlugin</pip>
+       </import>
+</data>
diff --git a/com.woltlab.wcf/styleattributes.xml b/com.woltlab.wcf/styleattributes.xml
new file mode 100644 (file)
index 0000000..ef84018
--- /dev/null
@@ -0,0 +1,4185 @@
+<?xml version="1.0"?>\r
+<!DOCTYPE data SYSTEM "http://www.woltlab.com/DTDs/styleattributes.dtd">\r
+<data>\r
+       <import>\r
+               <attribute>\r
+                       <selector><![CDATA[]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[user.additional.style.input1.use]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[user.additional.style.input2.use]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[page.header.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[page.header.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[background-position]]></name>\r
+                       <value><![CDATA[page.header.background.image.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[background-repeat]]></name>\r
+                       <value><![CDATA[page.header.background.image.repeat]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo]]></selector>\r
+                       <name><![CDATA[border-bottom-width]]></name>\r
+                       <value><![CDATA[menu.main.bar.divider.show]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo]]></selector>\r
+                       <name><![CDATA[height]]></name>\r
+                       <value><![CDATA[page.header.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo .pageLogo]]></selector>\r
+                       <name><![CDATA[text-align]]></name>\r
+                       <value><![CDATA[page.logo.image.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo .pageLogo img]]></selector>\r
+                       <name><![CDATA[margin-left]]></name>\r
+                       <value><![CDATA[page.logo.image.padding.left]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo .pageLogo img]]></selector>\r
+                       <name><![CDATA[margin-right]]></name>\r
+                       <value><![CDATA[page.logo.image.padding.right]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo .pageLogo img]]></selector>\r
+                       <name><![CDATA[margin-top]]></name>\r
+                       <value><![CDATA[page.logo.image.padding.top]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[global.title.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[text-align]]></name>\r
+                       <value><![CDATA[global.title.font.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[global.title.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[global.title.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[font-style]]></name>\r
+                       <value><![CDATA[global.title.font.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[font-weight]]></name>\r
+                       <value><![CDATA[global.title.font.weight]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[global.title.hide]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[global.title.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1 a]]></selector>\r
+                       <name><![CDATA[padding-left]]></name>\r
+                       <value><![CDATA[global.title.font.padding.left]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1 a]]></selector>\r
+                       <name><![CDATA[padding-right]]></name>\r
+                       <value><![CDATA[global.title.font.padding.right]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#logo h1 a]]></selector>\r
+                       <name><![CDATA[padding-top]]></name>\r
+                       <value><![CDATA[global.title.font.padding.top]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#userPanel]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.alignment.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.alignment.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footer]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.alignment.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#main]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.alignment.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#userPanel]]></selector>\r
+                       <name><![CDATA[width]]></name>\r
+                       <value><![CDATA[page.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[width]]></name>\r
+                       <value><![CDATA[page.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footer]]></selector>\r
+                       <name><![CDATA[width]]></name>\r
+                       <value><![CDATA[page.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.footerOptions li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.footerOptions li.extraButton]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.footerMenu li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#main]]></selector>\r
+                       <name><![CDATA[width]]></name>\r
+                       <value><![CDATA[page.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#userPanel]]></selector>\r
+                       <name><![CDATA[max-width]]></name>\r
+                       <value><![CDATA[page.width.max]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[max-width]]></name>\r
+                       <value><![CDATA[page.width.max]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footer]]></selector>\r
+                       <name><![CDATA[max-width]]></name>\r
+                       <value><![CDATA[page.width.max]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#main]]></selector>\r
+                       <name><![CDATA[max-width]]></name>\r
+                       <value><![CDATA[page.width.max]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#userPanel]]></selector>\r
+                       <name><![CDATA[min-width]]></name>\r
+                       <value><![CDATA[page.width.min]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[min-width]]></name>\r
+                       <value><![CDATA[page.width.min]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footer]]></selector>\r
+                       <name><![CDATA[min-width]]></name>\r
+                       <value><![CDATA[page.width.min]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#main]]></selector>\r
+                       <name><![CDATA[min-width]]></name>\r
+                       <value><![CDATA[page.width.min]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.columnContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[* a.externalURL]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.external.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[* a.externalURL:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.external.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeContainer a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeMessage]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.activeMessage]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.attachmentFile ul li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.attachmentPreview ul li a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.attachmentPreview ul li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.attachmentPreview ul li:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarDisplay div]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarDisplay div]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarDisplay div]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label:hover]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label:hover]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.boardlistCounter]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.boardlistDescription]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.boardlistLastPost]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.boardlistSubboards]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.boardlistUsersOnline]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border .container-1 a:active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.active]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border .container-2 a:active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.active]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border .container-3 a:active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.active]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border .containerHead a:active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.active]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border .tableList td]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.border .tableList th]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.breadCrumbs]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.dynBoxInner]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .signature]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .columnTitle a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 fieldset fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 fieldset fieldset.noJavaScript fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 legend]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .formFieldDesc]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.color-1 legend]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .formFieldDesc]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .signature]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .columnTitle a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 fieldset fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 legend]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.color-2 legend]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 fieldset fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-4]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container4.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-4]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container4.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-4 .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container4.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-4 .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container4.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-4 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container4.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-4 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container4.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.itemList .itemListCategory]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.itemList .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.itemList .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.itemList .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive > .border > .itemList > li:last-child > .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive > .border > .itemList > li:last-child > .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-top-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive > .border > .itemList > li:last-child > .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-top-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive .itemList > li > .itemList > li > .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive .itemList > li > .itemList > li > .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-top-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive .itemList > li > .itemList > li > .itemListTitle]]></selector>\r
+                       <name><![CDATA[border-top-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive .itemList > li > .itemList > li > .itemList]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive .itemList > li > .itemList > li > .itemList]]></selector>\r
+                       <name><![CDATA[border-top-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blogBoxArchive .itemList > li > .itemList > li > .itemList]]></selector>\r
+                       <name><![CDATA[border-top-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.simpleBar ul]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.simpleBar ul li]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.simpleBar ul li a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.simpleBar ul li a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.simpleBar ul li a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container4.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.simpleBar ul li.selected a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container4.background.color]]></value>\r
+               </attribute>            \r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[container.head.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.containerHead a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 .containerHead a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 .containerHead a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footer]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.dividers .messageAuthor]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.dividers .userAvatar]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.dividers .userCredits]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.dividers .userMessenger]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.dividers .userSymbols]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editNote]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editNote]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editNote]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editNote]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.deleteNote]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.deleteNote]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.deleteNote]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.deleteNote]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editor textarea]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[input.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editor textarea]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[input.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editor textarea]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.editor textarea:focus]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.error]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.error]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.error]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.firstPost]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.formField label]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.formFieldDesc]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.formFieldDesc]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.iframeBody]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[page.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.iframeBody]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.iframeBody]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.info]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.info]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.info]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter td]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter td]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[container.head.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter td a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter td a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter td span]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarFooter td span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader td]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader td]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[container.head.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader td a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader td a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader td span]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarHeader td span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable a:hover]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inlineCalendarTable a:hover]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[input.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[input.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[input.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[input.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[input.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText:focus]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText:focus]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[input.border.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText:focus]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[input.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.inputText:focus]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.large.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.large.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.large.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.large.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.large.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.large.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a span]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[buttons.large.caption.hide]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.large.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.large.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.large.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.large.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainMenu]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.alignment.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainMenu]]></selector>\r
+                       <name><![CDATA[width]]></name>\r
+                       <value><![CDATA[page.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainMenu]]></selector>\r
+                       <name><![CDATA[max-width]]></name>\r
+                       <value><![CDATA[page.width.max]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainMenu]]></selector>\r
+                       <name><![CDATA[min-width]]></name>\r
+                       <value><![CDATA[page.width.min]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.bar.hide]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .active a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .active a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .active a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.main.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .active a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.active.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .active a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.active.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .firstActive a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .firstActive a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .firstActive a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.main.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .firstActive a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.active.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .firstActive a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.active.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .lastActive a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .lastActive a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .lastActive a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.main.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .lastActive a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.active.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .lastActive a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.active.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.main.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.main.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.main.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.main.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu .mainMenuInner]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[menu.main.position]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .active a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .active a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .active a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .bottomSeparator a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .bottomSeparator a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .bottomSeparator a]]></selector>\r
+                       <name><![CDATA[border-bottom-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .topSeparator a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .topSeparator a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu .topSeparator a]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mainMenu span]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[menu.main.caption.hide]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.marked]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.markedDayField a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.markedDayField a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.markedDayField a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.markedDayField a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.markedDayField a]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.markedDayField a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mceEditor .mceColors li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mceResizeBox]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.mceResizeBox]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberName:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberRemove]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li .memberRemove:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.memberList li:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.message]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.message]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.message]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.message .messageSidebar]]></selector>\r
+                       <name><![CDATA[text-align]]></name>\r
+                       <value><![CDATA[messages.sidebar.text.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.message h3]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.message h4]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageBody]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageContainerFooter]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageContent]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageContentInner]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooter]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooter]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooter]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooterLeft]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooterLeft]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooterLeft]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooterRight]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooterRight]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageFooterRight]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageHeader]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageHeader]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageHeader]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .signature]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .smallButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .memberName]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 .memberName:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .memberName]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .memberName:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-1 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .signature]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .smallButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 .smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageInner .color-2 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.moderators]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li span]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .optionButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .optionButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation .active]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation .active]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation .active]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation .active span]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation .active span]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation .active span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation input]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li span]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li span]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li span]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li span]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li span:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li ul]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li ul]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li ul]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li ul]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children span]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children span]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children:hover > span]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children:hover > span]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children:hover span]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li.children:hover span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pageNavigation li:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.large.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.large.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.large.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.large.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.large.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.large.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmEditFolders a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.large.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmMove p]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmUsage]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmUsageBar]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmUsageBar]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.pmUsageBar]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.popupMenu]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.popupMenu]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.popupMenu]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.popupMenu]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#userCardCredits]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.friendsConnection]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.friendsNetwork]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.friendsNone]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.guestAdvice]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.buttonBar]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.buttonBar]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu li.container-1 a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu li.container-2 a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .twoRows a span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .twoRows a:hover span]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .twoRows a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.signature]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.signature]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.signature]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons span]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[buttons.small.caption.hide]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .smallButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .smallButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 .smallButtons a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-3 .smallButtons a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li span]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.extraButton span]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.inner.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[li.extraButton]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallFont]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.loginPopup]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.statusDisplay]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subHeadline]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subHeadline]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subHeadline]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu div.containerHead]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.button.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[menu.tab.button.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.active.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.button.active.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul .activeSubTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.border.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.button.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[menu.tab.button.border.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a:hover]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[menu.tab.button.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.subTabMenu ul li a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.button.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.success]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.success]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.success]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active .emptyHead]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active .emptyHead]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active .emptyHead]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active .emptyHead]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.active.border.bottom.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.active.border.bottom.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.active.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.active.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.active.border.bottom.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .emptyHead]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .emptyHead]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.border.bottom.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .emptyHead]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .emptyHead]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.border.bottom.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead a:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.border.bottom.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList th]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.tab.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.disabled a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.disabled a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.tab.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.disabled a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.tab.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.activeTabMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.activeTabMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.activeTabMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.tab.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.activeTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu li.activeTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container.head.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu ul li.activeTabMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu ul li.activeTabMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu ul li.activeTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.tab.active.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu ul li.activeTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.active.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tabMenu ul li.activeTabMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.tab.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.threadStarterPost .poll .container-3]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList tbody tr:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatar]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatar a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatarFramed]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatarFramed]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container4.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatarFramed a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userCredits]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userExtras]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userPanel]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userPanel a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userPanel a:active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.active]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.warning]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.warning]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.warning]]></selector>\r
+                       <name><![CDATA[line-height]]></name>\r
+                       <value><![CDATA[page.font.line.height]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.weekDays]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.weekDays]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[a:active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.active]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[blockquote.wysiwygQuote]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[blockquote.wysiwygQuote]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[blockquote.wysiwygQuote]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[blockquote.wysiwygQuote]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container4.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[page.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[page.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[background-position]]></name>\r
+                       <value><![CDATA[page.background.image.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[background-attachment]]></name>\r
+                       <value><![CDATA[page.background.image.attachment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[background-repeat]]></name>\r
+                       <value><![CDATA[page.background.image.repeat]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[page.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.inlineCalendar]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.smallButtons div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.smallButtons div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.smallButtons div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.smallButtons div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.smallButtons div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.messageInner div.smallButtons div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu li.active a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu li.active a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu li.active a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .bottomSeparator a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .bottomSeparator a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .bottomSeparator a]]></selector>\r
+                       <name><![CDATA[border-bottom-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .topSeparator a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .topSeparator a]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .topSeparator a]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blog .userBlogCategoryAdd]]></selector>\r
+                       <name><![CDATA[border-top-color]]></name>\r
+                       <value><![CDATA[divider.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blog .userBlogCategoryAdd]]></selector>\r
+                       <name><![CDATA[border-top-style]]></name>\r
+                       <value><![CDATA[divider.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.blog .userBlogCategoryAdd]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[divider.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList tr div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList tr div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.smallButtons div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.smallButtons div.pageMenu a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.smallButtons div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.smallButtons div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.smallButtons div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.smallButtons div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[fieldset]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[fieldset]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[fieldset]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container1.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[fieldset fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container2.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[page.title.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.title.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.title.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2]]></selector>\r
+                       <name><![CDATA[font-style]]></name>\r
+                       <value><![CDATA[page.title.font.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2]]></selector>\r
+                       <name><![CDATA[font-weight]]></name>\r
+                       <value><![CDATA[page.title.font.weight]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2 a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.title.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[h2 a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.title.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[html]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[page.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[html]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[page.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[html]]></selector>\r
+                       <name><![CDATA[background-position]]></name>\r
+                       <value><![CDATA[page.background.image.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[html]]></selector>\r
+                       <name><![CDATA[background-attachment]]></name>\r
+                       <value><![CDATA[page.background.image.attachment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[html]]></selector>\r
+                       <name><![CDATA[background-repeat]]></name>\r
+                       <value><![CDATA[page.background.image.repeat]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[legend]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[input.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[input.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[input.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[input.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[input.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select:focus]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select:focus]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[input.border.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select:focus]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[input.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[select:focus]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[td.columnLastActivity]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[td.columnLocation]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[td.columnRegistrationDate]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[td.columnUserAgent]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[input.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[input.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[input.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[input.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[input.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea]]></selector>\r
+                       <name><![CDATA[font-family]]></name>\r
+                       <value><![CDATA[page.font]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea:focus]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea:focus]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[input.border.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea:focus]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[input.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[textarea:focus]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color.focus]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[buttons.small.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[buttons.small.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.messageNumber:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#search]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#search .searchContainer p a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.button.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#search .searchContainer p a]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#search .searchContainer p a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.tab.button.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.searchContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.searchContainer]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.searchContainer]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.frame.general]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[page.frame.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[page.frame.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[border-top-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[border-right-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[border-left-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[page.frame.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[margin-top]]></name>\r
+                       <value><![CDATA[page.frame.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[padding-top]]></name>\r
+                       <value><![CDATA[page.frame.padding.vertical]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[padding-right]]></name>\r
+                       <value><![CDATA[page.frame.padding.horizontal]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#headerContainer]]></selector>\r
+                       <name><![CDATA[padding-left]]></name>\r
+                       <value><![CDATA[page.frame.padding.horizontal]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[page.frame.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[page.frame.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[border-right-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[border-left-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[page.frame.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[padding-right]]></name>\r
+                       <value><![CDATA[page.frame.padding.horizontal]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#mainContainer]]></selector>\r
+                       <name><![CDATA[padding-left]]></name>\r
+                       <value><![CDATA[page.frame.padding.horizontal]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[page.frame.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[page.frame.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[border-right-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[border-bottom-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[border-left-width]]></name>\r
+                       <value><![CDATA[page.frame.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[page.frame.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[margin-bottom]]></name>\r
+                       <value><![CDATA[page.frame.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[padding-right]]></name>\r
+                       <value><![CDATA[page.frame.padding.horizontal]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[padding-bottom]]></name>\r
+                       <value><![CDATA[page.frame.padding.vertical]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#footerContainer]]></selector>\r
+                       <name><![CDATA[padding-left]]></name>\r
+                       <value><![CDATA[page.frame.padding.horizontal]]></value>\r
+               </attribute>\r
+       </import>\r
+       \r
+       <!-- these obsolete declarations will be deleted -->\r
+       <delete>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.active.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.active.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead .active]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.caption.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead label:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[table.head.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead label:hover]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[table.head.background.image.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead label:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[table.head.caption.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead div]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.border.bottom.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead div]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[table.head.border.bottom.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableHead div:hover]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[table.head.border.bottom.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList tbody tr:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList tbody tr:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList tbody tr:hover .columnTitle a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-1:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-2:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-3:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr.container-3:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover .columnTopic .topic a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover .columnUsername a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover .light]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover .light a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[tr:hover .columnTitle a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[page.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .active a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .active a]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[div.pageMenu .active a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.copyright]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#header]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#page]]></selector>\r
+                       <name><![CDATA[]]></name>\r
+                       <value><![CDATA[page.alignment.margin]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#page]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#page]]></selector>\r
+                       <name><![CDATA[width]]></name>\r
+                       <value><![CDATA[page.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#page]]></selector>\r
+                       <name><![CDATA[max-width]]></name>\r
+                       <value><![CDATA[page.width.max]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[#page]]></selector>\r
+                       <name><![CDATA[min-width]]></name>\r
+                       <value><![CDATA[page.width.min]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallPages]]></selector>\r
+                       <name><![CDATA[font-size]]></name>\r
+                       <value><![CDATA[page.font.2nd.size]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[body]]></selector>\r
+                       <name><![CDATA[text-align]]></name>\r
+                       <value><![CDATA[page.alignment]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[buttons.small.background.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.profileDisplay fieldset]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userProfileBox #userProfileAvatar fieldset div]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .disabled]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-1 .disabled a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container1.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .disabled]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.container-2 .disabled a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container2.font.2nd.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[messages.boxes.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[messages.boxes.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[input.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.quoteBox]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[messages.boxes.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.attachmentPreview ul li a:hover]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarDisplay div]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatarFramed]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[input.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userAvatarFramed]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[messages.boxes.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeLineNumbers]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container3.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeLineNumbers]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[container3.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[container.border.outer.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.codeBox]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[container.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userProfileContent .fieldTitle]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.userProfileContent .fieldValue]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect li label]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container.border.inner.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect .selected label]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect .selected label]]></selector>\r
+                       <name><![CDATA[background-image]]></name>\r
+                       <value><![CDATA[selection.background.image]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect .selected label]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect .selected label]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.avatarSelect .selected label]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li.selected]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li.selected]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li.selected]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li.selected > a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.largeButtons li.selected > a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li.selected]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[selection.border.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li.selected]]></selector>\r
+                       <name><![CDATA[border-style]]></name>\r
+                       <value><![CDATA[selection.border.style]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li.selected]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[selection.border.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li.selected > a]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[selection.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.smallButtons li.selected > a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[selection.link.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.optionButtons li]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[menu.dropdown.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.li.extraButton]]></selector>\r
+                       <name><![CDATA[border-width]]></name>\r
+                       <value><![CDATA[buttons.small.border.outer.width]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.attachmentPreview ul li a]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container.border.outer.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.galleryAlbumCover img]]></selector>\r
+                       <name><![CDATA[background-color]]></name>\r
+                       <value><![CDATA[container4.background.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[blockquote.wysiwygQuote]]></selector>\r
+                       <name><![CDATA[border-color]]></name>\r
+                       <value><![CDATA[container1.font.color]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList div.pageMenu a:hover]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color.hover]]></value>\r
+               </attribute>\r
+               <attribute>\r
+                       <selector><![CDATA[.tableList div.pageMenu a]]></selector>\r
+                       <name><![CDATA[color]]></name>\r
+                       <value><![CDATA[menu.dropdown.link.color]]></value>\r
+               </attribute>\r
+       </delete>\r
+</data>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/documentHeader.tpl b/com.woltlab.wcf/templates/documentHeader.tpl
new file mode 100644 (file)
index 0000000..e39f180
--- /dev/null
@@ -0,0 +1,2 @@
+<!DOCTYPE html>\r
+<html dir="{lang}wcf.global.pageDirection{/lang}" lang="{@LANGUAGE_CODE}">\r
diff --git a/com.woltlab.wcf/templates/footer.tpl b/com.woltlab.wcf/templates/footer.tpl
new file mode 100644 (file)
index 0000000..9f17042
--- /dev/null
@@ -0,0 +1,5 @@
+<div id="footerContainer">\r
+       <div id="footer">\r
+               {include file=footerMenu}\r
+       </div>\r
+</div>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/footerMenu.tpl b/com.woltlab.wcf/templates/footerMenu.tpl
new file mode 100644 (file)
index 0000000..8b23119
--- /dev/null
@@ -0,0 +1,11 @@
+{if $__wcf->getPageMenu()->getMenuItems('footer')|count > 0}
+       <div id="footerMenu" class="footerMenu">
+               <div class="footerMenuInner">
+                       <ul>
+                               {foreach from=$__wcf->getPageMenu()->getMenuItems('footer') item=menuItem}
+                                       <li>{$menuItem|print_r}</li>
+                               {/foreach}
+                       </ul>
+               </div>
+       </div>
+{/if}
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/headInclude.tpl b/com.woltlab.wcf/templates/headInclude.tpl
new file mode 100644 (file)
index 0000000..162c75d
--- /dev/null
@@ -0,0 +1,5 @@
+<meta charset="utf-8" />\r
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />\r
+<meta name="description" content="{META_DESCRIPTION}" />\r
+<meta name="keywords" content="{META_KEYWORDS}" />\r
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/header.tpl b/com.woltlab.wcf/templates/header.tpl
new file mode 100644 (file)
index 0000000..e63f335
--- /dev/null
@@ -0,0 +1,5 @@
+<a id="top" name="top"></a>\r
+<div id="page">\r
+       <div id="header" class="border">\r
+               {include file=headerMenu}\r
+       </div>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/headerMenu.tpl b/com.woltlab.wcf/templates/headerMenu.tpl
new file mode 100644 (file)
index 0000000..43ee6c7
--- /dev/null
@@ -0,0 +1,21 @@
+{if $__wcf->getPageMenu()->getMenuItems('header')|count > 0}\r
+       <div id="mainMenu" class="mainMenu">\r
+               <div class="mainMenuInner">\r
+                       <ul>\r
+                               {foreach from=$__wcf->getPageMenu()->getMenuItems('header') item=menuItem}\r
+                                       <li><a href="{$menuItem->menuItemLink}">{$menuItem->menuItem} ({#$menuItem->getProvider()->getNotifications()})</a>\r
+                                       \r
+                                       {if $__wcf->getPageMenu()->getMenuItems($menuItem->menuItem)|count > 0}\r
+                                               <ul>\r
+                                                       {foreach from=$__wcf->getPageMenu()->getMenuItems($menuItem->menuItem) item=subMenuItem}\r
+                                                               <li><a href="{$subMenuItem->menuItemLink}">{$subMenuItem->menuItem} ({#$subMenuItem->getProvider()->getNotifications()})</a></li>\r
+                                                       {/foreach}\r
+                                               </ul>\r
+                                       {/if}\r
+                                       \r
+                                       </li>\r
+                               {/foreach}\r
+                       </ul>\r
+               </div>\r
+       </div>\r
+{/if}\r
diff --git a/com.woltlab.wcf/templates/imageViewer.tpl b/com.woltlab.wcf/templates/imageViewer.tpl
new file mode 100644 (file)
index 0000000..a8dccce
--- /dev/null
@@ -0,0 +1,31 @@
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/ImageViewer.class.js"></script>
+<script type="text/javascript">
+       //<![CDATA[                     
+       // when the window is fully loaded, add image viewer
+       Event.observe(window, 'load', function() {
+               new ImageViewer($$('.enlargable'), {
+                       langCaption             : '{lang}wcf.imageViewer.caption{/lang}',
+                       langPrevious            : '{lang}wcf.imageViewer.previous{/lang}',
+                       langNext                : '{lang}wcf.imageViewer.next{/lang}',
+                       langPlay                : '{lang}wcf.imageViewer.play{/lang}',
+                       langPause               : '{lang}wcf.imageViewer.pause{/lang}',
+                       langEnlarge             : '{lang}wcf.imageViewer.enlarge{/lang}',
+                       langClose               : '{lang}wcf.imageViewer.close{/lang}',
+                       imgBlankSrc             : '{@RELATIVE_WCF_DIR}images/imageViewer/blank.png',
+                       imgMenuSrc              : '{@RELATIVE_WCF_DIR}images/imageViewer/menu.png',
+                       imgPlaySrc              : '{icon}imageViewer/playM.png{/icon}',
+                       imgPreviousSrc          : '{icon}imageViewer/previousM.png{/icon}',
+                       imgNextSrc              : '{icon}imageViewer/nextM.png{/icon}',
+                       imgEnlargeSrc           : '{icon}imageViewer/enlargeM.png{/icon}',
+                       imgPauseSrc             : '{icon}imageViewer/pauseM.png{/icon}',
+                       imgCloseSrc             : '{icon}imageViewer/closeM.png{/icon}',
+                       imgPlayHoverSrc         : '{icon}imageViewer/playHoverM.png{/icon}',
+                       imgPreviousHoverSrc     : '{icon}imageViewer/previousHoverM.png{/icon}',
+                       imgNextHoverSrc         : '{icon}imageViewer/nextHoverM.png{/icon}',
+                       imgEnlargeHoverSrc      : '{icon}imageViewer/enlargeHoverM.png{/icon}',
+                       imgPauseHoverSrc        : '{icon}imageViewer/pauseHoverM.png{/icon}',
+                       imgCloseHoverSrc        : '{icon}imageViewer/closeHoverM.png{/icon}'    
+               });
+       });
+//]]>
+</script>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeBoolean.tpl b/com.woltlab.wcf/templates/optionTypeBoolean.tpl
new file mode 100644 (file)
index 0000000..971044f
--- /dev/null
@@ -0,0 +1,3 @@
+<input {if $optionData.enableOptions}onclick="{@$optionData.enableOptions}" {/if}\r
+id="{$optionData.optionName}" type="checkbox" name="values[{$optionData.optionName}]" value="1"\r
+{if $optionData.optionValue}checked="checked" {/if}/>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeDate.tpl b/com.woltlab.wcf/templates/optionTypeDate.tpl
new file mode 100644 (file)
index 0000000..2668c3f
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="floatContainer">\r
+       {foreach from=$dateInputOrder item=element}\r
+               <div class="floatedElement">\r
+                       <label for="{$optionData.optionName}{$element|ucfirst}">{lang}wcf.global.date.{$element}{/lang}</label>\r
+                       \r
+                       {if $element == 'day'}\r
+                               <select id="{$optionData.optionName}Day" name="values[{$optionData.optionName}][day]">\r
+                                       {htmlOptions options=$days selected=$day}\r
+                               </select>\r
+                       {/if}\r
+                       \r
+                       {if $element == 'month'}\r
+                               <select id="{$optionData.optionName}Month" name="values[{$optionData.optionName}][month]">\r
+                                       {htmlOptions options=$months selected=$month}\r
+                               </select>\r
+                       {/if}\r
+                       \r
+                       {if $element == 'year'}\r
+                               <input id="{$optionData.optionName}Year" class="inputText fourDigitInput" type="text" name="values[{$optionData.optionName}][year]" value="{$year}" maxlength="4" />\r
+                       {/if}\r
+               </div>\r
+       {/foreach}\r
+</div>\r
+{if !$yearRequired}\r
+       <p class="smallFont light">{lang}wcf.global.date.year.notRequired{/lang}</p>\r
+{/if}
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeMultiselect.tpl b/com.woltlab.wcf/templates/optionTypeMultiselect.tpl
new file mode 100644 (file)
index 0000000..5646331
--- /dev/null
@@ -0,0 +1,5 @@
+<select name="values[{$optionData.optionName}][]" id="{$optionData.optionName}" multiple="multiple" size="{if $options|count > 10}10{else}{@$options|count}{/if}">\r
+{foreach from=$options item=option key=key}\r
+       <option value="{$key}"{if $key|in_array:$optionData.optionValue} selected="selected"{/if}>{lang}{@$option}{/lang}</option>\r
+{/foreach}\r
+</select>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeRadiobuttons.tpl b/com.woltlab.wcf/templates/optionTypeRadiobuttons.tpl
new file mode 100644 (file)
index 0000000..d91419e
--- /dev/null
@@ -0,0 +1,10 @@
+<ul class="formOptionsLong">\r
+       {foreach from=$options item=option key=key}\r
+               <li>\r
+                       <label><input {if $option.enableOptions}onclick="if (IS_SAFARI) {@$option.enableOptions}" onfocus="{@$option.enableOptions}" {/if}\r
+                       type="radio" name="values[{$optionData.optionName}]" value="{$key}"\r
+                       {if $optionData.optionValue == $key}checked="checked" {/if}/>\r
+                       {lang}{@$option.value}{/lang}</label>\r
+               </li>\r
+       {/foreach}\r
+</ul>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeSelect.tpl b/com.woltlab.wcf/templates/optionTypeSelect.tpl
new file mode 100644 (file)
index 0000000..7bb2ee1
--- /dev/null
@@ -0,0 +1,5 @@
+<select name="values[{$optionData.optionName}]" id="{$optionData.optionName}">\r
+{foreach from=$options item=option key=key}\r
+       <option value="{$key}"{if $optionData.optionValue == $key} selected="selected"{/if}>{lang}{@$option}{/lang}</option>\r
+{/foreach}\r
+</select>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeText.tpl b/com.woltlab.wcf/templates/optionTypeText.tpl
new file mode 100644 (file)
index 0000000..ef885f2
--- /dev/null
@@ -0,0 +1 @@
+<input id="{$optionData.optionName}" type="{@$inputType}" class="inputText" name="values[{$optionData.optionName}]" value="{$optionData.optionValue}" />
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/optionTypeTextarea.tpl b/com.woltlab.wcf/templates/optionTypeTextarea.tpl
new file mode 100644 (file)
index 0000000..85fd945
--- /dev/null
@@ -0,0 +1 @@
+<textarea id="{$optionData.optionName}" cols="40" rows="10" name="values[{$optionData.optionName}]">{$optionData.optionValue}</textarea>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/permissionDenied.tpl b/com.woltlab.wcf/templates/permissionDenied.tpl
new file mode 100644 (file)
index 0000000..0aeb5eb
--- /dev/null
@@ -0,0 +1,17 @@
+{include file="documentHeader"}\r
+<head>\r
+       <title>{lang}wcf.global.error.permissionDenied.title{/lang} - {lang}{PAGE_TITLE}{/lang}</title>\r
+       {include file='headInclude' sandbox=false}\r
+</head>\r
+<body{if $templateName|isset} id="tpl{$templateName|ucfirst}"{/if}>\r
+{include file='header' sandbox=false}\r
+\r
+<div id="main">\r
+       \r
+       <p class="error">{lang}wcf.global.error.permissionDenied{/lang}</p>\r
+\r
+</div>\r
+\r
+{include file='footer' sandbox=false}\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/redirect.tpl b/com.woltlab.wcf/templates/redirect.tpl
new file mode 100644 (file)
index 0000000..98bd676
--- /dev/null
@@ -0,0 +1,21 @@
+{include file="documentHeader"}\r
+<head>\r
+       <title>{lang}wcf.global.redirect.title{/lang} - {lang}{PAGE_TITLE}{/lang}</title>\r
+       {include file='headInclude' sandbox=false}\r
+       <meta http-equiv="refresh" content="{if $wait|isset}{@$wait}{else}10{/if};URL={$url}" />\r
+</head>\r
+<body{if $templateName|isset} id="tpl{$templateName|ucfirst}"{/if}>\r
+{include file='header' sandbox=false}\r
+\r
+<div id="main">\r
+       \r
+       <div class="success">\r
+               <p>{@$message}</p>\r
+               <p><a href="{$url}">{lang}wcf.global.redirect.url{/lang}</a></p>\r
+       </div>\r
+\r
+</div>\r
+\r
+{include file='footer' sandbox=false}\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/userException.tpl b/com.woltlab.wcf/templates/userException.tpl
new file mode 100644 (file)
index 0000000..d8afeee
--- /dev/null
@@ -0,0 +1,30 @@
+{include file="documentHeader"}\r
+<head>\r
+       <title>{lang}wcf.global.error.title{/lang} - {lang}{PAGE_TITLE}{/lang}</title>\r
+       {include file='headInclude' sandbox=false}\r
+       <script type="text/javascript">\r
+               //<![CDATA[\r
+               if (document.referrer) {\r
+                       onloadEvents.push(function() { document.getElementById('errorMessage').innerHTML += "<br /><a href=\"" + document.referrer + "\">{lang}wcf.global.error.backward{/lang}</a>"; });\r
+               }\r
+               //]]>\r
+       </script>\r
+</head>\r
+<body{if $templateName|isset} id="tpl{$templateName|ucfirst}"{/if}>\r
+{include file='header' sandbox=false}\r
+\r
+<div id="main">\r
+       <p class="error" id="errorMessage">\r
+               {@$message}\r
+       </p>\r
+</div>\r
+\r
+<!-- \r
+{$name} thrown in {$file} ({@$line})\r
+Stracktrace:\r
+{$stacktrace}\r
+-->\r
+\r
+{include file='footer' sandbox=false}\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/com.woltlab.wcf/useroptions.xml b/com.woltlab.wcf/useroptions.xml
new file mode 100644 (file)
index 0000000..2ba4739
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/useroptions.xsd">\r
+       <import>\r
+               <categories>\r
+                       <category name="hidden"></category>\r
+               </categories>\r
+                       \r
+               <options>\r
+                       <option name="inlineHelpStatus">\r
+                               <categoryname>hidden</categoryname>\r
+                               <optiontype>text</optiontype>\r
+                               <visible>4</visible>\r
+                               <editable>4</editable>\r
+                               <defaultvalue>all</defaultvalue>\r
+                       </option>\r
+               </options>\r
+       </import>\r
+</data>
\ No newline at end of file
diff --git a/com.woltlab.wcf/woltlab-basic-style.tar b/com.woltlab.wcf/woltlab-basic-style.tar
new file mode 100644 (file)
index 0000000..58744e4
Binary files /dev/null and b/com.woltlab.wcf/woltlab-basic-style.tar differ
diff --git a/wcfsetup/install.php b/wcfsetup/install.php
new file mode 100644 (file)
index 0000000..c4059d8
--- /dev/null
@@ -0,0 +1,756 @@
+<?php\r
+/**\r
+ * This script tries to find the temp folder and unzip all setup files into.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ */\r
+// define constants\r
+define('INSTALL_SCRIPT_DIR', dirname(__FILE__).'/');\r
+define('SETUP_FILE', INSTALL_SCRIPT_DIR . 'WCFSetup.tar.gz');\r
+define('NO_IMPORTS', 1);\r
+\r
+// set exception handler\r
+set_exception_handler('handleException');\r
+// set php error handler\r
+set_error_handler('handleError', E_ALL);\r
+\r
+// define list of needed file\r
+$neededFilesPattern = array(\r
+       '!^setup/.*!',\r
+       '!^install/files/lib/data/.*!',\r
+       '!^install/files/lib/system/.*!',\r
+       '!^install/files/lib/util/.*!',\r
+       '!^install/files/acp/images/setup.*!',\r
+       '!^install/lang/.*!',\r
+       '!^install/packages/.*!');\r
+       \r
+// define needed functions and classes\r
+/**\r
+ * WCF::handleException() calls the show method on exceptions that implement this interface.\r
+ *\r
+ * @package    com.woltlab.wcf.system.exception\r
+ * @author     Marcel Werk\r
+ */\r
+interface PrintableException {\r
+       public function show();\r
+}\r
+\r
+// define needed classes\r
+// needed are:\r
+// SystemException, PrintableException, BasicFileUtil, Tar, File, ZipFile\r
+/**\r
+ * A SystemException is thrown when an unexpected error occurs.\r
+ *\r
+ * @package    com.woltlab.wcf.system.exception\r
+ * @author     Marcel Werk\r
+ */\r
+class SystemException extends \Exception implements PrintableException {\r
+       protected $description;\r
+       protected $information = '';\r
+       protected $functions = '';\r
+       \r
+       /**\r
+        * Creates a new SystemException.\r
+        *\r
+        * @param       message         string          error message\r
+        * @param       code            integer         error code\r
+        * @param       description     string          description of the error\r
+        */\r
+       public function __construct($message = '', $code = 0, $description = '') {\r
+               parent::__construct($message, $code);\r
+               $this->description = $description;\r
+       }\r
+       \r
+       /**\r
+        * Returns the description of this exception.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getDescription() {\r
+               return $this->description;\r
+       }\r
+       \r
+       /**\r
+        * Prints this exception.\r
+        * This method is called by WCF::handleException().\r
+        */\r
+       public function show() {\r
+               ?>\r
+<html>\r
+<head>\r
+<title>Fatal error: <?php echo htmlspecialchars($this->getMessage()); ?></title>\r
+<style type="text/css">\r
+body {\r
+       font-family: Verdana, Helvetica, sans-serif;\r
+       font-size: 0.8em;\r
+}\r
+div {\r
+       border: 1px outset lightgrey;\r
+       padding: 3px;\r
+       background-color: lightgrey;\r
+}\r
+\r
+div div {\r
+       border: 1px inset lightgrey;\r
+       padding: 4px;\r
+}\r
+\r
+h1 {\r
+       background-color: #154268;\r
+       padding: 4px;\r
+       color: #fff;\r
+       margin: 0 0 3px 0;\r
+       font-size: 1.15em;\r
+}\r
+h2 {\r
+       font-size: 1.1em;\r
+       margin-bottom: 0;\r
+}\r
+\r
+pre, p {\r
+       margin: 0;\r
+}\r
+</style>\r
+</head>\r
+<body>\r
+       <div>\r
+               <h1>Fatal error: <?php echo htmlspecialchars($this->getMessage()); ?></h1>\r
+       \r
+               <div>\r
+                       <p><?php echo $this->getDescription(); ?></p>\r
+                       <?php if ($this->getCode()) { ?><p>You get more information about the problem in our knowledge base: <a href="http://www.woltlab.com/help/?code=<?php echo intval($this->getCode()); ?>">http://www.woltlab.com/help/?code=<?php echo intval($this->getCode()); ?></a></p><?php } ?>\r
+                       \r
+                       <h2>Information:</h2>\r
+                       <p>\r
+                               <b>error message:</b> <?php echo htmlspecialchars($this->getMessage()); ?><br />\r
+                               <b>error code:</b> <?php echo intval($this->getCode()); ?><br />\r
+                               <?php echo $this->information; ?>\r
+                               <b>file:</b> <?php echo htmlspecialchars($this->getFile()); ?> (<?php echo $this->getLine(); ?>)<br />\r
+                               <b>php version:</b> <?php echo htmlspecialchars(phpversion()); ?><br />\r
+                               <b>wcf version:</b> <?php if (defined('WCF_VERSION')) echo WCF_VERSION; ?><br />\r
+                               <b>date:</b> <?php echo gmdate('r'); ?><br />\r
+                               <b>request:</b> <?php if (isset($_SERVER['REQUEST_URI'])) echo htmlspecialchars($_SERVER['REQUEST_URI']); ?><br />\r
+                               <b>referer:</b> <?php if (isset($_SERVER['HTTP_REFERER'])) echo htmlspecialchars($_SERVER['HTTP_REFERER']); ?><br />\r
+                       </p>\r
+                       \r
+                       <h2>Stacktrace:</h2>\r
+                       <pre><?php echo htmlspecialchars($this->getTraceAsString()); ?></pre>\r
+               </div>\r
+               \r
+               <?php echo $this->functions; ?>\r
+       </div>\r
+</body>\r
+</html>\r
+\r
+<?php\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * Loads the required classes automatically.\r
+ */\r
+function __autoload($className) {\r
+       $namespaces = explode('\\', $className);\r
+       if (count($namespaces) > 1) {\r
+               // remove 'wcf' component\r
+               array_shift($namespaces);\r
+               \r
+               $className = implode('/', $namespaces);\r
+               $classPath = TMP_DIR . 'install/files/lib/' . $className  . '.class.php';\r
+               if (file_exists($classPath)) {\r
+                       require_once($classPath);\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * Escapes strings for execution in sql queries.\r
+ */\r
+function escapeString($string) {\r
+       return \wcf\system\WCF::getDB()->escapeString($string);\r
+}\r
+\r
+/**\r
+ * Calls the show method on the given exception.\r
+ *\r
+ * @param      Exception       $e\r
+ */\r
+function handleException(\Exception $e) {\r
+       if ($e instanceof PrintableException || $e instanceof \wcf\system\exception\PrintableException) {\r
+               $e->show();\r
+               exit;\r
+       }\r
+       \r
+       print $e;\r
+}\r
+\r
+/**\r
+ * Catches php errors and throws instead a system exception.\r
+ *\r
+ * @param      integer         $errorNo\r
+ * @param      string          $message\r
+ * @param      string          $filename\r
+ * @param      integer         $lineNo\r
+ */\r
+function handleError($errorNo, $message, $filename, $lineNo) {\r
+       if (error_reporting() != 0) {\r
+               $type = 'error';\r
+               switch ($errorNo) {\r
+                       case 2: $type = 'warning';\r
+                               break;\r
+                       case 8: $type = 'notice';\r
+                               break;\r
+               }\r
+               \r
+               throw new SystemException('PHP '.$type.' in file '.$filename.' ('.$lineNo.'): '.$message, 0);\r
+       }\r
+}\r
+\r
+/**\r
+ * BasicFileUtil contains file-related functions.\r
+ *\r
+ * @package    com.woltlab.wcf.util\r
+ * @author     Marcel Werk\r
+ */\r
+class BasicFileUtil {\r
+       /**\r
+        * Tries to find the temp folder.\r
+        *\r
+        * @return      string\r
+        */\r
+       public static function getTempFolder() {\r
+               $tmpDirName = TMP_FILE_PREFIX.'/';\r
+               \r
+               // use tmp folder in document root by default\r
+               if (!empty($_SERVER['DOCUMENT_ROOT'])) {\r
+                       if (!@file_exists($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName)) {\r
+                               @mkdir($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName, 0777, true);\r
+                               @chmod($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName, 0777);\r
+                       }\r
+                       \r
+                       if (@file_exists($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName) && @is_writable($_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName)) {\r
+                               return $_SERVER['DOCUMENT_ROOT'].'/tmp/'.$tmpDirName;\r
+                       }\r
+               }\r
+               \r
+               foreach (array('TMP', 'TEMP', 'TMPDIR') as $tmpDir) {\r
+                       if (isset($_ENV[$tmpDir]) && @is_writable($_ENV[$tmpDir])) {\r
+                               $dir = $_ENV[$tmpDir] . '/' . $tmpDirName;\r
+                               @mkdir($dir, 0777);\r
+                               @chmod($dir, 0777);\r
+                               \r
+                               if (@file_exists($dir) && @is_writable($dir)) {\r
+                                       return $dir;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               $dir = INSTALL_SCRIPT_DIR . 'tmp/' . $tmpDir;\r
+               @mkdir($dir, 0777);\r
+               @chmod($dir, 0777);\r
+               \r
+               if (@file_exists($dir) && @is_writable($dir)) {\r
+                       $tmpDir = explode('/', $dir);\r
+                       array_pop($tmpDir);\r
+                       $dir = implode('/', $tmpDir);\r
+                       \r
+                       throw new SystemException('There is no access to the system temporary folder due to an unknown reason and no user specific temporary folder exists in '.INSTALL_SCRIPT_DIR.'! This is a misconfiguration of your webserver software! Please create a folder called '.$dir.' using your favorite ftp program, make it writable and then retry this installation.', 10000);\r
+               }\r
+               \r
+               return $dir;\r
+       }\r
+}\r
+\r
+/**\r
+ * Opens tar or tar.gz archives.\r
+ *\r
+ * Usage:\r
+ * ------\r
+ * $tar = new Tar('archive.tar');\r
+ * $contentList = $tar->getContentList();\r
+ * foreach ($contentList as $key => $val) {\r
+ *     $tar->extract($key, DESTINATION);\r
+ * }\r
+ */\r
+class Tar {\r
+       protected $archiveName = '';\r
+       protected $contentList = array();\r
+       protected $opened = false;\r
+       protected $read = false;\r
+       protected $file = null;\r
+       protected $isZipped = false;\r
+       protected $mode = 'rb';\r
+       \r
+       /**\r
+        * Creates a new Tar object.\r
+        * archiveName must be tarball or gzipped tarball\r
+        *\r
+        * @param       string          $archiveName\r
+        */\r
+       public function __construct($archiveName) {\r
+               $match = array();\r
+               if (!is_file($archiveName)) {\r
+                       throw new SystemException("unable to find tar archive '".$archiveName."'", 11002);\r
+               }\r
+               \r
+               $this->archiveName = $archiveName;\r
+               $this->open();\r
+               $this->readContent();\r
+       }\r
+       \r
+       /**\r
+        * Destructor of this class, closes tar archive.\r
+        */\r
+       public function __destruct() {\r
+               $this->close();\r
+       }\r
+       \r
+       /**\r
+        * Opens the tar archive and stores filehandle.\r
+        */\r
+       public function open() {\r
+               if (!$this->opened) {\r
+                       if ($this->isZipped) $this->file = new ZipFile($this->archiveName, $this->mode);\r
+                       else {\r
+                               // test compression\r
+                               $this->file = new File($this->archiveName, $this->mode);\r
+                               if ($this->file->read(2) == "\37\213") {\r
+                                       $this->file->close();\r
+                                       $this->isZipped = true;\r
+                                       $this->file = new ZipFile($this->archiveName, $this->mode);\r
+                               }\r
+                               else {\r
+                                       $this->file->seek(0);\r
+                               }\r
+                       }\r
+                       $this->opened = true;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Closes the opened file.\r
+        */\r
+       public function close() {\r
+               if ($this->opened) {\r
+                       $this->file->close();\r
+                       $this->opened = false;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the table of contents (TOC) list for this tar archive.\r
+        *\r
+        * @return      array           list of content\r
+        */\r
+       public function getContentList() {\r
+               if (!$this->read) {\r
+                       $this->open();\r
+                       $this->readContent();\r
+               }\r
+               return $this->contentList;\r
+       }\r
+       \r
+       /**\r
+        * Returns an associative array with information\r
+        * about a specific file in the archive.\r
+        *\r
+        * @param       mixed   $fileindex      index or name of the requested file\r
+        * @return      array   $fileInfo\r
+        */\r
+       public function getFileInfo($fileIndex) {\r
+               if (!is_int($fileIndex)) {\r
+                       $fileIndex = $this->getIndexByFilename($fileIndex);\r
+               }\r
+               \r
+               if (!isset($this->contentList[$fileIndex])) {\r
+                       throw new SystemException("Tar: could find file '$index' in archive", 11013);\r
+               }\r
+               return $this->contentList[$fileIndex];\r
+       }\r
+       \r
+       /**\r
+        * Searchs a file in the tar archive\r
+        * and returns the numeric fileindex.\r
+        * Returns false if not found.\r
+        *\r
+        * @param       string          $filename\r
+        * @return      integer                         index of the requested file\r
+        */\r
+       public function getIndexByFilename($filename) {\r
+               foreach ($this->contentList as $index => $file) {\r
+                       if ($file['filename'] == $filename) {\r
+                               return $index;\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Extracts a specific file and returns the content as string.\r
+        * Returns false if extraction failed.\r
+        *\r
+        * @param       mixed           $index          index or name of the requested file\r
+        * @return      string                          content of the requested file\r
+        */\r
+       public function extractToString($index) {\r
+               if (!$this->read) {\r
+                       $this->open();\r
+                       $this->readContent();\r
+               }\r
+               $header = $this->getFileInfo($index);\r
+               \r
+               // can not extract a folder\r
+               if ($header['type'] != 'file') {\r
+                       return false;\r
+               }\r
+               \r
+               // seek to offset\r
+               $this->file->seek($header['offset']);\r
+               \r
+               // read data\r
+               $content = '';\r
+               $n = floor($header['size'] / 512);\r
+               for($i = 0; $i < $n; $i++) {\r
+                       $content .= $this->file->read(512);\r
+               }\r
+               if(($header['size'] % 512) != 0) {\r
+                       $buffer = $this->file->read(512);\r
+                       $content .= substr($buffer, 0, ($header['size'] % 512));\r
+               }\r
+               \r
+               return $content;\r
+       }\r
+       \r
+       /**\r
+        * Extracts a specific file and writes it's content\r
+        * to the file specified with $destination.\r
+        *\r
+        * @param       mixed           $index          index or name of the requested file\r
+        * @param       string          $destination\r
+        * @return      boolean         $success\r
+        */\r
+       public function extract($index, $destination) {\r
+               if (!$this->read) {\r
+                       $this->open();\r
+                       $this->readContent();\r
+               }\r
+               $header = $this->getFileInfo($index);\r
+               \r
+               // can not extract a folder\r
+               if ($header['type'] != 'file') {\r
+                       return false;\r
+               }\r
+               \r
+               // seek to offset\r
+               $this->file->seek($header['offset']);\r
+               \r
+               $targetFile = new File($destination);\r
+               \r
+               // read data\r
+               $n = floor($header['size'] / 512);\r
+               for ($i = 0; $i < $n; $i++) {\r
+                       $content = $this->file->read(512);\r
+                       $targetFile->write($content, 512);\r
+               }\r
+               if (($header['size'] % 512) != 0) {\r
+                       $content = $this->file->read(512);\r
+                       $targetFile->write($content, ($header['size'] % 512));\r
+               }\r
+               \r
+               $targetFile->close();\r
+               if (function_exists('apache_get_version') || !@$targetFile->is_writable()) {\r
+                       @$targetFile->chmod(0777);\r
+               }\r
+               else {\r
+                       @$targetFile->chmod(0755);\r
+               }\r
+               \r
+               if ($header['mtime']) {\r
+                       @$targetFile->touch($header['mtime']);\r
+               }\r
+               \r
+               // check filesize\r
+               if (filesize($destination) != $header['size']) {\r
+                       throw new SystemException("Could not untar file '".$header['filename']."' to '".$destination."'. Maybe disk quota exceeded in folder '".dirname($destination)."'.", 11015);\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Reads table of contents (TOC) from tar archive.\r
+        * This does not get the entire to memory but only parts of it.\r
+        */\r
+       protected function readContent() {\r
+               $this->contentList = array();\r
+               $this->read = true;\r
+               $i = 0;\r
+               \r
+               // Read the 512 bytes header\r
+               while (strlen($binaryData = $this->file->read(512)) != 0) {\r
+                       // read header\r
+                       $header = $this->readHeader($binaryData);\r
+                       if ($header === false) {\r
+                               continue;\r
+                       }\r
+                       $this->contentList[$i] = $header;\r
+                       $this->contentList[$i]['index'] = $i;\r
+                       $i++;\r
+                       \r
+                       $this->file->seek($this->file->tell() + (512 * ceil(($header['size'] / 512))));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Unpacks file header for one file entry.\r
+        *\r
+        * @param       string          $binaryData\r
+        * @return      array           $fileheader\r
+        */\r
+       protected function readHeader($binaryData) {\r
+               if (strlen($binaryData) != 512) {\r
+                       return false;\r
+               }\r
+\r
+               $header = array();\r
+               $checksum = 0;\r
+               // First part of the header\r
+               for ($i = 0; $i < 148; $i++) {\r
+                       $checksum += ord(substr($binaryData, $i, 1));\r
+               }\r
+               // Calculate the checksum\r
+               // Ignore the checksum value and replace it by ' ' (space)\r
+               for ($i = 148; $i < 156; $i++) {\r
+                       $checksum += ord(' ');\r
+               }\r
+               // Last part of the header\r
+               for ($i = 156; $i < 512; $i++) {\r
+                       $checksum += ord(substr($binaryData, $i, 1));\r
+               }\r
+\r
+               // Extract the values\r
+               //$data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $binaryData);\r
+               $data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $binaryData);\r
+               \r
+               // Extract the properties\r
+               $header['checksum'] = octDec(trim($data['checksum']));\r
+               if ($header['checksum'] == $checksum) {\r
+                       $header['filename'] = trim($data['filename']);\r
+                       $header['mode'] = octDec(trim($data['mode']));\r
+                       $header['uid'] = octDec(trim($data['uid']));\r
+                       $header['gid'] = octDec(trim($data['gid']));\r
+                       $header['size'] = octDec(trim($data['size']));\r
+                       $header['mtime'] = octDec(trim($data['mtime']));\r
+                       $header['prefix'] = trim($data['prefix']);\r
+                       if ($header['prefix']) {\r
+                               $header['filename'] = $header['prefix'].'/'.$header['filename'];\r
+                       }\r
+                       if (($header['typeflag'] = $data['typeflag']) == '5') {\r
+                               $header['size'] = 0;\r
+                               $header['type'] = 'folder';\r
+                       }\r
+                       else {\r
+                               $header['type'] = 'file';\r
+                       }\r
+                       $header['offset'] = $this->file->tell();\r
+                       \r
+                       return $header;\r
+               }\r
+               else {\r
+                       return false;\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * The File class handles all file operations.\r
+ *\r
+ * Example:\r
+ * using php functions:\r
+ * $fp = fopen('filename', 'wb');\r
+ * fwrite($fp, '...');\r
+ * fclose($fp);\r
+ *\r
+ * using this class:\r
+ * $file = new File('filename');\r
+ * $file->write('...');\r
+ * $file->close();\r
+ *\r
+ * @author     Marcel Werk\r
+ */\r
+class File {\r
+       protected $resource = null;\r
+       protected $filename;\r
+       \r
+       /**\r
+        * Opens a new file.\r
+        *\r
+        * @param       string          $filename\r
+        * @param       string          $mode\r
+        */\r
+       public function __construct($filename, $mode = 'wb') {\r
+               $this->filename = $filename;\r
+               $this->resource = fopen($filename, $mode);\r
+               if ($this->resource === false) {\r
+                       throw new SystemException('Can not open file ' . $filename, 11012);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Calls the specified function on the open file.\r
+        * Do not call this function directly. Use $file->write('') instead.\r
+        *\r
+        * @param       string          $function\r
+        * @param       array           $arguments\r
+        */\r
+       public function __call($function, $arguments) {\r
+               if (function_exists('f' . $function)) {\r
+                       array_unshift($arguments, $this->resource);\r
+                       return call_user_func_array('f' . $function, $arguments);\r
+               }\r
+               else if (function_exists($function)) {\r
+                       array_unshift($arguments, $this->filename);\r
+                       return call_user_func_array($function, $arguments);\r
+               }\r
+               else {\r
+                       throw new SystemException('Can not call file method ' . $function, 11003);\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * The File class handles all file operations on a zipped file.\r
+ *\r
+ * @author     Marcel Werk\r
+ */\r
+class ZipFile extends File {\r
+       /**\r
+        * Opens a new zipped file.\r
+        *\r
+        * @param       string          $filename\r
+        * @param       string          $mode\r
+        */\r
+       public function __construct($filename, $mode = 'wb') {\r
+               $this->filename = $filename;\r
+               if (!function_exists('gzopen')) {\r
+                       throw new SystemException('Can not find functions of the zlib extension', 11004);\r
+               }\r
+               $this->resource = @gzopen($filename, $mode);\r
+               if ($this->resource === false) {\r
+                       throw new SystemException('Can not open file ' . $filename, 11012);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Calls the specified function on the open file.\r
+        *\r
+        * @param       string          $function\r
+        * @param       array           $arguments\r
+        */\r
+       public function __call($function, $arguments) {\r
+               if (function_exists('gz' . $function)) {\r
+                       array_unshift($arguments, $this->resource);\r
+                       return call_user_func_array('gz' . $function, $arguments);\r
+               }\r
+               else if (function_exists($function)) {\r
+                       array_unshift($arguments, $this->filename);\r
+                       return call_user_func_array($function, $arguments);\r
+               }\r
+               else {\r
+                       throw new SystemException('Can not call method ' . $function, 11003);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the filesize of the unzipped file\r
+        */\r
+       public function getFileSize() {\r
+               $byteBlock = 1<<14;\r
+               $eof = $byteBlock;\r
+               \r
+               // the correction is for zip files that are too small\r
+               // to get in the first while loop\r
+               $correction = 1;\r
+               while ($this->seek($eof) == 0) {\r
+                       $eof += $byteBlock;\r
+                       $correction = 0;\r
+               }\r
+               \r
+               while ($byteBlock > 1) {\r
+                       $byteBlock >>= 1;\r
+                       $eof += $byteBlock * ($this->seek($eof) ? -1 : 1);\r
+               }\r
+               \r
+               if ($this->seek($eof) == -1) $eof -= 1;\r
+               \r
+               $this->rewind();\r
+               return $eof - $correction;\r
+       }\r
+}\r
+\r
+// let's go\r
+// get temp file prefix\r
+if (isset($_REQUEST['tmpFilePrefix'])) {\r
+       $prefix = preg_replace('/[^a-f0-9_]+/', '', $_REQUEST['tmpFilePrefix']);\r
+}\r
+else {\r
+       $prefix = substr(sha1(uniqid(microtime())), 0, 8);\r
+}\r
+define('TMP_FILE_PREFIX', $prefix);\r
+\r
+// try to find the temp folder\r
+define('TMP_DIR', BasicFileUtil::getTempFolder());\r
+\r
+// show image from temp folder\r
+if (isset($_GET['showImage'])) {\r
+       if (preg_match('~[\w\-]+\.(jpg|png)~', $_GET['showImage'], $match)) {\r
+               if ($match[1] == 'jpg') header('Content-Type: image/jpg');\r
+               else header('Content-Type: image/png');\r
+               readfile(TMP_DIR . 'install/files/acp/images/' . $_GET['showImage']);\r
+       }\r
+       exit;\r
+}\r
+\r
+// check whether setup files already unzipped\r
+if (!file_exists(TMP_DIR . 'install/files/lib/system/WCFSetup.class.php')) {\r
+       // try to unzip all setup files into temp folder\r
+       $tar = new Tar(SETUP_FILE);\r
+       $contentList = $tar->getContentList();\r
+       if (!count($contentList)) {\r
+               throw new SystemException("Can not unpack 'WCFSetup.tar.gz'. File is probably broken.", 11016);\r
+       }\r
+       \r
+       foreach ($contentList as $file) {\r
+               foreach ($neededFilesPattern as $pattern) {\r
+                       if (preg_match($pattern, $file['filename'])) {\r
+                               // create directory if not exists\r
+                               $dir = TMP_DIR . dirname($file['filename']);\r
+                               if (!@is_dir($dir)) {\r
+                                       @mkdir($dir, 0777, true);\r
+                                       @chmod($dir, 0777);\r
+                               }\r
+                               \r
+                               $tar->extract($file['index'], TMP_DIR . $file['filename']);\r
+                       }\r
+               }\r
+       }\r
+       $tar->close();\r
+       \r
+       // create cache folders\r
+       @mkdir(TMP_DIR . 'setup/lang/cache/', 0777);\r
+       @chmod(TMP_DIR . 'setup/lang/cache/', 0777);\r
+       \r
+       @mkdir(TMP_DIR . 'setup/template/compiled/', 0777);\r
+       @chmod(TMP_DIR . 'setup/template/compiled/', 0777);\r
+}\r
+\r
+if (!class_exists('wcf\system\WCFSetup')) {\r
+       throw new SystemException("Can not find class 'WCFSetup'", 11006);\r
+}\r
+\r
+// start setup\r
+new \wcf\system\WCFSetup();\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/dereferrer.php b/wcfsetup/install/files/acp/dereferrer.php
new file mode 100644 (file)
index 0000000..11ea0ce
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+/**\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @category   Community Framework\r
+ */\r
+// get url\r
+$url = '';\r
+if (isset($_GET['url'])) $url = htmlspecialchars(str_replace(';', '', trim($_GET['url'])));\r
+if (empty($url)) exit;\r
+// check url\r
+$testURL = preg_replace('/[^a-z0-9:\/]+/', '', strtolower($url));\r
+if (strpos($testURL, 'script:') !== false || !preg_match('/^https?:\/\//', $testURL)) {\r
+       exit;\r
+}\r
+echo '<?xml version="1.0" encoding="UTF-8"?>';\r
+?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="de"><head>\r
+       <title>Dereferer</title>\r
+       <meta http-equiv="refresh" content="0;URL=<?php echo $url; ?>" />\r
+</head>\r
+<body>\r
+       <p><a href="<?php echo $url; ?>"><?php echo $url; ?></a></p>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/global.php b/wcfsetup/install/files/acp/global.php
new file mode 100644 (file)
index 0000000..936dc9c
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+/**\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @category   Community Framework\r
+ */\r
+// Constant to get relative path to the wcf-root-dir.\r
+// This constant is already set in each package which got an own config.inc.php \r
+if (!defined('RELATIVE_WCF_DIR')) define('RELATIVE_WCF_DIR', '../');\r
+\r
+// define the wcf-root-dir\r
+define('WCF_DIR', dirname(dirname(__FILE__)).'/');\r
+\r
+// starting wcf acp\r
+require_once(WCF_DIR.'lib/system/WCF.class.php');\r
+require_once(WCF_DIR.'lib/system/WCFACP.class.php');\r
+new wcf\system\WCFACP();\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/images/acpLogo.png b/wcfsetup/install/files/acp/images/acpLogo.png
new file mode 100644 (file)
index 0000000..e8de213
Binary files /dev/null and b/wcfsetup/install/files/acp/images/acpLogo.png differ
diff --git a/wcfsetup/install/files/acp/index.php b/wcfsetup/install/files/acp/index.php
new file mode 100644 (file)
index 0000000..ddcb1cf
--- /dev/null
@@ -0,0 +1,11 @@
+<?php\r
+/**\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @category   Community Framework\r
+ */\r
+require_once('./global.php');\r
+wcf\system\request\RequestHandler::getInstance()->handle('wcf', true);\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/install.php b/wcfsetup/install/files/acp/install.php
new file mode 100644 (file)
index 0000000..b368a40
--- /dev/null
@@ -0,0 +1,113 @@
+<?php\r
+namespace wcf\acp;\r
+use wcf\data\language\LanguageEditor;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\session\SessionHandler;\r
+use wcf\system\template\ACPTemplateEngine;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @category   Community Framework\r
+ */\r
+// make group names to language variables\r
+$groupNames = array(\r
+       'Everyone' => WCF::getLanguage()->get('wcf.acp.group.everyone'),\r
+       'Guests' => WCF::getLanguage()->get('wcf.acp.group.guests'),\r
+       'Users' => WCF::getLanguage()->get('wcf.acp.group.users'),\r
+       'Administrators' => WCF::getLanguage()->get('wcf.acp.group.administrators'),\r
+       'Moderators' => WCF::getLanguage()->get('wcf.acp.group.moderators'),\r
+       'Super Moderators' => WCF::getLanguage()->get('wcf.acp.group.superModerators')\r
+);\r
+\r
+$sql = "UPDATE wcf".WCF_N."_user_group\r
+       SET     groupName = ?\r
+       WHERE   groupName = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+foreach ($groupNames as $oldValue => $newValue) {\r
+       $statement->execute(array($newValue, $oldValue));\r
+}\r
+\r
+// change the priority of the PIP's to "1"\r
+$sql = "UPDATE wcf".WCF_N."_package_installation_plugin\r
+       SET     priority = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// change group options from admin group to true\r
+$sql = "UPDATE wcf".WCF_N."_user_group_option_value\r
+       SET     optionValue = ?\r
+       WHERE   groupID = ?\r
+               AND optionValue = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1, 4, '0'));\r
+\r
+// update accessible groups\r
+$sql = "UPDATE wcf".WCF_N."_user_group_option_value\r
+       SET     optionValue = ?\r
+       WHERE   groupID = ?\r
+               AND optionValue = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array('1,2,3,4,5,6', 4, ''));\r
+\r
+// reset sessions\r
+SessionHandler::resetSessions();\r
+\r
+// update acp session\r
+$sql = "UPDATE wcf".WCF_N."_acp_session\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// update acp templates\r
+$sql = "UPDATE wcf".WCF_N."_acp_template\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// update language\r
+$sql = "UPDATE wcf".WCF_N."_language_item\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+$sql = "UPDATE wcf".WCF_N."_language_to_package\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// update installation logs\r
+$sql = "UPDATE wcf".WCF_N."_package_installation_file_log\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+$sql = "UPDATE wcf".WCF_N."_package_installation_sql_log\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// update pips\r
+$sql = "UPDATE wcf".WCF_N."_package_installation_plugin\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// group options\r
+$sql = "UPDATE wcf".WCF_N."_user_group_option\r
+       SET     packageID = ?";\r
+$statement = WCF::getDB()->prepareStatement($sql);\r
+$statement->execute(array(1));\r
+\r
+// reset all caches\r
+CacheHandler::getInstance()->clear(WCF_DIR.'cache/', '*');\r
+\r
+// delete language files\r
+LanguageEditor::deleteLanguageFiles();\r
+\r
+// delete all compiled templates\r
+ACPTemplateEngine::deleteCompiledTemplates(WCF_DIR.'acp/templates/compiled/');\r
+?>\r
diff --git a/wcfsetup/install/files/acp/js/WCF.ACP.js b/wcfsetup/install/files/acp/js/WCF.ACP.js
new file mode 100644 (file)
index 0000000..c5a2b61
--- /dev/null
@@ -0,0 +1,487 @@
+/**\r
+ * Class and function collection for WCF ACP\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ */\r
+\r
+/**\r
+ * Initialize WCF.ACP namespace\r
+ */\r
+WCF.ACP = {};\r
+\r
+/**\r
+ * Handles ACPMenu.\r
+ *\r
+ * @param      array           activeMenuItems\r
+ */\r
+WCF.ACP.Menu = function(activeMenuItems) { this.init(activeMenuItems); };\r
+WCF.ACP.Menu.prototype = {\r
+       /**\r
+        * Initializes ACPMenu.\r
+        *\r
+        * @param       array           activeMenuItems\r
+        */\r
+       init: function(activeMenuItems) {\r
+               this._headerNavigation = $('nav#navigationTop');\r
+               this._sidebarNavigation = $('nav#navigationSide');\r
+               \r
+               this._prepareElements(activeMenuItems);\r
+       },\r
+       \r
+       /**\r
+        * Resets all elements and binds event listeners.\r
+        */\r
+       _prepareElements: function(activeMenuItems) {\r
+               this._headerNavigation.find('li').removeClass('activeMenuItem');\r
+               \r
+               this._sidebarNavigation.find('div.menuContainer h3').each($.proxy(function(index, menuHeader) {\r
+                       $(menuHeader).click($.proxy(this._toggleItem, this));\r
+               }, this));\r
+               \r
+               // close all navigation groups\r
+               this._sidebarNavigation.find('div.menuContainer div').each(function() {\r
+                       $(this).hide();\r
+               });\r
+               \r
+               this._headerNavigation.find('li').click($.proxy(this._toggleSidebar, this));\r
+               \r
+               if (activeMenuItems.length === 0) {\r
+                       this._renderSidebar(this._headerNavigation.find('li:first').data('menuItem'), []);\r
+               }\r
+               else {\r
+                       this._renderSidebar('', activeMenuItems);\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Toggles a navigation group entry.\r
+        */\r
+       _toggleItem: function(event) {\r
+               var $menuItem = $(event.target);\r
+               \r
+               $menuItem.next().stop(true, true).toggle('blind', { }, 200).end().toggleClass('activeMenuItem');\r
+       },\r
+       \r
+       /**\r
+        * Handles clicks on top navigation.\r
+        *\r
+        * @param       object          event\r
+        */\r
+       _toggleSidebar: function(event) {\r
+               if ($(event.target).hasClass('activeMenuItem')) {\r
+                       return;\r
+               }\r
+               \r
+               this._renderSidebar($(event.target).data('menuItem'), []);\r
+       },\r
+       \r
+       /**\r
+        * Renders sidebar including highlighting of currently active menu items.\r
+        *\r
+        * @param       string          menuItem\r
+        * @param       array           activeMenuItems\r
+        */\r
+       _renderSidebar: function(menuItem, activeMenuItems) {\r
+               // reset visible and active items\r
+               this._headerNavigation.find('li').removeClass('activeMenuItem');\r
+               this._sidebarNavigation.find('div.menuContainer').hide();\r
+               \r
+               if (activeMenuItems.length === 0) {\r
+                       // show active menu\r
+                       this._headerNavigation.find('li[data-menuItem="' + menuItem + '"]').addClass('activeMenuItem');\r
+                       this._sidebarNavigation.find('div[data-parentMenuItem="' + menuItem + '"]').show();\r
+               }\r
+               else {\r
+                       // open menu by active menu items, first element is always a head navigation item\r
+                       menuItem = activeMenuItems.shift();\r
+                       \r
+                       this._headerNavigation.find('li[data-menuItem="' + menuItem + '"]').addClass('activeMenuItem');\r
+                       this._sidebarNavigation.find('div[data-parentMenuItem="' + menuItem + '"]').show();\r
+                       \r
+                       for (var $i = 0, $size = activeMenuItems.length; $i < $size; $i++) {\r
+                               var $item = activeMenuItems[$i];\r
+                               \r
+                               if ($.wcfIsset($item)) {\r
+                                       var $menuItem = $('#' + $.wcfEscapeID($item));\r
+                                       \r
+                                       if ($menuItem.getTagName() === 'ul') {\r
+                                               $menuItem.parent('div').show().prev().addClass('activeMenuItem');\r
+                                       }\r
+                                       else {\r
+                                               $menuItem.addClass('activeMenuItem');\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+};\r
+\r
+/**\r
+ * Handles package installation dialog.\r
+ * \r
+ * @param      string          actionName\r
+ * @param      integer         queueID\r
+ * @param      boolean         initialize\r
+ */\r
+WCF.ACP.PackageInstallation = function(actionName, queueID, initialize) { this.init(actionName, queueID, initialize); };\r
+WCF.ACP.PackageInstallation.prototype = {\r
+       /**\r
+        * package installation type\r
+        * \r
+        * @var string\r
+        */\r
+       _actionName: '',\r
+       \r
+       /**\r
+        * package installation dialog\r
+        *\r
+        * @var object\r
+        */\r
+       _dialog: null,\r
+       \r
+       /**\r
+        * queue id\r
+        *\r
+        * @var integer\r
+        */\r
+       _queueID: 0,\r
+       \r
+       /**\r
+        * Initializes package installation.\r
+        * \r
+        * @param       string          actionName\r
+        * @param       integer         queueID\r
+        * @param       boolean         initialize\r
+        */\r
+       init: function(actionName, queueID, initialize) {\r
+               this._actionName = WCF.String.ucfirst(actionName) + 'Package';\r
+               this._queueID = queueID;\r
+               \r
+               if (initialize) {\r
+                       $('#submitButton').click($.proxy(function(event) {\r
+                               this.prepareInstallation();\r
+                               return false;\r
+                       }, this));\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Prepares installation dialog.\r
+        */\r
+       prepareInstallation: function() {\r
+               WCF.showAJAXDialog('packageInstallationDialog', true, {\r
+                       ajax: {\r
+                               url: 'index.php?action=' + this._actionName + '&t=' + SECURITY_TOKEN + SID_ARG_2ND,\r
+                               type: 'POST',\r
+                               data: { queueID: this._queueID, step: 'prepare' },\r
+                               success: $.proxy(this._handleResponse, this)\r
+                       },\r
+                       preventClose: true,\r
+                       hideTitle: true\r
+               });\r
+       },\r
+       \r
+       /**\r
+        * Executes response instructions.\r
+        */\r
+       _handleResponse: function() {\r
+               if (this._dialog == null) {\r
+                       this._dialog = $('#packageInstallationDialog');\r
+               }\r
+               \r
+               var $data = this._dialog.data('responseData');\r
+               \r
+               // receive new queue id\r
+               if ($data.queueID) {\r
+                       this._queueID = $data.queueID;\r
+               }\r
+               \r
+               // update progress\r
+               if ($data.progress) {\r
+                       $('#packageInstallationProgress').attr('value', $data.progress).text($data.progress + '%');\r
+               }\r
+               \r
+               // handle success\r
+               if ($data.step == 'success') {\r
+                       var $id = WCF.getRandomID();\r
+                       $('#packageInstallationInnerContent').append('<div class="formSubmit"><input type="button" id="' + $id + '" value="Weiter" /></div>');\r
+                       \r
+                       $('#' + $id).click($.proxy(function() {\r
+                               window.location.href = "index.php?page=PackageList" + SID_ARG_2ND;\r
+                       }, this));\r
+                       \r
+                       $('#packageInstallationInnerContentContainer').wcfBlindIn();\r
+                       \r
+                       return;\r
+               }\r
+               \r
+               // update template\r
+               if ($data.template && !$data.ignoreTemplate) {\r
+                       this._dialog.html($data.template);\r
+               }\r
+               \r
+               // update action\r
+               if ($data.currentAction) {\r
+                       $('#packageInstallationAction').text($data.currentAction);\r
+               }\r
+               \r
+               // handle inner template\r
+               if ($data.innerTemplate) {\r
+                       $('#packageInstallationInnerContent').html($data.innerTemplate);\r
+                       \r
+                       // create button to handle next step\r
+                       if ($data.step && $data.node) {\r
+                               var $id = WCF.getRandomID();\r
+                               $('#packageInstallationInnerContent').append('<div class="formSubmit"><input type="button" id="' + $id + '" value="Weiter" /></div>');\r
+                               \r
+                               $('#' + $id).click($.proxy(function() {\r
+                                       // collect form values\r
+                                       var $additionalData = {};\r
+                                       $('#packageInstallationInnerContent').find('input').each(function(index, inputElement) {\r
+                                               $additionalData[$(inputElement).attr('name')] = $(inputElement).attr('value');\r
+                                       });\r
+                                       \r
+                                       this._executeStep($data.step, $data.node, $additionalData);\r
+                               }, this));\r
+                       }\r
+                       \r
+                       $('#packageInstallationInnerContentContainer').wcfBlindIn();\r
+                       \r
+                       this._dialog.wcfDialog('redraw');\r
+                       return;\r
+               }\r
+               \r
+               // purge content\r
+               if ($('#packageInstallationInnerContent').children().length > 1) {\r
+                       $('#packageInstallationInnerContentContainer').wcfBlindOut('down', $.proxy(function() {\r
+                               $('#packageInstallationInnerContent').empty();\r
+                               this._dialog.wcfDialog('redraw');\r
+                               \r
+                               // execute next step\r
+                               if ($data.step && $data.node) {\r
+                                       this._executeStep($data.step, $data.node);\r
+                               }\r
+                       }, this));\r
+               }\r
+               else {\r
+                       // execute next step\r
+                       if ($data.step && $data.node) {\r
+                               this._executeStep($data.step, $data.node);\r
+                       }\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Executes the next installation step.\r
+        * \r
+        * @param       string          step\r
+        * @param       string          node\r
+        * @param       object          additionalData\r
+        */\r
+       _executeStep: function(step, node, additionalData) {\r
+               if (!additionalData) additionalData = {};\r
+               \r
+               var $data = $.extend({\r
+                               node: node,\r
+                               queueID: this._queueID,\r
+                               step: step\r
+               }, additionalData);\r
+               \r
+               $.ajax({\r
+                       url: 'index.php?action=' + this._actionName + '&t=' + SECURITY_TOKEN + SID_ARG_2ND,\r
+                       dataType: 'json',\r
+                       type: 'POST',\r
+                       data: $data,\r
+                       success: $.proxy(function(data) {\r
+                               this._dialog.data('responseData', data);\r
+                               this._handleResponse();\r
+                       }, this),\r
+                       error: function(transport) {\r
+                               alert(transport.responseText);\r
+                       }\r
+               });\r
+       }\r
+};\r
+\r
+/**\r
+ * Handles package uninstallation.\r
+ * \r
+ * @param      jQuery          elements\r
+ */\r
+WCF.ACP.PackageUninstallation = function(elements) { this.init(elements); };\r
+WCF.ACP.PackageUninstallation.prototype = {\r
+       /**\r
+        * WCF.ACP.PackageInstallation object\r
+        * \r
+        * @var WCF.ACP.PackageInstallation\r
+        */\r
+       _installation: null,\r
+       \r
+       /**\r
+        * Initializes package uninstallation.\r
+        * \r
+        * @param       jQuery          elements\r
+        */\r
+       init: function(elements) {\r
+               if (elements.length == 0) return;\r
+               \r
+               // bind event listener\r
+               elements.each($.proxy(function(index, element) {\r
+                       $(element).click($.proxy(this._createQueue, this));\r
+               }, this));\r
+       },\r
+       \r
+       /**\r
+        * Creates a new package uninstallation process.\r
+        * \r
+        * @param       object          event\r
+        */\r
+       _createQueue: function(event) {\r
+               var packageID = $(event.target).data('objectID');\r
+               \r
+               this._installation = new WCF.ACP.PackageInstallation('uninstall', 0, false);\r
+               \r
+               // initialize dialog\r
+               WCF.showAJAXDialog('packageInstallationDialog', true, {\r
+                       ajax: {\r
+                               url: 'index.php?action=UninstallPackage&t=' + SECURITY_TOKEN + SID_ARG_2ND,\r
+                               type: 'POST',\r
+                               data: { packageID: packageID, step: 'prepare' },\r
+                               success: $.proxy(this._installation._handleResponse, this._installation)\r
+                       },\r
+                       preventClose: true,\r
+                       hideTitle: true\r
+               });\r
+       }\r
+};\r
+\r
+/**\r
+ * Handles option selection.\r
+ */\r
+WCF.ACP.Options = function() { this.init(); };\r
+WCF.ACP.Options.prototype = {\r
+       /**\r
+        * Initializes options.\r
+        */\r
+       init: function() {\r
+               $('.enablesOptions').each($.proxy(this._initOption, this));\r
+       },\r
+       \r
+       /**\r
+        * Initializes an option.\r
+        * \r
+        * @param       integer         index\r
+        * @param       object          option\r
+        */\r
+       _initOption: function(index, option) {\r
+               // execute action on init\r
+               this._change(option);\r
+               \r
+               // bind event listener\r
+               $(option).change($.proxy(this._handleChange, this));\r
+       },\r
+       \r
+       /**\r
+        * Applies whenever an option is changed.\r
+        * \r
+        * @param       object          event\r
+        */\r
+       _handleChange: function(event) {\r
+               this._change($(event.target));\r
+       },\r
+       \r
+       /**\r
+        * Enables or disables options on option value change.\r
+        * \r
+        * @param       object          option\r
+        */\r
+       _change: function(option) {\r
+               option = $(option);\r
+               \r
+               var $disableOptions = eval(option.data('disableOptions'));\r
+               var $enableOptions = eval(option.data('enableOptions'));\r
+               \r
+               // determine action by type\r
+               switch(option.getTagName()) {\r
+                       case 'input':\r
+                               switch(option.attr('type')) {\r
+                                       case 'checkbox':\r
+                                               this._execute(option.attr('checked'), $disableOptions, $enableOptions);\r
+                                       break;\r
+                                       \r
+                                       case 'radio':\r
+                                               if (option.attr('checked')) {\r
+                                                       this._execute(true, $disableOptions, $enableOptions);\r
+                                               }\r
+                                       break;\r
+                               }\r
+                       break;\r
+                       \r
+                       case 'select':\r
+                               var $value = option.val();\r
+                               var $disableOptions = $enableOptions = [];\r
+                               \r
+                               if (option.data('disableOptions').length > 0) {\r
+                                       for (var $index in option.data('disableOptions')) {\r
+                                               var $item = option.data('disableOptions')[$index];\r
+                                               \r
+                                               if ($item.value == $value) {\r
+                                                       $disableOptions.push($item.option);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               if (option.data('enableOptions').length > 0) {\r
+                                       for (var $index in option.data('enableOptions')) {\r
+                                               var $item = option.data('enableOptions')[$index];\r
+                                               \r
+                                               if ($item.value == $value) {\r
+                                                       $enableOptions.push($item.option);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               this._execute(true, $disableOptions, $enableOptions);\r
+                       break;\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Enables or disables options.\r
+        * \r
+        * @param       boolean         isActive\r
+        * @param       array           disableOptions\r
+        * @param       array           enableOptions\r
+        */\r
+       _execute: function(isActive, disableOptions, enableOptions) {\r
+               if (disableOptions.length > 0) {\r
+                       for (var $i = 0, $size = disableOptions.length; $i < $size; $i++) {\r
+                               var $target = disableOptions[$i];\r
+                               if ($.wcfIsset($target)) {\r
+                                       if (isActive) {\r
+                                               $('#' + $.wcfEscapeID($target)).disable().closest('dl').addClass('disabled');\r
+                                       }\r
+                                       else {\r
+                                               $('#' + $.wcfEscapeID($target)).enable().closest('dl').removeClass('disabled');\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               if (enableOptions.length > 0) {\r
+                       for (var $i = 0, $size = enableOptions.length; $i < $size; $i++) {\r
+                               var $target = enableOptions[$i];\r
+                               if ($.wcfIsset($target)) {\r
+                                       if (isActive) {\r
+                                               $('#' + $.wcfEscapeID($target)).enable().closest('dl').removeClass('disabled');\r
+                                       }\r
+                                       else {\r
+                                               $('#' + $.wcfEscapeID($target)).disable().closest('dl').addClass('disabled');\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+};
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/style/extra/setupStyle-rtl.css b/wcfsetup/install/files/acp/style/extra/setupStyle-rtl.css
new file mode 100644 (file)
index 0000000..7bb6a7a
--- /dev/null
@@ -0,0 +1,261 @@
+
+/* ### -- -- -- -- -- Setup Styles -- -- -- -- -- ### */
+
+/* 
+
+File: setupStyle.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+html, body {
+       background-color: #eee;
+       background-image: url("../../images/setupBackground-rtl.png");
+       background-position: right;
+       background-repeat: repeat-y;
+       margin: 0;
+       padding: 0;
+}
+
+body {
+       color: #333;
+       font-family: "Trebuchet MS", Tahoma, Verdana, Arial, Helvetica, sans-serif; 
+       font-size: .85em;
+}
+
+.page {
+       background-color: #fff;
+       background-image: url("../../images/setupHeader-rtl.jpg");
+       background-repeat: no-repeat;
+       padding: 153px 40px 20px 40px;
+       width: 720px;
+}
+
+.inner {
+       padding: 0 20px 10px 20px;
+}
+
+h1 {
+       color: #164369;
+       font-size: 1.9em;
+       font-weight: normal;
+       text-shadow: -0 2px 3px #bbb;
+       margin: 5px 0;
+       padding: 5px 0;
+}
+
+h2 {
+       color: #164369;
+       font-size: 1.4em;
+       font-weight: bold;
+       margin: 0;
+       padding-top: 5px;
+}
+
+.icon {
+       margin-left: 30px;
+       float: right;
+}
+
+fieldset {
+       font-size: .82em;
+       border: 1px solid #8da4b7;
+       margin-bottom: 10px;
+       padding: 0;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+legend {
+       color: #164369;
+       font-size: 1em;
+       margin: 0 10px;
+       padding: 0 4px;
+}
+
+fieldset p, fieldset div {
+       margin: 0;
+       padding: 8px 0 0 0;
+}
+
+hr {
+       color: #8da4b7;
+       border: 0;
+       background-color: #8da4b7;
+       margin: 10px 0;
+       padding: 0;
+       clear: right;
+       height: 1px;
+       width: 100%;
+       position: relative;
+}
+
+/* ### -- -- -- -- -- Links -- -- -- -- -- ### */
+
+a {
+       color: #164369;
+}
+
+a:hover, a:active, a:visited {
+       color: #000;
+}
+
+/* ### -- -- -- -- -- Progress Bar -- -- -- -- -- ### */
+
+.progress {
+       border: 1px solid #b2b2b2;
+       margin: 0 128px 25px 0;
+       padding: 1px;
+       width: 300px;
+       height: 16px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+
+.progressBar {
+       font-size: 7px;
+       border-bottom: 8px solid #ddd;
+       background-color: #f1f1f1;
+       height: 8px;
+       -webkit-border-radius: 1px;
+       -moz-border-radius: 1px;
+}
+
+.progressText {
+       color: #333;
+       font-size: .75em;
+       text-shadow: -0 1px 1px #fff;
+       text-align: center;
+       margin-top: -15px;
+}
+
+.shortInfo {
+       color: #666;
+       font-size: .85em;
+       margin: 0;
+}
+
+fieldset #content .inner {
+       background-color: #f60;
+       margin-top: 0 !important;
+}
+
+/* -- -- -- -- -- -- -- Forms -- -- -- -- -- -- -- */
+
+form {
+       margin: 0;
+       padding: 0;
+}
+
+label {
+       padding-bottom: 2px;
+       display: block;
+}
+
+textarea, .inputText {
+       width: 100%;
+}
+
+textarea, select, input[type="text"], input[type="password"] {
+       border-width: 1px;
+       border-style: solid;
+       border-color: #666 #999 #ccc #999;
+       background-color: #fafafa;
+       background-image: url("../../images/setupInputBackground.png");
+       background-position: right top;
+       background-repeat: repeat-x;
+       padding: 2px;
+       min-height: 13px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+
+textarea:focus, select:focus, .inputText:focus {
+       border: 1px solid #fa2;
+       background-color: #fff9f4;
+       background-image: url("../../images/setupInputBackground.png");
+       background-repeat: repeat-x;
+       outline: 0;
+}
+
+iframe {
+       border: 0;
+       background-color: #fff;
+       margin: 10px 0 0 0;
+       padding: 0;
+       width: 100%;
+       height: 300px;
+}
+
+.nextButton {
+       float: left;
+}
+
+/* ### -- -- -- -- -- System Messages (Success, Warning, Error) -- -- -- -- -- ### */
+
+.success, .warning, .error {
+       border-width: 1px;
+       border-style: solid;
+       background-position: 10px center;
+       background-repeat: no-repeat;
+       padding: 7px 45px 7px 10px;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+.success {
+       color: #090;
+       border-color: #090;
+       background-color: #efe;
+       background-image: url("../../../icon/successM.png");
+}
+
+.success a, .success a:hover {
+       color: #333;
+}
+
+.warning {
+       color: #660;
+       border-color: #660;
+       background-color: #ffd;
+       background-image: url("../../../icon/warningM.png");
+}
+
+.warning a, .warning a:hover {
+       color: #333;
+}
+
+.error {
+       color: #c00;
+       border-color: #c00;
+       background-color: #fee;
+       background-image: url("../../../icon/errorM.png");
+}
+
+.error a, .error a:hover {
+       color: #333;
+}
+
+.errorField {
+       color: #c00;
+}
+
+.errorField .inputText, .errorField select, .errorField textarea {
+       border: 1px solid #c00;
+       background-color: #fee;
+}
+
+.errorField img {
+       vertical-align: middle;
+}
+
+#packageUrl {
+       text-decoration: underline;
+       border: none;
+       background: transparent;
+       padding: 0;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/acp/style/extra/setupStyle.css b/wcfsetup/install/files/acp/style/extra/setupStyle.css
new file mode 100644 (file)
index 0000000..accb5e9
--- /dev/null
@@ -0,0 +1,261 @@
+
+/* ### -- -- -- -- -- Setup Styles -- -- -- -- -- ### */
+
+/* 
+
+File: setupStyle.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+html, body {
+       background-color: #eee;
+       background-image: url("../../images/setupBackground-ltr.png");
+       background-position: left;
+       background-repeat: repeat-y;
+       margin: 0;
+       padding: 0;
+}
+
+body {
+       color: #333;
+       font-family: "Trebuchet MS", Tahoma, Verdana, Arial, Helvetica, sans-serif; 
+       font-size: .85em;
+}
+
+.page {
+       background-color: #fff;
+       background-image: url("../../images/setupHeader-ltr.jpg");
+       background-repeat: no-repeat;
+       padding: 153px 40px 20px 40px;
+       width: 720px;
+}
+
+.inner {
+       padding: 0 20px 10px 20px;
+}
+
+h1 {
+       color: #164369;
+       font-size: 1.9em;
+       font-weight: normal;
+       text-shadow: 0 2px 3px #bbb;
+       margin: 5px 0;
+       padding: 5px 0;
+}
+
+h2 {
+       color: #164369;
+       font-size: 1.4em;
+       font-weight: bold;
+       margin: 0;
+       padding-top: 5px;
+}
+
+.icon {
+       margin-right: 30px;
+       float: left;
+}
+
+fieldset {
+       font-size: .82em;
+       border: 1px solid #8da4b7;
+       margin-bottom: 10px;
+       padding: 0;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+legend {
+       color: #164369;
+       font-size: 1em;
+       margin: 0 10px;
+       padding: 0 4px;
+}
+
+fieldset p, fieldset div {
+       margin: 0;
+       padding: 8px 0 0 0;
+}
+
+hr {
+       color: #8da4b7;
+       border: 0;
+       background-color: #8da4b7;
+       margin: 10px 0;
+       padding: 0;
+       clear: left;
+       height: 1px;
+       width: 100%;
+       position: relative;
+}
+
+/* ### -- -- -- -- -- Links -- -- -- -- -- ### */
+
+a {
+       color: #164369;
+}
+
+a:hover, a:active, a:visited {
+       color: #000;
+}
+
+/* ### -- -- -- -- -- Progress Bar -- -- -- -- -- ### */
+
+.progress {
+       border: 1px solid #b2b2b2;
+       margin: 0 0 25px 128px;
+       padding: 1px;
+       width: 300px;
+       height: 16px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+
+.progressBar {
+       font-size: 7px;
+       border-bottom: 8px solid #ddd;
+       background-color: #f1f1f1;
+       height: 8px;
+       -webkit-border-radius: 1px;
+       -moz-border-radius: 1px;
+}
+
+.progressText {
+       color: #333;
+       font-size: .75em;
+       text-shadow: 0 1px 1px #fff;
+       text-align: center;
+       margin-top: -15px;
+}
+
+.shortInfo {
+       color: #666;
+       font-size: .85em;
+       margin: 0;
+}
+
+fieldset #content .inner {
+       background-color: #f60;
+       margin-top: 0 !important;
+}
+
+/* -- -- -- -- -- -- -- Forms -- -- -- -- -- -- -- */
+
+form {
+       margin: 0;
+       padding: 0;
+}
+
+label {
+       padding-bottom: 2px;
+       display: block;
+}
+
+textarea, .inputText {
+       width: 100%;
+}
+
+textarea, select, input[type="text"], input[type="password"] {
+       border-width: 1px;
+       border-style: solid;
+       border-color: #666 #999 #ccc #999;
+       background-color: #fafafa;
+       background-image: url("../../images/setupInputBackground.png");
+       background-position: left top;
+       background-repeat: repeat-x;
+       padding: 2px;
+       min-height: 13px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+
+textarea:focus, select:focus, .inputText:focus {
+       border: 1px solid #fa2;
+       background-color: #fff9f4;
+       background-image: url("../../images/setupInputBackground.png");
+       background-repeat: repeat-x;
+       outline: 0;
+}
+
+iframe {
+       border: 0;
+       background-color: #fff;
+       margin: 10px 0 0 0;
+       padding: 0;
+       width: 100%;
+       height: 300px;
+}
+
+.nextButton {
+       float: right;
+}
+
+/* ### -- -- -- -- -- System Messages (Success, Warning, Error) -- -- -- -- -- ### */
+
+.success, .warning, .error {
+       border-width: 1px;
+       border-style: solid;
+       background-position: 10px center;
+       background-repeat: no-repeat;
+       padding: 7px 10px 7px 45px;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+.success {
+       color: #090;
+       border-color: #090;
+       background-color: #efe;
+       background-image: url("../../../icon/successM.png");
+}
+
+.success a, .success a:hover {
+       color: #333;
+}
+
+.warning {
+       color: #660;
+       border-color: #660;
+       background-color: #ffd;
+       background-image: url("../../../icon/warningM.png");
+}
+
+.warning a, .warning a:hover {
+       color: #333;
+}
+
+.error {
+       color: #c00;
+       border-color: #c00;
+       background-color: #fee;
+       background-image: url("../../../icon/errorM.png");
+}
+
+.error a, .error a:hover {
+       color: #333;
+}
+
+.errorField {
+       color: #c00;
+}
+
+.errorField .inputText, .errorField select, .errorField textarea {
+       border: 1px solid #c00;
+       background-color: #fee;
+}
+
+.errorField img {
+       vertical-align: middle;
+}
+
+#packageUrl {
+       text-decoration: underline;
+       border: none;
+       background: transparent;
+       padding: 0;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/acp/style/extra/setupWindowStyle-rtl.css b/wcfsetup/install/files/acp/style/extra/setupWindowStyle-rtl.css
new file mode 100644 (file)
index 0000000..e11c612
--- /dev/null
@@ -0,0 +1,213 @@
+
+/* ### -- -- -- -- -- Setup Window Styles -- -- -- -- -- ### */
+
+/* 
+
+File: setupWindowStyle.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* -- -- -- -- -- -- -- Miscellaneous -- -- -- -- -- -- -- */
+
+body {
+       color: #333;
+       font-family: "Trebuchet MS", Tahoma, Verdana, Arial, Helvetica, sans-serif; 
+       font-size: .82em;
+       background-color: #fff;
+       margin: 0;
+       padding: 0;
+}
+
+.inner {
+       padding: 0 20px 10px 20px;
+}
+
+fieldset {
+       font-size: .82em;
+       border: 1px solid #8da4b7;
+       margin-bottom: 10px;
+       padding: 0;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+legend {
+       color: #164369;
+       font-size: 1em;
+       margin: 0 10px;
+       padding: 0 4px;
+}
+
+fieldset p, fieldset div {
+       margin: 8px 0 0 0;
+       padding: 0;
+}
+
+/* -- -- -- -- -- -- -- Forms -- -- -- -- -- -- -- */
+
+form {
+       margin: 0;
+       padding: 0;
+}
+
+label {
+       margin-bottom: 2px;
+       display: block;
+}
+
+textarea, .inputText {
+       width: 99%;
+}
+
+textarea, select, input[type="text"], input[type="password"] {
+       border-width: 1px;
+       border-style: solid;
+       border-color: #666 #999 #ccc #999;
+       background-color: #fafafa;
+       background-image: url("../../images/setupInputBackground.png");
+       background-position: right top;
+       background-repeat: repeat-x;
+       padding: 2px;
+       min-height: 13px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+
+textarea:focus, select:focus, .inputText:focus {
+       border: 1px solid #fa2;
+       background-color: #fff9f4;
+       background-image: url("../../images/setupInputBackground.png");
+       background-repeat: repeat-x;
+       outline: 0;
+}
+
+textarea, select, .inputText {
+       border: 1px solid #8da4b7;
+       background-color: #fafafa;
+}
+
+textarea:focus, select:focus, .inputText:focus {
+       border: 1px solid #fa2;
+       background-color: #fff9f4;
+}
+
+input[type="file"] {
+       width: 100%;
+}
+
+textarea, select, input[type="text"], input[type="password"] {
+       padding: 2px;
+}
+
+.select label {
+       margin-bottom: 5px;
+       padding-right: 25px;
+}
+
+.select input {
+       float: right;
+}
+
+.nextButton {
+       text-align: left;
+}
+
+.disabled {
+       color: #b2b2b2;
+}
+
+/* ### -- -- -- -- -- System Messages (Success, Warning, Error) -- -- -- -- -- ### */
+
+.success, .warning, .error {
+       border-width: 1px;
+       border-style: solid;
+       background-position: 10px center;
+       background-repeat: no-repeat;
+       padding: 7px 45px 7px 10px;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+.success {
+       color: #090;
+       border-color: #090;
+       background-color: #efe;
+       background-image: url("../../../icon/successM.png");
+}
+
+.success a, .success a:hover {
+       color: #333;
+}
+
+.warning {
+       color: #660;
+       border-color: #660;
+       background-color: #ffd;
+       background-image: url("../../../icon/warningM.png");
+}
+
+.warning a, .warning a:hover {
+       color: #333;
+}
+
+.error {
+       color: #c00;
+       border-color: #c00;
+       background-color: #fee;
+       background-image: url("../../../icon/errorM.png");
+}
+
+.error a, .error a:hover {
+       color: #333;
+}
+
+.errorField {
+       color: #c00;
+}
+
+.errorField img {
+       vertical-align: middle;
+}
+
+/* ### -- -- -- -- -- System Exception -- -- -- -- -- ### */
+
+#systemException {
+       font-family: Verdana, Helvetica, sans-serif;
+       font-size: 1em;
+       border: 1px outset lightgrey;
+       background-color: lightgrey;
+       padding: 3px;
+}
+
+#systemException div {
+       border: 1px inset lightgrey;
+       padding: 4px;
+}
+
+#systemException h1 {
+       color: #fff;
+       font-size: 1.2em;
+       background-color: #154268;
+       margin: 0 0 3px 0;
+       padding: 4px;
+}
+
+#systemException h2 {
+       font-size: 1.1em;
+       margin-bottom: 0;
+}
+
+#systemException pre, #systemException p {
+       font-size: 1em;
+       margin: 0;
+}
+
+#packageUrl {
+       text-decoration: underline;
+       border: none;
+       background: transparent;
+       padding: 0;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/acp/style/extra/setupWindowStyle.css b/wcfsetup/install/files/acp/style/extra/setupWindowStyle.css
new file mode 100644 (file)
index 0000000..65ea041
--- /dev/null
@@ -0,0 +1,213 @@
+
+/* ### -- -- -- -- -- Setup Window Styles -- -- -- -- -- ### */
+
+/* 
+
+File: setupWindowStyle.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* -- -- -- -- -- -- -- Miscellaneous -- -- -- -- -- -- -- */
+
+body {
+       color: #333;
+       font-family: "Trebuchet MS", Tahoma, Verdana, Arial, Helvetica, sans-serif; 
+       font-size: .82em;
+       background-color: #fff;
+       margin: 0;
+       padding: 0;
+}
+
+.inner {
+       padding: 0 20px 10px 20px;
+}
+
+fieldset {
+       font-size: .82em;
+       border: 1px solid #8da4b7;
+       margin-bottom: 10px;
+       padding: 0;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+legend {
+       color: #164369;
+       font-size: 1em;
+       margin: 0 10px;
+       padding: 0 4px;
+}
+
+fieldset p, fieldset div {
+       margin: 8px 0 0 0;
+       padding: 0;
+}
+
+/* -- -- -- -- -- -- -- Forms -- -- -- -- -- -- -- */
+
+form {
+       margin: 0;
+       padding: 0;
+}
+
+label {
+       margin-bottom: 2px;
+       display: block;
+}
+
+textarea, .inputText {
+       width: 99%;
+}
+
+textarea, select, input[type="text"], input[type="password"] {
+       border-width: 1px;
+       border-style: solid;
+       border-color: #666 #999 #ccc #999;
+       background-color: #fafafa;
+       background-image: url("../../images/setupInputBackground.png");
+       background-position: left top;
+       background-repeat: repeat-x;
+       padding: 2px;
+       min-height: 13px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+
+textarea:focus, select:focus, .inputText:focus {
+       border: 1px solid #fa2;
+       background-color: #fff9f4;
+       background-image: url("../../images/setupInputBackground.png");
+       background-repeat: repeat-x;
+       outline: 0;
+}
+
+textarea, select, .inputText {
+       border: 1px solid #8da4b7;
+       background-color: #fafafa;
+}
+
+textarea:focus, select:focus, .inputText:focus {
+       border: 1px solid #fa2;
+       background-color: #fff9f4;
+}
+
+input[type="file"] {
+       width: 100%;
+}
+
+textarea, select, input[type="text"], input[type="password"] {
+       padding: 2px;
+}
+
+.select label {
+       margin-bottom: 5px;
+       padding-left: 25px;
+}
+
+.select input {
+       float: left;
+}
+
+.nextButton {
+       text-align: right;
+}
+
+.disabled {
+       color: #b2b2b2;
+}
+
+/* ### -- -- -- -- -- System Messages (Success, Warning, Error) -- -- -- -- -- ### */
+
+.success, .warning, .error {
+       border-width: 1px;
+       border-style: solid;
+       background-position: 10px center;
+       background-repeat: no-repeat;
+       padding: 7px 10px 7px 45px;
+       -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+}
+
+.success {
+       color: #090;
+       border-color: #090;
+       background-color: #efe;
+       background-image: url("../../../icon/successM.png");
+}
+
+.success a, .success a:hover {
+       color: #333;
+}
+
+.warning {
+       color: #660;
+       border-color: #660;
+       background-color: #ffd;
+       background-image: url("../../../icon/warningM.png");
+}
+
+.warning a, .warning a:hover {
+       color: #333;
+}
+
+.error {
+       color: #c00;
+       border-color: #c00;
+       background-color: #fee;
+       background-image: url("../../../icon/errorM.png");
+}
+
+.error a, .error a:hover {
+       color: #333;
+}
+
+.errorField {
+       color: #c00;
+}
+
+.errorField img {
+       vertical-align: middle;
+}
+
+/* ### -- -- -- -- -- System Exception -- -- -- -- -- ### */
+
+#systemException {
+       font-family: Verdana, Helvetica, sans-serif;
+       font-size: 1em;
+       border: 1px outset lightgrey;
+       background-color: lightgrey;
+       padding: 3px;
+}
+
+#systemException div {
+       border: 1px inset lightgrey;
+       padding: 4px;
+}
+
+#systemException h1 {
+       color: #fff;
+       font-size: 1.2em;
+       background-color: #154268;
+       margin: 0 0 3px 0;
+       padding: 4px;
+}
+
+#systemException h2 {
+       font-size: 1.1em;
+       margin-bottom: 0;
+}
+
+#systemException pre, #systemException p {
+       font-size: 1em;
+       margin: 0;
+}
+
+#packageUrl {
+       text-decoration: underline;
+       border: none;
+       background: transparent;
+       padding: 0;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/acp/style/style.css b/wcfsetup/install/files/acp/style/style.css
new file mode 100644 (file)
index 0000000..dac5cd3
--- /dev/null
@@ -0,0 +1,224 @@
+\r
+/* dynamic style attributes */\r
+\r
+.largeButtons li a,.pmEditFolders a{background-image:url("../images/WoltLab Blue Sunrise/largeButtons-ltr.png")}\r
+.largeButtons li a:hover,.pmEditFolders a:hover{background-image:url("../images/WoltLab Blue Sunrise/largeButtons-ltr.png")}\r
+.largeButtons li a,.pmEditFolders a{border-style:solid}\r
+.largeButtons li a{border-width:0px}\r
+.largeButtons li{border-style:solid}\r
+.largeButtons li{border-width:0px}\r
+.largeButtons li a,.pmEditFolders a{color:#fff}\r
+.largeButtons li a:hover,.pmEditFolders a:hover{color:#fff}\r
+.memberList li .memberName,.messageNumber,.optionButtons a,.smallButtons a,li.extraButton a{background-color:#d9e5ef}\r
+.memberList li .memberName{border-color:#d9e5ef}\r
+.memberList li .memberName:hover,.messageNumber:hover,.optionButtons a:hover,.pageNavigation li ul,.smallButtons a:hover,li.extraButton a:hover{background-color:#ffe0b8}\r
+.memberList li .memberName,.messageNumber,.optionButtons a,.smallButtons a,li.extraButton a{background-image:url("../images/WoltLab Blue Sunrise/smallButtons.png")}\r
+.memberList li .memberName:hover,.messageNumber:hover,.optionButtons a:hover,.smallButtons a:hover,li.extraButton a:hover{background-image:url("../images/WoltLab Blue Sunrise/smallButtonsHover.png")}\r
+.memberList li,.memberList li .memberRemove{background-color:#fff}\r
+.optionButtons a,.pageNavigation a,.pageNavigation li span,.smallButtons a,li.extraButton a{border-color:#fff}\r
+.memberList li .memberRemove:hover,.memberList li:hover{background-color:#fff}\r
+.optionButtons a:hover,.pageNavigation a:hover,.smallButtons a:hover,li.extraButton a:hover{border-color:#fff}\r
+.pageNavigation li.children:hover > span{border-color:#fff}\r
+.optionButtons a,.pageNavigation a,.pageNavigation li span,.smallButtons a,li.extraButton a{border-style:solid}\r
+.optionButtons a,.pageNavigation a,.pageNavigation li span,.smallButtons a,li.extraButton a{border-width:1px}\r
+.footerOptions li.extraButton,.memberList li,.messageNumber,.optionButtons li,.pageNavigation li,.smallButtons li,li.extraButton{border-color:#8da4b7}\r
+.memberList li:hover,.messageNumber:hover,.optionButtons li:hover,.pageNavigation li:hover,.smallButtons li:hover,li.extraButton:hover{border-color:#fa2}\r
+.memberList li,.messageNumber,.optionButtons li,.smallButtons li,li.extraButton{border-style:solid}\r
+.li.extraButton,.memberList li,.messageNumber,.optionButtons li,.smallButtons li{border-width:1px}\r
+.container-1 .smallButtons a,.container-2 .smallButtons a,.container-3 .smallButtons a,.memberList li .memberName,.messageInner .color-1 .smallButtons a,.messageInner .color-2 .smallButtons a,.messageNumber,.optionButtons a,.smallButtons a,li.extraButton a{color:#666}\r
+.container-1 .smallButtons a:hover,.container-2 .smallButtons a:hover,.container-3 .smallButtons a:hover,.memberList li .memberName:hover,.messageInner .color-1 .smallButtons a:hover,.messageInner .color-2 .smallButtons a:hover,.messageNumber:hover,.optionButtons a:hover,.smallButtons a:hover,li.extraButton a:hover{color:#333}\r
+.border,.mceResizeBox,.pmEditFolders,.pmUsageBar,.popupMenu,.quoteBox,.subTabMenu{background-color:#fff}\r
+#logo,#search,.attachmentPreview ul li a,.border .tableList td,.border .tableList th,.columnContainer,.dividers .messageAuthor,.dividers .tocHeadline,.dividers .userAvatar,.dividers .userCredits,.dividers .userMessenger,.dividers .userSymbols,.inlineCalendarFooter td a,.inlineCalendarFooter td span,.inlineCalendarHeader td a,.inlineCalendarHeader td span,.mainMenu .mainMenuInner,.mainMenu a,.mceEditor .mceColors li,.messageContent,.messageInner,.subTabMenu div.containerHead,.tabMenu li a,.userAvatar,.userAvatarFramed{border-color:#fff}\r
+#footer,#header,.attachmentFile ul li,.attachmentPreview ul li:hover,.avatarDisplay div,.avatarSelect li label,.border,.footerMenu li,.footerOptions li,.galleryIndex li.floatedElement:hover,.inlineCalendarFooter,.inlineCalendarHeader,.inlineCalendarTable,.mainMenu,.marked,.mceResizeBox,.message,.messageContentInner,.messageNumber,.pageNavigation li ul,.pmEditFolders,.pmUsageBar,.popupMenu,.quoteBox,.searchContainer,.subTabMenu,.tabMenu li,.userAvatar a,.userAvatarFramed a,fieldset{border-color:#8da4b7}\r
+.border,.error,.info,.inlineCalendarFooter,.inlineCalendarHeader,.inlineCalendarTable,.message,.pageNavigation li ul,.pmEditFolders,.pmUsageBar,.popupMenu,.quoteBox,.searchContainer,.subTabMenu,.success,.tabMenu li,.warning,fieldset{border-style:solid}\r
+.border,.error,.info,.inlineCalendarFooter,.inlineCalendarHeader,.inlineCalendarTable,.message,.quoteBox,.searchContainer,.success,.warning,fieldset{border-width:1px}\r
+.containerHead,.inlineCalendarFooter td,.inlineCalendarHeader td,.tabMenu li.activeTabMenu a,.tabMenu li.activeTabMenu a:hover{background-color:#164369}\r
+.containerHead,.inlineCalendarFooter td,.inlineCalendarHeader td{background-image:url("../images/WoltLab Blue Sunrise/containerHead.png")}\r
+.containerHead .light,.containerHead .light a{color:#fff}\r
+.containerHead,.inlineCalendarFooter td a,.inlineCalendarFooter td span,.inlineCalendarHeader td a,.inlineCalendarHeader td span{color:#fff}\r
+.containerHead a,.tabMenu li.activeTabMenu a,.tabMenu li.activeTabMenu a:hover{color:#fff}\r
+.containerHead a:hover{color:#fff}\r
+.container-1,.container-1 fieldset fieldset,.container-2 fieldset,.dynBoxInner,.inlineCalendarTable,.messageInner .color-1,.pageNavigation li ul,div.pageMenu li.container-1 a,fieldset{background-color:#f8fafb}\r
+.inlineCalendarTable a{border-color:#f8fafb}\r
+.container-1 fieldset,.container-1 fieldset fieldset.noJavaScript fieldset,.container-2,.container-2 fieldset fieldset,.container-3 fieldset,.messageInner .color-2,.weekDays,div.pageMenu li.container-2 a,fieldset fieldset{background-color:#f2f6fa}\r
+.container-3,.container-3 fieldset fieldset,.itemList .itemListCategory,.tableList tbody tr:hover,.threadStarterPost .poll .container-3{background-color:#d8e7f5}\r
+.messageContainer,.messageContainerFooter{border-color:#d8e7f5}\r
+.container-4,.galleryAlbumCover img,.userAvatarFramed{background-color:#fff}\r
+#userCardCredits,.attachmentPreview ul li,.buttonBar,.deleteNote,.editNote,.friendsConnection,.friendsNetwork,.friendsNone,.galleryIndex li.floatedElement,.guestAdvice,.itemList .itemListTitle,.mainMenu div.pageMenu .bottomSeparator a,.mainMenu div.pageMenu .topSeparator a,.messageFooter,.messageFooterLeft,.messageFooterRight,.messageHeader,.signature,.subHeadline,div.pageMenu .bottomSeparator a,div.pageMenu .topSeparator a{border-color:#c5d0da}\r
+.buttonBar,.deleteNote,.editNote,.itemList .itemListTitle,.mainMenu div.pageMenu .bottomSeparator a,.mainMenu div.pageMenu .topSeparator a,.messageFooter,.messageFooterLeft,.messageFooterRight,.messageHeader,.signature,.subHeadline,div.pageMenu .bottomSeparator a,div.pageMenu .topSeparator a{border-style:solid}\r
+.mainMenu div.pageMenu .bottomSeparator a,div.pageMenu .bottomSeparator a{border-bottom-width:1px}\r
+.mainMenu div.pageMenu .topSeparator a,div.pageMenu .topSeparator a{border-top-width:1px}\r
+.deleteNote,.editNote,.itemList .itemListTitle,.messageFooter,.messageFooterLeft,.messageFooterRight,.messageHeader,.signature,.subHeadline{border-width:1px}\r
+#logo h1{position: absolute; top: -9000px; left: -9000px;}\r
+.inputText,select,textarea{background-color:#fff}\r
+.inputText:focus,select:focus,textarea:focus{background-color:#fff9f4}\r
+.inputText,select,textarea{border-color:#8da4b7}\r
+.inputText:focus,select:focus,textarea:focus{border-color:#fa2}\r
+.inputText,select,textarea{border-style:solid}\r
+.inputText,.inputText:focus,select,select:focus,textarea,textarea:focus{border-width:1px}\r
+.editor textarea,.inputText,select,textarea{font-family:'Trebuchet MS', Arial, sans-serif}\r
+.editor textarea,.inputText,select,textarea{color:#333}\r
+.editor textarea:focus,.inputText:focus,select:focus,textarea:focus{color:#000}\r
+.editor textarea,.inputText,select,textarea{font-size:.85em}\r
+.mainMenu div.pageMenu a,.optionButtons li,.pageNavigation a,.pageNavigation li.children span,div.messageInner div.pageMenu a,div.messageInner div.smallButtons div.pageMenu a,div.pageMenu a,div.smallButtons div.pageMenu a{background-color:#f8fafb}\r
+.mainMenu div.pageMenu a:hover,.pageNavigation a:hover,.pageNavigation li.children:hover span,div.messageInner div.pageMenu a:hover,div.messageInner div.smallButtons div.pageMenu a:hover,div.pageMenu .twoRows a:hover,div.pageMenu a:hover,div.smallButtons div.pageMenu a:hover{background-color:#ffe0b8}\r
+.mainMenu div.pageMenu a:hover,.pageNavigation a:hover,.pageNavigation li span:hover,div.messageInner div.pageMenu a:hover,div.messageInner div.smallButtons div.pageMenu a:hover,div.pageMenu a:hover,div.smallButtons div.pageMenu a:hover{background-image:url("../images/WoltLab Blue Sunrise/tableHeadHover.png")}\r
+.pageNavigation li.children:hover > span{background-image:url("../images/WoltLab Blue Sunrise/tableHeadHover.png")}\r
+.mainMenu div.pageMenu a,.pageNavigation a,.pageNavigation li.children span,.tableList div.pageMenu a,div.messageInner div.pageMenu a,div.messageInner div.smallButtons div.pageMenu a,div.pageMenu a,div.smallButtons div.pageMenu a{color:#333}\r
+.mainMenu div.pageMenu a:hover,.pageNavigation a:hover,.pageNavigation li.children:hover span,.tableList div.pageMenu a:hover,div.messageInner div.pageMenu a:hover,div.messageInner div.smallButtons div.pageMenu a:hover,div.pageMenu a:hover,div.smallButtons div.pageMenu a:hover{color:#333}\r
+.mainMenu .active a,.mainMenu .firstActive a,.mainMenu .lastActive a{background-color:#154268}\r
+.mainMenu .active a:hover,.mainMenu .firstActive a:hover,.mainMenu .lastActive a:hover{background-color:#154268}\r
+.mainMenu .active a,.mainMenu .firstActive a,.mainMenu .lastActive a{color:#d9e5ef}\r
+.mainMenu .active a:hover,.mainMenu .firstActive a:hover,.mainMenu .lastActive a:hover{color:#fff}\r
+.mainMenu a:hover{background-color:#ffe0b8}\r
+.mainMenu .active a,.mainMenu .firstActive a,.mainMenu .lastActive a,.mainMenu a:hover{background-image:url("../images/WoltLab Blue Sunrise/menuActive.png")}\r
+.mainMenu{background-color:transparent}\r
+.mainMenu a{color:#154268}\r
+.mainMenu a:hover{color:#333}\r
+.mainMenu div{text-align:left;margin:0 auto 0 0}\r
+.tabMenu ul li.activeTabMenu a{background-color:#164369}\r
+.tabMenu ul li.activeTabMenu a:hover{background-color:#164369}\r
+.tabMenu ul li.activeTabMenu a{color:#fff}\r
+.tabMenu li a,.tabMenu li.disabled a:hover{background-color:#e8e8e8}\r
+.tabMenu li a:hover{background-color:#8da4b7}\r
+.tabMenu li a,.tabMenu li.disabled a:hover{background-image:url("../images/WoltLab Blue Sunrise/tab.png")}\r
+.tabMenu li a:hover,.tabMenu li.activeTabMenu a,.tabMenu ul li.activeTabMenu a:hover{background-image:url("../images/WoltLab Blue Sunrise/tabActive.png")}\r
+.subTabMenu ul .activeSubTabMenu a{background-color:#17354e}\r
+.subTabMenu ul .activeSubTabMenu a:hover{background-color:#487397}\r
+.subTabMenu ul .activeSubTabMenu a{color:#fff}\r
+.subTabMenu ul .activeSubTabMenu a:hover{color:#fff}\r
+.subTabMenu ul li a:hover{background-color:#487397}\r
+.subTabMenu ul .activeSubTabMenu a,.subTabMenu ul li a{border-color:#487397}\r
+.subTabMenu ul .activeSubTabMenu a:hover,.subTabMenu ul li a:hover{border-color:#8da4b7}\r
+.subTabMenu ul .activeSubTabMenu a,.subTabMenu ul li a:hover{border-style:solid}\r
+#search .searchContainer p a,.subTabMenu ul li a{color:#ddd}\r
+#search .searchContainer p a:hover,.subTabMenu ul li a:hover{color:#fff}\r
+.tabMenu li a,.tabMenu li.disabled a:hover{color:#666}\r
+.tabMenu li a:hover{color:#fff}\r
+.message .messageSidebar{text-align:center}\r
+#footer,#header,#main,#mainMenu,#userPanel{margin-left:auto;margin-right:auto;}\r
+body,html{background-color:#fff}\r
+.iframeBody,body,textarea{font-family:'Trebuchet MS', Arial, sans-serif}\r
+.formFieldDesc,.light{color:#858789}\r
+#footer,#search .searchContainer p a,.boardlistCounter,.boardlistDescription,.boardlistLastPost,.boardlistSubboards,.boardlistUsersOnline,.deleteNote,.editNote,.firstPost,.formField label,.formFieldDesc,.loginPopup,.messageNumber,.moderators,.pageNavigation,.pageNavigation input,.pmMove p,.pmUsage,.popupMenu,.smallButtons li span,.smallFont,.statusDisplay,.subTabMenu ul li,.tableList th,.userCredits,.userExtras,.userPanel,div.inlineCalendar,td.columnLastActivity,td.columnLocation,td.columnRegistrationDate,td.columnUserAgent{font-size:.85em}\r
+.userPanel a,body,legend{color:#57595a}\r
+.breadCrumbs,.error,.info,.message h3,.message h4,.messageBody,.success,.warning{line-height:1.5}\r
+.iframeBody,body{font-size:.8em}\r
+#logo{height:90px}\r
+a,div.pageMenu .twoRows a span{color:#154268}\r
+a:hover,div.pageMenu .twoRows a:hover span{color:#000}\r
+* a.externalURL{color:#154268}\r
+* a.externalURL:hover{color:#08f}\r
+#logo .pageLogo{text-align:left}\r
+#logo .pageLogo img{margin-left:0px}\r
+#logo .pageLogo img{margin-right:0px}\r
+#logo .pageLogo img{margin-top:5px}\r
+h2{font-family:'Trebuchet MS', Arial, sans-serif}\r
+h2,h2 a,h2 a:hover{color:#173f61}\r
+h2{font-size:1.5em}\r
+h2{font-style:normal}\r
+h2{font-weight:normal}\r
+#footer,#header,#main,#mainMenu,#userPanel{max-width:80%}\r
+#footer,#header,#main,#mainMenu,#userPanel{min-width:760px}\r
+.activeContainer,.activeMessage,.mainMenu div.pageMenu .active a,.markedDayField a,.pageNavigation .active span,div.pageMenu li.active a{background-color:#d8e7f5}\r
+.activeContainer,.avatarSelect li label:hover,.inlineCalendarTable a:hover,.markedDayField a,.pageNavigation .active{border-color:#487397}\r
+.activeContainer,.avatarDisplay div,.avatarSelect li label,.avatarSelect li label:hover,.inlineCalendarTable a:hover,.markedDayField a,.pageNavigation .active{border-style:solid}\r
+.activeContainer,.avatarDisplay div,.avatarSelect li label,.avatarSelect li label:hover,.inlineCalendarTable a:hover,.markedDayField a,.pageNavigation .active{border-width:1px}\r
+.activeContainer .light,.activeContainer .light a,.activeContainer a:hover{color:#333}\r
+.activeContainer,.mainMenu div.pageMenu .active a,.markedDayField a,.pageNavigation .active span,div.pageMenu li.active a{color:#333}\r
+.activeContainer a{color:#333}\r
+.tableHead .active .emptyHead,.tableHead .active a{background-color:#ffe0b8}\r
+.tableHead .active a:hover{background-color:#ffe0b8}\r
+.tableHead .active .emptyHead,.tableHead .active a{border-color:#fa2}\r
+.tableHead .active a:hover{border-color:#f60}\r
+.tableHead .active .emptyHead,.tableHead .active a{color:#000}\r
+.tableHead .active a:hover{color:#000}\r
+.tableHead .emptyHead,.tableHead a{background-color:#eee}\r
+.tableHead a:hover{background-color:#ffe0b8}\r
+.tableHead .emptyHead,.tableHead a{background-image:url("../images/WoltLab Blue Sunrise/tableHead.png")}\r
+.tableHead .active .emptyHead,.tableHead .active a,.tableHead .active a:hover,.tableHead a:hover{background-image:url("../images/WoltLab Blue Sunrise/tableHeadHover.png")}\r
+.tableHead .emptyHead,.tableHead a{border-color:#8da4b7}\r
+.tableHead a:hover{border-color:#154268}\r
+.tableHead .emptyHead,.tableHead a{color:#154268}\r
+.tableHead a:hover{color:#000}\r
+\r
+/* user.additional.style.input1.use */\r
+\r
+html {background-color: #eee;}\r
+#main {padding-top: 0;}\r
+h1 {text-shadow: 0 -1px 1px #000;}\r
+h2, h2 a {text-shadow: 0 2px 3px #bbb;}\r
+legend {color: #487397;}\r
+#headerContainer {background-color: #164369;background-image: url("../images/WoltLab Blue Sunrise/header.jpg");background-repeat: repeat-x;background-position: left top;}\r
+#header {border-width: 0 !important;}\r
+#logo {margin: 0;border-width: 0 !important;}\r
+#userPanel {background-image: url("../images/WoltLab Blue Sunrise/userPanel.png");background-repeat: repeat-x;background-position: left bottom;max-width: 100%;min-width: 100%;width: 100%;}\r
+.userPanelInner {max-width: 80%;min-width: 770px;margin: 0 auto;}\r
+.userPanel, .userPanel a {color: #ebf1f6;}\r
+.userPanel a:hover {color: #fff;}\r
+.userPanel .border, .userPanel .popupMenu a {color: #57595a;}\r
+#search {right: 0;top: 23px;}\r
+#search .searchContainer {text-align: center;background-color: transparent;background-image: url("../images/WoltLab Blue Sunrise/searchContainer.png");background-repeat: no-repeat;background-position: right top;padding-left: 40px;min-height: 24px;}\r
+#mainMenu {max-width: 100%;min-width: 100%;width: 100%;}\r
+.mainMenu {min-height: 31px;background-color: transparent;background-image: url("../images/WoltLab Blue Sunrise/menuBar.png");background-repeat: repeat-x;background-position: left bottom;padding-bottom: 6px;border-width: 0 !important;}\r
+.mainMenu .mainMenuInner {max-width: 80%;min-width: 770px;margin: 0 auto;border-width: 0 !important;}\r
+.mainMenu a {text-shadow: 0 1px 0 #fff;border: 1px solid #c2c2c2;border-width: 0 1px 1px 1px;padding: 3px 5px 4px 5px;line-height: 1;}\r
+.mainMenu a:hover {background-image: url("../images/WoltLab Blue Sunrise/menuHover.png");}\r
+.mainMenu .active a, .mainMenu .firstActive a, .mainMenu .lastActive a {text-shadow: 0 -1px 0 #036;background-image: url("../images/WoltLab Blue Sunrise/menuActive.png") !important;}\r
+#mainMenu span {position: relative;top: 5px;}\r
+.mainMenu img {float: left;padding-right: 4px;}\r
+#footerContainer {background-color: #eee;border-top: 1px solid #8da4b7;}\r
+#footer {border: 0 !important;}\r
+.pageNavigation a:hover {background-image: url("../images/WoltLab Blue Sunrise/smallButtonsHover.png");}\r
+.messageLeft, .messageRight, .messageFramedLeft, .messageFramedRight, .messageTop, .messageFramedTop {background-image: url("../images/WoltLab Blue Sunrise/messageSidebar.jpg");background-repeat: repeat-x;}\r
+.userName a span, .quickReply h3 a {text-shadow: 0 1px 0 #fff;}\r
+.poll .pollQuestion {background-image: url("../images/WoltLab Blue Sunrise/poll.jpg");background-repeat: repeat-x;}\r
+.threadStarterPost .messageLeft, .threadStarterPost .messageRight, .threadStarterPost .messageFramedLeft, .threadStarterPost .messageFramedRight, .threadStarterPost .messageTop, .threadStarterPost .messageFramedTop  {background-image: url("../images/WoltLab Blue Sunrise/messageSidebarThreadStarter.jpg");background-repeat: repeat-x;}\r
+.threadStarterPost .container-3 {background-color: #ffddb7;}\r
+.threadStarterPost .codeBox .container-3 {background-color: #d8e7f5;}\r
+.firstPost a {color: #858789;}\r
+.smallButtons span {text-shadow: 0 1px 0 #fff;}\r
+.largeButtons a {line-height: 1;background-image: url("../images/WoltLab Blue Sunrise/largeButtons-ltr.png");background-position: right 0;background-repeat: no-repeat;padding: 0 7px 0 0;}\r
+.largeButtons a img {margin-top: 5px;margin-left: 7px;position: absolute;}\r
+.largeButtons a span {color: #fff;text-shadow: 0 -1px 0 #036;background-image: url("../images/WoltLab Blue Sunrise/largeButtons-ltr.png");background-position: left 0;background-repeat: no-repeat;padding: 9px 3px 0 36px;display: block;height: 25px;cursor: pointer;}\r
+.largeButtons a:hover {background-position: right -86px;}\r
+.largeButtons a:hover span {color: #000;text-shadow: 0 1px 0 #fff;background-position: left -86px;}\r
+.tabMenu a span, .tabMenu li.disabled a span {text-shadow: 0 1px 0 #fff;}\r
+.tabMenu .activeTabMenu a span, .tabMenu a:hover span, .subTabMenu a span {text-shadow: 0 -1px 0 #036;}\r
+.containerHead, .containerHead a {text-shadow: 0 -1px 0 #036;}\r
+.subHeadline {text-shadow: 0 1px 0 #fff;}\r
+.memberList li span {text-shadow: 0 1px 0 #fff;}\r
+.galleryIndex li span {text-shadow: 0 1px 0 #fff;}\r
+select, textarea, input[type="text"], input[type="password"] {border-width: 1px;border-style: solid;border-color: #666 #999 #ccc #999;background-image: url("../images/WoltLab Blue Sunrise/inputBackground.png");background-position: left top;background-repeat: repeat-x;min-height: 13px;}\r
+select, textarea:focus, input[type="text"]:focus, input[type="password"]:focus {background-image: url("../images/WoltLab Blue Sunrise/inputBackground.png");background-repeat: repeat-x;outline: 0;}\r
+\r
+/* user.additional.style.input2.use */\r
+\r
+* {-o-text-overflow: ellipsis;}\r
+.message, .messageInner, .quoteBox, fieldset, .info, .success, .warning, .error, .help, #userCard, .userCardInner, .second .border, .second .border .content, .avatarSelect li.container-4, .avatarSelect li label, .floatedElement, .popupMenu, .loginPopup, .loginPopup .container-1 {-webkit-border-radius: 5px; -moz-border-radius: 5px;}\r
+.messageLeft .messageContent, .messageLeft .messageContentInner {-webkit-border-top-right-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomright: 5px;}\r
+.messageRight .messageContent, .messageRight .messageContentInner {-webkit-border-top-left-radius: 5px; -moz-border-radius-topleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;}\r
+.messageFramedLeft .messageContent, .messageFramedLeft .messageContentInner, .messageFramedRight .messageContent, .messageFramedRight .messageContentInner {-webkit-border-radius: 5px; -moz-border-radius: 5px;}\r
+.messageTop .messageContent, .messageTop .messageContentInner {-webkit-border-radius: 0; -moz-border-radius: 0;}\r
+.messageFramedTop .messageContent, .messageFramedTop .messageContentInner {-webkit-border-radius: 5px; -moz-border-radius: 5px;}\r
+textarea, select, input[type="text"], input[type="password"], .memberList li, .smallButtons > ul > li, .smallButtons > ul > li > a, .extraButton, .extraButton a, .optionButtons > ul > li, .optionButtons > ul > li > a, .subTabMenu .containerHead li a, .pmUsageBar, .statBar, .userAvatarFramed, .userAvatarFramed a, .userAvatarFramed img {-webkit-border-radius: 3px; -moz-border-radius: 3px;}\r
+.pmUsageBar > div, .statBar > div {-webkit-border-radius: 1px; -moz-border-radius: 1px;}\r
+.popupMenu li:first-child a, #boardlist .border, .titleBarPanel, .titleBarPanel .containerHead, .messagePreview, .subTabMenu, .subTabMenu .containerHead, .containerHead, .messageTop .messageSidebar, .messageFramedTop .messageSidebar, .thumbnailButtons {-webkit-border-top-left-radius: 5px; -moz-border-radius-topleft: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topright: 5px;}\r
+.codeBox {-webkit-border-top-left-radius: 3px; -webkit-border-top-right-radius: 3px; -moz-border-radius-topleft: 3px; -moz-border-radius-topright: 3px;}\r
+.tabMenu li:first-child, .tabMenu li:first-child a {-webkit-border-top-left-radius: 5px; -moz-border-radius-topleft: 5px;}\r
+.tabMenu li:last-child, .tabMenu li:last-child a {-webkit-border-top-right-radius: 5px; -moz-border-radius-topright: 5px;}\r
+.searchInputMenu .pageMenu, .popupMenu li:last-child a, .twoRows li:last-child {-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomright: 5px;}\r
+#boardlist .border .boardlistInner, .twoRows li:last-child a, .datalist li:last-child {-webkit-border-bottom-left-radius: 3px; -webkit-border-bottom-right-radius: 3px; -moz-border-radius-bottomleft: 3px; -moz-border-radius-bottomright: 3px;}\r
+.popupMenu li a, #boardlist .border .boardlistInner:first-child {-webkit-border-bottom-left-radius: 0; -moz-border-radius-bottomleft: 0; -webkit-border-bottom-right-radius: 0; -moz-border-radius-bottomright: 0;}\r
+.mceToolbar .popupMenu, .mceToolbar .popupMenu li, .mceToolbar .popupMenu li a, .second fieldset .editor, .second fieldset .border, .attachmentPreview, .attachmentPreview li, .tableList td.containerHead {-webkit-border-top-left-radius: 0 !important; -webkit-border-top-right-radius: 0 !important; -webkit-border-bottom-right-radius: 0 !important; -moz-border-radius-topleft: 0 !important; -webkit-border-bottom-left-radius: 0 !important; -moz-border-radius-topright: 0 !important; -moz-border-radius-bottomleft: 0 !important; -moz-border-radius-bottomright: 0 !important;}\r
+.loginPopup input#quickLoginUsername {-webkit-border-top-right-radius: 0; -webkit-border-bottom-right-radius: 0; -moz-border-radius-topright: 0; -moz-border-radius-bottomright: 0;}\r
+.loginPopup input#quickLoginPassword {-webkit-border-top-left-radius: 0; -webkit-border-bottom-left-radius: 0; -moz-border-radius-topleft: 0; -moz-border-radius-bottomleft: 0;}\r
+input#searchInput {-webkit-border-radius: 12px; -moz-border-radius: 12px;}\r
+#searchInput {background-image: url("../images/WoltLab Blue Sunrise/searchBack-ltr.png"); background-position: -2px top; padding-left: 33px; width: 154px; height: 16px;}\r
+.searchOptions {background-image: url("../images/WoltLab Blue Sunrise/searchBackOptions-ltr.png") !important;}\r
+.searchOptions:focus {background-image: url("../images/WoltLab Blue Sunrise/searchBackOptionsActive-ltr.png") !important;}\r
+.galleryPhotoEdit img, .galleryAlbumCover img {-webkit-box-shadow: 0 3px 7px #666; -moz-box-shadow: 0 3px 7px #666;}\r
+.galleryIndex li.floatedElement .thumbnail img, .squared .thumbnail img {-webkit-box-shadow: 0 1px 3px #666; -moz-box-shadow: 0 1px 3px #666;}\r
+.galleryIndex li.floatedElement:hover, .avatarSelect li label:hover {-webkit-box-shadow: 0 1px 3px #999; -moz-box-shadow: 0 1px 3px #999;}\r
+.galleryPhoto img {-webkit-box-shadow: 0 3px 7px #666; -moz-box-shadow: 0 3px 7px #666; margin: 10px;}\r
+.imageViewerCurrentImage {-webkit-box-shadow: 0 3px 23px #000; -moz-box-shadow: 0 3px 23px #000;}\r
diff --git a/wcfsetup/install/files/acp/style/testing-reset.css b/wcfsetup/install/files/acp/style/testing-reset.css
new file mode 100644 (file)
index 0000000..e9e771a
--- /dev/null
@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/ \r
+   v2.0 | 20110126\r
+   License: none (public domain)\r
+*/\r
+\r
+html, body, div, span, applet, object, iframe,\r
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,\r
+a, abbr, acronym, address, big, cite, code,\r
+del, dfn, em, img, ins, kbd, q, s, samp,\r
+small, strike, strong, sub, sup, tt, var,\r
+b, u, i, center,\r
+dl, dt, dd, ol, ul, li,\r
+fieldset, form, label, legend,\r
+table, caption, tbody, tfoot, thead, tr, th, td,\r
+article, aside, canvas, details, embed, \r
+figure, figcaption, footer, header, hgroup, \r
+menu, nav, output, ruby, section, summary,\r
+time, mark, audio, video {\r
+       margin: 0;\r
+       padding: 0;\r
+       border: 0;\r
+       font-size: 100%;\r
+       font: inherit;\r
+       vertical-align: baseline;\r
+}\r
+/* HTML5 display-role reset for older browsers */\r
+article, aside, details, figcaption, figure, \r
+footer, header, hgroup, menu, nav, section {\r
+       display: block;\r
+}\r
+body {\r
+       line-height: 1;\r
+}\r
+ol, ul {\r
+       list-style: none;\r
+}\r
+blockquote, q {\r
+       quotes: none;\r
+}\r
+blockquote:before, blockquote:after,\r
+q:before, q:after {\r
+       content: '';\r
+       content: none;\r
+}\r
+table {\r
+       border-collapse: collapse;\r
+       border-spacing: 0;\r
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/style/testing.css b/wcfsetup/install/files/acp/style/testing.css
new file mode 100644 (file)
index 0000000..270d566
--- /dev/null
@@ -0,0 +1,687 @@
+body {\r
+       font-family: "Lucida Sans", "Lucida Grande", "Monaco", "Geneva", sans-serif;\r
+       font-size: 0.8em;\r
+}\r
+\r
+a {\r
+       color: #00c;\r
+       text-decoration: none;\r
+}\r
+\r
+a:hover {\r
+       color: #f80;\r
+       text-decoration: underline;\r
+}\r
+\r
+header {\r
+       border-bottom: 1px solid #ccc;\r
+       margin: 21px;\r
+       padding: 21px;\r
+       padding-bottom: 0;\r
+}\r
+\r
+header div#logo h1 {\r
+       font-size: 160%;\r
+       position: relative;\r
+       top: 45px;\r
+}\r
+\r
+header div#logo img {\r
+       float: left;\r
+}\r
+\r
+header div#logo a {\r
+       display: block;\r
+       height: 100px;\r
+       margin-bottom: 21px;\r
+       text-align: right;\r
+}\r
+\r
+aside {\r
+       float: left;\r
+       margin: 0 0 21px 21px;\r
+       width: 300px;\r
+}\r
+\r
+nav#navigationTop li {\r
+       background-color: #eee;\r
+       border: 1px solid #ccc;\r
+       border-bottom: 0;\r
+       cursor: pointer;\r
+       display: inline-block;\r
+       padding: 7px;\r
+}\r
+\r
+nav#navigationTop li.activeMenuItem {\r
+       background-color: #faebd7;\r
+       border-color: #ff8800;\r
+}\r
+\r
+nav#navigationSide div.menuContainer h3 {\r
+       background-color: #eee;\r
+       background-image: url(../../icon/testing/arrowRightS.png);\r
+       background-position: 7px center;\r
+       background-repeat: no-repeat;\r
+       border: 1px solid #ccc;\r
+       border-top-width: 0;\r
+       cursor: pointer;\r
+       font-size: 120%;\r
+       padding: 7px;\r
+       padding-left: 28px;\r
+       position: relative;\r
+}\r
+\r
+nav#navigationSide div.menuContainer h3.activeMenuItem {\r
+       background-image: url(../../icon/testing/arrowDownS.png);\r
+}\r
+\r
+nav#navigationSide div.menuContainer h3:first-child {\r
+       border-top: 1px solid #ccc;\r
+}\r
+\r
+nav#navigationSide div.menuContainer div {\r
+       background-color: #fefefe;\r
+       border: 1px solid #ccc;\r
+       border-top-width: 0;\r
+}\r
+\r
+nav#navigationSide div.menuContainer ul li {\r
+       padding: 7px 7px 7px 21px;\r
+}\r
+\r
+nav#navigationSide div.menuContainer ul li.activeMenuItem {\r
+       background-color: #faebd7;\r
+}\r
+\r
+nav#navigationSide div.menuContainer ul li.activeMenuItem a {\r
+       color: #ff8800;\r
+       font-weight: bold;\r
+}\r
+\r
+nav#navigationSide div.menuContainer ul li a {\r
+       text-decoration: none !important;\r
+}\r
+\r
+nav#navigationSide div.menuContainer ul li a:hover {\r
+       text-decoration: underline !important;\r
+}\r
+\r
+div#content {\r
+       background-color: #fefefe;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#eee, #fefefe);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#eee, #fefefe);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#eee), to(#fefefe));\r
+       \r
+       border: 1px solid #ccc;\r
+       margin: 0 21px 21px 340px;\r
+       padding: 21px;\r
+}\r
+\r
+footer {\r
+       background-color: #eee;\r
+       border: 1px solid #ccc;\r
+       border-bottom-width: 0;\r
+       clear: both;\r
+       margin: 0 21px 0 21px;\r
+       padding: 7px;\r
+}\r
+\r
+footer p.copyright {\r
+       display: inline-block;\r
+}\r
+\r
+footer nav#navigationFooter {\r
+       float: right;\r
+}\r
+\r
+footer nav#navigationFooter a span {\r
+       display: none;\r
+}\r
+\r
+footer nav#navigationFooter ul li {\r
+       display: inline-block;\r
+}\r
+\r
+div.wcfDimensions {\r
+       display: inline-block;\r
+}\r
+\r
+div.overlayLoading {\r
+       background-color: #fff;\r
+       background-image: url(../../images/spinner.gif);\r
+       background-position: center center;\r
+       background-repeat: no-repeat;\r
+}\r
+\r
+div.ui-dialog {\r
+       border: 10px solid rgba(0,0,0,0.2);\r
+       border-radius: 15px;\r
+       display: inline-block !important;\r
+       width: auto !important;\r
+       min-width: 80px;\r
+}\r
+\r
+div.ui-dialog-content p {\r
+       background-color: #fff;\r
+       padding: 7px;\r
+}\r
+\r
+div.ui-dialog-titlebar {\r
+       background-color: #ccc;\r
+       border-bottom: 5px solid rgba(0,0,0,0.6);\r
+       padding: 7px;\r
+       position: relative;\r
+}\r
+\r
+span.ui-dialog-title {\r
+       color: #fff;\r
+       text-shadow: #000 0 0 5px;\r
+}\r
+\r
+a.ui-dialog-titlebar-close {\r
+       background-image: url(../../icon/deleteM.png);\r
+       background-position: top left;\r
+       background-repeat: no-repeat;\r
+       height: 24px;\r
+       position: absolute !important;\r
+       right: -16px;\r
+       top: -16px;\r
+       width: 24px;\r
+}\r
+\r
+a.ui-dialog-titlebar-close span {\r
+       display: none;\r
+       visibility: hidden;\r
+}\r
+\r
+div.ui-widget-overlay {\r
+       background-color: #000;\r
+       left: 0px;\r
+       opacity: 0.6;\r
+       position: fixed;\r
+       top: 0px;\r
+}\r
+\r
+div.mainHeadline {\r
+       height: 48px;\r
+       margin-bottom: 7px;\r
+       position: relative;\r
+}\r
+\r
+div.mainHeadline img {\r
+       position: absolute;\r
+       top: -4px;\r
+       left: 0px;\r
+}\r
+\r
+div.mainHeadline div.headlineContainer {\r
+       height: 48px;\r
+       padding-left: 60px;\r
+       vertical-align: middle;\r
+}\r
+\r
+div.mainHeadline div.headlineContainer h2 {\r
+       border-bottom: 1px solid #ccc;\r
+       font-size: 140%;\r
+       padding-bottom: 3px;\r
+}\r
+\r
+div.mainHeadline div.headlineContainer p {\r
+       padding-top: 3px;\r
+} \r
+\r
+h3.subHeadline {\r
+       border-bottom: 2px solid #000;\r
+       font-size: 120%;\r
+       margin: 14px 0 14px 0;\r
+       padding: 7px;\r
+}\r
+\r
+fieldset {\r
+       border: 1px solid #ccc;\r
+       border-radius: 10px;\r
+       margin: 7px 0 7px 0;\r
+       padding: 14px;\r
+}\r
+\r
+fieldset legend {\r
+       padding: 0 7px 0 7px;\r
+}\r
+\r
+fieldset p.description {\r
+       color: #777;\r
+       font-size: 90%;\r
+}\r
+\r
+fieldset > ul {\r
+       margin: 7px 0 21px 21px;\r
+}\r
+\r
+fieldset > ul li {\r
+       list-style-type: circle;\r
+}\r
+\r
+div.formElement {\r
+       clear: both;\r
+       margin-bottom: 14px;\r
+}\r
+\r
+div.formFieldLabel {\r
+       float: left;\r
+       text-align: right;\r
+       width: 230px;\r
+}\r
+\r
+div.formField {\r
+       margin-left: 250px;\r
+}\r
+\r
+div.formFieldDesc {\r
+       color: #777;\r
+       font-size: 90%;\r
+       margin: 3px 0 7px 250px;\r
+}\r
+\r
+div.formGroupLabel label {\r
+       display: none;\r
+}\r
+\r
+div.formGroupField div.formField label {\r
+       display: block;\r
+}\r
+\r
+.border {\r
+       border: 1px solid #ccc;\r
+       border-radius: 5px;\r
+       margin: 14px 0 14px 0;\r
+}\r
+\r
+.borderMarginRemove {\r
+       border-radius: 0 0 5px 5px;\r
+       margin-top: 0;\r
+}\r
+\r
+.titleBarPanel {\r
+       background-color: #eee;\r
+       border-radius: 5px 5px 0 0;\r
+       border-bottom-width: 0;\r
+       margin-bottom: 0;\r
+       padding: 7px;\r
+}\r
+\r
+.tabMenuContent,\r
+.content {\r
+       border-width: 0 !important;\r
+}\r
+\r
+table {\r
+       border-radius: 0 0 5px 5px;\r
+       width: 100% !important;\r
+}\r
+\r
+th {\r
+       background-color: #fefefe;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#fefefe, #eee);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#fefefe, #eee);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#fefefe), to(#eee));\r
+       \r
+       border-right: 1px solid #fff;\r
+       border-bottom: 1px solid #fff;\r
+       padding: 7px;\r
+}\r
+\r
+th.active {\r
+       background-color: #faebd7;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#faebd7, #fa0);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#faebd7, #fa0);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#faebd7), to(#fa0));\r
+}\r
+\r
+th.active:hover {\r
+       background-color: #fa0;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#fa0, #faebd7);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#fa0, #faebd7);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#fa0), to(#faebd7));\r
+}\r
+\r
+th:hover {\r
+       background-color: #fefefe;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#eee, #fefefe);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#eee, #fefefe);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#eee), to(#fefefe));\r
+}\r
+\r
+th:last-child {\r
+       border-right-width: 0;\r
+}\r
+\r
+th a {\r
+       display: block;\r
+       text-decoration: none;\r
+}\r
+\r
+th a:hover {\r
+       color: #00c !important;\r
+       text-decoration: none !important;\r
+}\r
+\r
+td {\r
+       border-right: 1px solid #fff;\r
+       padding: 5px;\r
+}\r
+\r
+td:last-child {\r
+       border-right-width: 0;\r
+}\r
+\r
+tbody tr {\r
+       border-bottom: 1px solid #fff;\r
+}\r
+\r
+tbody tr:last-child {\r
+       border-bottom-width: 0;\r
+}\r
+\r
+tr.container-1:hover td,\r
+tr.container-2:hover td {\r
+       background-color: #ddd;\r
+}\r
+\r
+tr.container-1 td {\r
+       background-color: #fefefe;\r
+}\r
+\r
+tr.container-2 td {\r
+       background-color: #eee;\r
+}\r
+\r
+.pageNavigation ul li {\r
+       display: inline-block;\r
+}\r
+\r
+.pageNavigation ul li:not(.skip) {\r
+       background-color: #eee;\r
+       border: 1px solid #ccc;\r
+       padding: 3px;\r
+}\r
+\r
+.pageNavigation ul li.active,\r
+.pageNavigation ul li:not(.skip):hover {\r
+       background-color: #faebd7;\r
+       border-color: #ff8800;\r
+       color: #ff8800;\r
+}\r
+\r
+.pageNavigation ul li a {\r
+       text-decoration: none;\r
+}\r
+\r
+.pageNavigation ul li:not(.skip):hover a {\r
+       color: #ff8800;\r
+}\r
+\r
+.pageNavigation ul li.skip {\r
+       vertical-align: middle;\r
+}\r
+\r
+div.largeButtons {\r
+       text-align: right;\r
+}\r
+\r
+div.largeButtons ul li {\r
+       display: inline;\r
+}\r
+\r
+input[type='reset'],\r
+input[type='submit'],\r
+div.largeButtons ul li a {\r
+       background-color: #fefefe;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#fefefe, #eee);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#fefefe, #eee);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#fefefe), to(#eee));\r
+       \r
+       border: 1px solid #ccc;\r
+       border-radius: 10px;\r
+       display: inline-block;\r
+       padding: 7px;\r
+}\r
+\r
+input[type='reset']:hover,\r
+input[type='submit']:hover,\r
+div.largeButtons ul li a:hover {\r
+       background-color: #fefefe;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#eee, #fefefe);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#eee, #fefefe);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#eee), to(#fefefe));\r
+       \r
+       text-decoration: none;\r
+}\r
+\r
+div.largeButtons ul li a img {\r
+       vertical-align: middle;\r
+}\r
+\r
+div.formSubmit {\r
+       text-align: center;\r
+}\r
+\r
+input[type='reset'],\r
+input[type='submit'] {\r
+       cursor: pointer;\r
+}\r
+\r
+div#packageInstallationDialogContainer {\r
+       background-color: #fefefe;\r
+       \r
+       /* Opera */\r
+       background: -o-linear-gradient(#fefefe, #eee);\r
+       \r
+       /* Fuckyoufox */\r
+       background: -moz-linear-gradient(#fefefe, #eee);\r
+       \r
+       /* Chrome/Safari */\r
+       background: -webkit-gradient(linear, center top, center bottom, from(#fefefe), to(#eee));\r
+       \r
+       height: 100%;\r
+       max-width: 600px;\r
+       padding: 21px;\r
+}\r
+\r
+div#ajaxExceptionStacktrace {\r
+       overflow: scroll;\r
+       overflow-y: hidden;\r
+       white-space: nowrap;\r
+}\r
+\r
+div#packageInstallationInnerContentContainer {\r
+       border-top: 2px solid #999 !important;\r
+       border-radius: 0 !important;\r
+       margin-top: 21px;\r
+       padding-top: 14px;\r
+}\r
+\r
+div#packageInstallationInnerContent p.error {\r
+       background-color: #fdd;\r
+       border: 3px solid #ed1c24;\r
+       border-radius: 5px;\r
+       margin-bottom: 14px;\r
+       padding: 7px;\r
+}\r
+\r
+div#ajaxExceptionStacktrace {\r
+       border: 1px solid #ccc;\r
+       font-family: monospace;\r
+       font-size: 90%;\r
+       line-height: 1.2em;\r
+       padding: 3px;\r
+}\r
+\r
+p.success {\r
+       background-color: #b5e61d;\r
+       border: 1px solid #22b14c;\r
+       border-radius: 5px;\r
+       margin-bottom: 14px;\r
+       padding: 7px;\r
+}\r
+\r
+hr {\r
+       display: none;\r
+}\r
+\r
+#actionProxyLoading {\r
+       background-color: #faebd7;\r
+       border: 1px solid #f80;\r
+       border-top-width: 0;\r
+       border-radius: 0 0 5px 5px;\r
+       left: 43%;\r
+       padding: 7px 21px 7px 21px;\r
+       position: fixed;\r
+       top: 0;\r
+}\r
+\r
+fieldset legend ~ p {\r
+       margin-bottom: 14px;\r
+}\r
+\r
+dl {\r
+       clear: both;\r
+       margin-bottom: 7px;\r
+}\r
+\r
+dt /* is op */ {\r
+       float: left;\r
+       text-align: right;\r
+       width: 230px;\r
+}\r
+\r
+dd {\r
+       margin-left: 250px;\r
+}\r
+\r
+dl dd ~ p {\r
+       color: #777;\r
+       font-size: 90%;\r
+       margin: 3px 0 7px 250px;\r
+}\r
+\r
+dl.disabled dt {\r
+       color: #777;\r
+}\r
+\r
+/* Taken from jQuery UI @ themes/base/jquery.ui.tabs.css */\r
+.ui-tabs {\r
+       position: relative; /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */\r
+       padding: 3px;\r
+       zoom: 1;\r
+}\r
+.ui-tabs .ui-tabs-nav {\r
+       height: 18px !important; /* Fix for some cruel clearing problem */\r
+       margin: 0 0 0 14px;\r
+       \r
+       background-color: none;\r
+       padding: 3px 3px 0;\r
+}\r
+.ui-tabs .ui-tabs-nav li {\r
+       list-style: none;\r
+       float: left;\r
+       position: relative;\r
+       top: 1px;\r
+       margin: 0 3px 1px 0;\r
+       border-bottom: 0 !important;\r
+       padding: 0;\r
+       white-space: nowrap;\r
+       z-index: 90; /* Prevent border overlay during transition */\r
+}\r
+.ui-tabs .ui-tabs-nav li a {\r
+       background-color: #fefefe;\r
+       background: -o-linear-gradient(#fefefe, #eee);\r
+       border: 1px solid #ccc;\r
+       border-bottom-width: 0;\r
+       border-radius: 10px 10px 0 0;\r
+       \r
+       float: left;\r
+       padding: 7px 14px;\r
+       text-decoration: none;\r
+}\r
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected {\r
+       margin-bottom: 0;\r
+       padding-bottom: 1px;\r
+}\r
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a {\r
+       background-color: #fefefe;\r
+       background: -o-linear-gradient(#eee, #fefefe);\r
+       border-bottom: 1px solid #fefefe;\r
+}\r
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a,\r
+.ui-tabs .ui-tabs-nav li.ui-state-disabled a,\r
+.ui-tabs .ui-tabs-nav li.ui-state-processing a {\r
+       cursor: default;\r
+}\r
+.ui-tabs .ui-tabs-nav li a,\r
+.ui-tabs .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a {\r
+       cursor: pointer;\r
+}\r
+.ui-tabs .ui-tabs-panel {\r
+       background-color: #fefefe;\r
+       border: 1px solid #ccc !important;\r
+       z-index: 89; /* Prevent border overlay during transition */\r
+       \r
+       display: block;\r
+       padding: 14px 21px;\r
+}\r
+.ui-tabs .ui-tabs-hide {\r
+       display: none !important;\r
+}\r
+\r
+.ui-helper-hidden { display: none; }\r
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }\r
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }\r
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }\r
+.ui-helper-clearfix { display: inline-block; }\r
+/* required comment for clearfix to work in Opera \*/\r
+* html .ui-helper-clearfix { height:1%; }\r
+.ui-helper-clearfix { display:block; }\r
+/* end clearfix */\r
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/style/wcfAcp.css b/wcfsetup/install/files/acp/style/wcfAcp.css
new file mode 100644 (file)
index 0000000..851ea39
--- /dev/null
@@ -0,0 +1,455 @@
+\r
+/* ### -- -- -- -- -- ACP Special Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: acp.css \r
+Copyright 2006-2010 by WoltLab GmbH. \r
+\r
+*/\r
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */\r
+\r
+body, html {\r
+       background-color: #fff;\r
+       background-image: url("../images/WoltLab Blue Sunrise/body-ltr.png");\r
+       background-position: left;\r
+       background-repeat: repeat-y;\r
+       background-attachment: scroll;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+#content {\r
+       padding: 30px 0 20px 180px;\r
+       min-width: 800px;\r
+       max-width: 75%;\r
+}\r
+\r
+.userPanelInner, #header, #menuBar .mainMenuInner {\r
+       margin: 0;\r
+       padding: 0;\r
+       width: 100%;\r
+       min-width: 100%;\r
+       max-width: 100%;\r
+}\r
+\r
+#userNote {\r
+       padding-left: 23px;     \r
+}\r
+\r
+.logoInner {\r
+       padding-left: 5px;      \r
+}\r
+\r
+#date {\r
+       padding: 10px 23px 3px 5px;\r
+       position: absolute;\r
+       right: 0;\r
+}\r
+\r
+#header {\r
+       background-color: transparent !important;\r
+}\r
+\r
+#logo .pageLogo img {\r
+       margin-left: 20px;\r
+}\r
+\r
+h1 {\r
+       text-shadow: 0 -1px 1px #000;\r
+}\r
+\r
+#logo h1{\r
+       font-family: 'Trebuchet MS', Arial, sans-serif;\r
+       text-align: right;\r
+       position: absolute;\r
+       top: 0;\r
+       left: 0;\r
+}\r
+\r
+#logo h1, #logo h1 a{\r
+       color: #fff;\r
+}\r
+\r
+#logo h1 a{\r
+       padding-top: 35px;\r
+       padding-right: 23px;\r
+}\r
+\r
+#logo h1{\r
+       font-size: 1.5em;\r
+       font-weight: bold;\r
+}\r
+\r
+h2, h2 a {\r
+       text-shadow: 0 2px 3px #bbb;\r
+}\r
+\r
+#tplStyleList .styleList .subHeadline {\r
+       text-shadow: 0 1px 0 #fff;\r
+}\r
+\r
+#tplStyleList .styleList .messageBody {\r
+       padding-top: 0;\r
+}\r
+\r
+#footer {\r
+       margin: 0;\r
+       width: 100%;\r
+       min-width: 100%;\r
+       max-width: 100%;\r
+}\r
+\r
+#footer:after {\r
+       display: block;\r
+       clear: both;\r
+       content: "";\r
+       height: 0;\r
+}\r
+\r
+#footerContainer {\r
+       background-color: transparent;\r
+       margin: 0 0 0 180px;\r
+       min-width: 800px;\r
+       max-width: 75%;\r
+}\r
+\r
+.contentHeader form.quickJump div {\r
+       margin-top: 5px;\r
+       float: left;\r
+       display: inline;\r
+}\r
+\r
+.copyright {\r
+       padding-top: 5px;\r
+       float: left;\r
+       clear: none;\r
+}\r
+\r
+/* ### -- -- -- -- -- Sidebar -- -- -- -- -- ### */\r
+\r
+#sidebar {\r
+       background-color: transparent;\r
+       background-image: url("../images/WoltLab Blue Sunrise/sidebar.png");\r
+       background-repeat: repeat-x;\r
+       background-position: left top;\r
+       border-right: 1px solid #8da4b7;\r
+       position: absolute;\r
+       left: 0;\r
+       width: 129px;\r
+       min-height: 400px;\r
+}\r
+\r
+#sidebar ul {\r
+       list-style: none;\r
+       margin: 0 0 0 8px;\r
+       padding: 0;\r
+}\r
+\r
+#sidebar li {\r
+       text-align: center;\r
+       margin: 10px 0 0 0;\r
+       float: left;\r
+       width: 114px;\r
+}\r
+\r
+#sidebar a {\r
+       text-align: center;\r
+       text-decoration: none;\r
+       float: left;\r
+       clear: left;\r
+       width: 100%;\r
+}\r
+\r
+#sidebar img {\r
+       margin: 14px auto 3px auto;\r
+       height: 48px;\r
+       width: 48px;\r
+       display: block;\r
+}\r
+\r
+#sidebar span {\r
+       font-weight: bold;\r
+       text-shadow: 0 1px 0 #fff;\r
+       padding: 0 0 10px 0;\r
+       display: block;\r
+}\r
+\r
+#sidebar li:hover {\r
+       background-image: url("../images/WoltLab Blue Sunrise/sidebarHoverTop.png");\r
+       background-position: left top;\r
+       background-repeat: no-repeat;\r
+}\r
+\r
+#sidebar li:hover span {\r
+       background-image: url("../images/WoltLab Blue Sunrise/sidebarHoverBottom.png");\r
+       background-position: left bottom;\r
+}\r
+\r
+#sidebar li:active, #sidebar li.active {\r
+       background-image: url("../images/WoltLab Blue Sunrise/sidebarActiveTop.png");\r
+       background-repeat: no-repeat;\r
+}\r
+\r
+#sidebar li:active span, #sidebar li.active span {\r
+       color: #fff;\r
+       text-shadow: 0 -1px 0 #000;\r
+       background-image: url("../images/WoltLab Blue Sunrise/sidebarActiveBottom.png");\r
+       background-position: left bottom;\r
+}\r
+\r
+/* ### -- -- -- -- -- Menu -- -- -- -- -- ### */\r
+\r
+/* ToDo: Clean up this mess */\r
+\r
+#menuBar {\r
+       min-height: 31px;\r
+}\r
+\r
+#menuBar .mainMenuInner > ul {\r
+       padding-left: 129px;    \r
+}\r
+\r
+.mainMenu {\r
+       border: 0;      \r
+}\r
+\r
+.mainMenu a {\r
+       padding: 2px 5px 4px 5px;\r
+}\r
+\r
+.mainMenu ul {\r
+       margin: 0;\r
+}\r
+\r
+.mainMenu .mainMenuInner > ul > li > a {\r
+       min-height: 24px;\r
+}\r
+\r
+.mainMenu .mainMenuInner > ul > li > a > span {\r
+       padding: 2px 5px;\r
+       display: block;\r
+}\r
+\r
+.mainMenu .popupMenu {\r
+       border-top-width: 0;    \r
+}\r
+\r
+.mainMenu .popupMenu a {\r
+       color: #164369;\r
+       text-shadow: none !important;\r
+       background-color: #154268;\r
+       background-image: none !important;\r
+       min-height: 20px;\r
+}\r
+\r
+.mainMenu .popupMenu a:hover {\r
+       background-color: #ffe0b8;\r
+}\r
+\r
+#menuBar span {\r
+       position: relative;\r
+       top: 4px;\r
+}\r
+\r
+#menuBar li div span {\r
+       position: relative;\r
+       top: 0;\r
+}\r
+\r
+/* #### -- -- -- -- -- Sitemap -- -- -- -- -- #### */\r
+\r
+.sitemap {\r
+       padding: 20px 0 20px 180px;\r
+       width: 800px;\r
+}\r
+\r
+.sitemap ul {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+       min-height: 0;\r
+}\r
+\r
+.sitemap h2 img {\r
+       margin-right: 7px;\r
+}\r
+\r
+.sitemap h2 {\r
+       padding: 20px 0 10px 0;\r
+}\r
+\r
+.sitemap h3 {\r
+       margin-bottom: 5px;\r
+}\r
+\r
+.sitemap h4, .sitemap h5  {\r
+       padding: 5px 0;\r
+}\r
+\r
+.sitemap h4 img, .sitemap h5 img  {\r
+       position: absolute;\r
+}\r
+\r
+.sitemap h4 a, .sitemap h4 span, .sitemap h5 a, .sitemap h5 span {\r
+       margin-left: 30px;\r
+       display: block;\r
+}\r
+\r
+.sitemap .border {\r
+       padding-bottom: 1px;\r
+}\r
+\r
+.sitemap .container-1 {\r
+       margin-right: 1px;\r
+       padding: 4px;\r
+}\r
+\r
+.sitemap .sitemapDepth-1 li {\r
+       margin-right: 2%;\r
+       float: left;\r
+       width: 30%;\r
+}\r
+\r
+.sitemap .sitemapDepth-1:after {\r
+       content: "";\r
+       display: block;\r
+       clear: both;\r
+       height: 0;\r
+}\r
+\r
+.sitemap .sitemapDepth-2 li {\r
+       float: none;\r
+       width: auto;\r
+}\r
+\r
+.sitemap .clear {\r
+       clear: both;\r
+}\r
+\r
+/* ### -- -- -- -- Access Rights -- -- -- -- ### */\r
+\r
+.allow, .deny {\r
+       font-size: .85em;\r
+       font-weight: normal;\r
+       text-align: center;\r
+       float: right;\r
+       width: 80px;\r
+       height: 10px;\r
+}\r
+\r
+.accessRightsHeader {\r
+       margin-right: 20px;\r
+       min-height: 20px;\r
+}\r
+\r
+.accessRights {\r
+       border: 1px solid #999;\r
+       margin: 0;\r
+       padding: 0;\r
+       height: auto;\r
+       min-height: 100px;\r
+       overflow: auto;\r
+}\r
+\r
+.accessRights ul {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.accessRights ul li {\r
+       min-height: 0;\r
+}\r
+\r
+.formField .accessRights li span {\r
+       margin-left: 0;\r
+       float: none;\r
+}\r
+\r
+.accessRights ul li span {\r
+       padding: 2px 4px;\r
+       display: block;\r
+       vertical-align: middle;\r
+}\r
+\r
+.accessRights ul li a {\r
+       text-decoration: none;\r
+       padding: 2px 4px;\r
+       display: block;\r
+}\r
+\r
+.accessRights ul li a:hover {\r
+       background-color: #d8e7f5;\r
+}\r
+\r
+.accessRights ul li.selected a {\r
+       background-color: #8da4b7;\r
+}\r
+\r
+.accessRights ul li a img {\r
+       padding-right: 4px;\r
+       vertical-align: middle;\r
+}\r
+\r
+.accessRights ul li a.remove {\r
+       float: right;\r
+       display: inline;\r
+}\r
+\r
+.accessRights ul li a.remove:hover {\r
+       background-color: #c00;\r
+}\r
+\r
+.accessRights ul li a.remove img {\r
+       padding-right: 0;\r
+}\r
+\r
+.formField .accessRights label {\r
+       clear: none;\r
+}\r
+\r
+.accessRightsInput {\r
+       width: 300px !important;\r
+}\r
+\r
+.accessRightsTitle {\r
+       margin-top: 20px;\r
+}\r
+\r
+#permissions-content div.popupMenu a, #permissions-content div.popupMenu a:hover, #moderators-content div.popupMenu a, #moderators-content div.popupMenu a:hover, #tplGroupAdd div.popupMenu a, #tplGroupAdd div.popupMenu a:hover {\r
+       padding: 5px 7px 5px 35px !important;\r
+}\r
+\r
+/* ### -- -- -- -- Special Styles -- -- -- -- ### */\r
+\r
+* {-o-text-overflow: ellipsis;}\r
+\r
+.sitemap .container-1 {\r
+       -webkit-border-bottom-left-radius: 5px;\r
+       -webkit-border-bottom-right-radius: 5px;\r
+       -moz-border-radius-bottomleft: 5px;\r
+       -moz-border-radius-bottomright: 5px;\r
+       \r
+       border-bottom-left-radius: 5px;\r
+       border-bottom-right-radius: 5px;\r
+}\r
+\r
+.mainMenu .popupMenu, .mainMenu .popupMenu li a {\r
+       -webkit-border-top-left-radius: 0;\r
+       -webkit-border-top-right-radius: 0;\r
+       -moz-border-radius-topleft: 0;\r
+       -moz-border-radius-topright: 0;\r
+       \r
+       border-top-left-radius: 0;\r
+       border-top-right-radius: 0;\r
+}\r
+\r
+.sitemap .border {\r
+       -webkit-border-radius: 5px;\r
+       -moz-border-radius: 5px;\r
+       \r
+       border-radius: 5px;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/acp/templates/.htaccess b/wcfsetup/install/files/acp/templates/.htaccess
new file mode 100644 (file)
index 0000000..3418e55
--- /dev/null
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/acpSessionLog.tpl b/wcfsetup/install/files/acp/templates/acpSessionLog.tpl
new file mode 100644 (file)
index 0000000..f437813
--- /dev/null
@@ -0,0 +1,57 @@
+{include file='header'}
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/sessionLogL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.sessionLog.access.view{/lang}</h2>
+       </div>
+</div>
+
+<div class="contentHeader">
+       {pages print=true assign=pagesLinks link="index.php?page=ACPSessionLog&sessionLogID=$sessionLogID&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}
+</div>
+
+{if $sessionAccessLogs|count}
+       <div class="border titleBarPanel">
+               <div class="containerHead"><h3>{lang}wcf.acp.sessionLog.access.view.count{/lang}</h3></div>
+       </div>
+       <div class="border borderMarginRemove">
+               <table class="tableList">
+                       <thead>
+                               <tr class="tableHead">
+                                       <th class="columnSessionAccessLogID{if $sortField == 'sessionAccessLogID'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=sessionAccessLogID&amp;sortOrder={if $sortField == 'sessionAccessLogID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.sessionAccessLogID{/lang}{if $sortField == 'sessionAccessLogID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnIpAddress{if $sortField == 'ipAddress'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=ipAddress&amp;sortOrder={if $sortField == 'ipAddress' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.ipAddress{/lang}{if $sortField == 'ipAddress'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnTime{if $sortField == 'time'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=time&amp;sortOrder={if $sortField == 'time' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.time{/lang}{if $sortField == 'time'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnPackageName{if $sortField == 'packageName'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=packageName&amp;sortOrder={if $sortField == 'packageName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.packageName{/lang}{if $sortField == 'packageName'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnClassName{if $sortField == 'className'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=className&amp;sortOrder={if $sortField == 'className' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.className{/lang}{if $sortField == 'className'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnRequestURI{if $sortField == 'requestURI'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=requestURI&amp;sortOrder={if $sortField == 'requestURI' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.requestURI{/lang}{if $sortField == 'requestURI'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnRequestMethod{if $sortField == 'requestMethod'} active{/if}"><div><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLogID}&amp;pageNo={@$pageNo}&amp;sortField=requestMethod&amp;sortOrder={if $sortField == 'requestMethod' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.requestMethod{/lang}{if $sortField == 'requestMethod'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       
+                                       {if $additionalColumnHeads|isset}{@$additionalColumnHeads}{/if}
+                               </tr>
+                       </thead>
+                       <tbody>
+                       {foreach from=$sessionAccessLogs item=sessionAccessLog}
+                               <tr class="{cycle values="container-1,container-2"} smallFont">
+                                       <td class="columnSessionAccessLogID columnID">{@$sessionAccessLog->sessionAccessLogID}</td>
+                                       <td class="columnIpAddress columnText"{if $sessionAccessLog->ipAddress != $sessionLog->ipAddress} style="color: red"{/if}>{$sessionAccessLog->ipAddress}</td>
+                                       <td class="columnTime columnText">{@$sessionAccessLog->time|time}</td>
+                                       <td class="columnPackageName columnText">{$sessionAccessLog->packageName}</td>
+                                       <td class="columnClassName columnText">{$sessionAccessLog->className}</td>
+                                       <td class="columnRequestURI columnText" title="{$sessionAccessLog->requestURI}">{if !$sessionAccessLog->hasProtectedURI()}<a href="{$sessionAccessLog->requestURI}{@SID_ARG_2ND}">{$sessionAccessLog->requestURI|truncate:50}</a>{else}{$sessionAccessLog->requestURI|truncate:50}{/if}</td>
+                                       <td class="columnRequestMethod columnText">{$sessionAccessLog->requestMethod}</td>
+                                       
+                                       {if $additionalColumns.$sessionAccessLog->sessionAccessLogID|isset}{@$additionalColumns.$sessionAccessLog->sessionAccessLogID}{/if}
+                               </tr>
+                       {/foreach}
+                       </tbody>
+               </table>
+       </div>
+
+       <div class="contentFooter">
+               {@$pagesLinks}
+       </div>
+{/if}
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/acpSessionLogList.tpl b/wcfsetup/install/files/acp/templates/acpSessionLogList.tpl
new file mode 100644 (file)
index 0000000..06ce005
--- /dev/null
@@ -0,0 +1,57 @@
+{include file='header'}
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/sessionLogL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.sessionLog.view{/lang}</h2>
+       </div>
+</div>
+
+<div class="contentHeader">
+       {pages print=true assign=pagesLinks link="index.php?page=ACPSessionLogList&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}
+</div>
+
+{if $sessionLogs|count}
+       <div class="border titleBarPanel">
+               <div class="containerHead"><h3>{lang}wcf.acp.sessionLog.view.count{/lang}</h3></div>
+       </div>
+       <div class="border borderMarginRemove">
+               <table class="tableList">
+                       <thead>
+                               <tr class="tableHead">
+                                       <th class="columnSessionLogID{if $sortField == 'sessionLogID'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=sessionLogID&amp;sortOrder={if $sortField == 'sessionLogID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.sessionLogID{/lang}{if $sortField == 'sessionLogID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnUsername{if $sortField == 'username'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=username&amp;sortOrder={if $sortField == 'username' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.user.username{/lang}{if $sortField == 'username'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnIpAddress{if $sortField == 'ipAddress'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=ipAddress&amp;sortOrder={if $sortField == 'ipAddress' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.ipAddress{/lang}{if $sortField == 'ipAddress'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnUserAgent{if $sortField == 'userAgent'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=userAgent&amp;sortOrder={if $sortField == 'userAgent' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.userAgent{/lang}{if $sortField == 'userAgent'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnTime{if $sortField == 'time'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=time&amp;sortOrder={if $sortField == 'time' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.time{/lang}{if $sortField == 'time'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnLastActivityTime{if $sortField == 'lastActivityTime'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=lastActivityTime&amp;sortOrder={if $sortField == 'lastActivityTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.lastActivityTime{/lang}{if $sortField == 'lastActivityTime'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnAccesses{if $sortField == 'accesses'} active{/if}"><div><a href="index.php?page=ACPSessionLogList&amp;pageNo={@$pageNo}&amp;sortField=accesses&amp;sortOrder={if $sortField == 'accesses' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.sessionLog.accesses{/lang}{if $sortField == 'accesses'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       
+                                       {if $additionalColumnHeads|isset}{@$additionalColumnHeads}{/if}
+                               </tr>
+                       </thead>
+                       <tbody>
+                       {foreach from=$sessionLogs item=sessionLog}
+                               <tr class="{cycle values="container-1,container-2"}{if $sessionLog->active} activeContainer{/if}">
+                                       <td class="columnSessionLogID columnID">{@$sessionLog->sessionLogID}</td>
+                                       <td class="columnUsername columnText">{if $__wcf->user->userID == $sessionLog->userID}<img src="{@RELATIVE_WCF_DIR}icon/userS.png" alt="" />{/if} <a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLog->sessionLogID}{@SID_ARG_2ND}">{$sessionLog->username}</a></td>
+                                       <td class="columnIpAddress columnText"><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLog->sessionLogID}{@SID_ARG_2ND}">{$sessionLog->ipAddress}</a><br /><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLog->sessionLogID}{@SID_ARG_2ND}">{$sessionLog->hostname}</a></td>
+                                       <td class="columnUserAgent columnText smallFont"><a href="index.php?page=ACPSessionLog&amp;sessionLogID={@$sessionLog->sessionLogID}{@SID_ARG_2ND}">{$sessionLog->userAgent}</a></td>
+                                       <td class="columnTime columnText">{@$sessionLog->time|time}</td>
+                                       <td class="columnLastActivityTime columnText">{@$sessionLog->lastActivityTime|time}</td>
+                                       <td class="columnAccesses columnNumbers">{#$sessionLog->accesses}</td>
+                                       
+                                       {if $additionalColumns.$sessionLog->sessionLogID|isset}{@$additionalColumns.$sessionLog->sessionLogID}{/if}
+                               </tr>
+                       {/foreach}
+                       </tbody>
+               </table>
+       </div>
+
+       <div class="contentFooter">
+               {@$pagesLinks}
+       </div>
+{/if}
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/ajaxException.tpl b/wcfsetup/install/files/acp/templates/ajaxException.tpl
new file mode 100644 (file)
index 0000000..147a1de
--- /dev/null
@@ -0,0 +1,3 @@
+<p class="error">{$message}</p>
+<!--<img src="{@RELATIVE_WCF_DIR}icon/plusS.png" alt="" /> <span>Stacktrace</span>-->
+<div id="ajaxExceptionStacktrace"><pre>{$stacktrace}</pre></div> 
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/cacheList.tpl b/wcfsetup/install/files/acp/templates/cacheList.tpl
new file mode 100644 (file)
index 0000000..9722809
--- /dev/null
@@ -0,0 +1,90 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/cacheL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.cache.list{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $cleared}\r
+       <p class="success">{lang}wcf.acp.cache.clear.success{/lang}</p> \r
+{/if}\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.acp.cache.data{/lang}</legend>\r
+       \r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.cache.data.source{/lang}</p>\r
+               <p class="formField">{$cacheData.source}</p>\r
+       </div>\r
+       {if $cacheData.version}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.cache.data.version{/lang}</p>\r
+                       <p class="formField">{$cacheData.version}</p>\r
+               </div>\r
+       {/if}\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.cache.data.size{/lang}</p>\r
+               <p class="formField">{@$cacheData.size|filesize}</p>\r
+       </div>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.cache.data.files{/lang}</p>\r
+               <p class="formField">{#$cacheData.files}</p>\r
+       </div>\r
+       \r
+       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+</fieldset>\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a onclick="return confirm('{lang}wcf.acp.cache.clear.sure{/lang}')" href="index.php?action=CacheClear{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/deleteM.png" alt="" /> <span>{lang}wcf.acp.cache.button.clear{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+\r
+{foreach from=$caches key=cache item=files}\r
+       {if $files|count}\r
+               <div class="border titleBarPanel">\r
+                       <div class="containerHead">\r
+                               <div class="containerIcon">\r
+                                       <a onclick="openList('{$cache}')"><img src="{@RELATIVE_WCF_DIR}icon/minusS.png" id="{$cache}Image" alt="" /></a>\r
+                               </div>\r
+                               <div class="containerContent">\r
+                                       <h3>{$cache} ({#$files|count})</h3>\r
+                               </div>\r
+                       </div>\r
+               </div>\r
+               <div class="border borderMarginRemove" id="{$cache}">\r
+                       <table class="tableList">\r
+                               <thead>\r
+                                       <tr class="tableHead">\r
+                                               <th><div><span class="emptyHead">{lang}wcf.acp.cache.list.name{/lang}</span></div></th>\r
+                                               <th><div><span class="emptyHead">{lang}wcf.acp.cache.list.size{/lang}</span></div></th>\r
+                                               <th><div><span class="emptyHead">{lang}wcf.acp.cache.list.mtime{/lang}</span></div></th>\r
+                                               <th><div><span class="emptyHead">{lang}wcf.acp.cache.list.perm{/lang}</span></div></th>\r
+                                       </tr>\r
+                               </thead>\r
+                               <tbody>\r
+                               {foreach from=$files item=file}\r
+                                       <tr class="{cycle values="container-1,container-2"}">\r
+                                               <td class="columnText">{$file.filename}</td>\r
+                                               <td class="columnNumbers">{@$file.filesize|filesize}</td>\r
+                                               <td class="columnDate">{if $file.mtime > 1}{@$file.mtime|time}{/if}</td>\r
+                                               <td class="columnNumbers"{if !$file.writable} style="color: #c00"{/if}>{@$file.perm}</td>\r
+                                       </tr>\r
+                               {/foreach}\r
+                               </tbody>\r
+                       </table>\r
+               </div>\r
+               <script type="text/javascript">\r
+                       //<![CDATA[\r
+                       initList('{$cache}', 0);\r
+                       //]]>\r
+               </script>\r
+       {/if}\r
+{/foreach}\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/cronjobAdd.tpl b/wcfsetup/install/files/acp/templates/cronjobAdd.tpl
new file mode 100644 (file)
index 0000000..b09961b
--- /dev/null
@@ -0,0 +1,186 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/cronjobs{$action|ucfirst}L.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.cronjob.{$action}{/lang}</h2>\r
+               <p>{lang}wcf.acp.cronjob.subtitle{/lang}</p>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+{if $success|isset}\r
+       <p class="success">{lang}wcf.acp.cronjob.{$action}.success{/lang}</p>   \r
+{/if}\r
+\r
+<p class="info">{lang}wcf.acp.cronjob.intro{/lang}</p>\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?page=CronjobList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.cronjobs.view{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/cronjobsM.png" alt="" /> <span>{lang}wcf.acp.menu.link.cronjobs.view{/lang}</span></a></li>\r
+                       {if $action == 'edit'}<li><a href="index.php?action=CronjobExecute&amp;cronjobID={@$cronjobID}{@SID_ARG_2ND}" title="{lang}wcf.acp.cronjob.execute{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/cronjobExecuteM.png" alt="" /> <span>{lang}wcf.acp.cronjob.execute{/lang}</span></a></li>{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+<form method="post" action="index.php?form=Cronjob{$action|ucfirst}">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.cronjob.edit.data{/lang}</legend>\r
+                               \r
+                               <div class="formElement{if $errorField == 'className'} formError{/if}" id="classNameDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="className">{lang}wcf.acp.cronjob.className{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="className" name="className" value="{$className}" />\r
+                                               {if $errorField == 'className'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.acp.cronjob.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'doesNotExist'}{lang}wcf.acp.cronjob.error.doesNotExist{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="classNameHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.className.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('className');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement" id="descriptionDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="description">{lang}wcf.acp.cronjob.description{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="description" name="description" value="{$description}" />\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="descriptionHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.description.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('description');\r
+                               //]]></script>\r
+                       </fieldset>\r
+                       \r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.cronjob.edit.timing{/lang}</legend>\r
+                               <div class="formElement{if $errorField == 'startMinute'} formError{/if}" id="startMinuteDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="startMinute">{lang}wcf.acp.cronjob.startMinute{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="startMinute" name="startMinute" value="{$startMinute}" />\r
+                                               {if $errorField == 'startMinute'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.cronjob.error.notValid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="startMinuteHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.startMinute.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('startMinute');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'startHour'} formError{/if}" id="startHourDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="startHour">{lang}wcf.acp.cronjob.startHour{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="startHour" name="startHour" value="{$startHour}" />\r
+                                               {if $errorField == 'startHour'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.cronjob.error.notValid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="startHourHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.startHour.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('startHour');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'startDom'} formError{/if}" id="startDomDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="startDom">{lang}wcf.acp.cronjob.startDom{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="startDom" name="startDom" value="{$startDom}" />\r
+                                               {if $errorField == 'startDom'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.cronjob.error.notValid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="startDomHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.startDom.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('startDom');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'startMonth'} formError{/if}" id="startMonthDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="startMonth">{lang}wcf.acp.cronjob.startMonth{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="startMonth" name="startMonth" value="{$startMonth}" />\r
+                                               {if $errorField == 'startMonth'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.cronjob.error.notValid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="startMonthHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.startMonth.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('startMonth');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'startDow'} formError{/if}" id="startDowDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="startDow">{lang}wcf.acp.cronjob.startDow{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="startDow" name="startDow" value="{$startDow}" />\r
+                                               {if $errorField == 'startDow'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.cronjob.error.notValid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="startDowHelpMessage">\r
+                                               <p>{lang}wcf.acp.cronjob.startDow.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('startDow');\r
+                               //]]></script>\r
+                       </fieldset>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+               </div>\r
+       </div>\r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               {if $cronjobID|isset}<input type="hidden" name="cronjobID" value="{@$cronjobID}" />{/if}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/cronjobList.tpl b/wcfsetup/install/files/acp/templates/cronjobList.tpl
new file mode 100644 (file)
index 0000000..86004e9
--- /dev/null
@@ -0,0 +1,141 @@
+{include file='header'}
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/cronjobsL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.cronjob.list{/lang}</h2>
+               <p>{lang}wcf.acp.cronjob.subtitle{/lang}</p>
+       </div>
+       
+       <script type="text/javascript">
+               //<![CDATA[
+               $(function() {
+                       new WCF.Action.Delete('wcf\\data\\cronjob\\CronjobAction', $('.cronjobRow'));
+                       new WCF.Action.Toggle('wcf\\data\\cronjob\\CronjobAction', $('.cronjobRow'));
+                       new WCF.Action.SimpleProxy({
+                               action: 'execute',
+                               className: 'wcf\\data\\cronjob\\CronjobAction',
+                               elements: $('.cronjobRow .executeButton')
+                       }, {
+                               success: function(data, statusText, jqXHR) {
+                                       $('.cronjobRow').each(function(index, row) {
+                                               $button = $(row).find('.executeButton');
+                                               
+                                               if (WCF.inArray($($button).data('objectID'), data.objectIDs)) {
+                                                       // insert feedback here
+                                                       $(row).find('td.columnNextExec').html('...');
+                                                       $(row).wcfHighlight();
+                                               }
+                                       });
+                               }
+                       });
+               });
+               //]]>
+       </script>
+</div>
+
+<div class="contentHeader">
+       {pages print=true assign=pagesLinks link="index.php?page=CronjobList&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}
+       
+       {if $__wcf->session->getPermission('admin.system.cronjobs.canAddCronjob')}
+               <div class="largeButtons">
+                       <ul><li><a href="index.php?form=CronjobAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.cronjob.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/cronjobsAddM.png" alt="" /> <span>{lang}wcf.acp.cronjob.add{/lang}</span></a></li></ul>
+               </div>
+       {/if}
+</div>
+
+{if !$items}
+       <div class="border content">
+               <div class="container-1">
+                       <p>{lang}wcf.acp.cronjob.noneAvailable{/lang}</p>
+               </div>
+       </div>
+{else}
+       <div class="border titleBarPanel">
+               <div class="containerHead"><h3>{lang}wcf.acp.cronjob.list.count{/lang}</h3></div>
+       </div>
+       <div class="border borderMarginRemove">
+               <table class="tableList">
+                       <thead>
+                               <tr class="tableHead">
+                                       <th class="columnCronjobID{if $sortField == 'cronjobID'} active{/if}" colspan="2"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=cronjobID&amp;sortOrder={if $sortField == 'cronjobID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.cronjobID{/lang}{if $sortField == 'cronjobID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnStartMinute{if $sortField == 'startMinute'} active{/if}" title="{lang}wcf.acp.cronjob.startMinute{/lang}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=startMinute&amp;sortOrder={if $sortField == 'startMinute' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.startMinuteShort{/lang}{if $sortField == 'startMinute'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnStartHour{if $sortField == 'startHour'} active{/if}" title="{lang}wcf.acp.cronjob.startHour{/lang}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=startHour&amp;sortOrder={if $sortField == 'startHour' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.startHourShort{/lang}{if $sortField == 'startHour'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnStartDom{if $sortField == 'startDom'} active{/if}" title="{lang}wcf.acp.cronjob.startDom{/lang}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=startDom&amp;sortOrder={if $sortField == 'startDom' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.startDomShort{/lang}{if $sortField == 'startDom'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnStartMonth{if $sortField == 'startMonth'} active{/if}" title="{lang}wcf.acp.cronjob.startMonth{/lang}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=startMonth&amp;sortOrder={if $sortField == 'startMonth' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.startMonthShort{/lang}{if $sortField == 'startMonth'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnStartDow{if $sortField == 'startDow'} active{/if}" title="{lang}wcf.acp.cronjob.startDow{/lang}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=startDow&amp;sortOrder={if $sortField == 'startDow' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.startDowShort{/lang}{if $sortField == 'startDow'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnDescription{if $sortField == 'description'} active{/if}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=description&amp;sortOrder={if $sortField == 'description' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.description{/lang}{if $sortField == 'description'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnNextExec{if $sortField == 'nextExec'} active{/if}"><div><a href="index.php?page=CronjobList&amp;pageNo={@$pageNo}&amp;sortField=nextExec&amp;sortOrder={if $sortField == 'nextExec' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.nextExec{/lang}{if $sortField == 'nextExec'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       
+                                       {if $additionalHeadColumns|isset}{@$additionalHeadColumns}{/if}
+                               </tr>
+                       </thead>
+                       <tbody>
+                       {foreach from=$cronjobs item=cronjob}
+                               <tr class="cronjobRow {cycle values="container-1,container-2"}">
+                                       <td class="columnIcon">
+                                               {if $__wcf->session->getPermission('admin.system.cronjobs.canEditCronjob')}
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/cronjobExecuteS.png" alt="" class="executeButton" title="{lang}wcf.acp.cronjob.execute{/lang}" data-objectID="{@$cronjob->cronjobID}" />
+                                               {/if}
+                                               
+                                               {if $cronjob->canBeDisabled()}
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/{if $cronjob->active}enabled{else}disabled{/if}S.png" alt="" class="toggleButton" title="{lang}wcf.acp.cronjobs.{if $cronjob->active}disable{else}enable{/if}{/lang}" data-objectID="{@$cronjob->cronjobID}" data-disableMessage="{lang}wcf.acp.cronjob.disable{/lang}" data-enableMessage="{lang}wcf.acp.cronjob.enable{/lang}" />
+                                               {else}
+                                                       {if $cronjob->active}
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/enabledDisabledS.png" alt="" title="{lang}wcf.acp.cronjob.disable{/lang}" />
+                                                       {else}
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/disabledDisabledS.png" alt="" title="{lang}wcf.acp.cronjob.enable{/lang}" />
+                                                       {/if}
+                                               {/if}
+                                               
+                                               {if $cronjob->isEditable()}
+                                                       <a href="index.php?form=CronjobEdit&amp;cronjobID={@$cronjob->cronjobID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/editS.png" alt="" title="{lang}wcf.acp.cronjob.edit{/lang}" /></a>
+                                               {else}
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/editDisabledS.png" alt="" title="{lang}wcf.acp.cronjob.edit.disabled{/lang}" />
+                                               {/if}
+                                               {if $cronjob->isDeletable()}
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.cronjob.delete{/lang}" class="deleteButton" data-objectID="{@$cronjob->cronjobID}" data-confirmMessage="{lang}wcf.acp.cronjob.delete.sure{/lang}" />
+                                               {else}
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.cronjob.delete.disabled{/lang}" />
+                                               {/if}
+                                               {if $additionalButtons[$cronjob->cronjobID]|isset}{@$additionalButtons[$cronjob->cronjobID]}{/if}
+                                       </td>
+                                       <td class="columnID">{@$cronjob->cronjobID}</td>
+                                       <td class="columnStartMinute">{$cronjob->startMinute|truncate:30:' ...'}</td>
+                                       <td class="columnStartHour">{$cronjob->startHour|truncate:30:' ...'}</td>
+                                       <td class="columnStartDom">{$cronjob->startDom|truncate:30:' ...'}</td>
+                                       <td class="columnStartMonth">{$cronjob->startMonth|truncate:30:' ...'}</td>
+                                       <td class="columnStartDow">{$cronjob->startDow|truncate:30:' ...'}</td>
+                                       <td class="columnDescription columnText" title="{$cronjob->description}">
+                                               {if $cronjob->editable}
+                                                       <a title="{lang}wcf.acp.cronjob.edit{/lang}" href="index.php?form=CronjobEdit&amp;cronjobID={@$cronjob->cronjobID}{@SID_ARG_2ND}">{$cronjob->description|truncate:50:" ..."}</a>
+                                               {else}
+                                                       {$cronjob->description|truncate:50:' ...'}
+                                               {/if}
+                                       </td>
+                                       <td class="columnNextExec columnDate">
+                                               {if $cronjob->active && $cronjob->nextExec != 1}
+                                                       {@$cronjob->nextExec|plaintime}
+                                               {/if}
+                                       </td>
+                                       
+                                       {if $additionalColumns[$cronjob->cronjobID]|isset}{@$additionalColumns[$cronjob->cronjobID]}{/if}
+                               </tr>
+                       {/foreach}
+                       </tbody>
+               </table>
+       </div>
+       
+       <div class="contentFooter">
+               {@$pagesLinks}
+               
+               {if $__wcf->session->getPermission('admin.system.cronjobs.canAddCronjob')}
+                       <div class="largeButtons">
+                               <ul><li><a href="index.php?form=CronjobAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.cronjob.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/cronjobsAddM.png" alt="" /> <span>{lang}wcf.acp.cronjob.add{/lang}</span></a></li></ul>
+                       </div>
+               {/if}
+       </div>
+{/if}
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/cronjobLogList.tpl b/wcfsetup/install/files/acp/templates/cronjobLogList.tpl
new file mode 100644 (file)
index 0000000..2328099
--- /dev/null
@@ -0,0 +1,76 @@
+{include file='header'}\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/cronjobsLogL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.cronjob.log{/lang}</h2>\r
+               <p>{lang}wcf.acp.cronjob.subtitle{/lang}</p>\r
+       </div>\r
+</div>\r
+\r
+<div class="contentHeader">\r
+       {pages print=true assign=pagesLinks link="index.php?page=CronjobLogList&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}\r
+</div>\r
+\r
+{hascontent}\r
+       <form method="post" action="index.php?action=CronjobsLogDelete">\r
+               <div class="border titleBarPanel">\r
+                       <div class="containerHead"><h3>{lang}wcf.acp.cronjob.log.data{/lang}</h3></div>\r
+               </div>\r
+               <div class="border borderMarginRemove">\r
+                       <table class="tableList">\r
+                               <thead>\r
+                                       <tr class="tableHead">\r
+                                               <th class="columnCronjobID{if $sortField == 'cronjobID'} active{/if}"><div><a href="index.php?page=CronjobLogList&amp;pageNo={@$pageNo}&amp;sortField=cronjobID&amp;sortOrder={if $sortField == 'cronjobID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.cronjobID{/lang}{if $sortField == 'cronjobID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                               <th class="columnClassPath{if $sortField == 'classPath'} active{/if}"><div><a href="index.php?page=CronjobLogList&amp;pageNo={@$pageNo}&amp;sortField=classPath&amp;sortOrder={if $sortField == 'classPath' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.classPath{/lang}{if $sortField == 'classPath'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                               <th class="columnDescription{if $sortField == 'description'} active{/if}"><div><a href="index.php?page=CronjobLogList&amp;pageNo={@$pageNo}&amp;sortField=description&amp;sortOrder={if $sortField == 'description' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.description{/lang}{if $sortField == 'description'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                               <th class="columnExecTime{if $sortField == 'execTime'} active{/if}"><div><a href="index.php?page=CronjobLogList&amp;pageNo={@$pageNo}&amp;sortField=execTime&amp;sortOrder={if $sortField == 'execTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.cronjob.log.execTime{/lang}{if $sortField == 'execTime'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                               \r
+                                               {if $additionalColumns|isset}{@$additionalColumns}{/if}\r
+                                       </tr>\r
+                               </thead>\r
+                               <tbody>\r
+                               {content}\r
+                                       {foreach from=$cronjobLogs item=cronjobLog}\r
+                                               <tr class="{cycle values="container-1,container-2"}">\r
+                                                       <td class="columnCronjobID columnID">{@$cronjobLog->cronjobID}</td>\r
+                                                       <td class="columnClassPath columnText">{$cronjobLog->classPath}</td>\r
+                                                       <td class="columnDescription columnText">{$cronjobLog->description}</td>\r
+                                                       {if $cronjobLog->success}\r
+                                                               <td class="columnExecTime columnDate">{@$cronjobLog->execTime|time} {lang}wcf.acp.cronjob.log.success{/lang}</td>\r
+                                                       {elseif $cronjobLog->error}\r
+                                                               <td class="columnExecTime columnText">\r
+                                                                       {@$cronjobLog->execTime|time} {lang}wcf.acp.cronjob.log.error{/lang}<br />\r
+                                                                       {@$cronjobLog->error}\r
+                                                               </td>\r
+                                                       {else}\r
+                                                               <td class="columnExecTime columnText"></td>\r
+                                                       {/if}\r
+                                                       \r
+                                                       {if $cronjobLog->additionalColumns|isset}{@$cronjobLog->additionalColumns}{/if}\r
+                                               </tr>\r
+                                       {/foreach}\r
+                               {/content}\r
+                               </tbody>\r
+                       </table>\r
+               </div>\r
+               \r
+               <div class="formSubmit">\r
+                       {@SID_INPUT_TAG}\r
+                       <input type="submit" accesskey="c" value="{lang}wcf.acp.cronjob.log.clear{/lang}" onclick="return confirm('{lang}wcf.acp.cronjob.log.clear.confirm{/lang}')" />\r
+               </div>\r
+       </form>\r
+       \r
+       <div class="contentFooter">\r
+               {@$pagesLinks}\r
+       </div>\r
+{hascontentelse}\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <p>{lang}wcf.acp.cronjob.log.noEntries{/lang}</p>\r
+               </div>\r
+       </div>\r
+{/hascontent}\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/footer.tpl b/wcfsetup/install/files/acp/templates/footer.tpl
new file mode 100644 (file)
index 0000000..104f6a5
--- /dev/null
@@ -0,0 +1,15 @@
+               </div>\r
+       </div>\r
+       <!-- /CONTENT -->\r
+       \r
+       <!-- FOOTER -->\r
+       <footer>\r
+               <p class="copyright"><a href="http://www.woltlab.com" title="www.woltlab.com">&copy; WoltLab&reg; GmbH</a></p>\r
+               <nav id="footerNavigation">\r
+                       <ul>\r
+                               <li id="toTopLink"><a href="#top" title="{lang}wcf.global.scrollUp{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/upS.png" alt="{lang}wcf.global.scrollUp{/lang}" /> <span class="hidden">{lang}wcf.global.scrollUp{/lang}</span></a></li>\r
+                       </ul>\r
+               </nav>\r
+       </footer>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/header.tpl b/wcfsetup/install/files/acp/templates/header.tpl
new file mode 100644 (file)
index 0000000..b44bbc9
--- /dev/null
@@ -0,0 +1,127 @@
+<!DOCTYPE html>\r
+<html dir="{lang}wcf.global.pageDirection{/lang}" lang="{@LANGUAGE_CODE}">\r
+<head>\r
+       <meta charset="utf-8" />\r
+       <title>{if $pageTitle|isset}{@$pageTitle}{else}{lang}wcf.global.pageTitle{/lang}{/if} - {lang}wcf.acp{/lang}</title>\r
+       <meta http-equiv="X-UA-Compatible" content="IE=edge" />\r
+       <script type="text/javascript">\r
+               //<![CDATA[\r
+               var SID_ARG_2ND = '{@SID_ARG_2ND_NOT_ENCODED}';\r
+               var RELATIVE_WCF_DIR = '{@RELATIVE_WCF_DIR}';\r
+               var SECURITY_TOKEN = '{@SECURITY_TOKEN}';\r
+               //]]>\r
+       </script>\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/3rdParty/jquery.min.js"></script>\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/3rdParty/jquery-ui.min.js"></script>\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/WCF.js"></script>\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}acp/js/WCF.ACP.js"></script>\r
+       \r
+       {*\r
+       {if $specialStyles|isset}\r
+               <!-- special styles -->\r
+               {@$specialStyles}\r
+       {/if}\r
+       *}\r
+       \r
+       <!-- Testing stylesheets -->\r
+       <link rel="stylesheet" type="text/css" href="{@RELATIVE_WCF_DIR}acp/style/testing-reset.css" />\r
+       <link rel="stylesheet" type="text/css" href="{@RELATIVE_WCF_DIR}acp/style/testing.css" />\r
+       <!-- /Testing stylesheets -->\r
+       \r
+       {*\r
+       <style type="text/css">\r
+               @import url("{@RELATIVE_WCF_DIR}acp/style/style-{@PAGE_DIRECTION}.css");\r
+       </style>\r
+       \r
+       <!--[if IE 8]>\r
+               <style type="text/css">\r
+                       @import url("{@RELATIVE_WCF_DIR}style/extra/ie8-fix{if PAGE_DIRECTION == 'rtl'}-rtl{/if}.css");\r
+               </style>\r
+       <![endif]-->\r
+       *}\r
+       \r
+       <script type="text/javascript">\r
+               //<![CDATA[\r
+               $(function() {\r
+                       {* work-around for unknown core-object during WCFSetup *}\r
+                       {if PACKAGE_ID}\r
+                               {assign var=activeMenuItems value=$__wcf->getACPMenu()->getActiveMenuItems()|array_reverse}\r
+                               var $activeMenuItems = [{implode from=$activeMenuItems item=menuItem}'{$menuItem}'{/implode}];\r
+                               new WCF.ACP.Menu($activeMenuItems);\r
+                       {/if}\r
+                       \r
+                       WCF.Language.addObject({\r
+                               'wcf.global.date.relative.minutes': '{capture assign=relativeMinutes}{lang}wcf.global.date.relative.minutes{/lang}{/capture}{@$relativeMinutes|encodeJS}',\r
+                               'wcf.global.date.relative.hours': '{capture assign=relativeHours}{lang}wcf.global.date.relative.hours{/lang}{/capture}{@$relativeHours|encodeJS}',\r
+                               'wcf.global.date.relative.pastDays': '{capture assign=relativePastDays}{lang}wcf.global.date.relative.pastDays{/lang}{/capture}{@$relativePastDays|encodeJS}',\r
+                               'wcf.global.date.dateTimeFormat': '{lang}wcf.global.date.dateTimeFormat{/lang}',\r
+                               '__days': [ '{lang}wcf.global.date.day.sunday{/lang}', '{lang}wcf.global.date.day.monday{/lang}', '{lang}wcf.global.date.day.tuesday{/lang}', '{lang}wcf.global.date.day.wednesday{/lang}', '{lang}wcf.global.date.day.thursday{/lang}', '{lang}wcf.global.date.day.friday{/lang}', '{lang}wcf.global.date.day.saturday{/lang}' ]\r
+                       });\r
+                       new WCF.Date.Time();\r
+               });\r
+               //]]>\r
+       </script>\r
+</head>\r
+<body id="tpl{$templateName|ucfirst}">\r
+       <header>\r
+               <a id="top"></a>\r
+               \r
+               <!-- top nav -->\r
+               <!-- /top nav -->\r
+               \r
+               <!-- logo -->\r
+               <div id="logo">\r
+                       <a href="index.php{@SID_ARG_1ST}">\r
+                               <h1>WoltLab Community Framework 2.0 Pre-Alpha 1</h1>\r
+                               <img src="{@RELATIVE_WCF_DIR}acp/images/acpLogo.png" alt="WoltLab Community Framework 2.0 Pre-Alpha 1" />\r
+                       </a>\r
+               </div>\r
+               <!-- /logo -->\r
+               \r
+               <!-- top nav -->\r
+               <nav id="navigationTop">\r
+                       {* work-around for unknown core-object during WCFSetup *}\r
+                       {if PACKAGE_ID}\r
+                               <ul>\r
+                                       {foreach from=$__wcf->getACPMenu()->getMenuItems('') item=menuItem}\r
+                                               <li data-menuItem="{$menuItem->menuItem}">{lang}{@$menuItem->menuItem}{/lang}</li>\r
+                                       {/foreach}\r
+                               </ul>\r
+                       {/if}\r
+               </nav>\r
+               <!-- /top nav -->\r
+       </header>\r
+       \r
+       <!-- CONTENT -->\r
+       <div id="main">\r
+               <aside>\r
+                       <!-- sub nav -->\r
+                       <nav id="navigationSide">\r
+                               {* work-around for unknown core-object during WCFSetup *}\r
+                               {if PACKAGE_ID}\r
+                                       {foreach from=$__wcf->getACPMenu()->getMenuItems('') item=parentMenuItem}\r
+                                               <div class="menuContainer" data-parentMenuItem="{$parentMenuItem->menuItem}" id="{$parentMenuItem->menuItem}-container" style="display: none;">\r
+                                                       {foreach from=$__wcf->getACPMenu()->getMenuItems($parentMenuItem->menuItem) item=menuItem}\r
+                                                               <h3 data-menuItem="{$menuItem->menuItem}" class="menuHeader">{lang}{@$menuItem->menuItem}{/lang}</h3>\r
+                                                               <div>\r
+                                                                       <ul id="{$menuItem->menuItem}">\r
+                                                                               {foreach from=$__wcf->getACPMenu()->getMenuItems($menuItem->menuItem) item=menuItemCategory}\r
+                                                                                       {if $__wcf->getACPMenu()->getMenuItems($menuItemCategory->menuItem)|count > 0}\r
+                                                                                               {foreach from=$__wcf->getACPMenu()->getMenuItems($menuItemCategory->menuItem) item=subMenuItem}\r
+                                                                                                       <li data-menuItem="{$subMenuItem->menuItem}" id="{$subMenuItem->menuItem}"><a href="{$subMenuItem->getLink()}">{lang}{$subMenuItem->menuItem}{/lang}</a></li>\r
+                                                                                               {/foreach}\r
+                                                                                       {else}\r
+                                                                                               <li data-menuItem="{$menuItemCategory->menuItem}" id="{$menuItemCategory->menuItem}"><a href="{$menuItemCategory->getLink()}">{lang}{$menuItemCategory->menuItem}{/lang}</a></li>\r
+                                                                                       {/if}\r
+                                                                               {/foreach}\r
+                                                                       </ul>\r
+                                                               </div>\r
+                                                       {/foreach}\r
+                                               </div>\r
+                                       {/foreach}\r
+                               {/if}\r
+                       </nav>\r
+                       <!-- /sub nav -->\r
+               </aside>\r
+               \r
+               <div id="content">\r
diff --git a/wcfsetup/install/files/acp/templates/imageViewer.tpl b/wcfsetup/install/files/acp/templates/imageViewer.tpl
new file mode 100644 (file)
index 0000000..be642a9
--- /dev/null
@@ -0,0 +1,31 @@
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/ImageViewer.class.js"></script>
+<script type="text/javascript">
+       //<![CDATA[                     
+       // when the dom is fully loaded, add image viewer
+       document.observe("dom:loaded", function() {
+               new ImageViewer($$('.enlargable'), {
+                       langCaption             : '{lang}wcf.imageViewer.caption{/lang}',
+                       langPrevious            : '{lang}wcf.imageViewer.previous{/lang}',
+                       langNext                : '{lang}wcf.imageViewer.next{/lang}',
+                       langPlay                : '{lang}wcf.imageViewer.play{/lang}',
+                       langPause               : '{lang}wcf.imageViewer.pause{/lang}',
+                       langEnlarge             : '{lang}wcf.imageViewer.enlarge{/lang}',
+                       langClose               : '{lang}wcf.imageViewer.close{/lang}',
+                       imgBlankSrc             : '{@RELATIVE_WCF_DIR}images/imageViewer/blank.png',
+                       imgMenuSrc              : '{@RELATIVE_WCF_DIR}images/imageViewer/menu.png',
+                       imgPlaySrc              : '{@RELATIVE_WCF_DIR}icon/imageViewer/playM.png',
+                       imgPreviousSrc          : '{@RELATIVE_WCF_DIR}icon/imageViewer/previousM.png',
+                       imgNextSrc              : '{@RELATIVE_WCF_DIR}icon/imageViewer/nextM.png',
+                       imgEnlargeSrc           : '{@RELATIVE_WCF_DIR}icon/imageViewer/enlargeM.png',
+                       imgPauseSrc             : '{@RELATIVE_WCF_DIR}icon/imageViewer/pauseM.png',
+                       imgCloseSrc             : '{@RELATIVE_WCF_DIR}icon/imageViewer/closeM.png',
+                       imgPlayHoverSrc         : '{@RELATIVE_WCF_DIR}icon/imageViewer/playHoverM.png',
+                       imgPreviousHoverSrc     : '{@RELATIVE_WCF_DIR}icon/imageViewer/previousHoverM.png',
+                       imgNextHoverSrc         : '{@RELATIVE_WCF_DIR}icon/imageViewer/nextHoverM.png',
+                       imgEnlargeHoverSrc      : '{@RELATIVE_WCF_DIR}icon/imageViewer/enlargeHoverM.png',
+                       imgPauseHoverSrc        : '{@RELATIVE_WCF_DIR}icon/imageViewer/pauseHoverM.png',
+                       imgCloseHoverSrc        : '{@RELATIVE_WCF_DIR}icon/imageViewer/closeHoverM.png' 
+               });
+       });
+//]]>
+</script>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/index.tpl b/wcfsetup/install/files/acp/templates/index.tpl
new file mode 100644 (file)
index 0000000..cff6ff8
--- /dev/null
@@ -0,0 +1,3 @@
+{include file='header'}\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/languageServerAdd.tpl b/wcfsetup/install/files/acp/templates/languageServerAdd.tpl
new file mode 100644 (file)
index 0000000..1dc70ac
--- /dev/null
@@ -0,0 +1,63 @@
+{include file='header'}
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/languageServer{@$action|ucfirst}L.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.languageServer.{$action}{/lang}</h2>
+       </div>
+</div>
+
+{if $errorField}
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>
+{/if}
+
+{if $success|isset}
+       <p class="success">{lang}wcf.acp.languageServer.{$action}.success{/lang}</p>    
+{/if}
+
+<div class="contentHeader">
+       <div class="largeButtons">
+               <ul><li><a href="index.php?page=LanguageServerList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.package.server.view{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/languageServerM.png" alt="" /> <span>{lang}wcf.acp.menu.link.package.server.view{/lang}</span></a></li></ul>
+       </div>
+</div>
+<form method="post" action="index.php?form=LanguageServer{@$action|ucfirst}{if $languageServerID|isset}&amp;languageServerID={@$languageServerID}{/if}">
+       <div class="border content">
+               <div class="container-1">
+       
+                       <fieldset>
+                               <legend>{lang}wcf.acp.languageServer.data{/lang}</legend>
+                               
+                               <div class="formElement{if $errorField == 'server'} formError{/if}" id="serverDiv">
+                                       <div class="formFieldLabel">
+                                               <label for="server">{lang}wcf.acp.languageServer.server{/lang}</label>
+                                       </div>
+                                       <div class="formField">
+                                               <input type="text" class="inputText" name="server" value="{$server}" id="server" />
+                                               {if $errorField == 'server'}
+                                                       <p class="innerError">
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.languageServer.server.error.notValid{/lang}{/if}
+                                                       </p>
+                                               {/if}
+                                       </div>
+                                       <div class="formFieldDesc hidden" id="serverHelpMessage">
+                                               <p>{lang}wcf.acp.languageServer.server.description{/lang}</p>
+                                       </div>
+                               </div>
+                               <script type="text/javascript">//<![CDATA[
+                                       inlineHelp.register('server');
+                               //]]></script>
+                               
+                               {if $additionalFields|isset}{@$additionalFields}{/if}
+                       </fieldset>
+               </div>
+       </div>
+       
+       <div class="formSubmit">
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />
+               {@SID_INPUT_TAG}
+       </div>
+</form>
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/languageServerList.tpl b/wcfsetup/install/files/acp/templates/languageServerList.tpl
new file mode 100644 (file)
index 0000000..e2ddfa0
--- /dev/null
@@ -0,0 +1,74 @@
+{include file='header'}
+
+<script type="text/javascript">
+       //<![CDATA[
+       $(function() {
+               new WCF.Action.Delete('wcf\\data\\language\\server\\LanguageServerAction', $('.languageServerRow'));
+               new WCF.Action.Toggle('wcf\\data\\language\\server\\LanguageServerAction', $('.languageServerRow'));
+       });
+       //]]>
+</script>
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/languageServerL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.languageServer.view{/lang}</h2>
+       </div>
+</div>
+
+<div class="contentHeader">
+       <div class="largeButtons">
+               <ul><li><a href="index.php?form=LanguageServerAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.languageServer.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/languageServerAddM.png" alt="" /> <span>{lang}wcf.acp.languageServer.add{/lang}</span></a></li></ul>
+       </div>
+</div>
+
+{if !$languageServers|count}
+       <div class="border content">
+               <div class="container-1">
+                       <p>{lang}wcf.acp.languageServer.view.noneAvailable{/lang}</p>
+               </div>
+       </div>
+{else}
+       <div class="border titleBarPanel">
+               <div class="containerHead"><h3>{lang}wcf.acp.languageServer.list.available{/lang}</h3></div>
+       </div>
+       <div class="border borderMarginRemove">
+               <table class="tableList">
+                       <thead>
+                               <tr class="tableHead">
+                                       <th class="columnLanguageServerID{if $sortField == 'languageServerID'} active{/if}" colspan="2"><div><a href="index.php?page=LanguageServerList&amp;pageNo={@$pageNo}&amp;sortField=languageServerID&amp;sortOrder={if $sortField == 'languageServerID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.languageServer.languageServerID{/lang}{if $sortField == 'languageServerID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       <th class="columnServer{if $sortField == 'server'} active{/if}"><div><a href="index.php?page=LanguageServerList&amp;pageNo={@$pageNo}&amp;sortField=server&amp;sortOrder={if $sortField == 'server' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.languageServer.server{/lang}{if $sortField == 'server'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>
+                                       
+                                       {if $additionalHeadColumns|isset}{@$additionalHeadColumns}{/if}
+                               </tr>
+                       </thead>
+                       <tbody>
+                               {foreach from=$languageServers item=languageServer}
+                                       <tr class="languageServerRow {cycle values="container-1,container-2"}">
+                                               <td class="columnIcon">
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/{if !$languageServer->disabled}enabled{else}disabled{/if}S.png" alt="" class="toggleButton" title="{lang}wcf.acp.languageServer.{if !$languageServer->disabled}disable{else}enable{/if}{/lang}" data-objectID="{@$languageServer->languageServerID}" data-disableMessage="{lang}wcf.acp.languageServer.disable{/lang}" data-enableMessage="{lang}wcf.acp.languageServer.enable{/lang}" />
+                                                       <a href="index.php?form=LanguageServerEdit&amp;languageServerID={@$languageServer->languageServerID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/editS.png" alt="" title="{lang}wcf.acp.languageServer.edit{/lang}" /></a>
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.languageServer.delete{/lang}" class="deleteButton" data-objectID="{@$languageServer->languageServerID}" data-confirmMessage="{lang}wcf.acp.languageServer.delete.sure{/lang}" />
+                                                       
+                                                       {if $additionalButtons[$languageServer->languageServerID]|isset}{@$additionalButtons[$languageServer->languageServerID]}{/if}
+                                               </td>
+                                               <td class="columnID">{@$languageServer->languageServerID}</td>
+                                               <td class="columnText">
+                                                       <a href="index.php?form=LanguageServerEdit&amp;languageServerID={@$languageServer->languageServerID}{@SID_ARG_2ND}">
+                                                               {@$languageServer->serverURL}
+                                                       </a>
+                                               </td>
+                                               {if $additionalColumns[$languageServer->languageServerID]|isset}{@$additionalColumns[$languageServer->languageServerID]}{/if}
+                                       </tr>
+                               {/foreach}
+                       </tbody>
+               </table>
+       </div>
+       <div class="contentHeader">
+               <div class="largeButtons">
+                       <ul><li><a href="index.php?form=LanguageServerAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.languageServer.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/languageServerAddM.png" alt="" /> <span>{lang}wcf.acp.languageServer.add{/lang}</span></a></li></ul>
+               </div>
+       </div>
+{/if}
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/login.tpl b/wcfsetup/install/files/acp/templates/login.tpl
new file mode 100644 (file)
index 0000000..1ae856c
--- /dev/null
@@ -0,0 +1,61 @@
+{capture assign='pageTitle'}{lang}wcf.acp.login{/lang}{/capture}\r
+{include file='setupHeader'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       onloadEvents.push(function() { if (!'{$username|encodeJS}' || '{$errorField}' == 'username') document.getElementById('username').focus(); else document.getElementById('password').focus(); });\r
+       //]]>\r
+</script>\r
+\r
+<img class="icon" src="{@RELATIVE_WCF_DIR}icon/loginXL.png" alt="" />\r
+\r
+<h1><b>{@$pageTitle}</b></h1>\r
+\r
+<hr />\r
+\r
+{if $errorField != ''}\r
+<p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="index.php?form=Login">\r
+       <fieldset>\r
+               <legend>{lang}wcf.acp.login.data{/lang}</legend>\r
+               \r
+               <div class="inner">\r
+                       <div{if $errorField == 'username'} class="errorField"{/if}>\r
+                               <label for="username">{lang}wcf.user.username{/lang}</label>\r
+                               <input type="text" class="inputText" id="username" name="username" value="{$username}" />\r
+                               {if $errorField == 'username'}\r
+                                       <p>\r
+                                               <img src="{@RELATIVE_WCF_DIR}icon/errorS.png" alt="" />\r
+                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                               {if $errorType == 'notFound'}{lang}wcf.user.error.username.notFound{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+\r
+                       \r
+                       <div{if $errorField == 'password'} class="errorField"{/if}>\r
+                               <label for="password">{lang}wcf.user.password{/lang}</label>\r
+                               <input type="password" class="inputText" id="password" name="password" value="" />\r
+                               {if $errorField == 'password'}\r
+                                       <p>\r
+                                               <img src="{@RELATIVE_WCF_DIR}icon/errorS.png" alt="" />\r
+                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                               {if $errorType == 'false'}{lang}wcf.user.error.password.false{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+               </div>\r
+       </fieldset>\r
+       \r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="hidden" name="url" value="{$url}" />\r
+               {@SID_INPUT_TAG}\r
+       </div>\r
+</form>\r
+\r
+{include file='setupFooter'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/masterPassword.tpl b/wcfsetup/install/files/acp/templates/masterPassword.tpl
new file mode 100644 (file)
index 0000000..9786773
--- /dev/null
@@ -0,0 +1,64 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/loginL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.masterPassword.enter{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+\r
+{if $errorField != ''}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="index.php?form=MasterPassword">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.masterPassword.enter{/lang}</legend>\r
+                       \r
+                               <div class="formElement{if $errorField == 'masterPassword'} formError{/if}" id="masterPasswordDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="masterPassword">{lang}wcf.acp.masterPassword{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="password" class="inputText" id="masterPassword" name="masterPassword" value="{$masterPassword}" />\r
+                                               {if $errorField == 'masterPassword'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'invalid'}{lang}wcf.acp.masterPassword.error.invalid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="masterPasswordHelpMessage">\r
+                                               <p>{lang}wcf.acp.masterPassword.enter.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('masterPassword');\r
+                               //]]></script>\r
+                               \r
+                       </fieldset>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+               </div>\r
+       </div>\r
+\r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" name="submitButton" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="url" value="{$url}" />\r
+       </div>\r
+</form>\r
+
+<script type="text/javascript">
+       //<![CDATA[
+       document.observe("dom:loaded", function() {
+               $('masterPassword').focus();
+       });
+       //]]>
+</script>
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/masterPasswordInit.tpl b/wcfsetup/install/files/acp/templates/masterPasswordInit.tpl
new file mode 100644 (file)
index 0000000..315e316
--- /dev/null
@@ -0,0 +1,92 @@
+{include file='header'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       $(function() {\r
+               $('#setPassword').click(function() {\r
+                       $('input[type="password"]').val($.proxy(function(index, element) {\r
+                               return $(this).text();\r
+                       }, this));\r
+               });\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/loginL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.masterPassword.init{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+\r
+{if $errorField != ''}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="index.php?form=MasterPasswordInit">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.masterPassword.init{/lang}</legend>\r
+                       \r
+                               <div class="formElement{if $errorField == 'masterPassword'} formError{/if}" id="masterPasswordDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="masterPassword">{lang}wcf.acp.masterPassword{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="password" class="inputText" id="masterPassword" name="masterPassword" value="{$masterPassword}" />\r
+                                               {if $errorField == 'masterPassword'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'notSecure'}{lang}wcf.acp.masterPassword.error.notSecure{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="masterPasswordHelpMessage">\r
+                                               <p>{lang}wcf.acp.masterPassword.init.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('masterPassword');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'confirmMasterPassword'} formError{/if}">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="confirmMasterPassword">{lang}wcf.acp.masterPassword.confirm{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="password" class="inputText" id="confirmMasterPassword" name="confirmMasterPassword" value="{$confirmMasterPassword}" />\r
+                                               {if $errorField == 'confirmMasterPassword'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'notEqual'}{lang}wcf.acp.masterPassword.error.notEqual{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                               </div>\r
+                               \r
+                               <div class="formElement">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="exampleMasterPassword">{lang}wcf.acp.masterPassword.example{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <p><a href="#" id="setPassword" title="{lang}wcf.acp.masterPassword.example.set{/lang}">{@$exampleMasterPassword}</a></p>\r
+                                               <input type="hidden" id="exampleMasterPassword" name="exampleMasterPassword" value="{@$exampleMasterPassword}" />\r
+                                       </div>\r
+                               </div>\r
+                       </fieldset>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+               </div>\r
+       </div>\r
+\r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" name="submitButton" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="url" value="{$url}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/option.tpl b/wcfsetup/install/files/acp/templates/option.tpl
new file mode 100644 (file)
index 0000000..7d270fc
--- /dev/null
@@ -0,0 +1,71 @@
+{include file='header'}\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       $(function() {\r
+               WCF.TabMenu.init();\r
+               new WCF.ACP.Options();\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/optionL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.option.category.{$category->categoryName}{/lang}</h2>\r
+               <p>{lang}wcf.acp.option.category.{$category->categoryName}.description{/lang}</p>\r
+       </div>\r
+</div>\r
+\r
+{if $success|isset}\r
+       <p class="success">{lang}wcf.acp.option.success{/lang}</p>\r
+{/if}\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="index.php?form=Option&amp;categoryID={@$category->categoryID}">\r
+       <div class="tabMenuContainer" data-active="{$activeTabMenuItem}" data-store="activeTabMenuItem">\r
+               <ul class="tabMenu">\r
+                       {foreach from=$optionTree item=categoryLevel1}\r
+                               <li><a href="#{@$categoryLevel1[object]->categoryName}">{*<span>*}{lang}wcf.acp.option.category.{@$categoryLevel1[object]->categoryName}{/lang}{*</span>*}</a></li>\r
+                       {/foreach}\r
+               </ul>\r
+               \r
+               {foreach from=$optionTree item=categoryLevel1}\r
+                       <div class="border tabMenuContent hidden" id="{@$categoryLevel1[object]->categoryName}">\r
+                               <div class="container-1">\r
+                                       <h3 class="subHeadline">{lang}wcf.acp.option.category.{@$categoryLevel1[object]->categoryName}{/lang}</h3>\r
+                                       <p class="description">{lang}wcf.acp.option.category.{$categoryLevel1[object]->categoryName}.description{/lang}</p>\r
+                                       \r
+                                       {if $categoryLevel1[options]|count}\r
+                                               <fieldset>\r
+                                                       <legend>{lang}wcf.acp.option.category.{$categoryLevel1[object]->categoryName}{/lang}</legend>\r
+                                                       {include file='optionFieldList' options=$categoryLevel1[options] langPrefix='wcf.acp.option.'}\r
+                                               </fieldset>\r
+                                       {/if}\r
+                                       \r
+                                       {if $categoryLevel1[categories]|count}\r
+                                               {foreach from=$categoryLevel1[categories] item=categoryLevel2}\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.option.category.{@$categoryLevel2[object]->categoryName}{/lang}</legend>\r
+                                                               <p class="description">{lang}wcf.acp.option.category.{$categoryLevel2[object]->categoryName}.description{/lang}</p>\r
+                                                               \r
+                                                               {include file='optionFieldList' options=$categoryLevel2[options] langPrefix='wcf.acp.option.'}\r
+                                                       </fieldset>\r
+                                               {/foreach}\r
+                                       {/if}\r
+                               </div>\r
+                       </div>\r
+               {/foreach}\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" id="activeTabMenuItem" name="activeTabMenuItem" value="{$activeTabMenuItem}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionFieldList.tpl b/wcfsetup/install/files/acp/templates/optionFieldList.tpl
new file mode 100644 (file)
index 0000000..f0a1474
--- /dev/null
@@ -0,0 +1,22 @@
+{foreach from=$options item=optionData}\r
+       {assign var=option value=$optionData[object]}\r
+       {if $errorType|is_array && $errorType[$option->optionName]|isset}\r
+               {assign var=error value=$errorType[$option->optionName]}\r
+       {else}\r
+               {assign var=error value=''}\r
+       {/if}\r
+       <dl class="{$option->optionName}Input">\r
+               <dt><label for="{$option->optionName}">{lang}{@$langPrefix}{$option->optionName}{/lang}</label></dt>\r
+               <dd>{@$optionData[html]}</dd>\r
+               {if $error}\r
+                       <p class="innerError">\r
+                               {if $error == 'empty'}\r
+                                       {lang}wcf.global.error.empty{/lang}\r
+                               {else}  \r
+                                       {lang}wcf.user.option.error.{$error}{/lang}\r
+                               {/if}\r
+                       </p>\r
+               {/if}\r
+               <p>{lang}{@$langPrefix}{$option->optionName}.description{/lang}</p>\r
+       </dl>   \r
+{/foreach}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionImport.tpl b/wcfsetup/install/files/acp/templates/optionImport.tpl
new file mode 100644 (file)
index 0000000..0ef37c1
--- /dev/null
@@ -0,0 +1,80 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/optionImportAndExportL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.option.importAndExport{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $success|isset}\r
+       <p class="success">{lang}wcf.acp.option.import.success{/lang}</p>       \r
+{/if}\r
+\r
+{if $errorField != ''}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="index.php?form=OptionImport" enctype="multipart/form-data">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.option.import{/lang}</legend>\r
+                       \r
+                               <div class="formElement{if $errorField == 'optionImport'} formError{/if}" id="optionImportDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="optionImport">{lang}wcf.acp.option.import.upload{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="file" id="optionImport" name="optionImport" value="" />\r
+                                               {if $errorField == 'optionImport'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'importFailed'}{lang}wcf.acp.option.import.error.importFailed{/lang}{/if}\r
+                                                               {if $errorType == 'uploadFailed'}{lang}wcf.acp.option.import.error.uploadFailed{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="optionImportHelpMessage">\r
+                                               <p>{lang}wcf.acp.option.import.upload.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('optionImport');\r
+                               //]]></script>\r
+                       </fieldset>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+               </div>\r
+       </div>\r
+\r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" name="submitButton" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+       </div>\r
+</form>\r
+\r
+<div class="border content">\r
+       <div class="container-1">\r
+               <fieldset>\r
+                       <legend>{lang}wcf.acp.option.export{/lang}</legend>\r
+               \r
+                       <div class="formElement" id="optionExportDiv">\r
+                               <div class="formField">\r
+                                       <a href="index.php?action=OptionExport{@SID_ARG_2ND}" id="optionExport">{lang}wcf.acp.option.export.download{/lang}</a>\r
+                               </div>\r
+                               <div class="formFieldDesc hidden" id="optionExportHelpMessage">\r
+                                       <p>{lang}wcf.acp.option.export.download.description{/lang}</p>\r
+                               </div>\r
+                       </div>\r
+                       <script type="text/javascript">//<![CDATA[\r
+                               inlineHelp.register('optionExport');\r
+                       //]]></script>\r
+               </fieldset>\r
+               \r
+               {if $additionalFields|isset}{@$additionalFields}{/if}\r
+       </div>\r
+</div>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeBoolean.tpl b/wcfsetup/install/files/acp/templates/optionTypeBoolean.tpl
new file mode 100644 (file)
index 0000000..7e61779
--- /dev/null
@@ -0,0 +1,3 @@
+<input {if $disableOptions || $enableOptions}class="enablesOptions" data-disableOptions="[ {@$disableOptions}]" data-enableOptions="[ {@$enableOptions}]" {/if}\r
+id="{$option->optionName}" type="checkbox" name="values[{$option->optionName}]" value="1"\r
+{if $value} checked="checked"{/if} />
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeCustomselect.tpl b/wcfsetup/install/files/acp/templates/optionTypeCustomselect.tpl
new file mode 100644 (file)
index 0000000..0c4b9d6
--- /dev/null
@@ -0,0 +1,11 @@
+<ul class="formOptionsLong smallFont">\r
+       {foreach from=$selectOptions key=key item=selectOption}\r
+               <li>\r
+                       <label><input type="radio" name="values[{$option->optionName}]" value="{$key}"{if $value == $key} checked="checked"{/if} /> {lang}{@$selectOption}{/lang}</label>\r
+               </li>\r
+       {/foreach}\r
+       <li>\r
+               <label><input type="radio" name="values[{$option->optionName}]" value=""{if $value == $customValue} checked="checked"{/if} /></label>\r
+               <input style="width: 400px" id="{$option->optionName}_custom" type="text" class="inputText" name="values[{$option->optionName}_custom]" value="{$customValue}" />\r
+       </li>\r
+</ul>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeDate.tpl b/wcfsetup/install/files/acp/templates/optionTypeDate.tpl
new file mode 100644 (file)
index 0000000..2668c3f
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="floatContainer">\r
+       {foreach from=$dateInputOrder item=element}\r
+               <div class="floatedElement">\r
+                       <label for="{$optionData.optionName}{$element|ucfirst}">{lang}wcf.global.date.{$element}{/lang}</label>\r
+                       \r
+                       {if $element == 'day'}\r
+                               <select id="{$optionData.optionName}Day" name="values[{$optionData.optionName}][day]">\r
+                                       {htmlOptions options=$days selected=$day}\r
+                               </select>\r
+                       {/if}\r
+                       \r
+                       {if $element == 'month'}\r
+                               <select id="{$optionData.optionName}Month" name="values[{$optionData.optionName}][month]">\r
+                                       {htmlOptions options=$months selected=$month}\r
+                               </select>\r
+                       {/if}\r
+                       \r
+                       {if $element == 'year'}\r
+                               <input id="{$optionData.optionName}Year" class="inputText fourDigitInput" type="text" name="values[{$optionData.optionName}][year]" value="{$year}" maxlength="4" />\r
+                       {/if}\r
+               </div>\r
+       {/foreach}\r
+</div>\r
+{if !$yearRequired}\r
+       <p class="smallFont light">{lang}wcf.global.date.year.notRequired{/lang}</p>\r
+{/if}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeMultiselect.tpl b/wcfsetup/install/files/acp/templates/optionTypeMultiselect.tpl
new file mode 100644 (file)
index 0000000..5646331
--- /dev/null
@@ -0,0 +1,5 @@
+<select name="values[{$optionData.optionName}][]" id="{$optionData.optionName}" multiple="multiple" size="{if $options|count > 10}10{else}{@$options|count}{/if}">\r
+{foreach from=$options item=option key=key}\r
+       <option value="{$key}"{if $key|in_array:$optionData.optionValue} selected="selected"{/if}>{lang}{@$option}{/lang}</option>\r
+{/foreach}\r
+</select>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeRadiobuttons.tpl b/wcfsetup/install/files/acp/templates/optionTypeRadiobuttons.tpl
new file mode 100644 (file)
index 0000000..c115f19
--- /dev/null
@@ -0,0 +1,10 @@
+<ul class="formOptionsLong">\r
+       {foreach from=$selectOptions key=key item=selectOption}\r
+               <li>\r
+                       <label><input {if $disableOptions[$key] || $enableOptions[$key]}class="enablesOptions" data-disableOptions="[ {@$disableOptions[$key]}]" data-enableOptions="[ {@$enableOptions[$key]}]" {/if}\r
+                       type="radio" name="values[{$option->optionName}]" value="{$key}"\r
+                       {if $value == $key} checked="checked"{/if} />\r
+                       {lang}{@$selectOption}{/lang}</label>\r
+               </li>\r
+       {/foreach}\r
+</ul>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeSelect.tpl b/wcfsetup/install/files/acp/templates/optionTypeSelect.tpl
new file mode 100644 (file)
index 0000000..43f398b
--- /dev/null
@@ -0,0 +1,5 @@
+<select name="values[{$option->optionName}]" id="{$option->optionName}">\r
+{foreach from=$selectOptions key=key item=selectOption}\r
+       <option value="{$key}"{if $value == $key} selected="selected"{/if}>{lang}{@$selectOption}{/lang}</option>\r
+{/foreach}\r
+</select>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeText.tpl b/wcfsetup/install/files/acp/templates/optionTypeText.tpl
new file mode 100644 (file)
index 0000000..d23c034
--- /dev/null
@@ -0,0 +1,2 @@
+<input id="{$option->optionName}" type="{@$inputType}" class="inputText" name="values[{$option->optionName}]" \r
+value="{$value}" />
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/optionTypeTextarea.tpl b/wcfsetup/install/files/acp/templates/optionTypeTextarea.tpl
new file mode 100644 (file)
index 0000000..f9d93fa
--- /dev/null
@@ -0,0 +1 @@
+<textarea id="{$option->optionName}" cols="40" rows="10" name="values[{$option->optionName}]">{$value}</textarea>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageAutoUpdateList.tpl b/wcfsetup/install/files/acp/templates/packageAutoUpdateList.tpl
new file mode 100644 (file)
index 0000000..5cb8751
--- /dev/null
@@ -0,0 +1,106 @@
+{include file='header'}
+
+<script type="text/javascript">
+       //<![CDATA[
+       var checkedAll = true;
+       function checkUncheckAllPackages(parent) {
+               var inputs = parent.getElementsByTagName('input');
+               for (var i = 0, j = inputs.length; i < j; i++) {
+                       if (inputs[i].getAttribute('type') == 'checkbox') {
+                               inputs[i].checked = checkedAll;
+                       }
+               }
+               
+               var selects = parent.getElementsByTagName('select');
+               for (var i = 0, j = selects.length; i < j; i++) {
+                       selects[i].disabled = !checkedAll;
+               }
+               
+               checkedAll = (checkedAll) ? false : true;
+       }
+       //]]>
+</script>
+
+<form method="post" action="index.php?form=PackageUpdate" id="updateForm">
+       <div class="mainHeadline">
+               <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateL.png" alt="" />
+               <div class="headlineContainer">
+                       <h2>{lang}wcf.acp.packageUpdate{/lang}</h2>
+                       {if $availableUpdates|count}<p><label><input type="checkbox" onclick="checkUncheckAllPackages(document.getElementById('updateForm'))" /> {lang}wcf.acp.packageUpdate.selectAll{/lang}</label></p>{/if}
+               </div>
+       </div>
+
+       {if !$availableUpdates|count}
+               <div class="border content">
+                       <div class="container-1">
+                               <p>{lang}wcf.acp.packageUpdate.noneAvailable{/lang}</p>
+                       </div>
+               </div>
+       {else}
+               {foreach from=$availableUpdates item=availableUpdate}
+                       <div class="message content"{if $availableUpdate.version.updateType == 'security'} style="border-color: #c00"{/if}>
+                               <div class="messageInner container-{cycle name='styles' values='1,2'}">
+                                       <h3 class="subHeadline">
+                                               <label>
+                                                       <input onclick="enableFormElements(document.getElementById('version-{@$availableUpdate.packageID}Div'), this.checked)" type="checkbox" name="updates[{@$availableUpdate.packageID}]" value="{$availableUpdate.version.packageVersion}" />
+                                                       {$availableUpdate.packageName}{if $availableUpdate.instanceNo > 1} (#{#$availableUpdate.instanceNo}){/if}
+                                               </label>
+                                       </h3>
+
+                                       <div class="messageBody">
+                                               <div class="formElement">
+                                                       <div class="formFieldLabel">
+                                                               <label>{lang}wcf.acp.packageUpdate.currentVersion{/lang}</label>
+                                                       </div>
+                                                       <div class="formField">
+                                                               <span>{$availableUpdate.packageVersion}</span>
+                                                       </div>
+                                               </div>
+                                               
+                                               <div class="formElement" id="version-{@$availableUpdate.packageID}Div">
+                                                       <div class="formFieldLabel">
+                                                               <label for="version-{@$availableUpdate.packageID}">{lang}wcf.acp.packageUpdate.updateVersion{/lang}</label>
+                                                       </div>
+                                                       <div class="formField">
+                                                               <select name="updates[{@$availableUpdate.packageID}]" id="version-{@$availableUpdate.packageID}" disabled="disabled">
+                                                                       {foreach from=$availableUpdate.versions item=$version}
+                                                                               <option value="{$version.packageVersion}"{if $version.packageVersion == $availableUpdate.version.packageVersion} selected="selected"{/if}>{$version.packageVersion}</option>
+                                                                       {/foreach}
+                                                               </select>
+                                                       </div>
+                                               </div>
+                                               
+                                               {if $availableUpdate.author}
+                                                       <div class="formElement">
+                                                               <div class="formFieldLabel">
+                                                                       <label>{lang}wcf.acp.package.list.author{/lang}</label>
+                                                               </div>
+                                                               <div class="formField">
+                                                                       <span>{if $availableUpdate.authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$availableUpdate.authorURL|rawurlencode}" class="externalURL">{$availableUpdate.author}</a>{else}{$availableUpdate.author}{/if}</span>
+                                                               </div>
+                                                       </div>
+                                               {/if}
+                                               
+                                               {if $availableUpdate.packageDescription}
+                                                       <div class="formElement">
+                                                               <p class="formFieldLabel">{lang}wcf.acp.package.description{/lang}</p>
+                                                               <p class="formField">{$availableUpdate.packageDescription}</p>
+                                                       </div>
+                                               {/if}
+                                                       
+                                       </div>
+
+                                       <hr />
+                               </div>
+                       </div>                  
+               {/foreach}
+               
+               <div class="formSubmit">
+                       <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />
+                       <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />
+                       {@SID_INPUT_TAG}
+               </div>
+       {/if}
+</form>
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/packageInstallationConfirm.tpl b/wcfsetup/install/files/acp/templates/packageInstallationConfirm.tpl
new file mode 100644 (file)
index 0000000..3291453
--- /dev/null
@@ -0,0 +1,140 @@
+{include file='header'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       $(function() {\r
+               var packageInstallation = new WCF.ACP.PackageInstallation('install', {@$queueID}, true);\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/package{@$action|ucfirst}L.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{$archive->getPackageInfo('packageName')}</h2>\r
+               <p>{$archive->getPackageInfo('packageDescription')}</p>\r
+       </div>\r
+</div>\r
+\r
+{if $missingPackages > 0}\r
+       <p class="error">{lang}wcf.acp.package.install.error{/lang}</p>\r
+{/if}\r
+\r
+{if $excludingPackages|count > 0}\r
+       <div class="error">{lang}wcf.acp.package.install.error.excludingPackages{/lang}\r
+               <ul>\r
+               {foreach from=$excludingPackages item=excludingPackage}\r
+                       <li>{lang}wcf.acp.package.install.error.excludingPackages.excludingPackage{/lang}</li>\r
+               {/foreach}\r
+               </ul>\r
+       </div>\r
+{/if}\r
+\r
+{if $excludedPackages|count > 0}\r
+       <div class="error">{lang}wcf.acp.package.install.error.excludedPackages{/lang}\r
+               <ul>\r
+               {foreach from=$excludedPackages item=excludedPackage}\r
+                       <li>{lang}wcf.acp.package.install.error.excludedPackages.excludedPackage{/lang}</li>\r
+               {/foreach}\r
+               </ul>\r
+       </div>\r
+{/if}\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.acp.package.view.properties{/lang}</legend>\r
+\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.identifier{/lang}</p>\r
+               <p class="formField">{$archive->getPackageInfo('name')}</p>\r
+       </div>\r
+       \r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.install.version{/lang}</p>\r
+               <p class="formField">{$archive->getPackageInfo('version')}</p>\r
+       </div>\r
+\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.date{/lang}</p>\r
+               <p class="formField">{@$archive->getPackageInfo('date')|date}</p>\r
+       </div>\r
+\r
+       {if $archive->getPackageInfo('packageURL') != ''}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.url{/lang}</p>\r
+                       <p class="formField"><a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$archive->getPackageInfo('packageURL')|rawurlencode}" class="externalURL">{$archive->getPackageInfo('packageURL')}</a></p>\r
+               </div>\r
+       {/if}\r
+       \r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.author{/lang}</p>\r
+               <p class="formField">{if $archive->getPackageInfo('authorURL')}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$archive->getPackageInfo('authorURL')|rawurlencode}" class="externalURL">{$archive->getPackageInfo('author')}</a>{else}{$archive->getPackageInfo('author')}{/if}</p>\r
+       </div>\r
+       \r
+       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+</fieldset>\r
+\r
+{if $updatableInstances|count > 0}\r
+       <p class="warning" style="margin: 20px 0 10px 0">{lang}wcf.acp.package.install.updatableInstances.warning{/lang}</p>\r
+       \r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead">\r
+                       <h3>{lang}wcf.acp.package.install.updatableInstances{/lang}</h3>\r
+                       <p class="smallFont light">{lang}wcf.acp.package.install.updatableInstances.description{/lang}</p>\r
+               </div>\r
+       </div>\r
+       <div class="border borderMarginRemove">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.name{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.version{/lang}</span></div></th>\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                       {foreach from=$updatableInstances item=$package}\r
+                               <tr class="{cycle values="container-1,container-2"}">\r
+                                       <td class="columnText"><a href="index.php?page=Package&amp;action=install&amp;queueID={@$queueID}&amp;step=changeToUpdate&amp;updatePackageID={@$package.packageID}{@SID_ARG_2ND}">{$package.packageName}{if $package.instanceNo > 1 && $package.instanceName == ''} (#{#$package.instanceNo}){/if}</a></td>\r
+                                       <td class="columnText">{$package.packageVersion}</td>\r
+                               </tr>\r
+                       {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+{/if}\r
+\r
+{if $requiredPackages|count > 0}\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead">\r
+                       <h3>{lang}wcf.acp.package.view.requiredPackages{/lang}</h3>\r
+                       <p class="smallFont light">{lang}wcf.acp.package.view.requiredPackages.description{/lang}</p>\r
+               </div>\r
+       </div>\r
+       <div class="border borderMarginRemove">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.name{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.version{/lang}</span></div></th>\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                       {foreach from=$requiredPackages item=$package}\r
+                               <tr class="{cycle values="container-1,container-2"}">\r
+                                       <td class="columnText">{lang}wcf.acp.package.install.packageName{/lang}</td>\r
+                                       <td class="columnText">{if $package.minversion|isset}{$package.minversion}{/if}</td>\r
+                               </tr>\r
+                       {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+{/if}\r
+\r
+<div class="formSubmit">\r
+       <input type="button" accesskey="c" value="{lang}wcf.global.button.back{/lang}" onclick="document.location.href=fixURL('index.php?page=Package&amp;action={@$action}&amp;queueID={@$queueID}&amp;step=cancel{@SID_ARG_2ND}')" />\r
+       \r
+       {if $missingPackages == 0 && $excludingPackages|count == 0 && $excludedPackages|count == 0}\r
+               <input type="button" accesskey="s" id="submitButton" value="{lang}wcf.global.button.next{/lang}" />\r
+       {/if}\r
+</div>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageInstallationSetup.tpl b/wcfsetup/install/files/acp/templates/packageInstallationSetup.tpl
new file mode 100644 (file)
index 0000000..aaf131d
--- /dev/null
@@ -0,0 +1,10 @@
+{include file='header' templateName='packageInstallationSetup'}\r
+\r
+<script type="text/javascript">
+       //<![CDATA[\r
+       $installation = new WCF.ACP.PackageInstallation('install', {@$queueID}, false);\r
+       $installation.prepareInstallation();\r
+       //]]>
+</script>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageInstallationStepPrepare.tpl b/wcfsetup/install/files/acp/templates/packageInstallationStepPrepare.tpl
new file mode 100644 (file)
index 0000000..a6eedf1
--- /dev/null
@@ -0,0 +1,15 @@
+<div id="packageInstallationDialogContainer">
+       <div class="mainHeadline">
+               <img src="{@RELATIVE_WCF_DIR}icon/packageInstallL.png" alt="" />
+               <div class="headlineContainer">
+                       <h2>Paket &raquo;{$queue->packageName}&laquo; wird installiert &hellip;</h2>
+                       <p>Aktueller Schritt: <span id="packageInstallationAction">{lang}wcf.package.installation.step.prepare{/lang}</span></p>
+                       <p><progress value="0" max="100" style="width: 200px;" id="packageInstallationProgress">0%</progress></p>
+               </div>
+       </div>
+       
+       
+       <div class="border content" id="packageInstallationInnerContentContainer" style="display: none;">
+               <div class="container-1" id="packageInstallationInnerContent"></div>
+       </div>
+</div>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageList.tpl b/wcfsetup/install/files/acp/templates/packageList.tpl
new file mode 100644 (file)
index 0000000..4878349
--- /dev/null
@@ -0,0 +1,105 @@
+{include file='header'}\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       $(function() {\r
+               WCF.Language.add('wcf.acp.package.view.button.uninstall.sure', '{lang}wcf.acp.package.view.button.uninstall.sure{/lang}');\r
+               \r
+               new WCF.ACP.PackageUninstallation($('.packageRow .uninstallButton'));\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/packageL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.package.list{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+<div class="contentHeader">\r
+       {pages print=true assign=pagesLinks link="index.php?page=PackageList&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}\r
+\r
+       {if $__wcf->session->getPermission('admin.system.package.canInstallPackage') || $additionalLargeButtons|isset}\r
+               <div class="largeButtons">\r
+                       <ul>\r
+                               {if $__wcf->session->getPermission('admin.system.package.canInstallPackage')}<li><a href="index.php?form=PackageStartInstall&amp;action=install{@SID_ARG_2ND}" title="{lang}wcf.acp.package.startInstall{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/packageInstallM.png" alt="" /> <span>{lang}wcf.acp.package.startInstall{/lang}</span></a></li>{/if}\r
+                               {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+                       </ul>\r
+               </div>\r
+       {/if}\r
+</div>\r
+\r
+{if $packages|count > 0}\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead"><h3>{lang}wcf.acp.package.list.count{/lang}</h3></div>\r
+       </div>\r
+       <div class="border borderMarginRemove">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th colspan="2"{if $sortField == 'packageID'} class="active"{/if}><div><a href="index.php?page=PackageList&amp;pageNo={@$pageNo}&amp;sortField=packageID&amp;sortOrder={if $sortField == 'packageID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.package.list.id{/lang}{if $sortField == 'packageID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th colspan="2"{if $sortField == 'packageName'} class="active"{/if}><div><a href="index.php?page=PackageList&amp;pageNo={@$pageNo}&amp;sortField=packageName&amp;sortOrder={if $sortField == 'packageName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.package.list.name{/lang}{if $sortField == 'packageName'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th{if $sortField == 'author'} class="active"{/if}><div><a href="index.php?page=PackageList&amp;pageNo={@$pageNo}&amp;sortField=author&amp;sortOrder={if $sortField == 'author' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.package.list.author{/lang}{if $sortField == 'author'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th{if $sortField == 'packageVersion'} class="active"{/if}><div><a href="index.php?page=PackageList&amp;pageNo={@$pageNo}&amp;sortField=packageVersion&amp;sortOrder={if $sortField == 'packageVersion' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.package.list.version{/lang}{if $sortField == 'packageVersion'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th{if $sortField == 'updateDate'} class="active"{/if}><div><a href="index.php?page=PackageList&amp;pageNo={@$pageNo}&amp;sortField=updateDate&amp;sortOrder={if $sortField == 'updateDate' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.package.updateDate{/lang}{if $sortField == 'updateDate'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       \r
+                                       {if $additionalHeadColumns|isset}{@$additionalHeadColumns}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                               {foreach from=$packages item=$package}\r
+                                       <tr class="packageRow {cycle values="container-1,container-2"}">\r
+                                               <td class="columnIcon">\r
+                                                       {if $__wcf->session->getPermission('admin.system.package.canUpdatePackage')}\r
+                                                               <a href="index.php?form=PackageStartInstall&amp;action=update&amp;activePackageID={@$package->packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/packageUpdateS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" /></a>\r
+                                                       {else}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" />\r
+                                                       {/if}\r
+                                                       {if $__wcf->session->getPermission('admin.system.package.canUninstallPackage') && $package->package != 'com.woltlab.wcf' && $package->packageID != PACKAGE_ID}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" class="uninstallButton" data-objectID="{@$package->packageID}" />\r
+                                                       {else}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" />\r
+                                                       {/if}\r
+                                                       \r
+                                                       {if $additionalButtons[$package->packageID]|isset}{@$additionalButtons[$package->packageID]}{/if}\r
+                                               </td>\r
+                                               <td class="columnID">{@$package->packageID}</td>\r
+                                               <td class="columnIcon">\r
+                                                       {if $package->standalone}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/packageTypeStandaloneS.png" alt="" title="{lang}wcf.acp.package.list.standalone{/lang}" />\r
+                                                       {elseif $package->isPlugin()}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/packageTypePluginS.png" alt="" title="{lang}wcf.acp.package.list.plugin{/lang}" />\r
+                                                       {else}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/packageS.png" alt="" title="{lang}wcf.acp.package.list.other{/lang}" />\r
+                                                       {/if}\r
+                                               </td>\r
+                                               <td class="columnText" title="{$package->packageDescription}" id="packageName{@$package->packageID}">\r
+                                                       <a href="index.php?page=PackageView&amp;activePackageID={@$package->packageID}{@SID_ARG_2ND}"><span>{$package->getName()}{if $package->instanceNo > 1 && $package->instanceName == ''} (#{#$package->instanceNo}){/if}</span></a>\r
+                                               </td>\r
+                                               <td class="columnText">{if $package->authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package->authorURL|rawurlencode}" class="externalURL">{$package->author}</a>{else}{$package->author}{/if}</td>\r
+                                               <td class="columnText">{$package->packageVersion}</td>\r
+                                               <td class="columnDate">{@$package->updateDate|time}</td>\r
+                                               \r
+                                               {if $additionalColumns[$package->packageID]|isset}{@$additionalColumns[$package->packageID]}{/if}\r
+                                       </tr>\r
+                               {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+{/if}\r
+\r
+<div class="contentFooter">\r
+       {@$pagesLinks}\r
+       \r
+       {if $__wcf->session->getPermission('admin.system.package.canInstallPackage') || $additionalLargeButtons|isset}\r
+               <div class="largeButtons">\r
+                       <ul>\r
+                               {if $__wcf->session->getPermission('admin.system.package.canInstallPackage')}<li><a href="index.php?form=PackageStartInstall&amp;action=install{@SID_ARG_2ND}" title="{lang}wcf.acp.package.startInstall{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/packageInstallM.png" alt="" /> <span>{lang}wcf.acp.package.startInstall{/lang}</span></a></li>{/if}\r
+                               {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+                       </ul>\r
+               </div>\r
+       {/if}\r
+</div>\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/packageStartInstall.tpl b/wcfsetup/install/files/acp/templates/packageStartInstall.tpl
new file mode 100644 (file)
index 0000000..40795c9
--- /dev/null
@@ -0,0 +1,102 @@
+{include file='header'}\r
+\r
+{if $packageID == 0}\r
+       <div class="mainHeadline">\r
+               <img src="{@RELATIVE_WCF_DIR}icon/packageInstallL.png" alt="" />\r
+               <div class="headlineContainer">\r
+                       <h2>{lang}wcf.acp.package.startInstall{/lang}</h2>\r
+               </div>\r
+       </div>\r
+{else}\r
+       <div class="mainHeadline">\r
+               <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateL.png" alt="" />\r
+               <div class="headlineContainer">\r
+                       <h2>{lang}wcf.acp.package.startUpdate{/lang}</h2>\r
+               </div>\r
+       </div>\r
+{/if}\r
+\r
+{if $errorField != ''}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?page=PackageList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.package.view{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/packageM.png" alt="" /> <span>{lang}wcf.acp.menu.link.package.view{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+<form method="post" action="index.php?form=PackageStartInstall" enctype="multipart/form-data">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.package.startInstall.source{/lang}</legend>\r
+                       \r
+                               <div class="formElement{if $errorField == 'uploadPackage'} formError{/if}" id="uploadPackageDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="uploadPackage">{lang}wcf.acp.package.startInstall.source.upload{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="file" id="uploadPackage" name="uploadPackage" value="" />\r
+                                               {if $errorField == 'uploadPackage'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'noValidPackage'}{lang}wcf.acp.package.startInstall.error.noValidPackage{/lang}{/if}\r
+                                                               {if $errorType == 'noValidUpdate'}{lang}wcf.acp.package.startInstall.error.noValidUpdate{/lang}{/if}\r
+                                                               {if $errorType == 'noValidInstall'}{lang}wcf.acp.package.startInstall.error.noValidInstall{/lang}{/if}\r
+                                                               {if $errorType == 'uploadFailed'}{lang}wcf.acp.package.startInstall.error.uploadFailed{/lang}{/if}\r
+                                                               {if $errorType == 'uniqueAlreadyInstalled'}{lang}wcf.acp.package.startInstall.error.uniqueAlreadyInstalled{/lang}{/if}\r
+                                                               {if $errorType == 'phpRequirements'}<pre>{$phpRequirements|print_r}</pre>{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="uploadPackageHelpMessage">\r
+                                               <p>{lang}wcf.acp.package.startInstall.source.upload.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('uploadPackage');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'downloadPackage'} formError{/if}" id="downloadPackageDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="downloadPackage">{lang}wcf.acp.package.startInstall.source.download{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="downloadPackage" name="downloadPackage" value="" />\r
+                                               {if $errorField == 'downloadPackage'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'notFound'}{lang}wcf.acp.package.startInstall.error.notFound{/lang}{/if}\r
+                                                               {if $errorType == 'noValidPackage'}{lang}wcf.acp.package.startInstall.error.noValidPackage{/lang}{/if}\r
+                                                               {if $errorType == 'noValidUpdate'}{lang}wcf.acp.package.startInstall.error.noValidUpdate{/lang}{/if}\r
+                                                               {if $errorType == 'noValidInstall'}{lang}wcf.acp.package.startInstall.error.noValidInstall{/lang}{/if}\r
+                                                               {if $errorType == 'uniqueAlreadyInstalled'}{lang}wcf.acp.package.startInstall.error.uniqueAlreadyInstalled{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="downloadPackageHelpMessage">\r
+                                               <p>{lang}wcf.acp.package.startInstall.source.download.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('downloadPackage');\r
+                               //]]></script>\r
+                               \r
+                       </fieldset>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+               </div>\r
+       </div>\r
+\r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" name="submitButton" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="action" value="{$action}" />\r
+               {if $packageID != 0}<input type="hidden" name="activePackageID" value="{@$packageID}" />{/if}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/packageUninstallationDependencies.tpl b/wcfsetup/install/files/acp/templates/packageUninstallationDependencies.tpl
new file mode 100644 (file)
index 0000000..02dabd7
--- /dev/null
@@ -0,0 +1,137 @@
+{include file='header'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       $(function() {\r
+               new WCF.ACP.PackageUninstallation({@$packageObj->packageID});\r
+       });\r
+//     ]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/packageUninstallL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.package.uninstall{/lang}: {$packageObj->getName()}</h2>\r
+               <p>{$packageObj->packageDescription}</p>\r
+       </div>\r
+</div>\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.acp.package.view.properties{/lang}</legend>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.identifier{/lang}</p>\r
+               <p class="formField">{$packageObj->package}</p>\r
+       </div>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.version{/lang}</p>\r
+               <p class="formField">{$packageObj->packageVersion}</p>\r
+       </div>\r
+       {if $packageObj->instanceNo > 0}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.instanceNo{/lang}</p>\r
+                       <p class="formField">{$packageObj->instanceNo}</p>\r
+               </div>\r
+       {/if}\r
+       {if $packageObj->packageDir != ''}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.dir{/lang}</p>\r
+                       <p class="formField"><a href="{@RELATIVE_WCF_DIR}{$packageObj->packageDir}">{$packageObj->packageDir}</a></p>\r
+               </div>\r
+       {/if}\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.date{/lang}</p>\r
+               <p class="formField">{@$packageObj->packageDate|date}</p>\r
+       </div>\r
+       {if $packageObj->packageURL != ''}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.url{/lang}</p>\r
+                       <p class="formField"><a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$packageObj->packageURL|rawurlencode}" class="externalURL">{$packageObj->packageURL}</a></p>\r
+               </div>\r
+       {/if}\r
+       {if $packageObj->parentPackageID}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.parent{/lang}</p>\r
+                       <p class="formField"><a href="index.php?page=PackageView&amp;activePackageID={@$packageObj->parentPackageID}{@SID_ARG_2ND}">{$packageObj->getParentPackage()->getName()}</a></p>\r
+               </div>\r
+       {/if}\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.author{/lang}</p>\r
+               <p class="formField">{if $packageObj->authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$packageObj->authorURL|rawurlencode}" class="externalURL">{$packageObj->author}</a>{else}{$packageObj->author}{/if}</p>\r
+       </div>\r
+       \r
+       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+</fieldset>\r
+\r
+{if $dependentPackages|count > 0}\r
+       {if $uninstallAvailable}\r
+               <p class="warning">{lang}wcf.acp.package.uninstall.dependentPackages.warning{/lang}</p>\r
+       {else}\r
+               <p class="error">{lang}wcf.acp.package.uninstall.dependentPackages.error{/lang}</p>\r
+       {/if}\r
+\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead"><h3>{lang}wcf.acp.package.view.dependentPackages{/lang}</h3></div>\r
+       </div>\r
+       <div class="border borderMarginRemove">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th colspan="2"><div><span class="emptyHead">{lang}wcf.acp.package.list.id{/lang}</span></div></th>\r
+                                       <th colspan="2"><div><span class="emptyHead">{lang}wcf.acp.package.list.name{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.author{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.version{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.date{/lang}</span></div></th>\r
+                                       \r
+                                       {if $additionalColumns|isset}{@$additionalColumns}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                       {foreach from=$dependentPackages item=package}\r
+                               <tr class="{cycle values="container-1,container-2"}">\r
+                                       <td class="columnIcon">\r
+                                               {if $__wcf->user->getPermission('admin.system.package.canUpdatePackage')}\r
+                                                       <a href="index.php?form=PackageStartInstall&amp;action=update&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/packageUpdateS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" />\r
+                                               {/if}\r
+                                               {if $__wcf->user->getPermission('admin.system.package.canUninstallPackage') && $package.package != 'com.woltlab.wcf' && $package.packageID != PACKAGE_ID}\r
+                                                       <a onclick="return confirm('{lang}wcf.acp.package.view.button.uninstall.sure{/lang}')" href="index.php?page=Package&amp;action=startUninstall&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" />\r
+                                               {/if}\r
+                                               \r
+                                               {if $package.additionalButtons|isset}{@$package.additionalButtons}{/if}\r
+                                       </td>\r
+                                       <td class="columnID">{@$package.packageID}</td>\r
+                                       <td class="columnIcon">\r
+                                               {if $package.standalone}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageTypeStandaloneS.png" alt="" title="{lang}wcf.acp.package.list.standalone{/lang}" />\r
+                                               {elseif $package.parentPackageID}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageTypePluginS.png" alt="" title="{lang}wcf.acp.package.list.plugin{/lang}" />\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageS.png" alt="" title="{lang}wcf.acp.package.list.other{/lang}" />\r
+                                               {/if}\r
+                                       </td>\r
+                                       <td class="columnText" title="{$package.packageDescription}"><a href="index.php?page=PackageView&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}">{$package.packageName}{if $package.instanceNo > 1 && $package.instanceName == ''} (#{#$package.instanceNo}){/if}</a></td>\r
+                                       <td class="columnText">{if $package.authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package.authorURL|rawurlencode}" class="externalURL">{$package.author}</a>{else}{$package.author}{/if}</td>\r
+                                       <td class="columnText">{$package.packageVersion}</td>\r
+                                       <td class="columnDate">{@$package.packageDate|date}</td>\r
+                                       \r
+                                       {if $package.additionalColumns|isset}{@$package.additionalColumns}{/if}\r
+                               </tr>\r
+                       {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+{/if}\r
+\r
+<div class="formSubmit">\r
+       {@SID_INPUT_TAG}\r
+       <input type="hidden" name="action" value="startUninstall" />\r
+       <input type="hidden" name="activePackageID" value="{@$packageObj->packageID}" />\r
+       <input type="hidden" name="send" value="1" />\r
+       <input type="button" accesskey="c" value="{lang}wcf.global.button.back{/lang}" onclick="document.location.href=fixURL('index.php?page=PackageView&amp;activePackageID={$activePackageID}{@SID_ARG_2ND}')" />\r
+       <input type="button" accesskey="s" id="uninstallPackage" value="{lang}wcf.global.button.next{/lang}" />\r
+</div>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageUninstallationStepPrepare.tpl b/wcfsetup/install/files/acp/templates/packageUninstallationStepPrepare.tpl
new file mode 100644 (file)
index 0000000..9ce2068
--- /dev/null
@@ -0,0 +1,15 @@
+<div id="packageInstallationDialogContainer">
+       <div class="mainHeadline">
+               <img src="{@RELATIVE_WCF_DIR}icon/packageUninstallL.png" alt="" />
+               <div class="headlineContainer">
+                       <h2>Paket &raquo;{$queue->packageName}&laquo; wird deinstalliert &hellip;</h2>
+                       <p>Aktueller Schritt: <span id="packageInstallationAction">{lang}wcf.package.uninstallation.step.prepare{/lang}</span></p>
+                       <p><progress value="0" max="100" style="width: 200px;" id="packageInstallationProgress">0%</progress></p>
+               </div>
+       </div>
+       
+       
+       <div class="border content" id="packageInstallationInnerContentContainer" style="display: none;">
+               <div class="container-1" id="packageInstallationInnerContent"></div>
+       </div>
+</div>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageUpdate.tpl b/wcfsetup/install/files/acp/templates/packageUpdate.tpl
new file mode 100644 (file)
index 0000000..9e0d915
--- /dev/null
@@ -0,0 +1,65 @@
+{include file='header'}
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.packageUpdate{/lang}</h2>
+       </div>
+</div>
+
+{if $errorField == 'updates'}
+       {if $errorType === 'empty'}
+               <p class="error">{lang}wcf.acp.packageUpdate.noneSelected{/lang}</p>
+       {else}
+               <p class="error">{lang}wcf.acp.packageUpdate.error{/lang} {$errorType->getMessage()} ({@$errorType->getCode()})</p>
+               <!-- {$errorType->getTraceAsString()} -->
+       {/if}
+{/if}
+
+{if $errorField == 'excludedPackages'}
+       <div class="error">{lang}wcf.acp.packageUpdate.excludedPackages{/lang}
+               <ul>
+               {foreach from=$excludedPackages item=excludedPackage}
+                       <li>{if $excludedPackage.conflict == 'existingPackageExcludesNewPackage'}{lang}wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage{/lang}{else}{lang}wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage{/lang}{/if}</li>
+               {/foreach}
+               </ul>
+       </div>
+{/if}
+
+{if $packageInstallationStack|count}
+       <form method="post" action="index.php?form=PackageUpdate">
+               <div class="border content">
+                       <div class="container-1">
+                               <fieldset>
+                                       <legend>{lang}wcf.acp.packageUpdate.updates{/lang}</legend>
+                                       
+                                       <ul>
+                                               {foreach from=$packageInstallationStack item=package}
+                                                       <li>
+                                                               {if $package.action == 'install'}
+                                                                       {lang}wcf.acp.packageUpdate.install{/lang}
+                                                               {else}
+                                                                       {lang}wcf.acp.packageUpdate.update{/lang}
+                                                               {/if}
+                                                       </li>
+                                               {/foreach}
+                                       </ul>
+                               </fieldset>
+                       </div>
+               </div>
+               
+               <div class="formSubmit">
+                       {if !$errorField}<input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />{/if}
+                       {*<input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />*}
+                       {@SID_INPUT_TAG}
+                       <input type="hidden" name="send" value="1" />
+                       
+                       {foreach from=$updates key=package item=version}
+                               <input type="hidden" name="updates[{$package}]" value="{$version}" />
+                       {/foreach}
+               </div>
+       </form>
+{/if}
+
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/packageUpdateAuth.tpl b/wcfsetup/install/files/acp/templates/packageUpdateAuth.tpl
new file mode 100644 (file)
index 0000000..183dbe1
--- /dev/null
@@ -0,0 +1,104 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.packageUpdate.auth{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField != ''}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="{$requestMethod}" action="index.php{if $getParameters}?{@$getParameters}{/if}">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.packageUpdate.auth.data{/lang}</legend>\r
+                               \r
+                               <div class="formElement">\r
+                                       <p class="formFieldLabel">{lang}wcf.acp.packageUpdate.auth.url{/lang}</p>\r
+                                       <p class="formField">{$url}</p>\r
+                               </div>\r
+                               {if $realm}\r
+                                       <div class="formElement">\r
+                                               <p class="formFieldLabel">{lang}wcf.acp.packageUpdate.auth.realm{/lang}</p>\r
+                                               <p class="formField">{$realm}</p>\r
+                                       </div>\r
+                               {/if}\r
+                               {if $message}\r
+                                       <div class="formElement">\r
+                                               <p class="formFieldLabel">{lang}wcf.acp.packageUpdate.auth.message{/lang}</p>\r
+                                               <p class="formField">{@$message}</p>\r
+                                       </div>\r
+                               {/if}\r
+                       </fieldset>\r
+                       \r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.packageUpdate.auth.input{/lang}</legend>\r
+                               \r
+                               <div class="formElement{if $errorField == 'loginPassword'} formError{/if}" id="loginUsernameDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="loginUsername">{lang}wcf.acp.packageUpdate.auth.loginUsername{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="loginUsername" name="loginUsername" value="{$loginUsername}" />\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="loginUsernameHelpMessage">\r
+                                               <p>{lang}wcf.acp.packageUpdate.auth.loginUsername.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('loginUsername');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement{if $errorField == 'loginPassword'} formError{/if}" id="loginPasswordDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="loginPassword">{lang}wcf.acp.packageUpdate.auth.loginPassword{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="password" class="inputText" id="loginPassword" name="loginPassword" value="{$loginPassword}" />\r
+                                               {if $errorField == 'loginPassword'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'invalid'}{lang}wcf.acp.packageUpdate.auth.error{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="loginPasswordHelpMessage">\r
+                                               <p>{lang}wcf.acp.packageUpdate.auth.loginPassword.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('loginPassword');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement" id="saveAuthDataDiv">\r
+                                       <div class="formField">\r
+                                               <label><input type="checkbox" id="saveAuthData" name="saveAuthData" value="1" {if $saveAuthData == 1}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.auth.save{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="saveAuthDataHelpMessage">\r
+                                               <p>{lang}wcf.acp.packageUpdate.auth.save.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('saveAuthData');\r
+                               //]]></script>\r
+                       </fieldset>\r
+                       \r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               \r
+               <input type="hidden" name="form" value="PackageUpdateAuth" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="packageUpdateServerID" value="{@$packageUpdateServerID}" />\r
+               \r
+               {@$postParameters}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/packageUpdateSearch.tpl b/wcfsetup/install/files/acp/templates/packageUpdateSearch.tpl
new file mode 100644 (file)
index 0000000..1a9991e
--- /dev/null
@@ -0,0 +1,137 @@
+{include file='header'}
+
+<script type="text/javascript">
+       //<![CDATA[
+       $(function() {
+               // count checkboxes and those already checked (faster than retrieving that number with every change)
+               var $checked = $('input[name="packageUpdateServerIDs[]"]:checked').length;
+               var $count = $('input[name="packageUpdateServerIDs[]"]').length;
+               
+               // handle clicks on 'seach all'
+               $('input[name="checkUncheck"]').change(function() {
+                       if ($(this).attr('checked')) {
+                               $('input[name="packageUpdateServerIDs[]"]').attr('checked', 'checked');
+                               $checked = $count;
+                       }
+                       else {
+                               $('input[name="packageUpdateServerIDs[]"]').attr('checked', '');
+                               $checked = 0;
+                       }
+               });
+               
+               // handle clicks on each other checkbox (literally each server)
+               $('input[name="packageUpdateServerIDs[]"]').change(function() {
+                       if ($(this).attr('checked')) {
+                               $checked++;
+                               
+                               if ($checked === $count) {
+                                       $('input[name="checkUncheck"]').attr('checked', 'checked');
+                               }
+                       }
+                       else {
+                               $('input[name="checkUncheck"]').attr('checked', '');
+                               $checked--;
+                       }
+               });
+       });
+       //]]>
+</script>
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/packageSearchL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.packageUpdate.search{/lang}</h2>
+       </div>
+</div>
+
+{if $errorField != ''}
+       <p class="error">{lang}wcf.acp.packageUpdate.noneAvailable{/lang}</p>
+{/if}
+
+{if !$updateServers|count}
+       <p class="warning">{lang}wcf.acp.updateServer.view.noneAvailable{/lang}</p>
+{else}
+       <form method="post" action="index.php?form=PackageUpdateSearch">
+               <div class="border content">
+                       <div class="container-1">
+                       
+                               <fieldset>
+                                       <legend>{lang}wcf.acp.packageUpdate.search.server{/lang}</legend>
+                                       
+                                       <div>
+                                               <div class="formElement">
+                                                       <div class="formField">
+                                                               <label><input type="checkbox" name="checkUncheck" value="" /> {lang}wcf.acp.packageUpdate.search.server.all{/lang}</label> 
+                                                       </div>
+                                               </div>
+                                               
+                                               <div id="updateServerList">
+                                                       {foreach from=$updateServers item=updateServer}
+                                                               <div class="formElement">
+                                                                       <div class="formField">
+                                                                               <label><input type="checkbox" name="packageUpdateServerIDs[]" value="{@$updateServer->packageUpdateServerID}" {if $updateServer->packageUpdateServerID|in_array:$packageUpdateServerIDs}checked="checked" {/if}/> {$updateServer->serverURL}</label>
+                                                                       </div>
+                                                               </div>
+                                                       {/foreach}
+                                               </div>
+                                       </div>
+                               </fieldset>
+                               
+                               <fieldset>
+                                       <legend>{lang}wcf.acp.packageUpdate.search.conditions{/lang}</legend>
+                                       
+                                       <div>
+                                               <div class="formElement">
+                                                       <div class="formFieldLabel">
+                                                               <label for="packageName">{lang}wcf.acp.packageUpdate.search.packageName{/lang}</label>
+                                                       </div>
+                                                       <div class="formField">
+                                                               <input type="text" class="inputText" id="packageName" name="packageName" value="{$packageName}" />
+                                                               <label><input type="checkbox" name="searchDescription" value="1" {if $searchDescription == 1}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.search.searchDescription{/lang}</label>
+                                                       </div>
+                                               </div>
+                                               
+                                               <div class="formElement">
+                                                       <div class="formFieldLabel">
+                                                               <label for="author">{lang}wcf.acp.packageUpdate.search.author{/lang}</label>
+                                                       </div>
+                                                       <div class="formField">
+                                                               <input type="text" class="inputText" id="author" name="author" value="{$author}" />
+                                                       </div>
+                                               </div>
+                                               
+                                               <div class="formElement">
+                                                       <div class="formFieldLabel">
+                                                               <label>{lang}wcf.acp.packageUpdate.search.type{/lang}</label>
+                                                       </div>
+                                                       
+                                                       <div class="formField">
+                                                               <label><input type="checkbox" name="standalone" value="1" {if $standalone == 1}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.search.type.standalone{/lang}</label> 
+                                                       </div>
+                                                       <div class="formField">
+                                                               <label><input type="checkbox" name="plugin" value="1" {if $plugin == 1}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.search.type.plugin{/lang}</label> 
+                                                       </div>
+                                                       <div class="formField">
+                                                               <label><input type="checkbox" name="other" value="1" {if $other == 1}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.search.type.other{/lang}</label> 
+                                                       </div>
+                                               </div>
+                                               <div class="formElement">
+                                                       <div class="formField">
+                                                               <label><input type="checkbox" name="ignoreUniques" value="1" {if $ignoreUniques == 1}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.search.ignoreUniques{/lang}</label> 
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </fieldset>
+                       </div>
+               </div>
+               
+               <div class="formSubmit">
+                       <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />
+                       <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />
+                       {@SID_INPUT_TAG}
+               </div>
+       </form>
+
+{/if}
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/packageUpdateSearchResult.tpl b/wcfsetup/install/files/acp/templates/packageUpdateSearchResult.tpl
new file mode 100644 (file)
index 0000000..08ac297
--- /dev/null
@@ -0,0 +1,119 @@
+{include file='header'}
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>
+
+<div class="mainHeadline">
+       <img src="{@RELATIVE_WCF_DIR}icon/packageSearchL.png" alt="" />
+       <div class="headlineContainer">
+               <h2>{lang}wcf.acp.packageUpdate.search{/lang}</h2>
+       </div>
+</div>
+
+<div class="contentHeader">
+       {pages print=true assign=pagesLinks link="index.php?page=PackageUpdateSearchResult&searchID=$searchID&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}
+</div>
+
+<form method="post" action="index.php?form=PackageUpdate">
+       {foreach from=$packages item=package}
+               <div class="message content">
+                       <div class="messageInner container-{cycle name='styles' values='1,2'}">
+                               <h3 class="subHeadline">
+                                       {if $package.standalone == 1}
+                                               <img src="{@RELATIVE_WCF_DIR}icon/packageTypeStandaloneS.png" alt="" title="{lang}wcf.acp.package.list.standalone{/lang}" />
+                                       {elseif $package.plugin != ''}
+                                               <img src="{@RELATIVE_WCF_DIR}icon/packageTypePluginS.png" alt="" title="{lang}wcf.acp.package.list.plugin{/lang}" />
+                                       {else}
+                                               <img src="{@RELATIVE_WCF_DIR}icon/packageS.png" alt="" title="{lang}wcf.acp.package.list.other{/lang}" />
+                                       {/if}
+                                       {$package.packageName}
+                               </h3>
+
+                               <div class="messageBody">
+                                       <div class="formElement">
+                                               <div class="formFieldLabel">
+                                                       <label for="packageVersion-{$package.package}">{lang}wcf.acp.package.list.version{/lang}</label>
+                                               </div>
+                                               <div class="formField">
+                                                       <select id="packageVersion-{$package.package}">
+                                                               {foreach from=$package.packageVersions item=$packageVersion}
+                                                                       <option value="{$packageVersion}"{if $packageVersion == $package.packageVersion} selected="selected"{/if}>{$packageVersion}</option>
+                                                               {/foreach}
+                                                       </select>
+                                                       <script type="text/javascript">
+                                                               //<![CDATA[
+                                                               onloadEvents.push(function() {
+                                                                       document.getElementById('packageVersion-{$package.package|encodeJS}').onchange = function() {
+                                                                               // get value
+                                                                               var select = document.getElementById('packageVersion-{$package.package|encodeJS}');
+                                                                               var packageVersion = select.options[select.selectedIndex].value;
+                                                                               
+                                                                               // set value
+                                                                               {if !$package.isUnique}document.getElementById('updates-{$package.package}').value = packageVersion;{/if}
+                                                                               {foreach from=$package.updatableInstances item=updatableInstance}
+                                                                                       document.getElementById('updates-{$updatableInstance.packageID}').value = packageVersion;
+                                                                               {/foreach}
+                                                                       }
+                                                               });
+                                                               //]]>
+                                                       </script>
+                                               </div>
+                                       </div>
+                                       
+                                       {if $package.author != ''}
+                                               <div class="formElement">
+                                                       <div class="formFieldLabel">
+                                                               <label>{lang}wcf.acp.package.list.author{/lang}</label>
+                                                       </div>
+                                                       <div class="formField">
+                                                               <span>{if $package.authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package.authorURL|rawurlencode}" class="externalURL">{$package.author}</a>{else}{$package.author}{/if}</span>
+                                                       </div>
+                                               </div>
+                                       {/if}
+                                       
+                                       {if $package.packageDescription}
+                                               <div class="formElement">
+                                                       <p class="formFieldLabel">{lang}wcf.acp.package.description{/lang}</p>
+                                                       <p class="formField">{$package.packageDescription}</p>
+                                               </div>
+                                       {/if}
+                                       
+                                       <fieldset>
+                                               <legend>{lang}wcf.acp.packageUpdate.options{/lang}</legend>
+                                       
+                                               <div class="formField">
+                                                       <ul class="formOptionsLong">
+                                                               {* new installation *}
+                                                               {if $package.isUnique && !$package.updatableInstances|count}
+                                                                       <li>{lang}wcf.acp.packageUpdate.options.alreadyInstalledUnique{/lang}</li>
+                                                               {/if}
+                                                               {if !$package.isUnique}
+                                                                       <li><label><input type="checkbox" id="updates-{$package.package}" name="updates[{$package.package}]" value="{$package.packageVersion}" {if $selectedPackages[$package.package]|isset}checked="checked" {/if}/> {if $package.instances}{lang}wcf.acp.packageUpdate.options.installAlreadyInstalled{/lang}{else}{lang}wcf.acp.packageUpdate.options.install{/lang}{/if}</label></li>
+                                                               {/if}
+                                                               
+                                                               {* update *}
+                                                               {foreach from=$package.updatableInstances item=updatableInstance}
+                                                                       <li><label><input type="checkbox" id="updates-{$updatableInstance.packageID}" name="updates[{$updatableInstance.packageID}]" value="{$package.packageVersion}" {if $selectedPackages[$updatableInstance.packageID]|isset}checked="checked" {/if}/> {lang}wcf.acp.packageUpdate.options.update{/lang}</label></li>
+                                                               {/foreach}
+                                                       </<ul>
+                                               </div>
+                                       </fieldset>
+                               </div>
+
+                               <hr />
+                       </div>
+               </div>                  
+       {/foreach}
+       
+       <div class="formSubmit">
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />
+               <input type="hidden" name="packageID" value="{@PACKAGE_ID}" />
+               {@SID_INPUT_TAG}
+               <input type="hidden" name="searchID" value="{@$searchID}" />
+       </div>
+</form>
+
+<div class="contentFooter">
+       {@$pagesLinks}
+</div>
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/acp/templates/packageView.tpl b/wcfsetup/install/files/acp/templates/packageView.tpl
new file mode 100644 (file)
index 0000000..8aa426c
--- /dev/null
@@ -0,0 +1,234 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/packageL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{$package->getName()}</h2>\r
+               <p>{$package->packageDescription}</p>\r
+       </div>\r
+</div>\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.acp.package.view.properties{/lang}</legend>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.identifier{/lang}</p>\r
+               <p class="formField">{$package->package}</p>\r
+       </div>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.version{/lang}</p>\r
+               <p class="formField">{$package->packageVersion}</p>\r
+       </div>\r
+       {if $package->instanceNo > 1}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.instanceNo{/lang}</p>\r
+                       <p class="formField">{#$package->instanceNo}</p>\r
+               </div>\r
+       {elseif $package->package == 'com.woltlab.wcf' && WCF_N != 1}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.instanceNo{/lang}</p>\r
+                       <p class="formField">{#WCF_N}</p>\r
+               </div>\r
+       {/if}\r
+       {if $package->packageDir != ''}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.dir{/lang}</p>\r
+                       <p class="formField"><a href="{@RELATIVE_WCF_DIR}{$package->packageDir}">{$package->packageDir}</a></p>\r
+               </div>\r
+       {elseif $package->package == 'com.woltlab.wcf'}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.dir{/lang}</p>\r
+                       <p class="formField">{WCF_DIR}</p>\r
+               </div>\r
+       {/if}\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.date{/lang}</p>\r
+               <p class="formField">{@$package->packageDate|date}</p>\r
+       </div>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.installDate{/lang}</p>\r
+               <p class="formField">{@$package->installDate|time}</p>\r
+       </div>\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.updateDate{/lang}</p>\r
+               <p class="formField">{@$package->updateDate|time}</p>\r
+       </div>\r
+       {if $package->packageURL != ''}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.url{/lang}</p>\r
+                       <p class="formField"><a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package->packageURL|rawurlencode}" class="externalURL">{$package->packageURL}</a></p>\r
+               </div>\r
+       {/if}\r
+       {if $package->parentPackageID}\r
+               <div class="formElement">\r
+                       <p class="formFieldLabel">{lang}wcf.acp.package.view.parent{/lang}</p>\r
+                       <p class="formField"><a href="index.php?page=PackageView&amp;activePackageID={@$package->parentPackageID}{@SID_ARG_2ND}">{$package->parentPackage()->getName()}</a></p>\r
+               </div>\r
+       {/if}\r
+       <div class="formElement">\r
+               <p class="formFieldLabel">{lang}wcf.acp.package.view.author{/lang}</p>\r
+               <p class="formField">{if $package->authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package->authorURL|rawurlencode}" class="externalURL">{$package->author}</a>{else}{$package->author}{/if}</p>\r
+       </div>\r
+       \r
+       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+</fieldset>\r
+\r
+{assign var=noDependentIsActive value=true}\r
+{foreach from=$dependentPackages item=dependentPackage}\r
+       {if $dependentPackage.package != 'com.woltlab.wcf' && $dependentPackage.packageID == PACKAGE_ID}\r
+               {assign var=noDependentIsActive value=false}\r
+               {* TODO: maybe show user that this package can't be uninstalled because a dependent package is the active standalone application *}\r
+       {/if}\r
+{/foreach}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       {if PACKAGE_ID != $package->packageID}\r
+                               {if $package->standalone && $package->package != 'com.woltlab.wcf'}<li><a href="{@RELATIVE_WCF_DIR}{$package->packageDir}acp/index.php?packageID={@$package->packageID}{@SID_ARG_2ND}" title="{lang}wcf.acp.package.view.button.makeActive{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/packageMakeActiveM.png" alt="" /> <span>{lang}wcf.acp.package.view.button.makeActive{/lang}</span></a></li>{/if}\r
+                               {if $__wcf->user->getPermission('admin.system.package.canUninstallPackage') && $noDependentIsActive}<li><a href="index.php?page=Package&amp;action=startUninstall&amp;activePackageID={@$package->packageID}{@SID_ARG_2ND}" onclick="return confirm('{lang}wcf.acp.package.view.button.uninstall.sure{/lang}')" title="{lang}wcf.acp.package.view.button.uninstall{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/packageUninstallM.png" alt="" /> <span>{lang}wcf.acp.package.view.button.uninstall{/lang}</span></a></li>{/if}\r
+                       {/if}\r
+                       {if $__wcf->user->getPermission('admin.system.package.canUpdatePackage')}<li><a href="index.php?form=PackageStartInstall&amp;action=update&amp;activePackageID={@$package->packageID}{@SID_ARG_2ND}" title="{lang}wcf.acp.package.view.button.update{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/packageUpdateM.png" alt="" /> <span>{lang}wcf.acp.package.view.button.update{/lang}</span></a></li>{/if}\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+\r
+{if $requiredPackages|count > 0}\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead">\r
+                       <div class="containerIcon"><a onclick="openList('requiredPackages')"><img id="requiredPackagesImage" src="{@RELATIVE_WCF_DIR}icon/minusS.png" alt="" /></a></div>\r
+                       <div class="containerContent">\r
+                               <h3><a onclick="openList('requiredPackages')">{lang}wcf.acp.package.view.requiredPackages{/lang}</a></h3>\r
+                               <p class="smallFont light">{lang}wcf.acp.package.view.requiredPackages.description{/lang}</p>\r
+                       </div>\r
+               </div>\r
+       </div>\r
+       <div class="border borderMarginRemove" id="requiredPackages">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th colspan="2"><div><span class="emptyHead">{lang}wcf.acp.package.list.id{/lang}</span></div></th>\r
+                                       <th colspan="2"><div><span class="emptyHead">{lang}wcf.acp.package.list.name{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.author{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.version{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.date{/lang}</span></div></th>\r
+                                       \r
+                                       {if $additionalColumns|isset}{@$additionalColumns}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                       {foreach from=$requiredPackages item=$package}\r
+                               <tr class="{cycle values="container-1,container-2"}">\r
+                                       <td class="columnIcon">\r
+                                               {if $__wcf->user->getPermission('admin.system.package.canUpdatePackage')}\r
+                                                       <a href="index.php?form=PackageStartInstall&amp;action=update&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/packageUpdateS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" />\r
+                                               {/if}\r
+                                               {if $__wcf->user->getPermission('admin.system.package.canUninstallPackage') && $package.package != 'com.woltlab.wcf' && $package.packageID != PACKAGE_ID}\r
+                                                       <a onclick="return confirm('{lang}wcf.acp.package.view.button.uninstall.sure{/lang}')" href="index.php?page=Package&amp;action=startUninstall&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" />\r
+                                               {/if}\r
+                                               \r
+                                               {if $package.additionalButtons|isset}{@$package.additionalButtons}{/if}\r
+                                       </td>\r
+                                       <td class="columnID">{@$package.packageID}</td>\r
+                                       <td class="columnIcon">\r
+                                               {if $package.standalone}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageTypeStandaloneS.png" alt="" title="{lang}wcf.acp.package.list.standalone{/lang}" />\r
+                                               {elseif $package.parentPackageID}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageTypePluginS.png" alt="" title="{lang}wcf.acp.package.list.plugin{/lang}" />\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageS.png" alt="" title="{lang}wcf.acp.package.list.other{/lang}" />\r
+                                               {/if}\r
+                                       </td>\r
+                                       <td class="columnText" title="{$package.packageDescription}"><a href="index.php?page=PackageView&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}">{$package.packageName}{if $package.instanceNo > 1 && $package.instanceName == ''} (#{#$package.instanceNo}){/if}</a></td>\r
+                                       <td class="columnText">{if $package.authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package.authorURL|rawurlencode}" class="externalURL">{$package.author}</a>{else}{$package.author}{/if}</td>\r
+                                       <td class="columnText">{$package.packageVersion}</td>\r
+                                       <td class="columnDate">{@$package.packageDate|date}</td>\r
+                                       \r
+                                       {if $package.additionalColumns|isset}{@$package.additionalColumns}{/if}\r
+                               </tr>\r
+                       {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+       \r
+       <script type="text/javascript">\r
+               //<![CDATA[\r
+               initList('requiredPackages', 0);\r
+               //]]>\r
+       </script>\r
+{/if}\r
+\r
+{if $dependentPackages|count > 0}\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead">\r
+                       <div class="containerIcon"><a onclick="openList('dependentPackages')"><img id="dependentPackagesImage" src="{@RELATIVE_WCF_DIR}icon/minusS.png" alt="" /></a></div>\r
+                       <div class="containerContent">\r
+                               <h3><a onclick="openList('dependentPackages')">{lang}wcf.acp.package.view.dependentPackages{/lang}</a></h3>\r
+                               <p class="smallFont light">{lang}wcf.acp.package.view.dependentPackages.description{/lang}</p>\r
+                       </div>\r
+               </div>\r
+       </div>\r
+       <div class="border borderMarginRemove" id="dependentPackages">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th colspan="2"><div><span class="emptyHead">{lang}wcf.acp.package.list.id{/lang}</span></div></th>\r
+                                       <th colspan="2"><div><span class="emptyHead">{lang}wcf.acp.package.list.name{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.author{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.version{/lang}</span></div></th>\r
+                                       <th><div><span class="emptyHead">{lang}wcf.acp.package.list.date{/lang}</span></div></th>\r
+                                       \r
+                                       {if $additionalColumns|isset}{@$additionalColumns}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                       {foreach from=$dependentPackages item=$package}\r
+                               <tr class="{cycle values="container-1,container-2"}">\r
+                                       <td class="columnIcon">\r
+                                               {if $__wcf->user->getPermission('admin.system.package.canUpdatePackage')}\r
+                                                       <a href="index.php?form=PackageStartInstall&amp;action=update&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/packageUpdateS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageUpdateDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.update{/lang}" />\r
+                                               {/if}\r
+                                               {if $__wcf->user->getPermission('admin.system.package.canUninstallPackage') && $package.package != 'com.woltlab.wcf' && $package.packageID != PACKAGE_ID}\r
+                                                       <a onclick="return confirm('{lang}wcf.acp.package.view.button.uninstall.sure{/lang}')" href="index.php?page=Package&amp;action=startUninstall&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.package.view.button.uninstall{/lang}" />\r
+                                               {/if}\r
+                                               \r
+                                               {if $package.additionalButtons|isset}{@$package.additionalButtons}{/if}\r
+                                       </td>\r
+                                       <td class="columnID">{@$package.packageID}</td>\r
+                                       <td class="columnIcon">\r
+                                               {if $package.standalone}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageTypeStandaloneS.png" alt="" title="{lang}wcf.acp.package.list.standalone{/lang}" />\r
+                                               {elseif $package.parentPackageID}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageTypePluginS.png" alt="" title="{lang}wcf.acp.package.list.plugin{/lang}" />\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/packageS.png" alt="" title="{lang}wcf.acp.package.list.other{/lang}" />\r
+                                               {/if}\r
+                                       </td>\r
+                                       <td class="columnText" title="{$package.packageDescription}"><a href="index.php?page=PackageView&amp;activePackageID={@$package.packageID}{@SID_ARG_2ND}">{$package.packageName}{if $package.instanceNo > 1 && $package.instanceName == ''} (#{#$package.instanceNo}){/if}</a></td>\r
+                                       <td class="columnText">{if $package.authorURL}<a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={$package.authorURL|rawurlencode}" class="externalURL">{$package.author}</a>{else}{$package.author}{/if}</td>\r
+                                       <td class="columnText">{$package.packageVersion}</td>\r
+                                       <td class="columnDate">{@$package.packageDate|date}</td>\r
+                                       \r
+                                       {if $package.additionalColumns|isset}{@$package.additionalColumns}{/if}\r
+                               </tr>\r
+                       {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+       \r
+       <script type="text/javascript">\r
+               //<![CDATA[\r
+               initList('dependentPackages', 0);\r
+               //]]>\r
+       </script>\r
+{/if}\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/permissionDenied.tpl b/wcfsetup/install/files/acp/templates/permissionDenied.tpl
new file mode 100644 (file)
index 0000000..7869663
--- /dev/null
@@ -0,0 +1,18 @@
+{if $__wcf->session->getPermission('admin.general.canUseAcp')}{include file='header' templateName='permissionDenied'}\r
+\r
+<p class="error">{lang}wcf.global.error.permissionDenied{/lang}</p>\r
+\r
+{include file='footer'}\r
+{else}{capture assign='pageTitle'}{lang}wcf.global.error.permissionDenied.title{/lang}{/capture}\r
+{include file='setupHeader'}\r
+\r
+<img class="icon" src="{@RELATIVE_WCF_DIR}icon/loginXL.png" alt="" />\r
+\r
+<h1><b>{@$pageTitle}</b></h1>\r
+\r
+<hr />\r
+\r
+<p class="error">{lang}wcf.global.error.permissionDenied{/lang}</p>\r
+\r
+{include file='setupFooter'}\r
+{/if}\r
diff --git a/wcfsetup/install/files/acp/templates/setupFooter.tpl b/wcfsetup/install/files/acp/templates/setupFooter.tpl
new file mode 100644 (file)
index 0000000..b034bf6
--- /dev/null
@@ -0,0 +1,3 @@
+</div>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/setupHeader.tpl b/wcfsetup/install/files/acp/templates/setupHeader.tpl
new file mode 100644 (file)
index 0000000..4de4001
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" dir="{lang}wcf.global.pageDirection{/lang}" xml:lang="{@LANGUAGE_CODE}">\r
+       <head>\r
+               <title>{@$pageTitle} - {lang}wcf.global.pageTitle{/lang}</title>\r
+               <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+               <script type="text/javascript">\r
+                       //<![CDATA[\r
+                       var SID_ARG_2ND = '{@SID_ARG_2ND_NOT_ENCODED}';\r
+                       var RELATIVE_WCF_DIR = '{@RELATIVE_WCF_DIR}';\r
+                       //]]>\r
+               </script>\r
+               <script type="text/javascript" src="{@RELATIVE_WCF_DIR}acp/js/x.js"></script>\r
+               <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/3rdParty/protoaculous.1.8.2.min.js"></script>\r
+               <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/default.js"></script>\r
+               <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/AjaxRequest.class.js"></script>\r
+               <script type="text/javascript" src="{@RELATIVE_WCF_DIR}acp/js/default.js"></script>\r
+               <style type="text/css">\r
+                       @import url("{@RELATIVE_WCF_DIR}acp/style/extra/setupStyle{if PAGE_DIRECTION == 'rtl'}-rtl{/if}.css");\r
+               </style>\r
+               \r
+               <!--[if lt IE 7]>\r
+                       <style type="text/css">\r
+                               .page {\r
+                                       width: 800px;\r
+                               }\r
+                               .progressText {\r
+                                       margin-top: -16px;\r
+                               }\r
+                       </style>\r
+               <![endif]-->\r
+               <!--[if IE]>\r
+                       <style type="text/css">\r
+                               hr {\r
+                                       margin: 0;\r
+                               }\r
+                               fieldset p, fieldset div {\r
+                                       min-height: 0;\r
+                               }\r
+                       </style>\r
+               <![endif]-->\r
+       </head>\r
+<body>\r
+<div class="page">\r
+\r
diff --git a/wcfsetup/install/files/acp/templates/setupWindowFooter.tpl b/wcfsetup/install/files/acp/templates/setupWindowFooter.tpl
new file mode 100644 (file)
index 0000000..b034bf6
--- /dev/null
@@ -0,0 +1,3 @@
+</div>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/setupWindowHeader.tpl b/wcfsetup/install/files/acp/templates/setupWindowHeader.tpl
new file mode 100644 (file)
index 0000000..283925b
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" dir="{lang}wcf.global.pageDirection{/lang}" xml:lang="{@LANGUAGE_CODE}">\r
+       <head>\r
+               <title></title>\r
+               <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+               <link href="{@RELATIVE_WCF_DIR}acp/style/extra/setupWindowStyle{if PAGE_DIRECTION == 'rtl'}-rtl{/if}.css" rel="stylesheet" type="text/css" />\r
+               <script type="text/javascript">\r
+                       //<![CDATA[\r
+                       function changeHeight() {\r
+                               if (parent.document.getElementById('iframe').style.visibility != 'hidden') {\r
+                                       parent.document.getElementById('iframe').style.height = document.getElementById('content').offsetHeight + 4 + 'px';\r
+                               }\r
+                       }\r
+                       //]]>\r
+               </script>\r
+       </head>\r
+<body>\r
+<div id="content" class="page" style="padding: 2px 4px">\r
diff --git a/wcfsetup/install/files/acp/templates/success.tpl b/wcfsetup/install/files/acp/templates/success.tpl
new file mode 100644 (file)
index 0000000..3fa06c2
--- /dev/null
@@ -0,0 +1,5 @@
+{include file='header'}\r
+\r
+<p class="success">{lang}{@$message}{/lang}</p>        \r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/updateServerAdd.tpl b/wcfsetup/install/files/acp/templates/updateServerAdd.tpl
new file mode 100644 (file)
index 0000000..65e5972
--- /dev/null
@@ -0,0 +1,97 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/updateServer{@$action|ucfirst}L.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.updateServer.{$action}{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+{if $success|isset}\r
+       <p class="success">{lang}wcf.acp.updateServer.{$action}.success{/lang}</p>      \r
+{/if}\r
+\r
+{if $packageUpdateServer|isset && $packageUpdateServer->errorMessage}\r
+       <p class="warning">{lang}wcf.acp.updateServer.lastErrorMessage{/lang}<br />{$packageUpdateServer->errorMessage}</p>     \r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul><li><a href="index.php?page=UpdateServerList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.package.server.view{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/updateServerM.png" alt="" /> <span>{lang}wcf.acp.menu.link.package.server.view{/lang}</span></a></li></ul>\r
+       </div>\r
+</div>\r
+<form method="post" action="index.php?form=UpdateServer{@$action|ucfirst}{if $packageUpdateServerID|isset}&amp;packageUpdateServerID={@$packageUpdateServerID}{/if}">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+       \r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.updateServer.data{/lang}</legend>\r
+                               \r
+                               <div class="formElement{if $errorField == 'server'} formError{/if}" id="serverDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="server">{lang}wcf.acp.updateServer.server{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" name="server" value="{$server}" id="server" />\r
+                                               {if $errorField == 'server'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               {if $errorType == 'notValid'}{lang}wcf.acp.updateServer.server.error.notValid{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="serverHelpMessage">\r
+                                               <p>{lang}wcf.acp.updateServer.server.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('server');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement" id="loginUsernameDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="loginUsername">{lang}wcf.acp.updateServer.loginUsername{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" name="loginUsername" value="{$loginUsername}" id="loginUsername" />\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="loginUsernameHelpMessage">\r
+                                               <p>{lang}wcf.acp.updateServer.loginUsername.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('loginUsername');\r
+                               //]]></script>\r
+                               \r
+                               <div class="formElement" id="loginPasswordDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="loginPassword">{lang}wcf.acp.updateServer.loginPassword{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="password" class="inputText" name="loginPassword" value="{$loginPassword}" id="loginPassword" />\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="loginPasswordHelpMessage">\r
+                                               <p>{lang}wcf.acp.updateServer.loginPassword.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('loginPassword');\r
+                               //]]></script>\r
+                               \r
+                               {if $additionalFields|isset}{@$additionalFields}{/if}\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/updateServerList.tpl b/wcfsetup/install/files/acp/templates/updateServerList.tpl
new file mode 100644 (file)
index 0000000..6bfebfe
--- /dev/null
@@ -0,0 +1,97 @@
+{include file='header'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       $(function() {\r
+               new WCF.Action.Delete('wcf\\data\\package\\update\\server\\PackageUpdateServerAction', $('.updateServerRow'));\r
+               new WCF.Action.Toggle('wcf\\data\\package\\update\\server\\PackageUpdateServerAction', $('.updateServerRow'));\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/updateServerL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.updateServer.view{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $deletedPackageUpdateServerID}\r
+       <p class="success">{lang}wcf.acp.updateServer.delete.success{/lang}</p>\r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul><li><a href="index.php?form=UpdateServerAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.updateServer.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/updateServerAddM.png" alt="" /> <span>{lang}wcf.acp.updateServer.add{/lang}</span></a></li></ul>\r
+       </div>\r
+</div>\r
+\r
+{if !$updateServers|count}\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <p>{lang}wcf.acp.updateServer.view.noneAvailable{/lang}</p>\r
+               </div>\r
+       </div>\r
+{else}\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead"><h3>{lang}wcf.acp.updateServer.list.available{/lang}</h3></div>\r
+       </div>\r
+       <div class="border borderMarginRemove">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th class="columnPackageUpdateServerID{if $sortField == 'packageUpdateServerID'} active{/if}" colspan="2"><div><a href="index.php?page=UpdateServerList&amp;pageNo={@$pageNo}&amp;sortField=packageUpdateServerID&amp;sortOrder={if $sortField == 'packageUpdateServerID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.updateServer.packageUpdateServerID{/lang}{if $sortField == 'packageUpdateServerID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnServer{if $sortField == 'server'} active{/if}"><div><a href="index.php?page=UpdateServerList&amp;pageNo={@$pageNo}&amp;sortField=server&amp;sortOrder={if $sortField == 'server' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.updateServer.server{/lang}{if $sortField == 'server'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnPackages{if $sortField == 'packages'} active{/if}"><div><a href="index.php?page=UpdateServerList&amp;pageNo={@$pageNo}&amp;sortField=packages&amp;sortOrder={if $sortField == 'packages' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.updateServer.packages{/lang}{if $sortField == 'packages'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnStatus{if $sortField == 'status'} active{/if}"><div><a href="index.php?page=UpdateServerList&amp;pageNo={@$pageNo}&amp;sortField=status&amp;sortOrder={if $sortField == 'status' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.updateServer.status{/lang}{if $sortField == 'status'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnErrorText{if $sortField == 'errorMessage'} active{/if}"><div><a href="index.php?page=UpdateServerList&amp;pageNo={@$pageNo}&amp;sortField=errorMessage&amp;sortOrder={if $sortField == 'errorMessage' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.updateServer.errorMessage{/lang}{if $sortField == 'errorMessage'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnTimestamp{if $sortField == 'lastUpdateTime'} active{/if}"><div><a href="index.php?page=UpdateServerList&amp;pageNo={@$pageNo}&amp;sortField=lastUpdateTime&amp;sortOrder={if $sortField == 'lastUpdateTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.updateServer.lastUpdateTime{/lang}{if $sortField == 'lastUpdateTime'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       \r
+                                       {if $additionalHeadColumns|isset}{@$additionalHeadColumns}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                               {foreach from=$updateServers item=updateServer}\r
+                                       <tr class="updateServerRow {cycle values="container-1,container-2"}">\r
+                                               <td class="columnIcon">\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/{if !$updateServer->disabled}enabled{else}disabled{/if}S.png" alt="" class="toggleButton" title="{lang}wcf.acp.updateServer.{if !$updateServer->disabled}disable{else}enable{/if}{/lang}" data-objectID="{@$updateServer->packageUpdateServerID}" data-disableMessage="{lang}wcf.acp.updateServer.disable{/lang}" data-enableMessage="{lang}wcf.acp.updateServer.enable{/lang}" />\r
+                                                       <a href="index.php?form=UpdateServerEdit&amp;packageUpdateServerID={@$updateServer->packageUpdateServerID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/editS.png" alt="" title="{lang}wcf.acp.updateServer.edit{/lang}" /></a>\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.updateServer.delete{/lang}" class="deleteButton" data-objectID="{@$updateServer->packageUpdateServerID}" data-confirmMessage="{lang}wcf.acp.updateServer.delete.sure{/lang}" />\r
+                                                       \r
+                                                       {if $additionalButtons[$updateServer->packageUpdateServerID]|isset}{@$additionalButtons[$updateServer->packageUpdateServerID]}{/if}\r
+                                               </td>\r
+                                               <td class="columnID">{@$updateServer->packageUpdateServerID}</td>\r
+                                               <td class="columnText">\r
+                                                       <a href="index.php?form=UpdateServerEdit&amp;packageUpdateServerID={@$updateServer->packageUpdateServerID}{@SID_ARG_2ND}">\r
+                                                               {@$updateServer->serverURL}\r
+                                                       </a>\r
+                                               </td>\r
+                                               <td class="columnText smallFont">\r
+                                                       {#$updateServer->packages}\r
+                                               </td>\r
+                                               <td class="columnText smallFont" style="color: {if $updateServer->status == 'online'}green{else}red{/if}">\r
+                                                       {@$updateServer->status}\r
+                                               </td>\r
+                                               <td class="columnText smallFont">\r
+                                                       <div title="{@$updateServer->errorMessage}">\r
+                                                               {@$updateServer->errorMessage|truncate:"30"}\r
+                                                       </div>\r
+                                               </td>\r
+                                               <td class="columnDate smallFont">\r
+                                                       {if $updateServer->lastUpdateTime}{@$updateServer->lastUpdateTime|time}{/if}\r
+                                               </td>\r
+                                               \r
+                                               {if $additionalColumns[$updateServer->packageUpdateServerID]|isset}{@$additionalColumns[$updateServer->packageUpdateServerID]}{/if}\r
+                                       </tr>\r
+                               {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+       <div class="contentHeader">\r
+               <div class="largeButtons">\r
+                       <ul><li><a href="index.php?form=UpdateServerAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.updateServer.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/updateServerAddM.png" alt="" /> <span>{lang}wcf.acp.updateServer.add{/lang}</span></a></li></ul>\r
+               </div>\r
+       </div>\r
+{/if}\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/userAdd.tpl b/wcfsetup/install/files/acp/templates/userAdd.tpl
new file mode 100644 (file)
index 0000000..368b5f7
--- /dev/null
@@ -0,0 +1,261 @@
+{include file='header'}\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/TabMenu.class.js"></script>\r
+{if $userID|isset}\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/AjaxRequest.class.js"></script>\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/InlineListEdit.class.js"></script>\r
+       <script type="text/javascript" src="{@RELATIVE_WCF_DIR}acp/js/UserListEdit.class.js"></script>\r
+{/if}\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       var tabMenu = new TabMenu();\r
+       {if $optionTree|count}onloadEvents.push(function() { tabMenu.showSubTabMenu('{@$options[0][object]->categoryName}') });{/if}\r
+       \r
+       {if $userID|isset}\r
+               var userData = new Hash();\r
+               userData.set({@$userID}, {\r
+                       'isMarked': {@$user->isMarked()}\r
+               });\r
+               \r
+               var url = '{@$url|encodeJS}';\r
+               \r
+               // language\r
+               var language = new Object();\r
+               language['wcf.global.button.mark']              = '{lang}wcf.global.button.mark{/lang}';\r
+               language['wcf.global.button.unmark']            = '{lang}wcf.global.button.unmark{/lang}';\r
+               language['wcf.global.button.delete']            = '{lang}wcf.global.button.delete{/lang}';\r
+               language['wcf.acp.user.button.sendMail']        = '{lang}wcf.acp.user.button.sendMail{/lang}';\r
+               language['wcf.acp.user.button.exportMail']      = '{lang}wcf.acp.user.button.exportMail{/lang}';\r
+               language['wcf.acp.user.button.assignGroup']     = '{lang}wcf.acp.user.button.assignGroup{/lang}';\r
+               language['wcf.acp.user.deleteMarked.sure']      = '{lang}wcf.acp.user.deleteMarked.sure{/lang}';\r
+               language['wcf.acp.user.delete.sure']            = '{lang}wcf.acp.user.delete.sure{/lang}';\r
+               language['wcf.acp.user.markedUsers']            = '{lang}wcf.acp.user.markedUsers{/lang}';\r
+               \r
+               // additional options\r
+               var additionalOptions = new Array();\r
+               var additionalUserOptions = new Array();\r
+               {if $additionalUserOptions|isset}{@$additionalUserOptions}{/if}\r
+               {if $additionalMarkedOptions|isset}{@$additionalMarkedOptions}{/if}\r
+               \r
+               // permissions\r
+               var permissions = new Object();\r
+               permissions['canEditUser'] = {if $__wcf->session->getPermission('admin.user.canEditUser')}1{else}0{/if};\r
+               permissions['canDeleteUser'] = {if $__wcf->session->getPermission('admin.user.canDeleteUser')}1{else}0{/if};\r
+               permissions['canMailUser'] = {if $__wcf->session->getPermission('admin.user.canMailUser')}1{else}0{/if};\r
+               permissions['canEditMailAddress'] = {if $__wcf->session->getPermission('admin.user.canEditMailAddress')}1{else}0{/if};\r
+               permissions['canEditPassword'] = {if $__wcf->session->getPermission('admin.user.canEditPassword')}1{else}0{/if};\r
+               \r
+               onloadEvents.push(function() { userListEdit = new UserListEdit(userData, {@$markedUsers}, additionalUserOptions, additionalOptions); });\r
+       {/if}\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img {if $userID|isset}id="userEdit{@$userID}" {/if}src="{@RELATIVE_WCF_DIR}icon/user{@$action|ucfirst}L.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.user.{@$action}{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+{if $success|isset}\r
+       <p class="success">{lang}wcf.acp.user.{@$action}.success{/lang}</p>     \r
+{/if}\r
+\r
+{if $userID|isset && $__wcf->user->userID == $userID}\r
+       <p class="warning">{lang}wcf.acp.user.edit.warning.selfEdit{/lang}</p>  \r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?page=UserList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.user.list{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/usersM.png" alt="" /> <span>{lang}wcf.acp.menu.link.user.list{/lang}</span></a></li>\r
+                       <li><a href="index.php?form=UserSearch{@SID_ARG_2ND}" title="{lang}wcf.acp.user.search{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/searchM.png" alt="" /> <span>{lang}wcf.acp.user.search{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+<form method="post" action="index.php?form=User{@$action|ucfirst}">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <div class="formElement{if $errorType.username|isset} formError{/if}">\r
+                               <div class="formFieldLabel">\r
+                                       <label for="username">{lang}wcf.user.username{/lang}</label>\r
+                               </div>\r
+                               <div class="formField">\r
+                                       <input type="text" class="inputText" id="username" name="username" value="{$username}" />\r
+                                       {if $errorType.username|isset}\r
+                                               <p class="innerError">\r
+                                                       {if $errorType.username == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                       {if $errorType.username == 'notValid'}{lang}wcf.user.error.username.notValid{/lang}{/if}\r
+                                                       {if $errorType.username == 'notUnique'}{lang}wcf.user.error.username.notUnique{/lang}{/if}\r
+                                               </p>\r
+                                       {/if}\r
+                               </div>\r
+                       </div>\r
+                       \r
+                       {if $availableGroups|count}\r
+                               <div class="formGroup">\r
+                                       <div class="formGroupLabel">\r
+                                               <label>{lang}wcf.acp.user.groups{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formGroupField">\r
+                                               <fieldset>\r
+                                                       <legend>{lang}wcf.acp.user.groups{/lang}</legend>\r
+                                                       \r
+                                                       <div class="formField">\r
+                                                               {htmlCheckboxes options=$availableGroups name=groupIDs selected=$groupIDs}\r
+                                                       </div>\r
+                                               </fieldset>\r
+                                       </div>\r
+                               </div>\r
+                       {/if}\r
+                       \r
+                       {if $action == 'add' || $__wcf->session->getPermission('admin.user.canEditMailAddress')}\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.user.email{/lang}</legend>\r
+                                       <div class="formElement{if $errorType.email|isset} formError{/if}">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="email">{lang}wcf.user.email{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField"> \r
+                                                       <input type="text" class="inputText" id="email" name="email" value="{$email}" />\r
+                                                       {if $errorType.email|isset}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType.email == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                                       {if $errorType.email == 'notValid'}{lang}wcf.user.error.email.notValid{/lang}{/if}\r
+                                                                       {if $errorType.email == 'notUnique'}{lang}wcf.user.error.email.notUnique{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                                       \r
+                                       <div class="formElement{if $errorType.confirmEmail|isset} formError{/if}">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="confirmEmail">{lang}wcf.user.confirmEmail{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <input type="text" class="inputText" id="confirmEmail" name="confirmEmail" value="{$confirmEmail}" />\r
+                                                       {if $errorType.confirmEmail|isset}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType.confirmEmail == 'notEqual'}{lang}wcf.user.error.confirmEmail.notEqual{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                               </fieldset>\r
+                       {/if}\r
+                       \r
+                       {if $action == 'add' || $__wcf->session->getPermission('admin.user.canEditPassword')}\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.user.password{/lang}</legend>\r
+                                       <div class="formElement{if $errorType.password|isset} formError{/if}">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="password">{lang}wcf.user.password{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <input type="password" class="inputText" id="password" name="password" value="{$password}" />\r
+                                                       {if $errorType.password|isset}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType.password == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                                       \r
+                                       <div class="formElement{if $errorType.confirmPassword|isset} formError{/if}">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="confirmPassword">{lang}wcf.user.confirmPassword{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <input type="password" class="inputText" id="confirmPassword" name="confirmPassword" value="{$confirmPassword}" />\r
+                                                       {if $errorType.confirmPassword|isset}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType.confirmPassword == 'notEqual'}{lang}wcf.user.error.confirmPassword.notEqual{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                               </fieldset>\r
+                       {/if}\r
+               \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+                       \r
+                       {if $optionTree|count || $additionalTabs|isset}\r
+                               <div class="tabMenu">\r
+                                       <ul>\r
+                                               {foreach from=$optionTree item=categoryLevel1}\r
+                                                       <li id="{@$categoryLevel1[object]->categoryName}"><a onclick="tabMenu.showSubTabMenu('{@$categoryLevel1[object]->categoryName}');"><span>{lang}wcf.user.option.category.{@$categoryLevel1[object]->categoryName}{/lang}</span></a></li>\r
+                                               {/foreach}\r
+                                               \r
+                                               {if $additionalTabs|isset}{@$additionalTabs}{/if}\r
+                                       </ul>\r
+                               </div>\r
+                               <div class="subTabMenu">\r
+                                       <div class="containerHead"><div> </div></div>\r
+                               </div>\r
+                               \r
+                               {foreach from=$optionTree item=categoryLevel1}\r
+                                       <div class="border tabMenuContent hidden" id="{@$categoryLevel1[object]->categoryName}-content">\r
+                                               <div class="container-1">\r
+                                                       <h3 class="subHeadline">{lang}wcf.user.option.category.{@$categoryLevel1[object]->categoryName}{/lang}</h3>\r
+                                                       \r
+                                                       {foreach from=$categoryLevel1[categories] item=categoryLevel2}\r
+                                                               <fieldset>\r
+                                                                       <legend>{lang}wcf.user.option.category.{@$categoryLevel2[object]->categoryName}{/lang}</legend>\r
+                                                                       \r
+                                                                       {if $categoryLevel2[object]->categoryName == 'settings.general' && $availableLanguages|count > 1}\r
+                                                                               <div class="formElement">\r
+                                                                                       <div class="formFieldLabel">\r
+                                                                                               <label for="languageID">{lang}wcf.user.language{/lang}</label>\r
+                                                                                       </div>\r
+                                                                                       <div class="formField">\r
+                                                                                               {htmlOptions options=$availableLanguages selected=$languageID name=languageID id=languageID disableEncoding=true}\r
+                                                                                       </div>\r
+                                                                               </div>\r
+                                                                                       \r
+                                                                               {if $availableContentLanguages|count > 1}\r
+                                                                                       <div class="formGroup">\r
+                                                                                               <div class="formGroupLabel">\r
+                                                                                                       {lang}wcf.user.visibleLanguages{/lang}\r
+                                                                                               </div>\r
+                                                                                               <div class="formGroupField">\r
+                                                                                                       <fieldset>\r
+                                                                                                               <legend>{lang}wcf.user.visibleLanguages{/lang}</legend>\r
+                                                                                                               <div class="formField">\r
+                                                                                                                       <ul class="formOptions">\r
+                                                                                                                       {foreach from=$availableContentLanguages key=availableLanguageID item=availableLanguage}\r
+                                                                                                                               <li><label><input type="checkbox" name="visibleLanguages[]" value="{@$availableLanguageID}"{if $availableLanguageID|in_array:$visibleLanguages} checked="checked"{/if} /> {@$availableLanguage}</label></li>\r
+                                                                                                                       {/foreach}\r
+                                                                                                                       </ul>\r
+                                                                                                               </div>\r
+                                                                                                       </fieldset>\r
+                                                                                               </div>\r
+                                                                                       </div>\r
+                                                                               {/if}\r
+                                                                       {/if}\r
+                                                                       \r
+                                                                       {include file='optionFieldList' options=$categoryLevel2[options] langPrefix='wcf.user.option.'}\r
+                                                               </fieldset>\r
+                                                       {/foreach}\r
+                                               </div>\r
+                                       </div>\r
+                               {/foreach}\r
+                       {/if}\r
+                       \r
+                       {if $additionalTabContents|isset}{@$additionalTabContents}{/if}\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="action" value="{@$action}" />\r
+               {if $userID|isset}<input type="hidden" name="userID" value="{@$userID}" />{/if}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/userAssignToGroup.tpl b/wcfsetup/install/files/acp/templates/userAssignToGroup.tpl
new file mode 100644 (file)
index 0000000..403e91e
--- /dev/null
@@ -0,0 +1,51 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/usersL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.user.assignToGroup{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="index.php?form=UserAssignToGroup">\r
+\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.assignToGroup.markedUsers{/lang}</legend>\r
+                               \r
+                               <div>\r
+                                       {implode from=$users item=$user}<a href="index.php?form=UserEdit&amp;userID={@$user->userID}{@SID_ARG_2ND}">{$user}</a>{/implode}\r
+                               </div>\r
+                       </fieldset>     \r
+                       \r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.groups{/lang}</legend>\r
+                               \r
+                               <div>\r
+                                       <div class="formField{if $errorField == 'groupIDs'} formError{/if}">\r
+                                               {htmlCheckboxes options=$groups name=groupIDs selected=$groupIDs}\r
+                                               {if $errorField == 'groupIDs'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                               </div>\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="userIDs" value="{@$userIDs}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/userEmailAddressExport.tpl b/wcfsetup/install/files/acp/templates/userEmailAddressExport.tpl
new file mode 100644 (file)
index 0000000..ed7c2e2
--- /dev/null
@@ -0,0 +1,90 @@
+{include file='header'}\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       function setFileType(newType) {\r
+               switch (newType) {\r
+                       case 'csv':\r
+                               showOptions('separatorDiv', 'textSeparatorDiv');\r
+                               break;\r
+                       case 'xml':\r
+                               hideOptions('separatorDiv', 'textSeparatorDiv');\r
+                               break;\r
+               }\r
+       }\r
+       onloadEvents.push(function() { setFileType('{@$fileType}'); });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/usersL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.user.exportEmailAddress{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+<form method="post" action="index.php?form=UserEmailAddressExport">\r
+\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.exportEmailAddress.markedUsers{/lang}</legend>\r
+                               \r
+                               <div>\r
+                                       {implode from=$users item=$user}<a href="index.php?form=UserEdit&amp;userID={@$user->userID}{@SID_ARG_2ND}">{$user}</a>{/implode}\r
+                               </div>\r
+                       </fieldset>     \r
+                       \r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.exportEmailAddress.format{/lang}</legend>\r
+                               \r
+                               <div>\r
+                                       <div class="formGroup">\r
+                                               <div class="formGroupLabel">\r
+                                                       <label>{lang}wcf.acp.user.exportEmailAddress.fileType{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formGroupField">\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.user.exportEmailAddress.fileType{/lang}</legend>\r
+                                                               \r
+                                                               <div class="formField">\r
+                                                                       <ul class="formOptionsLong">\r
+                                                                               <li><label><input onclick="if (IS_SAFARI) setFileType('csv')" onfocus="setFileType('csv')" type="radio" name="fileType" value="csv" {if $fileType == 'csv'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.csv{/lang}</label></li>\r
+                                                                               <li><label><input onclick="if (IS_SAFARI) setFileType('xml')" onfocus="setFileType('xml')" type="radio" name="fileType" value="xml" {if $fileType == 'xml'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.xml{/lang}</label></li>\r
+                                                                       </ul>\r
+                                                               </div>\r
+                                                       </fieldset>\r
+                                               </div>\r
+                                       </div>\r
+                               \r
+                                       <div class="formElement" id="separatorDiv">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="separator">{lang}wcf.acp.user.exportEmailAddress.separator{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <textarea id="separator" name="separator" rows="2" cols="40">{$separator}</textarea>\r
+                                               </div>\r
+                                       </div>\r
+                                       \r
+                                       <div class="formElement" id="textSeparatorDiv">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="textSeparator">{lang}wcf.acp.user.exportEmailAddress.textSeparator{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <input type="text" class="inputText" id="textSeparator" name="textSeparator" value="{$textSeparator}" />\r
+                                               </div>\r
+                                       </div>\r
+                               </div>\r
+                       </fieldset>\r
+       \r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="userIDs" value="{@$userIDs}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/userException.tpl b/wcfsetup/install/files/acp/templates/userException.tpl
new file mode 100644 (file)
index 0000000..1da9bae
--- /dev/null
@@ -0,0 +1,21 @@
+{include file='header' templateName='userException'}\r
+\r
+<p class="error" id="errorMessage">\r
+       {@$message}\r
+</p>\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       if (document.referrer) {\r
+               onloadEvents.push(function() { document.getElementById('errorMessage').innerHTML += "<br /><a href=\"" + document.referrer + "{@SID_ARG_2ND_NOT_ENCODED}\">{lang}wcf.global.error.backward{/lang}</a>"; });\r
+       }\r
+       //]]>\r
+</script>\r
+\r
+<!-- \r
+{$name} thrown in {$file} ({@$line})\r
+Stracktrace:\r
+{$stacktrace}\r
+-->\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/userGroupAdd.tpl b/wcfsetup/install/files/acp/templates/userGroupAdd.tpl
new file mode 100644 (file)
index 0000000..625a2aa
--- /dev/null
@@ -0,0 +1,129 @@
+{include file='header'}\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/TabMenu.class.js"></script>\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       var tabMenu = new TabMenu();\r
+       onloadEvents.push(function() { tabMenu.showSubTabMenu("{$activeTabMenuItem}", "{$activeSubTabMenuItem}"); });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/userGroup{@$action|ucfirst}L.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.group.{@$action}{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+{if $success|isset}\r
+       <p class="success">{lang}wcf.acp.group.{@$action}.success{/lang}</p>    \r
+{/if}\r
+\r
+{if $warningSelfEdit|isset}\r
+       <p class="warning">{lang}wcf.acp.group.edit.warning.selfIsMember{/lang}</p>     \r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?page=UserGroupList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.group.view{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/userGroupM.png" alt="" /> <span>{lang}wcf.acp.menu.link.group.view{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+<form method="post" action="index.php?form=UserGroup{@$action|ucfirst}">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.group.data{/lang}</legend>\r
+                               \r
+                               <div class="formElement{if $errorType.groupName|isset} formError{/if}" id="groupNameDiv">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="groupName">{lang}wcf.acp.group.groupName{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="groupName" name="groupName" value="{$groupName}" />\r
+                                               {if $errorType.groupName|isset}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType.groupName == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </div>\r
+                                       <div class="formFieldDesc hidden" id="groupNameHelpMessage">\r
+                                               <p>{lang}wcf.acp.group.groupName.description{/lang}</p>\r
+                                       </div>\r
+                               </div>\r
+                               <script type="text/javascript">//<![CDATA[\r
+                                       inlineHelp.register('groupName');\r
+                               //]]></script>\r
+                               \r
+                               {if $additionalFields|isset}{@$additionalFields}{/if}\r
+                       </fieldset>\r
+               \r
+                       {if $additionalFieldSets|isset}{@$additionalFieldSets}{/if}\r
+               \r
+                       <div class="tabMenu">\r
+                               <ul>\r
+                                       {foreach from=$optionTree item=categoryLevel1}\r
+                                               <li id="{@$categoryLevel1[object]->categoryName}"><a onclick="tabMenu.showSubTabMenu('{@$categoryLevel1[object]->categoryName}');"><span>{lang}wcf.acp.group.option.category.{@$categoryLevel1[object]->categoryName}{/lang}</span></a></li>\r
+                                       {/foreach}\r
+                               </ul>\r
+                       </div>\r
+                       <div class="subTabMenu">\r
+                               <div class="containerHead">\r
+                                       {foreach from=$optionTree item=categoryLevel1}\r
+                                               <ul class="hidden" id="{@$categoryLevel1[object]->categoryName}-categories">\r
+                                                       {foreach from=$categoryLevel1[categories] item=categoryLevel2}\r
+                                                               <li id="{@$categoryLevel1[object]->categoryName}-{@$categoryLevel2[object]->categoryName}"><a onclick="tabMenu.showTabMenuContent('{@$categoryLevel1[object]->categoryName}-{@$categoryLevel2[object]->categoryName}');"><span>{lang}wcf.acp.group.option.category.{@$categoryLevel2[object]->categoryName}{/lang}</span></a></li>\r
+                                                       {/foreach}\r
+                                               </ul>\r
+                                       {/foreach}\r
+                               </div>\r
+                       </div>\r
+                       \r
+                       {foreach from=$optionTree item=categoryLevel1}\r
+                               {foreach from=$categoryLevel1[categories] item=categoryLevel2}\r
+                                       <div class="border tabMenuContent hidden" id="{@$categoryLevel1[object]->categoryName}-{@$categoryLevel2[object]->categoryName}-content">\r
+                                               <div class="container-1">\r
+                                                       <h3 class="subHeadline">{lang}wcf.acp.group.option.category.{@$categoryLevel2[object]->categoryName}{/lang}</h3>\r
+                                                       <p class="description">{lang}wcf.acp.group.option.category.{@$categoryLevel2[object]->categoryName}.description{/lang}</p>\r
+                                                       \r
+                                                       {if $categoryLevel2[options]|count}\r
+                                                               {include file='optionFieldList' options=$categoryLevel2[options] langPrefix='wcf.acp.group.option.'}\r
+                                                       {/if}\r
+                                                       \r
+                                                       {if $categoryLevel2[categories]|count}\r
+                                                               {foreach from=$categoryLevel2[categories] item=categoryLevel3}\r
+                                                                       <fieldset>\r
+                                                                               <legend>{lang}wcf.acp.group.option.category.{@$categoryLevel3[object]->categoryName}{/lang}</legend>\r
+                                                                               <p class="description">{lang}wcf.acp.group.option.category.{@$categoryLevel3[object]->categoryName}.description{/lang}</p>\r
+                                                                       \r
+                                                                               <div>\r
+                                                                                       {include file='optionFieldList' options=$categoryLevel3[options] langPrefix='wcf.acp.group.option.'}\r
+                                                                               </div>\r
+                                                                       </fieldset>\r
+                                                               {/foreach}\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                               {/foreach}\r
+                       {/foreach}\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="action" value="{@$action}" />\r
+               {if $groupID|isset}<input type="hidden" name="groupID" value="{@$groupID}" />{/if}\r
+               \r
+               <input type="hidden" id="activeTabMenuItem" name="activeTabMenuItem" value="{$activeTabMenuItem}" />\r
+               <input type="hidden" id="activeSubTabMenuItem" name="activeSubTabMenuItem" value="{$activeSubTabMenuItem}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/userGroupList.tpl b/wcfsetup/install/files/acp/templates/userGroupList.tpl
new file mode 100644 (file)
index 0000000..f878807
--- /dev/null
@@ -0,0 +1,100 @@
+{include file='header'}\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/RemoveObjectAction.class.js"></script>\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       var removeGroup = new RemoveObjectAction();\r
+       removeGroup.setOptions({\r
+               actionClass: 'UserGroup',\r
+               containerPrefix: 'groupContainer',\r
+               iconPrefix: 'groupDeleteIcon',\r
+               langDeleteSure: '{lang}wcf.acp.group.delete.sure{/lang}',\r
+               url: 'index.php?action=RemoveObject'\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/userGroupL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.group.list{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $deletedGroups}\r
+       <p class="success">{lang}wcf.acp.group.delete.success{/lang}</p>\r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       {pages print=true assign=pagesLinks link="index.php?page=UserGroupList&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?form=UserGroupAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.group.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/userGroupAddM.png" alt="" /> <span>{lang}wcf.acp.group.add{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}                       \r
+               </ul>\r
+       </div>\r
+</div>\r
+\r
+{if $groups|count}\r
+       <div class="border titleBarPanel">\r
+               <div class="containerHead"><h3>{lang}wcf.acp.group.list.data{/lang}</h3></div>\r
+       </div>\r
+       <div class="border borderMarginRemove">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th class="columnGroupID{if $sortField == 'groupID'} active{/if}" colspan="2"><div><a href="index.php?page=UserGroupList&amp;pageNo={@$pageNo}&amp;sortField=groupID&amp;sortOrder={if $sortField == 'groupID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.group.groupID{/lang}{if $sortField == 'groupID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnGroupName{if $sortField == 'groupName'} active{/if}"><div><a href="index.php?page=UserGroupList&amp;pageNo={@$pageNo}&amp;sortField=groupName&amp;sortOrder={if $sortField == 'groupName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.group.groupName{/lang}{if $sortField == 'groupName'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnMembers{if $sortField == 'members'} active{/if}"><div><a href="index.php?page=UserGroupList&amp;pageNo={@$pageNo}&amp;sortField=members&amp;sortOrder={if $sortField == 'members' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.acp.group.members{/lang}{if $sortField == 'members'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       \r
+                                       {if $additionalHeadColumns|isset}{@$additionalHeadColumns}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                               {foreach from=$groups item=group}\r
+                                       <tr class="{cycle values="container-1,container-2"}" id="groupContainer{@$group->groupID}">\r
+                                               <td class="columnIcon">\r
+                                                       {if $group->isEditable()}\r
+                                                               <a href="index.php?form=UserGroupEdit&amp;groupID={@$group->groupID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/editS.png" alt="" title="{lang}wcf.acp.group.edit{/lang}" /></a>\r
+                                                       {else}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/editDisabledS.png" alt="" title="{lang}wcf.acp.group.edit{/lang}" />\r
+                                                       {/if}\r
+                                                       {if $group->isDeletable()}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.group.delete{/lang}" id="groupDeleteIcon{@$group->groupID}" />\r
+                                                               <script type="text/javascript">\r
+                                                                       //<![CDATA[\r
+                                                                       removeGroup.registerObject({@$group->groupID}, {\r
+                                                                               objectID: {@$group->groupID}\r
+                                                                       });\r
+                                                                       //]]>\r
+                                                               </script>\r
+                                                       {else}\r
+                                                               <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.group.delete{/lang}" />\r
+                                                       {/if}\r
+                                                       \r
+                                                       {if $additionalButtons[$group->groupID]|isset}{@$additionalButtons[$group->groupID]}{/if}\r
+                                               </td>\r
+                                               <td class="columnGroupID columnID">{@$group->groupID}</td>\r
+                                               <td class="columnGroupName columnText">{if $group->isEditable()}<a title="{lang}wcf.acp.group.edit{/lang}" href="index.php?form=UserGroupEdit&amp;groupID={@$group->groupID}{@SID_ARG_2ND}">{$group->groupName}</a>{else}{$group->groupName}{/if}</td>\r
+                                               <td class="columnMembers columnNumbers"><a title="{lang}wcf.acp.group.showMembers{/lang}" href="index.php?form=UserSearch&amp;groupID={@$group->groupID}{@SID_ARG_2ND}">{#$group->members}</a></td>\r
+                                               \r
+                                               {if $additionalColumns[$group->groupID]|isset}{@$additionalColumns[$group->groupID]}{/if}\r
+                                       </tr>\r
+                               {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+{/if}\r
+\r
+<div class="contentFooter">\r
+       {@$pagesLinks}\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?form=UserGroupAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.group.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/userGroupAddM.png" alt="" /> <span>{lang}wcf.acp.group.add{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/userList.tpl b/wcfsetup/install/files/acp/templates/userList.tpl
new file mode 100644 (file)
index 0000000..c91ce1d
--- /dev/null
@@ -0,0 +1,148 @@
+{include file='header'}\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/MultiPagesLinks.class.js"></script>\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/AjaxRequest.class.js"></script>\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/InlineListEdit.class.js"></script>\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}acp/js/UserListEdit.class.js"></script>\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       // data array\r
+       var userData = new Hash();\r
+       var url = '{@$url|encodeJS}';\r
+       \r
+       // language\r
+       var language = new Object();\r
+       language['wcf.global.button.mark']              = '{lang}wcf.global.button.mark{/lang}';\r
+       language['wcf.global.button.unmark']            = '{lang}wcf.global.button.unmark{/lang}';\r
+       language['wcf.global.button.delete']            = '{lang}wcf.global.button.delete{/lang}';\r
+       language['wcf.acp.user.button.sendMail']        = '{lang}wcf.acp.user.button.sendMail{/lang}';\r
+       language['wcf.acp.user.button.exportMail']      = '{lang}wcf.acp.user.button.exportMail{/lang}';\r
+       language['wcf.acp.user.button.assignGroup']     = '{lang}wcf.acp.user.button.assignGroup{/lang}';\r
+       language['wcf.acp.user.deleteMarked.sure']      = '{lang}wcf.acp.user.deleteMarked.sure{/lang}';\r
+       language['wcf.acp.user.delete.sure']            = '{lang}wcf.acp.user.delete.sure{/lang}';\r
+       language['wcf.acp.user.markedUsers']            = '{lang}wcf.acp.user.markedUsers{/lang}';\r
+       \r
+       // additional options\r
+       var additionalOptions = new Array();\r
+       var additionalUserOptions = new Array();\r
+       {if $additionalMarkedOptions|isset}{@$additionalMarkedOptions}{/if}\r
+       \r
+       // permissions\r
+       var permissions = new Object();\r
+       permissions['canEditUser'] = {if $__wcf->session->getPermission('admin.user.canEditUser')}1{else}0{/if};\r
+       permissions['canDeleteUser'] = {if $__wcf->session->getPermission('admin.user.canDeleteUser')}1{else}0{/if};\r
+       permissions['canMailUser'] = {if $__wcf->session->getPermission('admin.user.canMailUser')}1{else}0{/if};\r
+       permissions['canEditMailAddress'] = {if $__wcf->session->getPermission('admin.user.canEditMailAddress')}1{else}0{/if};\r
+       permissions['canEditPassword'] = {if $__wcf->session->getPermission('admin.user.canEditPassword')}1{else}0{/if};\r
+       \r
+       onloadEvents.push(function() { userListEdit = new UserListEdit(userData, {@$markedUsers}, additionalUserOptions, additionalOptions); });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/{if $searchID}userSearch{else}users{/if}L.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.user.{if $searchID}search{else}list{/if}{/lang}</h2>\r
+               <p>{if $searchID}{lang}wcf.acp.user.search.matches{/lang}{else}{lang}wcf.acp.user.list.count{/lang}{/if}</p>\r
+       </div>\r
+</div>\r
+\r
+{assign var=encodedURL value=$url|rawurlencode}\r
+{assign var=encodedAction value=$action|rawurlencode}\r
+<div class="contentHeader">\r
+       {pages print=true assign=pagesLinks link="index.php?page=UserList&pageNo=%d&searchID=$searchID&action=$encodedAction&sortField=$sortField&sortOrder=$sortOrder&packageID="|concat:SID_ARG_2ND_NOT_ENCODED}\r
+       \r
+       <div class="largeButtons">\r
+               <ul>\r
+                       {if $__wcf->session->getPermission('admin.user.canAddUser')}\r
+                               <li><a href="index.php?form=UserAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.user.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/userAddM.png" alt="" /> <span>{lang}wcf.acp.user.add{/lang}</span></a></li>\r
+                       {/if}\r
+                       <li><a href="index.php?form=UserSearch{@SID_ARG_2ND}" title="{lang}wcf.acp.user.search{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/searchM.png" alt="" /> <span>{lang}wcf.acp.user.search{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+\r
+<div class="subTabMenu">\r
+       <div class="containerHead">\r
+               <ul>\r
+                       <li{if $action == ''} class="activeSubTabMenu"{/if}><a href="index.php?page=UserList{@SID_ARG_2ND}"><span>{lang}wcf.acp.user.list.all{/lang}</span></a></li>\r
+                       {if $additionalUserListOptions|isset}{@$additionalUserListOptions}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+{if $users|count}\r
+       <div class="border">\r
+               <table class="tableList">\r
+                       <thead>\r
+                               <tr class="tableHead">\r
+                                       <th class="columnMark"><div><label class="emptyHead"><input name="userMarkAll" type="checkbox" /></label></div></th>\r
+                                       <th class="columnUserID{if $sortField == 'userID'} active{/if}" colspan="2"><div><a href="index.php?page=UserList&amp;searchID={@$searchID}&amp;action={@$encodedAction}&amp;pageNo={@$pageNo}&amp;sortField=userID&amp;sortOrder={if $sortField == 'userID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.user.userID{/lang}{if $sortField == 'userID'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       <th class="columnUsername{if $sortField == 'username'} active{/if}"><div><a href="index.php?page=UserList&amp;searchID={@$searchID}&amp;action={@$encodedAction}&amp;pageNo={@$pageNo}&amp;sortField=username&amp;sortOrder={if $sortField == 'username' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}wcf.user.username{/lang}{if $sortField == 'username'} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       \r
+                                       {foreach from=$columnHeads key=column item=columnLanguageVariable}\r
+                                               <th class="column{$column|ucfirst}{if $sortField == $column} active{/if}"><div><a href="index.php?page=UserList&amp;searchID={@$searchID}&amp;action={@$encodedAction}&amp;pageNo={@$pageNo}&amp;sortField={$column}&amp;sortOrder={if $sortField == $column && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@SID_ARG_2ND}">{lang}{$columnLanguageVariable}{/lang}{if $sortField == $column} <img src="{@RELATIVE_WCF_DIR}icon/sort{@$sortOrder}S.png" alt="" />{/if}</a></div></th>\r
+                                       {/foreach}\r
+                                       \r
+                                       {if $additionalColumnHeads|isset}{@$additionalColumnHeads}{/if}\r
+                               </tr>\r
+                       </thead>\r
+                       <tbody>\r
+                       {foreach from=$users item=user}\r
+                               <tr class="{cycle values="container-1,container-2" advance=false}" id="userRow{@$user->userID}">\r
+                                       <td class="columnMark"><input name="userMark" id="userMark{@$user->userID}" type="checkbox" value="{@$user->userID}" /></td>\r
+                                       <td class="columnIcon">\r
+                                               <script type="text/javascript">\r
+                                                       //<![CDATA[\r
+                                                       userData.set({@$user->userID}, {\r
+                                                               'isMarked': {@$user->isMarked},\r
+                                                               'className': '{cycle values="container-1,container-2"}'\r
+                                                       });\r
+                                                       //]]>\r
+                                               </script>\r
+                                               \r
+                                               {if $user->editable}\r
+                                                       <a href="index.php?form=UserEdit&amp;userID={@$user->userID}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/editS.png" alt="" title="{lang}wcf.acp.user.edit{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/editDisabledS.png" alt="" title="{lang}wcf.acp.user.edit{/lang}" />\r
+                                               {/if}\r
+                                               {if $user->deletable}\r
+                                                       <a onclick="return confirm('{lang}wcf.acp.user.delete.sure{/lang}')" href="index.php?action=UserDelete&amp;userID={@$user->userID}&amp;url={@$encodedURL}{@SID_ARG_2ND}"><img src="{@RELATIVE_WCF_DIR}icon/deleteS.png" alt="" title="{lang}wcf.acp.user.delete{/lang}" /></a>\r
+                                               {else}\r
+                                                       <img src="{@RELATIVE_WCF_DIR}icon/deleteDisabledS.png" alt="" title="{lang}wcf.acp.user.delete{/lang}" />\r
+                                               {/if}\r
+                                               \r
+                                               {if $additionalButtons[$user->userID]|isset}{@$additionalButtons[$user->userID]}{/if}\r
+                                       </td>\r
+                                       <td class="columnUserID columnID">{@$user->userID}</td>\r
+                                       <td class="columnUsername columnText">{if $user->editable}<a title="{lang}wcf.acp.user.edit{/lang}" href="index.php?form=UserEdit&amp;userID={@$user->userID}{@SID_ARG_2ND}">{$user->username}</a>{else}{$user->username}{/if}</td>\r
+                                       \r
+                                       {foreach from=$columnHeads key=column item=columnLanguageVariable}\r
+                                               <td class="column{$column|ucfirst}">{if $columnValues[$user->userID][$column]|isset}{@$columnValues[$user->userID][$column]}{/if}</td>\r
+                                       {/foreach}\r
+                                       \r
+                                       {if $additionalColumns[$user->userID]|isset}{@$additionalColumns[$user->userID]}{/if}\r
+                               </tr>\r
+                       {/foreach}\r
+                       </tbody>\r
+               </table>\r
+       </div>\r
+       <div class="contentFooter">\r
+               {@$pagesLinks} <div id="userEditMarked" class="optionButtons"></div>\r
+               \r
+               <div class="largeButtons">\r
+                       <ul>\r
+                               {if $__wcf->session->getPermission('admin.user.canAddUser')}\r
+                                       <li><a href="index.php?form=UserAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.user.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/userAddM.png" alt="" /> <span>{lang}wcf.acp.user.add{/lang}</span></a></li>\r
+                               {/if}\r
+                               <li><a href="index.php?form=UserSearch{@SID_ARG_2ND}" title="{lang}wcf.acp.user.search{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/searchM.png" alt="" /> <span>{lang}wcf.acp.user.search{/lang}</span></a></li>\r
+                               {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+                       </ul>\r
+               </div>\r
+       </div>\r
+{else}\r
+       <div class="border content">\r
+               <div class="container-1">{lang}wcf.acp.user.search.error.noMatches{/lang}</div>\r
+       </div>\r
+{/if}\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/userMail.tpl b/wcfsetup/install/files/acp/templates/userMail.tpl
new file mode 100644 (file)
index 0000000..25969b4
--- /dev/null
@@ -0,0 +1,154 @@
+{include file='header'}\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/emailL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>\r
+                       {if $action == 'all'}\r
+                               {lang}wcf.acp.user.sendMail.all{/lang}\r
+                       {elseif $action == 'group'}\r
+                               {lang}wcf.acp.user.sendMail.group{/lang}\r
+                       {else}\r
+                               {lang}wcf.acp.user.sendMail{/lang}\r
+                       {/if}\r
+               </h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       <li><a href="index.php?page=UserList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.user.list{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/usersM.png" alt="" /> <span>{lang}wcf.acp.menu.link.user.list{/lang}</span></a></li>\r
+                       <li><a href="index.php?form=UserSearch{@SID_ARG_2ND}" title="{lang}wcf.acp.user.search{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/searchM.png" alt="" /> <span>{lang}wcf.acp.user.search{/lang}</span></a></li>\r
+                       {if $additionalLargeButtons|isset}{@$additionalLargeButtons}{/if}\r
+               </ul>\r
+       </div>\r
+</div>\r
+<form method="post" action="index.php?form=UserMail">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+       \r
+                       {if $action == ''}\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.acp.user.sendMail.markedUsers{/lang}</legend>\r
+                                       \r
+                                       <div>\r
+                                               {implode from=$users item=$user}<a href="index.php?form=UserEdit&amp;userID={@$user->userID}{@SID_ARG_2ND}">{$user}</a>{/implode}\r
+                                       </div>\r
+                               </fieldset>     \r
+                       {/if}\r
+                       {if $action == 'group'}\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.acp.user.sendMail.groups{/lang}</legend>\r
+                                       \r
+                                       <div class="formGroup{if $errorField == 'groupIDs'} formError{/if}">\r
+                                               <div class="formGroupLabel">\r
+                                                       <label>{lang}wcf.acp.user.groups{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formGroupField">\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.user.groups{/lang}</legend>\r
+                                                               \r
+                                                               <div class="formField">\r
+                                                                       {htmlCheckboxes options=$groups name=groupIDs selected=$groupIDs}\r
+                                                               </div>\r
+                                                       </fieldset>\r
+                                                       {if $errorField == 'groupIDs'}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                               </fieldset>     \r
+                       {/if}\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.sendMail.mail{/lang}</legend>\r
+                               \r
+                               <div>\r
+                                       <div class="formElement{if $errorField == 'subject'} formError{/if}" id="subjectDiv">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="subject">{lang}wcf.acp.user.sendMail.subject{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <input type="text" class="inputText" id="subject" name="subject" value="{$subject}" />\r
+                                                       {if $errorField == 'subject'}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                               <div class="formFieldDesc hidden" id="subjectHelpMessage">\r
+                                                       <p>{lang}wcf.acp.user.sendMail.subject.description{/lang}</p>\r
+                                               </div>\r
+                                       </div>\r
+                                       <script type="text/javascript">//<![CDATA[\r
+                                               inlineHelp.register('subject');\r
+                                       //]]></script>\r
+                                       \r
+                                       <div class="formElement{if $errorField == 'from'} formError{/if}" id="fromDiv">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="from">{lang}wcf.acp.user.sendMail.from{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <input type="text" class="inputText" id="from" name="from" value="{$from}" />\r
+                                                       {if $errorField == 'from'}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                               <div class="formFieldDesc hidden" id="fromHelpMessage">\r
+                                                       <p>{lang}wcf.acp.user.sendMail.from.description{/lang}</p>\r
+                                               </div>\r
+                                       </div>\r
+                                       <script type="text/javascript">//<![CDATA[\r
+                                               inlineHelp.register('from');\r
+                                       //]]></script>\r
+                               \r
+                                       <div class="formElement{if $errorField == 'text'} formError{/if}" id="textDiv">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="text">{lang}wcf.acp.user.sendMail.text{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField">\r
+                                                       <textarea id="text" name="text" rows="15" cols="40">{$text}</textarea>\r
+                                                       {if $errorField == 'text'}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                               <div class="formFieldDesc hidden" id="textHelpMessage">\r
+                                                       <p>{lang}wcf.acp.user.sendMail.text.description{/lang}</p>\r
+                                               </div>\r
+                                       </div>\r
+                                       <script type="text/javascript">//<![CDATA[\r
+                                               inlineHelp.register('text');\r
+                                       //]]></script>\r
+                                       \r
+                                       <div class="formElement">\r
+                                               <div class="formField">\r
+                                                       <label><input type="checkbox" name="enableHTML" id="enableHTML" value="1" {if $enableHTML == 1}checked="checked" {/if}/> {lang}wcf.acp.user.sendMail.enableHTML{/lang}</label>\r
+                                               </div>\r
+                                       </div>\r
+                               </div>\r
+                               \r
+                               {if $additionalFields|isset}{@$additionalFields}{/if}\r
+                       </fieldset>\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               <input type="hidden" name="action" value="{@$action}" />\r
+               {@SID_INPUT_TAG}\r
+               <input type="hidden" name="userIDs" value="{@$userIDs}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/userSearch.tpl b/wcfsetup/install/files/acp/templates/userSearch.tpl
new file mode 100644 (file)
index 0000000..23273f5
--- /dev/null
@@ -0,0 +1,238 @@
+{include file='header'}\r
+\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/Suggestion.class.js"></script>\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/TabMenu.class.js"></script>\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       var tabMenu = new TabMenu();\r
+       onloadEvents.push(function() {\r
+               //tabMenu.showSubTabMenu('profile');\r
+               tabMenu.showSubTabMenu('resultOptions');\r
+               $('username').focus();\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/userSearchL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.user.search{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField == 'search'}\r
+<p class="error">{lang}wcf.acp.user.search.error.noMatches{/lang}</p>\r
+{/if}\r
+\r
+{*if $deletedUsers}\r
+       <p class="success">{lang}wcf.acp.user.delete.success{/lang}</p> \r
+{elseif $deletedUsers === 0}\r
+       <p class="error">{lang}wcf.acp.user.delete.error{/lang}</p>     \r
+{/if*}\r
+\r
+<div class="contentHeader">\r
+       <div class="largeButtons">\r
+               <ul>\r
+                       {if $__wcf->session->getPermission('admin.user.canAddUser')}\r
+                               <li><a href="index.php?form=UserAdd{@SID_ARG_2ND}" title="{lang}wcf.acp.user.add{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/userAddM.png" alt="" /> <span>{lang}wcf.acp.user.add{/lang}</span></a></li>\r
+                       {/if}\r
+                       <li><a href="index.php?page=UserList{@SID_ARG_2ND}" title="{lang}wcf.acp.menu.link.user.list{/lang}"><img src="{@RELATIVE_WCF_DIR}icon/usersM.png" alt="" /> <span>{lang}wcf.acp.menu.link.user.list{/lang}</span></a>\r
+                       </li>\r
+               </ul>\r
+       </div>\r
+</div>\r
+\r
+<form method="post" action="index.php?form=UserSearch">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.search.conditions.general{/lang}</legend>\r
+                               <div class="formElement">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="username">{lang}wcf.user.username{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="username" name="username" value="{$username}" />\r
+                                               <script type="text/javascript">\r
+                                                       //<![CDATA[\r
+                                                       var suggestion = new Suggestion('username');\r
+                                                       suggestion.enableMultiple(false);\r
+                                                       //]]>\r
+                                               </script>\r
+                                       </div>\r
+                               </div>\r
+                               \r
+                               <div class="formElement">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="userID">{lang}wcf.user.userID{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField"> \r
+                                               <input type="text" class="inputText" id="userID" name="userID" value="{$userID}" />\r
+                                       </div>\r
+                               </div>\r
+                               \r
+                               {if $__wcf->session->getPermission('admin.user.canEditMailAddress')}\r
+                                       <div class="formElement">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="email">{lang}wcf.user.email{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField"> \r
+                                                       <input type="text" class="inputText" id="email" name="email" value="{$email}" />\r
+                                               </div>\r
+                                       </div>\r
+                               {/if}\r
+                               \r
+                               {if $availableGroups|count}\r
+                                       <div class="formGroup">\r
+                                               <div class="formGroupLabel">\r
+                                                       <label>{lang}wcf.acp.user.groups{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formGroupField">\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.user.groups{/lang}</legend>\r
+                                                               \r
+                                                               <div class="formField">\r
+                                                                       {htmlCheckboxes options=$availableGroups name='groupIDs' selected=$groupIDs}\r
+                                                                       \r
+                                                                       <label style="margin-top: 10px"><input type="checkbox" name="invertGroupIDs" value="1" {if $invertGroupIDs == 1}checked="checked" {/if}/> {lang}wcf.acp.user.groups.invertSearch{/lang}</label>\r
+                                                               </div>\r
+                                                       </fieldset>\r
+                                               </div>\r
+                                       </div>\r
+                               {/if}\r
+                               \r
+                               {if $availableLanguages|count > 1}\r
+                                       <div class="formGroup">\r
+                                               <div class="formGroupLabel">\r
+                                                       <label>{lang}wcf.user.language{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formGroupField">\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.user.language{/lang}</legend>\r
+                                                               \r
+                                                               <div class="formField">\r
+                                                                       {htmlCheckboxes options=$availableLanguages name='languageIDs' selected=$languageIDs disableEncoding=true}\r
+                                                               </div>\r
+                                                       </fieldset>\r
+                                               </div>\r
+                                       </div>\r
+                               {/if}\r
+                       </fieldset>\r
+                       \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+                       \r
+                       <div class="tabMenu">\r
+                               <ul>\r
+                                       {if $optionTree|count}<li id="profile"><a onclick="tabMenu.showSubTabMenu('profile');"><span>{lang}wcf.acp.user.search.conditions.profile{/lang}</span></a></li>{/if}\r
+                                       {if $additionalTabs|isset}{@$additionalTabs}{/if}\r
+                                       <li id="resultOptions"><a onclick="tabMenu.showSubTabMenu('resultOptions');"><span>{lang}wcf.acp.user.search.display{/lang}</span></a></li>\r
+                               </ul>\r
+                       </div>\r
+                       <div class="subTabMenu">\r
+                               <div class="containerHead"><div> </div></div>\r
+                       </div>\r
+                       \r
+                       {if $optionTree|count}\r
+                               <div class="border tabMenuContent hidden" id="profile-content">\r
+                                       <div class="container-1">\r
+                                               <h3 class="subHeadline">{lang}wcf.acp.user.search.conditions.profile{/lang}</h3>\r
+                                               {include file='optionFieldList' langPrefix='wcf.user.option.' options=$optionTree}\r
+                                       </div>\r
+                               </div>\r
+                       {/if}\r
+                       \r
+                       {if $additionalTabContents|isset}{@$additionalTabContents}{/if}\r
+                       \r
+                       <div class="border tabMenuContent hidden" id="resultOptions-content">\r
+                               <div class="container-1">\r
+                                       <h3 class="subHeadline">{lang}wcf.acp.user.search.display{/lang}</h3>\r
+                                       \r
+                                       <fieldset>\r
+                                               <legend>{lang}wcf.acp.user.search.display.general{/lang}</legend>\r
+                                               \r
+                                               <div class="formElement">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="sortField">{lang}wcf.acp.user.search.display.sort{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <select name="sortField" id="sortField">\r
+                                                                       <option value="userID"{if $sortField == 'userID'} selected="selected"{/if}>{lang}wcf.user.userID{/lang}</option>\r
+                                                                       <option value="username"{if $sortField == 'username'} selected="selected"{/if}>{lang}wcf.user.username{/lang}</option>\r
+                                                                       <option value="email"{if $sortField == 'email'} selected="selected"{/if}>{lang}wcf.user.email{/lang}</option>\r
+                                                                       <option value="registrationDate"{if $sortField == 'registrationDate'} selected="selected"{/if}>{lang}wcf.user.registrationDate{/lang}</option>\r
+                                                                       \r
+                                                                       {if $additionalSortFields|isset}{@$additionalSortFields}{/if}\r
+                                                               </select>\r
+                                                               <select name="sortOrder" id="sortOrder">\r
+                                                                       <option value="ASC"{if $sortOrder == 'ASC'} selected="selected"{/if}>{lang}wcf.global.sortOrder.ascending{/lang}</option>\r
+                                                                       <option value="DESC"{if $sortOrder == 'DESC'} selected="selected"{/if}>{lang}wcf.global.sortOrder.descending{/lang}</option>\r
+                                                               </select>\r
+                                                       </div>\r
+                                               </div>\r
+                                               \r
+                                               <div class="formElement">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="itemsPerPage">{lang}wcf.acp.user.search.display.itemsPerPage{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <input type="text" class="inputText" id="itemsPerPage" name="itemsPerPage" value="{@$itemsPerPage}" />\r
+                                                       </div>\r
+                                               </div>\r
+                                       </fieldset>\r
+                                       \r
+                                       <fieldset>\r
+                                               <legend>{lang}wcf.acp.user.search.display.columns{/lang}</legend>\r
+                                               \r
+                                               {if $optionTree|count}\r
+                                                       <div class="formGroup">\r
+                                                               <div class="formGroupLabel">\r
+                                                                       <label>{lang}wcf.acp.user.search.display.columns.profile{/lang}</label>\r
+                                                               </div>\r
+                                                               <div class="formGroupField">\r
+                                                                       <fieldset>\r
+                                                                               <legend>{lang}wcf.acp.user.search.display.columns.profile{/lang}</legend>\r
+                                                                               \r
+                                                                               <div class="formField">\r
+                                                                                       {foreach from=$optionTree item=option}\r
+                                                                                               <label><input type="checkbox" name="columns[]" value="{$option->optionName}" {if $option->optionName|in_array:$columns}checked="checked" {/if}/> {lang}wcf.user.option.{$option->optionName}{/lang}</label>\r
+                                                                                       {/foreach}\r
+                                                                               </div>\r
+                                                                       </fieldset>\r
+                                                               </div>\r
+                                                       </div>\r
+                                               {/if}\r
+                                               \r
+                                               <div class="formGroup">\r
+                                                       <div class="formGroupLabel">\r
+                                                               <label>{lang}wcf.acp.user.search.display.columns.other{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formGroupField">\r
+                                                               <fieldset>\r
+                                                                       <legend>{lang}wcf.acp.user.search.display.columns.other{/lang}</legend>\r
+                                                                       \r
+                                                                       <div class="formField">\r
+                                                                               <label><input type="checkbox" name="columns[]" value="email" {if "email"|in_array:$columns}checked="checked" {/if}/> {lang}wcf.user.email{/lang}</label>\r
+                                                                               <label><input type="checkbox" name="columns[]" value="registrationDate" {if "registrationDate"|in_array:$columns}checked="checked" {/if}/> {lang}wcf.user.registrationDate{/lang}</label>\r
+                                                                               \r
+                                                                               {if $additionalColumns|isset}{@$additionalColumns}{/if}\r
+                                                                       </div>\r
+                                                               </fieldset>\r
+                                                       </div>\r
+                                               </div>\r
+                                               \r
+                                               \r
+                                       </fieldset>\r
+                               </div>\r
+                       </div>\r
+                       \r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}\r
diff --git a/wcfsetup/install/files/acp/templates/usersMassProcessing.tpl b/wcfsetup/install/files/acp/templates/usersMassProcessing.tpl
new file mode 100644 (file)
index 0000000..4434bb5
--- /dev/null
@@ -0,0 +1,361 @@
+{include file='header'}\r
+\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/Suggestion.class.js"></script>\r
+<script type="text/javascript" src="{@RELATIVE_WCF_DIR}js/TabMenu.class.js"></script>\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       // disable
+       function disableAll() {
+               {foreach from=$availableActions item=availableAction}
+               disable{@$availableAction|ucfirst}();
+               {/foreach}
+       }
+       
+       function disableSendMail() {
+               hideOptions('sendMailDiv');
+       }
+       
+       function disableExportMailAddress() {
+               hideOptions('exportMailAddressDiv');
+       }
+       
+       function disableAssignToGroup() {
+               hideOptions('assignToGroupDiv');
+       }
+       
+       function disableDelete() { }
+       
+       // enable
+       function enableSendMail() {
+               disableAll();
+               showOptions('sendMailDiv');
+       }
+       
+       function enableExportMailAddress() {
+               disableAll();
+               showOptions('exportMailAddressDiv');
+       }
+       
+       function enableAssignToGroup() {
+               disableAll();
+               showOptions('assignToGroupDiv');
+       }
+       
+       function enableDelete() {
+               disableAll();
+       }
+       
+       var tabMenu = new TabMenu();\r
+       onloadEvents.push(function() {
+               tabMenu.showSubTabMenu('profile')
+               {if $action != ''}enable{@$action|ucfirst}();{else}disableAll();{/if}
+       });
+       
+       function setFileType(newType) {
+               switch (newType) {
+                       case 'csv':
+                               showOptions('separatorDiv', 'textSeparatorDiv');
+                               break;
+                       case 'xml':
+                               hideOptions('separatorDiv', 'textSeparatorDiv');
+                               break;
+               }
+       }
+       onloadEvents.push(function() { setFileType('{@$fileType}'); });\r
+       //]]>\r
+</script>\r
+\r
+<div class="mainHeadline">\r
+       <img src="{@RELATIVE_WCF_DIR}icon/usersMassProcessingL.png" alt="" />\r
+       <div class="headlineContainer">\r
+               <h2>{lang}wcf.acp.user.massProcessing{/lang}</h2>\r
+       </div>\r
+</div>\r
+\r
+{if $errorField}\r
+       <p class="error">{lang}wcf.global.form.error{/lang}</p>\r
+{/if}\r
+\r
+{if $affectedUsers|isset}\r
+       <p class="success">{lang}wcf.acp.user.massProcessing.success{/lang}</p> \r
+{/if}\r
+\r
+<p class="warning">{lang}wcf.acp.user.massProcessing.warning{/lang}</p>\r
+\r
+<form method="post" action="index.php?form=UsersMassProcessing">\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <h3 class="subHeadline">{lang}wcf.acp.user.massProcessing.conditions{/lang}</h3>\r
+                       \r
+                       <fieldset>\r
+                               <legend>{lang}wcf.acp.user.search.conditions.general{/lang}</legend>\r
+                               \r
+                               <div class="formElement">\r
+                                       <div class="formFieldLabel">\r
+                                               <label for="username">{lang}wcf.user.username{/lang}</label>\r
+                                       </div>\r
+                                       <div class="formField">\r
+                                               <input type="text" class="inputText" id="username" name="username" value="{$username}" />\r
+                                               <script type="text/javascript">\r
+                                                       //<![CDATA[\r
+                                                       suggestion.enableMultiple(false);\r
+                                                       suggestion.init('username');\r
+                                                       //]]>\r
+                                               </script>\r
+                                       </div>\r
+                               </div>\r
+                               \r
+                               {if $__wcf->user->getPermission('admin.user.canEditMailAddress')}\r
+                                       <div class="formElement">\r
+                                               <div class="formFieldLabel">\r
+                                                       <label for="email">{lang}wcf.user.email{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formField"> \r
+                                                       <input type="text" class="inputText" id="email" name="email" value="{$email}" />\r
+                                               </div>\r
+                                       </div>\r
+                               {/if}\r
+                               \r
+                               {if $availableGroups|count}\r
+                                       <div class="formGroup">\r
+                                               <div class="formGroupLabel">\r
+                                                       <label>{lang}wcf.acp.user.groups{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formGroupField">\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.user.groups{/lang}</legend>\r
+                                                               \r
+                                                               <div class="formField">\r
+                                                                       {htmlCheckboxes options=$availableGroups name='groupIDArray' selected=$groupIDArray}\r
+                                                                       \r
+                                                                       <label style="margin-top: 10px"><input type="checkbox" name="invertGroupIDs" value="1" {if $invertGroupIDs == 1}checked="checked" {/if}/> {lang}wcf.acp.user.groups.invertSearch{/lang}</label>\r
+                                                               </div>\r
+                                                       </fieldset>\r
+                                               </div>\r
+                                       </div>\r
+                               {/if}\r
+                               \r
+                               {if $availableLanguages|count > 1}\r
+                                       <div class="formGroup">\r
+                                               <div class="formGroupLabel">\r
+                                                       <label>{lang}wcf.user.language{/lang}</label>\r
+                                               </div>\r
+                                               <div class="formGroupField">\r
+                                                       <fieldset>\r
+                                                               <legend>{lang}wcf.acp.user.language{/lang}</legend>\r
+                                                               \r
+                                                               <div class="formField">\r
+                                                                       {htmlCheckboxes options=$availableLanguages name='languageIDArray' selected=$languageIDArray disableEncoding=true}\r
+                                                               </div>\r
+                                                       </fieldset>\r
+                                               </div>\r
+                                       </div>\r
+                               {/if}\r
+                       </fieldset>\r
+               \r
+                       {if $additionalFields|isset}{@$additionalFields}{/if}\r
+                       \r
+                       <div class="tabMenu">\r
+                               <ul>\r
+                                       {if $options|count}<li id="profile"><a onclick="tabMenu.showSubTabMenu('profile');"><span>{lang}wcf.acp.user.search.conditions.profile{/lang}</span></a></li>{/if}\r
+                                       {if $additionalTabs|isset}{@$additionalTabs}{/if}\r
+                               </ul>\r
+                       </div>\r
+                       <div class="subTabMenu">\r
+                               <div class="containerHead"><div> </div></div>\r
+                       </div>\r
+                       \r
+                       {if $options|count}\r
+                               <div class="border tabMenuContent hidden" id="profile-content">\r
+                                       <div class="container-1">\r
+                                               <h3 class="subHeadline">{lang}wcf.acp.user.search.conditions.profile{/lang}</h3>\r
+                                               {include file='optionFieldList' langPrefix='wcf.user.option.'}\r
+                                       </div>\r
+                               </div>\r
+                       {/if}\r
+                       \r
+                       {if $additionalTabContents|isset}{@$additionalTabContents}{/if}
+               </div>
+       </div>\r
+       <div class="border content">\r
+               <div class="container-1">\r
+                       <h3 class="subHeadline">{lang}wcf.acp.user.massProcessing.action{/lang}</h3>\r
+                               \r
+                       <div class="formGroup{if $errorField == 'action'} formError{/if}">\r
+                               <div class="formGroupLabel">\r
+                                       <label>{lang}wcf.acp.user.massProcessing.action{/lang}</label>\r
+                               </div>\r
+                               <div class="formGroupField">\r
+                                       <fieldset>\r
+                                               <legend>{lang}wcf.acp.user.massProcessing.action{/lang}</legend>\r
+                                               <div class="formField">\r
+                                                       <ul class="formOptionsLong">\r
+                                                               {if $__wcf->user->getPermission('admin.user.canMailUser')}\r
+                                                                       <li><label><input onclick="if (IS_SAFARI) enableSendMail()" onfocus="enableSendMail()" type="radio" name="action" value="sendMail" {if $action == 'sendMail'}checked="checked" {/if}/> {lang}wcf.acp.user.sendMail{/lang}</label></li>\r
+                                                                       <li><label><input onclick="if (IS_SAFARI) enableExportMailAddress()" onfocus="enableExportMailAddress()" type="radio" name="action" value="exportMailAddress" {if $action == 'exportMailAddress'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress{/lang}</label></li>\r
+                                                               {/if}\r
+                                                               {if $__wcf->user->getPermission('admin.user.canEditUser')}\r
+                                                                       <li><label><input onclick="if (IS_SAFARI) enableAssignToGroup()" onfocus="enableAssignToGroup()" type="radio" name="action" value="assignToGroup" {if $action == 'assignToGroup'}checked="checked" {/if}/> {lang}wcf.acp.user.assignToGroup{/lang}</label></li>\r
+                                                               {/if}\r
+                                                               {if $__wcf->user->getPermission('admin.user.canDeleteUser')}\r
+                                                                       <li><label><input onclick="if (IS_SAFARI) enableDelete()" onfocus="enableDelete()" type="radio" name="action" value="delete" {if $action == 'delete'}checked="checked" {/if}/> {lang}wcf.acp.user.delete{/lang}</label></li>\r
+                                                               {/if}\r
+                                                               {if $additionalActions|isset}{@$additionalActions}{/if}\r
+                                                       </ul>\r
+                                               </div>\r
+                                               {if $errorField == 'action'}\r
+                                                       <p class="innerError">\r
+                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                       </p>\r
+                                               {/if}\r
+                                       </fieldset>\r
+                               </div>\r
+                       </div>\r
+                       \r
+                       <div id="sendMailDiv">\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.acp.user.sendMail.mail{/lang}</legend>\r
+                                       \r
+                                       <div>\r
+                                               <div class="formElement{if $errorField == 'subject'} formError{/if}" id="subjectDiv">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="subject">{lang}wcf.acp.user.sendMail.subject{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <input type="text" class="inputText" id="subject" name="subject" value="{$subject}" />\r
+                                                               {if $errorField == 'subject'}\r
+                                                                       <p class="innerError">\r
+                                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                                       </p>\r
+                                                               {/if}\r
+                                                       </div>\r
+                                                       <div class="formFieldDesc hidden" id="subjectHelpMessage">\r
+                                                               <p>{lang}wcf.acp.user.sendMail.subject.description{/lang}</p>\r
+                                                       </div>\r
+                                               </div>\r
+                                               <script type="text/javascript">//<![CDATA[\r
+                                                       inlineHelp.register('subject');\r
+                                               //]]></script>\r
+                                               \r
+                                               <div class="formElement{if $errorField == 'from'} formError{/if}" id="fromDiv">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="from">{lang}wcf.acp.user.sendMail.from{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <input type="text" class="inputText" id="from" name="from" value="{$from}" />\r
+                                                               {if $errorField == 'from'}\r
+                                                                       <p class="innerError">\r
+                                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                                       </p>\r
+                                                               {/if}\r
+                                                       </div>\r
+                                                       <div class="formFieldDesc hidden" id="fromHelpMessage">\r
+                                                               {lang}wcf.acp.user.sendMail.from.description{/lang}\r
+                                                       </div>\r
+                                               </div>\r
+                                               <script type="text/javascript">//<![CDATA[\r
+                                                       inlineHelp.register('from');\r
+                                               //]]></script>\r
+                                       \r
+                                               <div class="formElement{if $errorField == 'text'} formError{/if}" id="textDiv">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="text">{lang}wcf.acp.user.sendMail.text{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <textarea id="text" name="text" rows="15" cols="40">{$text}</textarea>\r
+                                                               {if $errorField == 'text'}\r
+                                                                       <p class="innerError">\r
+                                                                               {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                                       </p>\r
+                                                               {/if}\r
+                                                       </div>\r
+                                                       <div class="formFieldDesc hidden" id="textHelpMessage">\r
+                                                               <p>{lang}wcf.acp.user.sendMail.text.description{/lang}</p>\r
+                                                       </div>\r
+                                               </div>\r
+                                               <script type="text/javascript">//<![CDATA[\r
+                                                       inlineHelp.register('text');\r
+                                               //]]></script>\r
+                                               \r
+                                               <div class="formElement">\r
+                                                       <div class="formField">\r
+                                                               <label><input type="checkbox" name="enableHTML" id="enableHTML" value="1" {if $enableHTML == 1}checked="checked" {/if}/> {lang}wcf.acp.user.sendMail.enableHTML{/lang}</label>\r
+                                                       </div>\r
+                                               </div>\r
+                                       </div>\r
+                               </fieldset>\r
+                       </div>\r
+                       \r
+                       <div id="exportMailAddressDiv">\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.acp.user.exportEmailAddress.format{/lang}</legend>\r
+                                       \r
+                                       <div>\r
+                                               <div class="formGroup">\r
+                                                       <div class="formGroupLabel">\r
+                                                               <label>{lang}wcf.acp.user.exportEmailAddress.fileType{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formGroupField">\r
+                                                               <fieldset>\r
+                                                                       <legend>{lang}wcf.acp.user.exportEmailAddress.fileType{/lang}</legend>\r
+                                                                       \r
+                                                                       <div class="formField">\r
+                                                                               <ul class="formOptionsLong">\r
+                                                                                       <li><label><input onclick="if (IS_SAFARI) setFileType('csv')" onfocus="setFileType('csv')" type="radio" name="fileType" value="csv" {if $fileType == 'csv'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.csv{/lang}</label></li>\r
+                                                                                       <li><label><input onclick="if (IS_SAFARI) setFileType('xml')" onfocus="setFileType('xml')" type="radio" name="fileType" value="xml" {if $fileType == 'xml'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.xml{/lang}</label></li>\r
+                                                                               </ul>\r
+                                                                       </div>\r
+                                                               </fieldset>\r
+                                                       </div>\r
+                                               </div>\r
+                                       \r
+                                               <div class="formElement" id="separatorDiv">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="separator">{lang}wcf.acp.user.exportEmailAddress.separator{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <textarea id="separator" name="separator" rows="2" cols="40">{$separator}</textarea>\r
+                                                       </div>\r
+                                               </div>\r
+                                               \r
+                                               <div class="formElement" id="textSeparatorDiv">\r
+                                                       <div class="formFieldLabel">\r
+                                                               <label for="textSeparator">{lang}wcf.acp.user.exportEmailAddress.textSeparator{/lang}</label>\r
+                                                       </div>\r
+                                                       <div class="formField">\r
+                                                               <input type="text" class="inputText" id="textSeparator" name="textSeparator" value="{$textSeparator}" />\r
+                                                       </div>\r
+                                               </div>\r
+                                       </div>\r
+                               </fieldset>\r
+                       </div>\r
+                       \r
+                       <div id="assignToGroupDiv">\r
+                               <fieldset>\r
+                                       <legend>{lang}wcf.acp.user.groups{/lang}</legend>\r
+                                       \r
+                                       <div>\r
+                                               <div class="formField{if $errorField == 'assignToGroupIDArray'} formError{/if}">\r
+                                                       {htmlCheckboxes options=$availableGroups name=assignToGroupIDArray selected=$assignToGroupIDArray}\r
+                                                       {if $errorField == 'assignToGroupIDArray'}\r
+                                                               <p class="innerError">\r
+                                                                       {if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}\r
+                                                               </p>\r
+                                                       {/if}\r
+                                               </div>\r
+                                       </div>\r
+                               </fieldset>\r
+                       </div>\r
+                       
+                       {if $additionalActionSettings|isset}{@$additionalActionSettings}{/if}\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="formSubmit">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.submit{/lang}" />\r
+               <input type="reset" accesskey="r" value="{lang}wcf.global.button.reset{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/worker.tpl b/wcfsetup/install/files/acp/templates/worker.tpl
new file mode 100644 (file)
index 0000000..bcd2aa6
--- /dev/null
@@ -0,0 +1,70 @@
+{if !$progress|isset}{assign var="progress" value=0}{/if}\r
+{assign var="actionTitle" value=$pageTitle}\r
+{capture assign="pageTitle"}{lang}wcf.acp.worker.progressBar{/lang} - {@$pageTitle}{/capture}\r
+{include file='setupHeader'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       function showWindow(show) {\r
+               if (show) {\r
+                       document.getElementById('iframe').style.visibility = 'visible';\r
+                       window.focus();\r
+               } else {\r
+                       xHeight('iframe', 0);\r
+                       document.getElementById('iframe').style.visibility = 'hidden';\r
+               }\r
+       }\r
+       \r
+       function setCurrentStep(title) {\r
+               document.getElementById('currentStep').innerHTML = title;\r
+       }\r
+       \r
+       function setProgress(progress) {\r
+               document.getElementById('progressBar').style.width = Math.round(300 * progress / 100) + 'px';\r
+               {literal}\r
+               document.getElementById('progressText').innerHTML = document.getElementById('progressText').innerHTML.replace(/\d{1,3}%/, progress + '%');\r
+               document.title = document.title.replace(/\d{1,3}%/, progress + '%');\r
+               {/literal}\r
+       }\r
+       \r
+       onloadEvents.push(function() {\r
+               document.getElementById('workerIcon').onclick = function(event) {\r
+                       if (!event) event = window.event;\r
+                       \r
+                       if (event.altKey) {\r
+                               showWindow(true);\r
+                               if (!xHeight('iframe')) {\r
+                                       xHeight('iframe', 300);\r
+                               }\r
+                       }\r
+               }\r
+       });\r
+       //]]>\r
+</script>\r
+\r
+<img id="workerIcon" class="icon" src="{@RELATIVE_WCF_DIR}icon/workerXL.png" alt="" />\r
+\r
+<h1><b>{lang}wcf.global.pageTitle{/lang}</b><br />{@$actionTitle}</h1>\r
+\r
+<div class="progress">\r
+       <div id="progressBar" class="progressBar" style="width: {@300*$progress/100|round:0}px"></div>\r
+       <div id="progressText" class="progressText">{lang}wcf.acp.worker.progressBar{/lang}</div>\r
+</div>\r
+\r
+<hr />\r
+\r
+<h2>{lang}wcf.acp.worker.title{/lang}</h2>\r
+\r
+<p>{lang}wcf.acp.worker.description{/lang}</p>\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.acp.worker.currentStep{/lang}</legend>\r
+       \r
+       <div class="inner">\r
+               <div><span id="currentStep"></span></div>\r
+               \r
+               <iframe id="iframe" frameborder="0" src="{$url}"></iframe>\r
+       </div>\r
+</fieldset>\r
+\r
+{include file='setupFooter'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/workerException.tpl b/wcfsetup/install/files/acp/templates/workerException.tpl
new file mode 100644 (file)
index 0000000..f2e46bb
--- /dev/null
@@ -0,0 +1,14 @@
+{include file='setupWindowHeader'}\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       window.onload = function() {\r
+       changeHeight(); \r
+};\r
+       parent.showWindow(true);\r
+       //]]>\r
+</script>\r
+\r
+{$e->show()}\r
+\r
+{include file='setupWindowFooter'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/acp/templates/workerFinish.tpl b/wcfsetup/install/files/acp/templates/workerFinish.tpl
new file mode 100644 (file)
index 0000000..f5e86f0
--- /dev/null
@@ -0,0 +1,23 @@
+{include file='setupWindowHeader'}\r
+\r
+<div class="nextButton">\r
+       <input type="button" value="{lang}wcf.global.button.next{/lang}" onclick="parent.location.href='{if $url|isset}{$url}{else}index.php{@SID_ARG_1ST}{/if}'; parent.stopAnimating();" />\r
+</div>\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       window.onload = function() {\r
+       changeHeight(); \r
+};\r
+       parent.setProgress(100);\r
+       parent.showWindow(true);\r
+       parent.setCurrentStep('{@$stepTitle}');\r
+       //]]>\r
+</script>\r
+\r
+{if $message|isset}\r
+       {@$message}\r
+{/if}\r
+\r
+{include file='setupWindowFooter'}\r
+\r
diff --git a/wcfsetup/install/files/acp/templates/workerNext.tpl b/wcfsetup/install/files/acp/templates/workerNext.tpl
new file mode 100644 (file)
index 0000000..98eff2a
--- /dev/null
@@ -0,0 +1,21 @@
+{include file='setupWindowHeader'}\r
+\r
+<h2>Step: {@$stepTitle}</h2>\r
+\r
+<form method="post" action="{$url}">\r
+       <input type="submit" value="Go" onclick="parent.stopAnimating()" />\r
+</form>\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       {if $progress|isset}parent.setProgress({@$progress});{/if}\r
+       parent.showWindow(false);\r
+       parent.setCurrentStep('{@$stepTitle}');\r
+       \r
+       window.onload = function() {\r
+               document.forms[0].submit();\r
+       }\r
+       //]]>\r
+</script>\r
+\r
+{include file='setupWindowFooter'}
\ No newline at end of file
diff --git a/wcfsetup/install/files/cache/.htaccess b/wcfsetup/install/files/cache/.htaccess
new file mode 100644 (file)
index 0000000..3418e55
--- /dev/null
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/wcfsetup/install/files/cache/templateListener/.htaccess b/wcfsetup/install/files/cache/templateListener/.htaccess
new file mode 100644 (file)
index 0000000..3418e55
--- /dev/null
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/wcfsetup/install/files/global.php b/wcfsetup/install/files/global.php
new file mode 100644 (file)
index 0000000..376d467
--- /dev/null
@@ -0,0 +1,15 @@
+<?php\r
+/**\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @category   Community Framework\r
+ */\r
+// define the wcf-root-dir\r
+define('WCF_DIR', dirname(__FILE__).'/');\r
+\r
+// initiate wcf core\r
+require_once(WCF_DIR.'lib/system/WCF.class.php');\r
+new wcf\system\WCF();\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/icon/imageViewer/closeHoverM.png b/wcfsetup/install/files/icon/imageViewer/closeHoverM.png
new file mode 100644 (file)
index 0000000..d34a888
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/closeHoverM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/closeM.png b/wcfsetup/install/files/icon/imageViewer/closeM.png
new file mode 100644 (file)
index 0000000..be83a0f
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/closeM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/enlargeHoverM.png b/wcfsetup/install/files/icon/imageViewer/enlargeHoverM.png
new file mode 100644 (file)
index 0000000..a175ff2
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/enlargeHoverM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/enlargeM.png b/wcfsetup/install/files/icon/imageViewer/enlargeM.png
new file mode 100644 (file)
index 0000000..e1103ff
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/enlargeM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/nextHoverM.png b/wcfsetup/install/files/icon/imageViewer/nextHoverM.png
new file mode 100644 (file)
index 0000000..0a7d9d4
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/nextHoverM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/nextM.png b/wcfsetup/install/files/icon/imageViewer/nextM.png
new file mode 100644 (file)
index 0000000..9eb6b80
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/nextM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/pauseHoverM.png b/wcfsetup/install/files/icon/imageViewer/pauseHoverM.png
new file mode 100644 (file)
index 0000000..3dadf5f
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/pauseHoverM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/pauseM.png b/wcfsetup/install/files/icon/imageViewer/pauseM.png
new file mode 100644 (file)
index 0000000..4ea60e6
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/pauseM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/playHoverM.png b/wcfsetup/install/files/icon/imageViewer/playHoverM.png
new file mode 100644 (file)
index 0000000..70135c7
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/playHoverM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/playM.png b/wcfsetup/install/files/icon/imageViewer/playM.png
new file mode 100644 (file)
index 0000000..9896ebc
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/playM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/previousHoverM.png b/wcfsetup/install/files/icon/imageViewer/previousHoverM.png
new file mode 100644 (file)
index 0000000..99af8ef
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/previousHoverM.png differ
diff --git a/wcfsetup/install/files/icon/imageViewer/previousM.png b/wcfsetup/install/files/icon/imageViewer/previousM.png
new file mode 100644 (file)
index 0000000..7ad6539
Binary files /dev/null and b/wcfsetup/install/files/icon/imageViewer/previousM.png differ
diff --git a/wcfsetup/install/files/images/imageViewer/blank.png b/wcfsetup/install/files/images/imageViewer/blank.png
new file mode 100644 (file)
index 0000000..bf62edd
Binary files /dev/null and b/wcfsetup/install/files/images/imageViewer/blank.png differ
diff --git a/wcfsetup/install/files/images/imageViewer/menu.png b/wcfsetup/install/files/images/imageViewer/menu.png
new file mode 100644 (file)
index 0000000..caf7914
Binary files /dev/null and b/wcfsetup/install/files/images/imageViewer/menu.png differ
diff --git a/wcfsetup/install/files/images/spinner.gif b/wcfsetup/install/files/images/spinner.gif
new file mode 100644 (file)
index 0000000..dd3e850
Binary files /dev/null and b/wcfsetup/install/files/images/spinner.gif differ
diff --git a/wcfsetup/install/files/js/3rdParty/jquery-ui.min.js b/wcfsetup/install/files/js/3rdParty/jquery-ui.min.js
new file mode 100644 (file)
index 0000000..67cd598
--- /dev/null
@@ -0,0 +1,406 @@
+/*!\r
+ * jQuery UI 1.8.11\r
+ *\r
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)\r
+ * Dual licensed under the MIT or GPL Version 2 licenses.\r
+ * http://jquery.org/license\r
+ *\r
+ * http://docs.jquery.com/UI\r
+ */\r
+(function(b,d){function e(g){return!b(g).parents().andSelf().filter(function(){return b.curCSS(this,"visibility")==="hidden"||b.expr.filters.hidden(this)}).length}b.ui=b.ui||{};if(!b.ui.version){b.extend(b.ui,{version:"1.8.11",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,\r
+NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});b.fn.extend({_focus:b.fn.focus,focus:function(g,f){return typeof g==="number"?this.each(function(){var a=this;setTimeout(function(){b(a).focus();f&&f.call(a)},g)}):this._focus.apply(this,arguments)},scrollParent:function(){var g;g=b.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(b.curCSS(this,\r
+"position",1))&&/(auto|scroll)/.test(b.curCSS(this,"overflow",1)+b.curCSS(this,"overflow-y",1)+b.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(b.curCSS(this,"overflow",1)+b.curCSS(this,"overflow-y",1)+b.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!g.length?b(document):g},zIndex:function(g){if(g!==d)return this.css("zIndex",g);if(this.length){g=b(this[0]);for(var f;g.length&&g[0]!==document;){f=g.css("position");\r
+if(f==="absolute"||f==="relative"||f==="fixed"){f=parseInt(g.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}g=g.parent()}}return 0},disableSelection:function(){return this.bind((b.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(g){g.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});b.each(["Width","Height"],function(g,f){function a(j,n,p,l){b.each(c,function(){n-=parseFloat(b.curCSS(j,"padding"+this,true))||0;if(p)n-=parseFloat(b.curCSS(j,\r
+"border"+this+"Width",true))||0;if(l)n-=parseFloat(b.curCSS(j,"margin"+this,true))||0});return n}var c=f==="Width"?["Left","Right"]:["Top","Bottom"],h=f.toLowerCase(),i={innerWidth:b.fn.innerWidth,innerHeight:b.fn.innerHeight,outerWidth:b.fn.outerWidth,outerHeight:b.fn.outerHeight};b.fn["inner"+f]=function(j){if(j===d)return i["inner"+f].call(this);return this.each(function(){b(this).css(h,a(this,j)+"px")})};b.fn["outer"+f]=function(j,n){if(typeof j!=="number")return i["outer"+f].call(this,j);return this.each(function(){b(this).css(h,\r
+a(this,j,true,n)+"px")})}});b.extend(b.expr[":"],{data:function(g,f,a){return!!b.data(g,a[3])},focusable:function(g){var f=g.nodeName.toLowerCase(),a=b.attr(g,"tabindex");if("area"===f){f=g.parentNode;a=f.name;if(!g.href||!a||f.nodeName.toLowerCase()!=="map")return false;g=b("img[usemap=#"+a+"]")[0];return!!g&&e(g)}return(/input|select|textarea|button|object/.test(f)?!g.disabled:"a"==f?g.href||!isNaN(a):!isNaN(a))&&e(g)},tabbable:function(g){var f=b.attr(g,"tabindex");return(isNaN(f)||f>=0)&&b(g).is(":focusable")}});\r
+b(function(){var g=document.body,f=g.appendChild(f=document.createElement("div"));b.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});b.support.minHeight=f.offsetHeight===100;b.support.selectstart="onselectstart"in f;g.removeChild(f).style.display="none"});b.extend(b.ui,{plugin:{add:function(g,f,a){g=b.ui[g].prototype;for(var c in a){g.plugins[c]=g.plugins[c]||[];g.plugins[c].push([f,a[c]])}},call:function(g,f,a){if((f=g.plugins[f])&&g.element[0].parentNode)for(var c=0;c<f.length;c++)g.options[f[c][0]]&&\r
+f[c][1].apply(g.element,a)}},contains:function(g,f){return document.compareDocumentPosition?g.compareDocumentPosition(f)&16:g!==f&&g.contains(f)},hasScroll:function(g,f){if(b(g).css("overflow")==="hidden")return false;f=f&&f==="left"?"scrollLeft":"scrollTop";var a=false;if(g[f]>0)return true;g[f]=1;a=g[f]>0;g[f]=0;return a},isOverAxis:function(g,f,a){return g>f&&g<f+a},isOver:function(g,f,a,c,h,i){return b.ui.isOverAxis(g,a,h)&&b.ui.isOverAxis(f,c,i)}})}})(jQuery);\r
+(function(b,d){if(b.cleanData){var e=b.cleanData;b.cleanData=function(f){for(var a=0,c;(c=f[a])!=null;a++)b(c).triggerHandler("remove");e(f)}}else{var g=b.fn.remove;b.fn.remove=function(f,a){return this.each(function(){if(!a)if(!f||b.filter(f,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return g.call(b(this),f,a)})}}b.widget=function(f,a,c){var h=f.split(".")[0],i;f=f.split(".")[1];i=h+"-"+f;if(!c){c=a;a=b.Widget}b.expr[":"][i]=function(j){return!!b.data(j,\r
+f)};b[h]=b[h]||{};b[h][f]=function(j,n){arguments.length&&this._createWidget(j,n)};a=new a;a.options=b.extend(true,{},a.options);b[h][f].prototype=b.extend(true,a,{namespace:h,widgetName:f,widgetEventPrefix:b[h][f].prototype.widgetEventPrefix||f,widgetBaseClass:i},c);b.widget.bridge(f,b[h][f])};b.widget.bridge=function(f,a){b.fn[f]=function(c){var h=typeof c==="string",i=Array.prototype.slice.call(arguments,1),j=this;c=!h&&i.length?b.extend.apply(null,[true,c].concat(i)):c;if(h&&c.charAt(0)==="_")return j;\r
+h?this.each(function(){var n=b.data(this,f),p=n&&b.isFunction(n[c])?n[c].apply(n,i):n;if(p!==n&&p!==d){j=p;return false}}):this.each(function(){var n=b.data(this,f);n?n.option(c||{})._init():b.data(this,f,new a(c,this))});return j}};b.Widget=function(f,a){arguments.length&&this._createWidget(f,a)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,a){b.data(a,this.widgetName,this);this.element=b(a);this.options=b.extend(true,{},this.options,\r
+this._getCreateOptions(),f);var c=this;this.element.bind("remove."+this.widgetName,function(){c.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},\r
+widget:function(){return this.element},option:function(f,a){var c=f;if(arguments.length===0)return b.extend({},this.options);if(typeof f==="string"){if(a===d)return this.options[f];c={};c[f]=a}this._setOptions(c);return this},_setOptions:function(f){var a=this;b.each(f,function(c,h){a._setOption(c,h)});return this},_setOption:function(f,a){this.options[f]=a;if(f==="disabled")this.widget()[a?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",a);return this},\r
+enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(f,a,c){var h=this.options[f];a=b.Event(a);a.type=(f===this.widgetEventPrefix?f:this.widgetEventPrefix+f).toLowerCase();c=c||{};if(a.originalEvent){f=b.event.props.length;for(var i;f;){i=b.event.props[--f];a[i]=a.originalEvent[i]}}this.element.trigger(a,c);return!(b.isFunction(h)&&h.call(this.element[0],a,c)===false||a.isDefaultPrevented())}}})(jQuery);\r
+(function(b){b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(d){d.originalEvent=\r
+d.originalEvent||{};if(!d.originalEvent.mouseHandled){this._mouseStarted&&this._mouseUp(d);this._mouseDownEvent=d;var e=this,g=d.which==1,f=typeof this.options.cancel=="string"?b(d.target).parents().add(d.target).filter(this.options.cancel).length:false;if(!g||f||!this._mouseCapture(d))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=\r
+this._mouseStart(d)!==false;if(!this._mouseStarted){d.preventDefault();return true}}true===b.data(d.target,this.widgetName+".preventClickEvent")&&b.removeData(d.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(a){return e._mouseMove(a)};this._mouseUpDelegate=function(a){return e._mouseUp(a)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);d.preventDefault();return d.originalEvent.mouseHandled=\r
+true}},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button)return this._mouseUp(d);if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,d)!==false)?this._mouseDrag(d):this._mouseUp(d);return!this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);\r
+if(this._mouseStarted){this._mouseStarted=false;d.target==this._mouseDownEvent.target&&b.data(d.target,this.widgetName+".preventClickEvent",true);this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);\r
+(function(b){b.widget("ui.draggable",b.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==\r
+"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(d){var e=\r
+this.options;if(this.helper||e.disabled||b(d.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(d);if(!this.handle)return false;return true},_mouseStart:function(d){var e=this.options;this.helper=this._createHelper(d);this._cacheHelperProportions();if(b.ui.ddmanager)b.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-\r
+this.margins.top,left:this.offset.left-this.margins.left};b.extend(this.offset,{click:{left:d.pageX-this.offset.left,top:d.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(d);this.originalPageX=d.pageX;this.originalPageY=d.pageY;e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt);e.containment&&this._setContainment();if(this._trigger("start",d)===false){this._clear();return false}this._cacheHelperProportions();\r
+b.ui.ddmanager&&!e.dropBehaviour&&b.ui.ddmanager.prepareOffsets(this,d);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(d,true);return true},_mouseDrag:function(d,e){this.position=this._generatePosition(d);this.positionAbs=this._convertPositionTo("absolute");if(!e){e=this._uiHash();if(this._trigger("drag",d,e)===false){this._mouseUp({});return false}this.position=e.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||\r
+this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";b.ui.ddmanager&&b.ui.ddmanager.drag(this,d);return false},_mouseStop:function(d){var e=false;if(b.ui.ddmanager&&!this.options.dropBehaviour)e=b.ui.ddmanager.drop(this,d);if(this.dropped){e=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!e||this.options.revert=="valid"&&e||this.options.revert===true||b.isFunction(this.options.revert)&&\r
+this.options.revert.call(this.element,e)){var g=this;b(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){g._trigger("stop",d)!==false&&g._clear()})}else this._trigger("stop",d)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(d){var e=!this.options.handle||!b(this.options.handle,this.element).length?true:false;b(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==\r
+d.target)e=true});return e},_createHelper:function(d){var e=this.options;d=b.isFunction(e.helper)?b(e.helper.apply(this.element[0],[d])):e.helper=="clone"?this.element.clone():this.element;d.parents("body").length||d.appendTo(e.appendTo=="parent"?this.element[0].parentNode:e.appendTo);d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute");return d},_adjustOffsetFromHelper:function(d){if(typeof d=="string")d=d.split(" ");if(b.isArray(d))d={left:+d[0],top:+d[1]||\r
+0};if("left"in d)this.offset.click.left=d.left+this.margins.left;if("right"in d)this.offset.click.left=this.helperProportions.width-d.right+this.margins.left;if("top"in d)this.offset.click.top=d.top+this.margins.top;if("bottom"in d)this.offset.click.top=this.helperProportions.height-d.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var d=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&b.ui.contains(this.scrollParent[0],\r
+this.offsetParent[0])){d.left+=this.scrollParent.scrollLeft();d.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&b.browser.msie)d={top:0,left:0};return{top:d.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:d.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var d=this.element.position();return{top:d.top-\r
+(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:d.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),\r
+height:this.helper.outerHeight()}},_setContainment:function(){var d=this.options;if(d.containment=="parent")d.containment=this.helper[0].parentNode;if(d.containment=="document"||d.containment=="window")this.containment=[(d.containment=="document"?0:b(window).scrollLeft())-this.offset.relative.left-this.offset.parent.left,(d.containment=="document"?0:b(window).scrollTop())-this.offset.relative.top-this.offset.parent.top,(d.containment=="document"?0:b(window).scrollLeft())+b(d.containment=="document"?\r
+document:window).width()-this.helperProportions.width-this.margins.left,(d.containment=="document"?0:b(window).scrollTop())+(b(d.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(d.containment)&&d.containment.constructor!=Array){var e=b(d.containment)[0];if(e){d=b(d.containment).offset();var g=b(e).css("overflow")!="hidden";this.containment=[d.left+(parseInt(b(e).css("borderLeftWidth"),\r
+10)||0)+(parseInt(b(e).css("paddingLeft"),10)||0),d.top+(parseInt(b(e).css("borderTopWidth"),10)||0)+(parseInt(b(e).css("paddingTop"),10)||0),d.left+(g?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(b(e).css("borderLeftWidth"),10)||0)-(parseInt(b(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,d.top+(g?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(b(e).css("borderTopWidth"),10)||0)-(parseInt(b(e).css("paddingBottom"),\r
+10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom]}}else if(d.containment.constructor==Array)this.containment=d.containment},_convertPositionTo:function(d,e){if(!e)e=this.position;d=d=="absolute"?1:-1;var g=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&b.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(g[0].tagName);return{top:e.top+this.offset.relative.top*d+this.offset.parent.top*d-(b.browser.safari&&\r
+b.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:g.scrollTop())*d),left:e.left+this.offset.relative.left*d+this.offset.parent.left*d-(b.browser.safari&&b.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:g.scrollLeft())*d)}},_generatePosition:function(d){var e=this.options,g=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&b.ui.contains(this.scrollParent[0],\r
+this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(g[0].tagName),a=d.pageX,c=d.pageY;if(this.originalPosition){if(this.containment){if(d.pageX-this.offset.click.left<this.containment[0])a=this.containment[0]+this.offset.click.left;if(d.pageY-this.offset.click.top<this.containment[1])c=this.containment[1]+this.offset.click.top;if(d.pageX-this.offset.click.left>this.containment[2])a=this.containment[2]+this.offset.click.left;if(d.pageY-this.offset.click.top>this.containment[3])c=\r
+this.containment[3]+this.offset.click.top}if(e.grid){c=this.originalPageY+Math.round((c-this.originalPageY)/e.grid[1])*e.grid[1];c=this.containment?!(c-this.offset.click.top<this.containment[1]||c-this.offset.click.top>this.containment[3])?c:!(c-this.offset.click.top<this.containment[1])?c-e.grid[1]:c+e.grid[1]:c;a=this.originalPageX+Math.round((a-this.originalPageX)/e.grid[0])*e.grid[0];a=this.containment?!(a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2])?\r
+a:!(a-this.offset.click.left<this.containment[0])?a-e.grid[0]:a+e.grid[0]:a}}return{top:c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(b.browser.safari&&b.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:g.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(b.browser.safari&&b.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():\r
+f?0:g.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(d,e,g){g=g||this._uiHash();b.ui.plugin.call(this,d,[e,g]);if(d=="drag")this.positionAbs=this._convertPositionTo("absolute");return b.Widget.prototype._trigger.call(this,d,e,g)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,\r
+offset:this.positionAbs}}});b.extend(b.ui.draggable,{version:"1.8.11"});b.ui.plugin.add("draggable","connectToSortable",{start:function(d,e){var g=b(this).data("draggable"),f=g.options,a=b.extend({},e,{item:g.element});g.sortables=[];b(f.connectToSortable).each(function(){var c=b.data(this,"sortable");if(c&&!c.options.disabled){g.sortables.push({instance:c,shouldRevert:c.options.revert});c.refreshPositions();c._trigger("activate",d,a)}})},stop:function(d,e){var g=b(this).data("draggable"),f=b.extend({},\r
+e,{item:g.element});b.each(g.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;g.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(d);this.instance.options.helper=this.instance.options._helper;g.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",d,f)}})},drag:function(d,e){var g=\r
+b(this).data("draggable"),f=this;b.each(g.sortables,function(){this.instance.positionAbs=g.positionAbs;this.instance.helperProportions=g.helperProportions;this.instance.offset.click=g.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=b(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return e.helper[0]};\r
+d.target=this.instance.currentItem[0];this.instance._mouseCapture(d,true);this.instance._mouseStart(d,true,true);this.instance.offset.click.top=g.offset.click.top;this.instance.offset.click.left=g.offset.click.left;this.instance.offset.parent.left-=g.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=g.offset.parent.top-this.instance.offset.parent.top;g._trigger("toSortable",d);g.dropped=this.instance.element;g.currentItem=g.element;this.instance.fromOutside=g}this.instance.currentItem&&\r
+this.instance._mouseDrag(d)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",d,this.instance._uiHash(this.instance));this.instance._mouseStop(d,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();g._trigger("fromSortable",d);g.dropped=false}})}});b.ui.plugin.add("draggable","cursor",\r
+{start:function(){var d=b("body"),e=b(this).data("draggable").options;if(d.css("cursor"))e._cursor=d.css("cursor");d.css("cursor",e.cursor)},stop:function(){var d=b(this).data("draggable").options;d._cursor&&b("body").css("cursor",d._cursor)}});b.ui.plugin.add("draggable","iframeFix",{start:function(){var d=b(this).data("draggable").options;b(d.iframeFix===true?"iframe":d.iframeFix).each(function(){b('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+\r
+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(b(this).offset()).appendTo("body")})},stop:function(){b("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});b.ui.plugin.add("draggable","opacity",{start:function(d,e){d=b(e.helper);e=b(this).data("draggable").options;if(d.css("opacity"))e._opacity=d.css("opacity");d.css("opacity",e.opacity)},stop:function(d,e){d=b(this).data("draggable").options;d._opacity&&b(e.helper).css("opacity",\r
+d._opacity)}});b.ui.plugin.add("draggable","scroll",{start:function(){var d=b(this).data("draggable");if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML")d.overflowOffset=d.scrollParent.offset()},drag:function(d){var e=b(this).data("draggable"),g=e.options,f=false;if(e.scrollParent[0]!=document&&e.scrollParent[0].tagName!="HTML"){if(!g.axis||g.axis!="x")if(e.overflowOffset.top+e.scrollParent[0].offsetHeight-d.pageY<g.scrollSensitivity)e.scrollParent[0].scrollTop=f=e.scrollParent[0].scrollTop+\r
+g.scrollSpeed;else if(d.pageY-e.overflowOffset.top<g.scrollSensitivity)e.scrollParent[0].scrollTop=f=e.scrollParent[0].scrollTop-g.scrollSpeed;if(!g.axis||g.axis!="y")if(e.overflowOffset.left+e.scrollParent[0].offsetWidth-d.pageX<g.scrollSensitivity)e.scrollParent[0].scrollLeft=f=e.scrollParent[0].scrollLeft+g.scrollSpeed;else if(d.pageX-e.overflowOffset.left<g.scrollSensitivity)e.scrollParent[0].scrollLeft=f=e.scrollParent[0].scrollLeft-g.scrollSpeed}else{if(!g.axis||g.axis!="x")if(d.pageY-b(document).scrollTop()<\r
+g.scrollSensitivity)f=b(document).scrollTop(b(document).scrollTop()-g.scrollSpeed);else if(b(window).height()-(d.pageY-b(document).scrollTop())<g.scrollSensitivity)f=b(document).scrollTop(b(document).scrollTop()+g.scrollSpeed);if(!g.axis||g.axis!="y")if(d.pageX-b(document).scrollLeft()<g.scrollSensitivity)f=b(document).scrollLeft(b(document).scrollLeft()-g.scrollSpeed);else if(b(window).width()-(d.pageX-b(document).scrollLeft())<g.scrollSensitivity)f=b(document).scrollLeft(b(document).scrollLeft()+\r
+g.scrollSpeed)}f!==false&&b.ui.ddmanager&&!g.dropBehaviour&&b.ui.ddmanager.prepareOffsets(e,d)}});b.ui.plugin.add("draggable","snap",{start:function(){var d=b(this).data("draggable"),e=d.options;d.snapElements=[];b(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var g=b(this),f=g.offset();this!=d.element[0]&&d.snapElements.push({item:this,width:g.outerWidth(),height:g.outerHeight(),top:f.top,left:f.left})})},drag:function(d,e){for(var g=b(this).data("draggable"),\r
+f=g.options,a=f.snapTolerance,c=e.offset.left,h=c+g.helperProportions.width,i=e.offset.top,j=i+g.helperProportions.height,n=g.snapElements.length-1;n>=0;n--){var p=g.snapElements[n].left,l=p+g.snapElements[n].width,k=g.snapElements[n].top,m=k+g.snapElements[n].height;if(p-a<c&&c<l+a&&k-a<i&&i<m+a||p-a<c&&c<l+a&&k-a<j&&j<m+a||p-a<h&&h<l+a&&k-a<i&&i<m+a||p-a<h&&h<l+a&&k-a<j&&j<m+a){if(f.snapMode!="inner"){var o=Math.abs(k-j)<=a,q=Math.abs(m-i)<=a,s=Math.abs(p-h)<=a,r=Math.abs(l-c)<=a;if(o)e.position.top=\r
+g._convertPositionTo("relative",{top:k-g.helperProportions.height,left:0}).top-g.margins.top;if(q)e.position.top=g._convertPositionTo("relative",{top:m,left:0}).top-g.margins.top;if(s)e.position.left=g._convertPositionTo("relative",{top:0,left:p-g.helperProportions.width}).left-g.margins.left;if(r)e.position.left=g._convertPositionTo("relative",{top:0,left:l}).left-g.margins.left}var u=o||q||s||r;if(f.snapMode!="outer"){o=Math.abs(k-i)<=a;q=Math.abs(m-j)<=a;s=Math.abs(p-c)<=a;r=Math.abs(l-h)<=a;if(o)e.position.top=\r
+g._convertPositionTo("relative",{top:k,left:0}).top-g.margins.top;if(q)e.position.top=g._convertPositionTo("relative",{top:m-g.helperProportions.height,left:0}).top-g.margins.top;if(s)e.position.left=g._convertPositionTo("relative",{top:0,left:p}).left-g.margins.left;if(r)e.position.left=g._convertPositionTo("relative",{top:0,left:l-g.helperProportions.width}).left-g.margins.left}if(!g.snapElements[n].snapping&&(o||q||s||r||u))g.options.snap.snap&&g.options.snap.snap.call(g.element,d,b.extend(g._uiHash(),\r
+{snapItem:g.snapElements[n].item}));g.snapElements[n].snapping=o||q||s||r||u}else{g.snapElements[n].snapping&&g.options.snap.release&&g.options.snap.release.call(g.element,d,b.extend(g._uiHash(),{snapItem:g.snapElements[n].item}));g.snapElements[n].snapping=false}}}});b.ui.plugin.add("draggable","stack",{start:function(){var d=b(this).data("draggable").options;d=b.makeArray(b(d.stack)).sort(function(g,f){return(parseInt(b(g).css("zIndex"),10)||0)-(parseInt(b(f).css("zIndex"),10)||0)});if(d.length){var e=\r
+parseInt(d[0].style.zIndex)||0;b(d).each(function(g){this.style.zIndex=e+g});this[0].style.zIndex=e+d.length}}});b.ui.plugin.add("draggable","zIndex",{start:function(d,e){d=b(e.helper);e=b(this).data("draggable").options;if(d.css("zIndex"))e._zIndex=d.css("zIndex");d.css("zIndex",e.zIndex)},stop:function(d,e){d=b(this).data("draggable").options;d._zIndex&&b(e.helper).css("zIndex",d._zIndex)}})})(jQuery);\r
+(function(b){b.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var d=this.options,e=d.accept;this.isover=0;this.isout=1;this.accept=b.isFunction(e)?e:function(g){return g.is(e)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};b.ui.ddmanager.droppables[d.scope]=b.ui.ddmanager.droppables[d.scope]||[];b.ui.ddmanager.droppables[d.scope].push(this);\r
+d.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var d=b.ui.ddmanager.droppables[this.options.scope],e=0;e<d.length;e++)d[e]==this&&d.splice(e,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(d,e){if(d=="accept")this.accept=b.isFunction(e)?e:function(g){return g.is(e)};b.Widget.prototype._setOption.apply(this,arguments)},_activate:function(d){var e=b.ui.ddmanager.current;this.options.activeClass&&\r
+this.element.addClass(this.options.activeClass);e&&this._trigger("activate",d,this.ui(e))},_deactivate:function(d){var e=b.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);e&&this._trigger("deactivate",d,this.ui(e))},_over:function(d){var e=b.ui.ddmanager.current;if(!(!e||(e.currentItem||e.element)[0]==this.element[0]))if(this.accept.call(this.element[0],e.currentItem||e.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);\r
+this._trigger("over",d,this.ui(e))}},_out:function(d){var e=b.ui.ddmanager.current;if(!(!e||(e.currentItem||e.element)[0]==this.element[0]))if(this.accept.call(this.element[0],e.currentItem||e.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",d,this.ui(e))}},_drop:function(d,e){var g=e||b.ui.ddmanager.current;if(!g||(g.currentItem||g.element)[0]==this.element[0])return false;var f=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var a=\r
+b.data(this,"droppable");if(a.options.greedy&&!a.options.disabled&&a.options.scope==g.options.scope&&a.accept.call(a.element[0],g.currentItem||g.element)&&b.ui.intersect(g,b.extend(a,{offset:a.element.offset()}),a.options.tolerance)){f=true;return false}});if(f)return false;if(this.accept.call(this.element[0],g.currentItem||g.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",\r
+d,this.ui(g));return this.element}return false},ui:function(d){return{draggable:d.currentItem||d.element,helper:d.helper,position:d.position,offset:d.positionAbs}}});b.extend(b.ui.droppable,{version:"1.8.11"});b.ui.intersect=function(d,e,g){if(!e.offset)return false;var f=(d.positionAbs||d.position.absolute).left,a=f+d.helperProportions.width,c=(d.positionAbs||d.position.absolute).top,h=c+d.helperProportions.height,i=e.offset.left,j=i+e.proportions.width,n=e.offset.top,p=n+e.proportions.height;\r
+switch(g){case "fit":return i<=f&&a<=j&&n<=c&&h<=p;case "intersect":return i<f+d.helperProportions.width/2&&a-d.helperProportions.width/2<j&&n<c+d.helperProportions.height/2&&h-d.helperProportions.height/2<p;case "pointer":return b.ui.isOver((d.positionAbs||d.position.absolute).top+(d.clickOffset||d.offset.click).top,(d.positionAbs||d.position.absolute).left+(d.clickOffset||d.offset.click).left,n,i,e.proportions.height,e.proportions.width);case "touch":return(c>=n&&c<=p||h>=n&&h<=p||c<n&&h>p)&&(f>=\r
+i&&f<=j||a>=i&&a<=j||f<i&&a>j);default:return false}};b.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(d,e){var g=b.ui.ddmanager.droppables[d.options.scope]||[],f=e?e.type:null,a=(d.currentItem||d.element).find(":data(droppable)").andSelf(),c=0;a:for(;c<g.length;c++)if(!(g[c].options.disabled||d&&!g[c].accept.call(g[c].element[0],d.currentItem||d.element))){for(var h=0;h<a.length;h++)if(a[h]==g[c].element[0]){g[c].proportions.height=0;continue a}g[c].visible=g[c].element.css("display")!=\r
+"none";if(g[c].visible){f=="mousedown"&&g[c]._activate.call(g[c],e);g[c].offset=g[c].element.offset();g[c].proportions={width:g[c].element[0].offsetWidth,height:g[c].element[0].offsetHeight}}}},drop:function(d,e){var g=false;b.each(b.ui.ddmanager.droppables[d.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&b.ui.intersect(d,this,this.options.tolerance))g=g||this._drop.call(this,e);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],d.currentItem||\r
+d.element)){this.isout=1;this.isover=0;this._deactivate.call(this,e)}}});return g},drag:function(d,e){d.options.refreshPositions&&b.ui.ddmanager.prepareOffsets(d,e);b.each(b.ui.ddmanager.droppables[d.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var g=b.ui.intersect(d,this,this.options.tolerance);if(g=!g&&this.isover==1?"isout":g&&this.isover==0?"isover":null){var f;if(this.options.greedy){var a=this.element.parents(":data(droppable):eq(0)");if(a.length){f=\r
+b.data(a[0],"droppable");f.greedyChild=g=="isover"?1:0}}if(f&&g=="isover"){f.isover=0;f.isout=1;f._out.call(f,e)}this[g]=1;this[g=="isout"?"isover":"isout"]=0;this[g=="isover"?"_over":"_out"].call(this,e);if(f&&g=="isout"){f.isout=0;f.isover=1;f._over.call(f,e)}}}})}}})(jQuery);\r
+(function(b){b.widget("ui.resizable",b.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var g=this,f=this.options;this.element.addClass("ui-resizable");b.extend(this,{_aspectRatio:!!f.aspectRatio,aspectRatio:f.aspectRatio,originalElement:this.element,\r
+_proportionallyResizeElements:[],_helper:f.helper||f.ghost||f.animate?f.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&b.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(b('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),\r
+top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=\r
+this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=f.handles||(!b(".ui-resizable-handle",this.element).length?"e,s,se":{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",\r
+nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var a=this.handles.split(",");this.handles={};for(var c=0;c<a.length;c++){var h=b.trim(a[c]),i=b('<div class="ui-resizable-handle '+("ui-resizable-"+h)+'"></div>');/sw|se|ne|nw/.test(h)&&i.css({zIndex:++f.zIndex});"se"==h&&i.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[h]=".ui-resizable-"+h;this.element.append(i)}}this._renderAxis=function(j){j=j||this.element;for(var n in this.handles){if(this.handles[n].constructor==\r
+String)this.handles[n]=b(this.handles[n],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var p=b(this.handles[n],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(n)?p.outerHeight():p.outerWidth();p=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");j.css(p,l);this._proportionallyResize()}b(this.handles[n])}};this._renderAxis(this.element);this._handles=b(".ui-resizable-handle",this.element).disableSelection();\r
+this._handles.mouseover(function(){if(!g.resizing){if(this.className)var j=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);g.axis=j&&j[1]?j[1]:"se"}});if(f.autoHide){this._handles.hide();b(this.element).addClass("ui-resizable-autohide").hover(function(){b(this).removeClass("ui-resizable-autohide");g._handles.show()},function(){if(!g.resizing){b(this).addClass("ui-resizable-autohide");g._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var g=function(a){b(a).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};\r
+if(this.elementIsWrapper){g(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);g(this.originalElement);return this},_mouseCapture:function(g){var f=false;for(var a in this.handles)if(b(this.handles[a])[0]==g.target)f=true;return!this.options.disabled&&f},_mouseStart:function(g){var f=this.options,a=this.element.position(),\r
+c=this.element;this.resizing=true;this.documentScroll={top:b(document).scrollTop(),left:b(document).scrollLeft()};if(c.is(".ui-draggable")||/absolute/.test(c.css("position")))c.css({position:"absolute",top:a.top,left:a.left});b.browser.opera&&/relative/.test(c.css("position"))&&c.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();a=d(this.helper.css("left"));var h=d(this.helper.css("top"));if(f.containment){a+=b(f.containment).scrollLeft()||0;h+=b(f.containment).scrollTop()||0}this.offset=\r
+this.helper.offset();this.position={left:a,top:h};this.size=this._helper?{width:c.outerWidth(),height:c.outerHeight()}:{width:c.width(),height:c.height()};this.originalSize=this._helper?{width:c.outerWidth(),height:c.outerHeight()}:{width:c.width(),height:c.height()};this.originalPosition={left:a,top:h};this.sizeDiff={width:c.outerWidth()-c.width(),height:c.outerHeight()-c.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=typeof f.aspectRatio=="number"?f.aspectRatio:\r
+this.originalSize.width/this.originalSize.height||1;f=b(".ui-resizable-"+this.axis).css("cursor");b("body").css("cursor",f=="auto"?this.axis+"-resize":f);c.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(g){var f=this.helper,a=this.originalMousePosition,c=this._change[this.axis];if(!c)return false;a=c.apply(this,[g,g.pageX-a.left||0,g.pageY-a.top||0]);if(this._aspectRatio||g.shiftKey)a=this._updateRatio(a,g);a=this._respectSize(a,g);this._propagate("resize",\r
+g);f.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(a);this._trigger("resize",g,this.ui());return false},_mouseStop:function(g){this.resizing=false;var f=this.options,a=this;if(this._helper){var c=this._proportionallyResizeElements,h=c.length&&/textarea/i.test(c[0].nodeName);c=h&&b.ui.hasScroll(c[0],"left")?0:a.sizeDiff.height;\r
+h=h?0:a.sizeDiff.width;h={width:a.helper.width()-h,height:a.helper.height()-c};c=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var i=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;f.animate||this.element.css(b.extend(h,{top:i,left:c}));a.helper.height(a.size.height);a.helper.width(a.size.width);this._helper&&!f.animate&&this._proportionallyResize()}b("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");\r
+this._propagate("stop",g);this._helper&&this.helper.remove();return false},_updateCache:function(g){this.offset=this.helper.offset();if(e(g.left))this.position.left=g.left;if(e(g.top))this.position.top=g.top;if(e(g.height))this.size.height=g.height;if(e(g.width))this.size.width=g.width},_updateRatio:function(g){var f=this.position,a=this.size,c=this.axis;if(g.height)g.width=a.height*this.aspectRatio;else if(g.width)g.height=a.width/this.aspectRatio;if(c=="sw"){g.left=f.left+(a.width-g.width);g.top=\r
+null}if(c=="nw"){g.top=f.top+(a.height-g.height);g.left=f.left+(a.width-g.width)}return g},_respectSize:function(g){var f=this.options,a=this.axis,c=e(g.width)&&f.maxWidth&&f.maxWidth<g.width,h=e(g.height)&&f.maxHeight&&f.maxHeight<g.height,i=e(g.width)&&f.minWidth&&f.minWidth>g.width,j=e(g.height)&&f.minHeight&&f.minHeight>g.height;if(i)g.width=f.minWidth;if(j)g.height=f.minHeight;if(c)g.width=f.maxWidth;if(h)g.height=f.maxHeight;var n=this.originalPosition.left+this.originalSize.width,p=this.position.top+\r
+this.size.height,l=/sw|nw|w/.test(a);a=/nw|ne|n/.test(a);if(i&&l)g.left=n-f.minWidth;if(c&&l)g.left=n-f.maxWidth;if(j&&a)g.top=p-f.minHeight;if(h&&a)g.top=p-f.maxHeight;if((f=!g.width&&!g.height)&&!g.left&&g.top)g.top=null;else if(f&&!g.top&&g.left)g.left=null;return g},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var g=this.helper||this.element,f=0;f<this._proportionallyResizeElements.length;f++){var a=this._proportionallyResizeElements[f];if(!this.borderDif){var c=\r
+[a.css("borderTopWidth"),a.css("borderRightWidth"),a.css("borderBottomWidth"),a.css("borderLeftWidth")],h=[a.css("paddingTop"),a.css("paddingRight"),a.css("paddingBottom"),a.css("paddingLeft")];this.borderDif=b.map(c,function(i,j){i=parseInt(i,10)||0;j=parseInt(h[j],10)||0;return i+j})}b.browser.msie&&(b(g).is(":hidden")||b(g).parents(":hidden").length)||a.css({height:g.height()-this.borderDif[0]-this.borderDif[2]||0,width:g.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var g=\r
+this.options;this.elementOffset=this.element.offset();if(this._helper){this.helper=this.helper||b('<div style="overflow:hidden;"></div>');var f=b.browser.msie&&b.browser.version<7,a=f?1:0;f=f?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-a+"px",top:this.elementOffset.top-a+"px",zIndex:++g.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(g,\r
+f){return{width:this.originalSize.width+f}},w:function(g,f){return{left:this.originalPosition.left+f,width:this.originalSize.width-f}},n:function(g,f,a){return{top:this.originalPosition.top+a,height:this.originalSize.height-a}},s:function(g,f,a){return{height:this.originalSize.height+a}},se:function(g,f,a){return b.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,a]))},sw:function(g,f,a){return b.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,\r
+a]))},ne:function(g,f,a){return b.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,a]))},nw:function(g,f,a){return b.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,a]))}},_propagate:function(g,f){b.ui.plugin.call(this,g,[f,this.ui()]);g!="resize"&&this._trigger(g,f,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,\r
+originalPosition:this.originalPosition}}});b.extend(b.ui.resizable,{version:"1.8.11"});b.ui.plugin.add("resizable","alsoResize",{start:function(){var g=b(this).data("resizable").options,f=function(a){b(a).each(function(){var c=b(this);c.data("resizable-alsoresize",{width:parseInt(c.width(),10),height:parseInt(c.height(),10),left:parseInt(c.css("left"),10),top:parseInt(c.css("top"),10),position:c.css("position")})})};if(typeof g.alsoResize=="object"&&!g.alsoResize.parentNode)if(g.alsoResize.length){g.alsoResize=\r
+g.alsoResize[0];f(g.alsoResize)}else b.each(g.alsoResize,function(a){f(a)});else f(g.alsoResize)},resize:function(g,f){var a=b(this).data("resizable");g=a.options;var c=a.originalSize,h=a.originalPosition,i={height:a.size.height-c.height||0,width:a.size.width-c.width||0,top:a.position.top-h.top||0,left:a.position.left-h.left||0},j=function(n,p){b(n).each(function(){var l=b(this),k=b(this).data("resizable-alsoresize"),m={},o=p&&p.length?p:l.parents(f.originalElement[0]).length?["width","height"]:["width",\r
+"height","top","left"];b.each(o,function(q,s){if((q=(k[s]||0)+(i[s]||0))&&q>=0)m[s]=q||null});if(b.browser.opera&&/relative/.test(l.css("position"))){a._revertToRelativePosition=true;l.css({position:"absolute",top:"auto",left:"auto"})}l.css(m)})};typeof g.alsoResize=="object"&&!g.alsoResize.nodeType?b.each(g.alsoResize,function(n,p){j(n,p)}):j(g.alsoResize)},stop:function(){var g=b(this).data("resizable"),f=g.options,a=function(c){b(c).each(function(){var h=b(this);h.css({position:h.data("resizable-alsoresize").position})})};\r
+if(g._revertToRelativePosition){g._revertToRelativePosition=false;typeof f.alsoResize=="object"&&!f.alsoResize.nodeType?b.each(f.alsoResize,function(c){a(c)}):a(f.alsoResize)}b(this).removeData("resizable-alsoresize")}});b.ui.plugin.add("resizable","animate",{stop:function(g){var f=b(this).data("resizable"),a=f.options,c=f._proportionallyResizeElements,h=c.length&&/textarea/i.test(c[0].nodeName),i=h&&b.ui.hasScroll(c[0],"left")?0:f.sizeDiff.height;h={width:f.size.width-(h?0:f.sizeDiff.width),height:f.size.height-\r
+i};i=parseInt(f.element.css("left"),10)+(f.position.left-f.originalPosition.left)||null;var j=parseInt(f.element.css("top"),10)+(f.position.top-f.originalPosition.top)||null;f.element.animate(b.extend(h,j&&i?{top:j,left:i}:{}),{duration:a.animateDuration,easing:a.animateEasing,step:function(){var n={width:parseInt(f.element.css("width"),10),height:parseInt(f.element.css("height"),10),top:parseInt(f.element.css("top"),10),left:parseInt(f.element.css("left"),10)};c&&c.length&&b(c[0]).css({width:n.width,\r
+height:n.height});f._updateCache(n);f._propagate("resize",g)}})}});b.ui.plugin.add("resizable","containment",{start:function(){var g=b(this).data("resizable"),f=g.element,a=g.options.containment;if(f=a instanceof b?a.get(0):/parent/.test(a)?f.parent().get(0):a){g.containerElement=b(f);if(/document/.test(a)||a==document){g.containerOffset={left:0,top:0};g.containerPosition={left:0,top:0};g.parentData={element:b(document),left:0,top:0,width:b(document).width(),height:b(document).height()||document.body.parentNode.scrollHeight}}else{var c=\r
+b(f),h=[];b(["Top","Right","Left","Bottom"]).each(function(n,p){h[n]=d(c.css("padding"+p))});g.containerOffset=c.offset();g.containerPosition=c.position();g.containerSize={height:c.innerHeight()-h[3],width:c.innerWidth()-h[1]};a=g.containerOffset;var i=g.containerSize.height,j=g.containerSize.width;j=b.ui.hasScroll(f,"left")?f.scrollWidth:j;i=b.ui.hasScroll(f)?f.scrollHeight:i;g.parentData={element:f,left:a.left,top:a.top,width:j,height:i}}}},resize:function(g){var f=b(this).data("resizable"),a=f.options,\r
+c=f.containerOffset,h=f.position;g=f._aspectRatio||g.shiftKey;var i={top:0,left:0},j=f.containerElement;if(j[0]!=document&&/static/.test(j.css("position")))i=c;if(h.left<(f._helper?c.left:0)){f.size.width+=f._helper?f.position.left-c.left:f.position.left-i.left;if(g)f.size.height=f.size.width/a.aspectRatio;f.position.left=a.helper?c.left:0}if(h.top<(f._helper?c.top:0)){f.size.height+=f._helper?f.position.top-c.top:f.position.top;if(g)f.size.width=f.size.height*a.aspectRatio;f.position.top=f._helper?\r
+c.top:0}f.offset.left=f.parentData.left+f.position.left;f.offset.top=f.parentData.top+f.position.top;a=Math.abs((f._helper?f.offset.left-i.left:f.offset.left-i.left)+f.sizeDiff.width);c=Math.abs((f._helper?f.offset.top-i.top:f.offset.top-c.top)+f.sizeDiff.height);h=f.containerElement.get(0)==f.element.parent().get(0);i=/relative|absolute/.test(f.containerElement.css("position"));if(h&&i)a-=f.parentData.left;if(a+f.size.width>=f.parentData.width){f.size.width=f.parentData.width-a;if(g)f.size.height=\r
+f.size.width/f.aspectRatio}if(c+f.size.height>=f.parentData.height){f.size.height=f.parentData.height-c;if(g)f.size.width=f.size.height*f.aspectRatio}},stop:function(){var g=b(this).data("resizable"),f=g.options,a=g.containerOffset,c=g.containerPosition,h=g.containerElement,i=b(g.helper),j=i.offset(),n=i.outerWidth()-g.sizeDiff.width;i=i.outerHeight()-g.sizeDiff.height;g._helper&&!f.animate&&/relative/.test(h.css("position"))&&b(this).css({left:j.left-c.left-a.left,width:n,height:i});g._helper&&!f.animate&&\r
+/static/.test(h.css("position"))&&b(this).css({left:j.left-c.left-a.left,width:n,height:i})}});b.ui.plugin.add("resizable","ghost",{start:function(){var g=b(this).data("resizable"),f=g.options,a=g.size;g.ghost=g.originalElement.clone();g.ghost.css({opacity:0.25,display:"block",position:"relative",height:a.height,width:a.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof f.ghost=="string"?f.ghost:"");g.ghost.appendTo(g.helper)},resize:function(){var g=b(this).data("resizable");\r
+g.ghost&&g.ghost.css({position:"relative",height:g.size.height,width:g.size.width})},stop:function(){var g=b(this).data("resizable");g.ghost&&g.helper&&g.helper.get(0).removeChild(g.ghost.get(0))}});b.ui.plugin.add("resizable","grid",{resize:function(){var g=b(this).data("resizable"),f=g.options,a=g.size,c=g.originalSize,h=g.originalPosition,i=g.axis;f.grid=typeof f.grid=="number"?[f.grid,f.grid]:f.grid;var j=Math.round((a.width-c.width)/(f.grid[0]||1))*(f.grid[0]||1);f=Math.round((a.height-c.height)/\r
+(f.grid[1]||1))*(f.grid[1]||1);if(/^(se|s|e)$/.test(i)){g.size.width=c.width+j;g.size.height=c.height+f}else if(/^(ne)$/.test(i)){g.size.width=c.width+j;g.size.height=c.height+f;g.position.top=h.top-f}else{if(/^(sw)$/.test(i)){g.size.width=c.width+j;g.size.height=c.height+f}else{g.size.width=c.width+j;g.size.height=c.height+f;g.position.top=h.top-f}g.position.left=h.left-j}}});var d=function(g){return parseInt(g,10)||0},e=function(g){return!isNaN(parseInt(g,10))}})(jQuery);\r
+(function(b){b.widget("ui.selectable",b.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var d=this;this.element.addClass("ui-selectable");this.dragged=false;var e;this.refresh=function(){e=b(d.options.filter,d.element[0]);e.each(function(){var g=b(this),f=g.offset();b.data(this,"selectable-item",{element:this,$element:g,left:f.left,top:f.top,right:f.left+g.outerWidth(),bottom:f.top+g.outerHeight(),startselected:false,selected:g.hasClass("ui-selected"),\r
+selecting:g.hasClass("ui-selecting"),unselecting:g.hasClass("ui-unselecting")})})};this.refresh();this.selectees=e.addClass("ui-selectee");this._mouseInit();this.helper=b("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(d){var e=this;this.opos=[d.pageX,\r
+d.pageY];if(!this.options.disabled){var g=this.options;this.selectees=b(g.filter,this.element[0]);this._trigger("start",d);b(g.appendTo).append(this.helper);this.helper.css({left:d.clientX,top:d.clientY,width:0,height:0});g.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var f=b.data(this,"selectable-item");f.startselected=true;if(!d.metaKey){f.$element.removeClass("ui-selected");f.selected=false;f.$element.addClass("ui-unselecting");f.unselecting=true;e._trigger("unselecting",\r
+d,{unselecting:f.element})}});b(d.target).parents().andSelf().each(function(){var f=b.data(this,"selectable-item");if(f){var a=!d.metaKey||!f.$element.hasClass("ui-selected");f.$element.removeClass(a?"ui-unselecting":"ui-selected").addClass(a?"ui-selecting":"ui-unselecting");f.unselecting=!a;f.selecting=a;(f.selected=a)?e._trigger("selecting",d,{selecting:f.element}):e._trigger("unselecting",d,{unselecting:f.element});return false}})}},_mouseDrag:function(d){var e=this;this.dragged=true;if(!this.options.disabled){var g=\r
+this.options,f=this.opos[0],a=this.opos[1],c=d.pageX,h=d.pageY;if(f>c){var i=c;c=f;f=i}if(a>h){i=h;h=a;a=i}this.helper.css({left:f,top:a,width:c-f,height:h-a});this.selectees.each(function(){var j=b.data(this,"selectable-item");if(!(!j||j.element==e.element[0])){var n=false;if(g.tolerance=="touch")n=!(j.left>c||j.right<f||j.top>h||j.bottom<a);else if(g.tolerance=="fit")n=j.left>f&&j.right<c&&j.top>a&&j.bottom<h;if(n){if(j.selected){j.$element.removeClass("ui-selected");j.selected=false}if(j.unselecting){j.$element.removeClass("ui-unselecting");\r
+j.unselecting=false}if(!j.selecting){j.$element.addClass("ui-selecting");j.selecting=true;e._trigger("selecting",d,{selecting:j.element})}}else{if(j.selecting)if(d.metaKey&&j.startselected){j.$element.removeClass("ui-selecting");j.selecting=false;j.$element.addClass("ui-selected");j.selected=true}else{j.$element.removeClass("ui-selecting");j.selecting=false;if(j.startselected){j.$element.addClass("ui-unselecting");j.unselecting=true}e._trigger("unselecting",d,{unselecting:j.element})}if(j.selected)if(!d.metaKey&&\r
+!j.startselected){j.$element.removeClass("ui-selected");j.selected=false;j.$element.addClass("ui-unselecting");j.unselecting=true;e._trigger("unselecting",d,{unselecting:j.element})}}}});return false}},_mouseStop:function(d){var e=this;this.dragged=false;b(".ui-unselecting",this.element[0]).each(function(){var g=b.data(this,"selectable-item");g.$element.removeClass("ui-unselecting");g.unselecting=false;g.startselected=false;e._trigger("unselected",d,{unselected:g.element})});b(".ui-selecting",this.element[0]).each(function(){var g=\r
+b.data(this,"selectable-item");g.$element.removeClass("ui-selecting").addClass("ui-selected");g.selecting=false;g.selected=true;g.startselected=true;e._trigger("selected",d,{selected:g.element})});this._trigger("stop",d);this.helper.remove();return false}});b.extend(b.ui.selectable,{version:"1.8.11"})})(jQuery);\r
+(function(b){b.widget("ui.sortable",b.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");\r
+this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var d=this.items.length-1;d>=0;d--)this.items[d].item.removeData("sortable-item");return this},_setOption:function(d,e){if(d==="disabled"){this.options[d]=\r
+e;this.widget()[e?"addClass":"removeClass"]("ui-sortable-disabled")}else b.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(d,e){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(d);var g=null,f=this;b(d.target).parents().each(function(){if(b.data(this,"sortable-item")==f){g=b(this);return false}});if(b.data(d.target,"sortable-item")==f)g=b(d.target);if(!g)return false;if(this.options.handle&&!e){var a=false;\r
+b(this.options.handle,g).find("*").andSelf().each(function(){if(this==d.target)a=true});if(!a)return false}this.currentItem=g;this._removeCurrentsFromItems();return true},_mouseStart:function(d,e,g){e=this.options;var f=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(d);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-\r
+this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");b.extend(this.offset,{click:{left:d.pageX-this.offset.left,top:d.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(d);this.originalPageX=d.pageX;this.originalPageY=d.pageY;e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};\r
+this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();e.containment&&this._setContainment();if(e.cursor){if(b("body").css("cursor"))this._storedCursor=b("body").css("cursor");b("body").css("cursor",e.cursor)}if(e.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",e.opacity)}if(e.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",e.zIndex)}if(this.scrollParent[0]!=\r
+document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",d,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!g)for(g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",d,f._uiHash(this));if(b.ui.ddmanager)b.ui.ddmanager.current=this;b.ui.ddmanager&&!e.dropBehaviour&&b.ui.ddmanager.prepareOffsets(this,d);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(d);\r
+return true},_mouseDrag:function(d){this.position=this._generatePosition(d);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var e=this.options,g=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-d.pageY<e.scrollSensitivity)this.scrollParent[0].scrollTop=g=this.scrollParent[0].scrollTop+e.scrollSpeed;else if(d.pageY-this.overflowOffset.top<\r
+e.scrollSensitivity)this.scrollParent[0].scrollTop=g=this.scrollParent[0].scrollTop-e.scrollSpeed;if(this.overflowOffset.left+this.scrollParent[0].offsetWidth-d.pageX<e.scrollSensitivity)this.scrollParent[0].scrollLeft=g=this.scrollParent[0].scrollLeft+e.scrollSpeed;else if(d.pageX-this.overflowOffset.left<e.scrollSensitivity)this.scrollParent[0].scrollLeft=g=this.scrollParent[0].scrollLeft-e.scrollSpeed}else{if(d.pageY-b(document).scrollTop()<e.scrollSensitivity)g=b(document).scrollTop(b(document).scrollTop()-\r
+e.scrollSpeed);else if(b(window).height()-(d.pageY-b(document).scrollTop())<e.scrollSensitivity)g=b(document).scrollTop(b(document).scrollTop()+e.scrollSpeed);if(d.pageX-b(document).scrollLeft()<e.scrollSensitivity)g=b(document).scrollLeft(b(document).scrollLeft()-e.scrollSpeed);else if(b(window).width()-(d.pageX-b(document).scrollLeft())<e.scrollSensitivity)g=b(document).scrollLeft(b(document).scrollLeft()+e.scrollSpeed)}g!==false&&b.ui.ddmanager&&!e.dropBehaviour&&b.ui.ddmanager.prepareOffsets(this,\r
+d)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(e=this.items.length-1;e>=0;e--){g=this.items[e];var f=g.item[0],a=this._intersectsWithPointer(g);if(a)if(f!=this.currentItem[0]&&this.placeholder[a==1?"next":"prev"]()[0]!=f&&!b.ui.contains(this.placeholder[0],f)&&(this.options.type=="semi-dynamic"?!b.ui.contains(this.element[0],\r
+f):true)){this.direction=a==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(g))this._rearrange(d,g);else break;this._trigger("change",d,this._uiHash());break}}this._contactContainers(d);b.ui.ddmanager&&b.ui.ddmanager.drag(this,d);this._trigger("sort",d,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(d,e){if(d){b.ui.ddmanager&&!this.options.dropBehaviour&&b.ui.ddmanager.drop(this,d);if(this.options.revert){var g=this;e=g.placeholder.offset();\r
+g.reverting=true;b(this.helper).animate({left:e.left-this.offset.parent.left-g.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-g.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){g._clear(d)})}else this._clear(d,e);return false}},cancel:function(){var d=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):\r
+this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--){this.containers[e]._trigger("deactivate",null,d._uiHash(this));if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",null,d._uiHash(this));this.containers[e].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();b.extend(this,{helper:null,\r
+dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?b(this.domPosition.prev).after(this.currentItem):b(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(d){var e=this._getItemsAsjQuery(d&&d.connected),g=[];d=d||{};b(e).each(function(){var f=(b(d.item||this).attr(d.attribute||"id")||"").match(d.expression||/(.+)[-=_](.+)/);if(f)g.push((d.key||f[1]+"[]")+"="+(d.key&&d.expression?f[1]:f[2]))});!g.length&&d.key&&g.push(d.key+"=");return g.join("&")},\r
+toArray:function(d){var e=this._getItemsAsjQuery(d&&d.connected),g=[];d=d||{};e.each(function(){g.push(b(d.item||this).attr(d.attribute||"id")||"")});return g},_intersectsWith:function(d){var e=this.positionAbs.left,g=e+this.helperProportions.width,f=this.positionAbs.top,a=f+this.helperProportions.height,c=d.left,h=c+d.width,i=d.top,j=i+d.height,n=this.offset.click.top,p=this.offset.click.left;n=f+n>i&&f+n<j&&e+p>c&&e+p<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||\r
+this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>d[this.floating?"width":"height"]?n:c<e+this.helperProportions.width/2&&g-this.helperProportions.width/2<h&&i<f+this.helperProportions.height/2&&a-this.helperProportions.height/2<j},_intersectsWithPointer:function(d){var e=b.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top,d.height);d=b.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left,d.width);e=e&&d;d=this._getDragVerticalDirection();\r
+var g=this._getDragHorizontalDirection();if(!e)return false;return this.floating?g&&g=="right"||d=="down"?2:1:d&&(d=="down"?2:1)},_intersectsWithSides:function(d){var e=b.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top+d.height/2,d.height);d=b.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left+d.width/2,d.width);var g=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:g&&(g=="down"&&e||g=="up"&&!e)},\r
+_getDragVerticalDirection:function(){var d=this.positionAbs.top-this.lastPositionAbs.top;return d!=0&&(d>0?"down":"up")},_getDragHorizontalDirection:function(){var d=this.positionAbs.left-this.lastPositionAbs.left;return d!=0&&(d>0?"right":"left")},refresh:function(d){this._refreshItems(d);this.refreshPositions();return this},_connectWith:function(){var d=this.options;return d.connectWith.constructor==String?[d.connectWith]:d.connectWith},_getItemsAsjQuery:function(d){var e=[],g=[],f=this._connectWith();\r
+if(f&&d)for(d=f.length-1;d>=0;d--)for(var a=b(f[d]),c=a.length-1;c>=0;c--){var h=b.data(a[c],"sortable");if(h&&h!=this&&!h.options.disabled)g.push([b.isFunction(h.options.items)?h.options.items.call(h.element):b(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}g.push([b.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):b(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),\r
+this]);for(d=g.length-1;d>=0;d--)g[d][0].each(function(){e.push(this)});return b(e)},_removeCurrentsFromItems:function(){for(var d=this.currentItem.find(":data(sortable-item)"),e=0;e<this.items.length;e++)for(var g=0;g<d.length;g++)d[g]==this.items[e].item[0]&&this.items.splice(e,1)},_refreshItems:function(d){this.items=[];this.containers=[this];var e=this.items,g=[[b.isFunction(this.options.items)?this.options.items.call(this.element[0],d,{item:this.currentItem}):b(this.options.items,this.element),\r
+this]],f=this._connectWith();if(f)for(var a=f.length-1;a>=0;a--)for(var c=b(f[a]),h=c.length-1;h>=0;h--){var i=b.data(c[h],"sortable");if(i&&i!=this&&!i.options.disabled){g.push([b.isFunction(i.options.items)?i.options.items.call(i.element[0],d,{item:this.currentItem}):b(i.options.items,i.element),i]);this.containers.push(i)}}for(a=g.length-1;a>=0;a--){d=g[a][1];f=g[a][0];h=0;for(c=f.length;h<c;h++){i=b(f[h]);i.data("sortable-item",d);e.push({item:i,instance:d,width:0,height:0,left:0,top:0})}}},refreshPositions:function(d){if(this.offsetParent&&\r
+this.helper)this.offset.parent=this._getParentOffset();for(var e=this.items.length-1;e>=0;e--){var g=this.items[e],f=this.options.toleranceElement?b(this.options.toleranceElement,g.item):g.item;if(!d){g.width=f.outerWidth();g.height=f.outerHeight()}f=f.offset();g.left=f.left;g.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(e=this.containers.length-1;e>=0;e--){f=this.containers[e].element.offset();this.containers[e].containerCache.left=\r
+f.left;this.containers[e].containerCache.top=f.top;this.containers[e].containerCache.width=this.containers[e].element.outerWidth();this.containers[e].containerCache.height=this.containers[e].element.outerHeight()}return this},_createPlaceholder:function(d){var e=d||this,g=e.options;if(!g.placeholder||g.placeholder.constructor==String){var f=g.placeholder;g.placeholder={element:function(){var a=b(document.createElement(e.currentItem[0].nodeName)).addClass(f||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];\r
+if(!f)a.style.visibility="hidden";return a},update:function(a,c){if(!(f&&!g.forcePlaceholderSize)){c.height()||c.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10));c.width()||c.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10))}}}}e.placeholder=b(g.placeholder.element.call(e.element,e.currentItem));e.currentItem.after(e.placeholder);\r
+g.placeholder.update(e,e.placeholder)},_contactContainers:function(d){for(var e=null,g=null,f=this.containers.length-1;f>=0;f--)if(!b.ui.contains(this.currentItem[0],this.containers[f].element[0]))if(this._intersectsWith(this.containers[f].containerCache)){if(!(e&&b.ui.contains(this.containers[f].element[0],e.element[0]))){e=this.containers[f];g=f}}else if(this.containers[f].containerCache.over){this.containers[f]._trigger("out",d,this._uiHash(this));this.containers[f].containerCache.over=0}if(e)if(this.containers.length===\r
+1){this.containers[g]._trigger("over",d,this._uiHash(this));this.containers[g].containerCache.over=1}else if(this.currentContainer!=this.containers[g]){e=1E4;f=null;for(var a=this.positionAbs[this.containers[g].floating?"left":"top"],c=this.items.length-1;c>=0;c--)if(b.ui.contains(this.containers[g].element[0],this.items[c].item[0])){var h=this.items[c][this.containers[g].floating?"left":"top"];if(Math.abs(h-a)<e){e=Math.abs(h-a);f=this.items[c]}}if(f||this.options.dropOnEmpty){this.currentContainer=\r
+this.containers[g];f?this._rearrange(d,f,null,true):this._rearrange(d,null,this.containers[g].element,true);this._trigger("change",d,this._uiHash());this.containers[g]._trigger("change",d,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[g]._trigger("over",d,this._uiHash(this));this.containers[g].containerCache.over=1}}},_createHelper:function(d){var e=this.options;d=b.isFunction(e.helper)?b(e.helper.apply(this.element[0],[d,this.currentItem])):\r
+e.helper=="clone"?this.currentItem.clone():this.currentItem;d.parents("body").length||b(e.appendTo!="parent"?e.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]);if(d[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(d[0].style.width==""||e.forceHelperSize)d.width(this.currentItem.width());if(d[0].style.height==\r
+""||e.forceHelperSize)d.height(this.currentItem.height());return d},_adjustOffsetFromHelper:function(d){if(typeof d=="string")d=d.split(" ");if(b.isArray(d))d={left:+d[0],top:+d[1]||0};if("left"in d)this.offset.click.left=d.left+this.margins.left;if("right"in d)this.offset.click.left=this.helperProportions.width-d.right+this.margins.left;if("top"in d)this.offset.click.top=d.top+this.margins.top;if("bottom"in d)this.offset.click.top=this.helperProportions.height-d.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=\r
+this.helper.offsetParent();var d=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&b.ui.contains(this.scrollParent[0],this.offsetParent[0])){d.left+=this.scrollParent.scrollLeft();d.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&b.browser.msie)d={top:0,left:0};return{top:d.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:d.left+(parseInt(this.offsetParent.css("borderLeftWidth"),\r
+10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var d=this.currentItem.position();return{top:d.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:d.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions=\r
+{width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var d=this.options;if(d.containment=="parent")d.containment=this.helper[0].parentNode;if(d.containment=="document"||d.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,b(d.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b(d.containment=="document"?document:window).height()||\r
+document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(d.containment)){var e=b(d.containment)[0];d=b(d.containment).offset();var g=b(e).css("overflow")!="hidden";this.containment=[d.left+(parseInt(b(e).css("borderLeftWidth"),10)||0)+(parseInt(b(e).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(b(e).css("borderTopWidth"),10)||0)+(parseInt(b(e).css("paddingTop"),10)||0)-this.margins.top,d.left+(g?Math.max(e.scrollWidth,\r
+e.offsetWidth):e.offsetWidth)-(parseInt(b(e).css("borderLeftWidth"),10)||0)-(parseInt(b(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(g?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(b(e).css("borderTopWidth"),10)||0)-(parseInt(b(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(d,e){if(!e)e=this.position;d=d=="absolute"?1:-1;var g=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=\r
+document&&b.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(g[0].tagName);return{top:e.top+this.offset.relative.top*d+this.offset.parent.top*d-(b.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:g.scrollTop())*d),left:e.left+this.offset.relative.left*d+this.offset.parent.left*d-(b.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():\r
+f?0:g.scrollLeft())*d)}},_generatePosition:function(d){var e=this.options,g=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&b.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(g[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var a=d.pageX,c=d.pageY;if(this.originalPosition){if(this.containment){if(d.pageX-\r
+this.offset.click.left<this.containment[0])a=this.containment[0]+this.offset.click.left;if(d.pageY-this.offset.click.top<this.containment[1])c=this.containment[1]+this.offset.click.top;if(d.pageX-this.offset.click.left>this.containment[2])a=this.containment[2]+this.offset.click.left;if(d.pageY-this.offset.click.top>this.containment[3])c=this.containment[3]+this.offset.click.top}if(e.grid){c=this.originalPageY+Math.round((c-this.originalPageY)/e.grid[1])*e.grid[1];c=this.containment?!(c-this.offset.click.top<\r
+this.containment[1]||c-this.offset.click.top>this.containment[3])?c:!(c-this.offset.click.top<this.containment[1])?c-e.grid[1]:c+e.grid[1]:c;a=this.originalPageX+Math.round((a-this.originalPageX)/e.grid[0])*e.grid[0];a=this.containment?!(a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2])?a:!(a-this.offset.click.left<this.containment[0])?a-e.grid[0]:a+e.grid[0]:a}}return{top:c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(b.browser.safari&&\r
+this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:g.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(b.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:g.scrollLeft())}},_rearrange:function(d,e,g,f){g?g[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?e.item[0]:e.item[0].nextSibling);this.counter=\r
+this.counter?++this.counter:1;var a=this,c=this.counter;window.setTimeout(function(){c==a.counter&&a.refreshPositions(!f)},0)},_clear:function(d,e){this.reverting=false;var g=[];!this._noFinalSort&&this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();\r
+this.fromOutside&&!e&&g.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!e)g.push(function(a){this._trigger("update",a,this._uiHash())});if(!b.ui.contains(this.element[0],this.currentItem[0])){e||g.push(function(a){this._trigger("remove",a,this._uiHash())});for(f=this.containers.length-1;f>=0;f--)if(b.ui.contains(this.containers[f].element[0],\r
+this.currentItem[0])&&!e){g.push(function(a){return function(c){a._trigger("receive",c,this._uiHash(this))}}.call(this,this.containers[f]));g.push(function(a){return function(c){a._trigger("update",c,this._uiHash(this))}}.call(this,this.containers[f]))}}for(f=this.containers.length-1;f>=0;f--){e||g.push(function(a){return function(c){a._trigger("deactivate",c,this._uiHash(this))}}.call(this,this.containers[f]));if(this.containers[f].containerCache.over){g.push(function(a){return function(c){a._trigger("out",\r
+c,this._uiHash(this))}}.call(this,this.containers[f]));this.containers[f].containerCache.over=0}}this._storedCursor&&b("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!e){this._trigger("beforeStop",d,this._uiHash());for(f=0;f<g.length;f++)g[f].call(this,d);this._trigger("stop",d,this._uiHash())}return false}e||\r
+this._trigger("beforeStop",d,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!e){for(f=0;f<g.length;f++)g[f].call(this,d);this._trigger("stop",d,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){b.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(d){var e=d||this;return{helper:e.helper,placeholder:e.placeholder||b([]),position:e.position,\r
+originalPosition:e.originalPosition,offset:e.positionAbs,item:e.currentItem,sender:d?d.element:null}}});b.extend(b.ui.sortable,{version:"1.8.11"})})(jQuery);\r
+jQuery.effects||function(b,d){function e(l){var k;if(l&&l.constructor==Array&&l.length==3)return l;if(k=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(l))return[parseInt(k[1],10),parseInt(k[2],10),parseInt(k[3],10)];if(k=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(l))return[parseFloat(k[1])*2.55,parseFloat(k[2])*2.55,parseFloat(k[3])*2.55];if(k=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(l))return[parseInt(k[1],\r
+16),parseInt(k[2],16),parseInt(k[3],16)];if(k=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(l))return[parseInt(k[1]+k[1],16),parseInt(k[2]+k[2],16),parseInt(k[3]+k[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(l))return j.transparent;return j[b.trim(l).toLowerCase()]}function g(l,k){var m;do{m=b.curCSS(l,k);if(m!=""&&m!="transparent"||b.nodeName(l,"body"))break;k="backgroundColor"}while(l=l.parentNode);return e(m)}function f(){var l=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,\r
+k={},m,o;if(l&&l.length&&l[0]&&l[l[0]])for(var q=l.length;q--;){m=l[q];if(typeof l[m]=="string"){o=m.replace(/\-(\w)/g,function(s,r){return r.toUpperCase()});k[o]=l[m]}}else for(m in l)if(typeof l[m]==="string")k[m]=l[m];return k}function a(l){var k,m;for(k in l){m=l[k];if(m==null||b.isFunction(m)||k in p||/scrollbar/.test(k)||!/color/i.test(k)&&isNaN(parseFloat(m)))delete l[k]}return l}function c(l,k){var m={_:0},o;for(o in k)if(l[o]!=k[o])m[o]=k[o];return m}function h(l,k,m,o){if(typeof l=="object"){o=\r
+k;m=null;k=l;l=k.effect}if(b.isFunction(k)){o=k;m=null;k={}}if(typeof k=="number"||b.fx.speeds[k]){o=m;m=k;k={}}if(b.isFunction(m)){o=m;m=null}k=k||{};m=m||k.duration;m=b.fx.off?0:typeof m=="number"?m:m in b.fx.speeds?b.fx.speeds[m]:b.fx.speeds._default;o=o||k.complete;return[l,k,m,o]}function i(l){if(!l||typeof l==="number"||b.fx.speeds[l])return true;if(typeof l==="string"&&!b.effects[l])return true;return false}b.effects={};b.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor",\r
+"borderTopColor","borderColor","color","outlineColor"],function(l,k){b.fx.step[k]=function(m){if(!m.colorInit){m.start=g(m.elem,k);m.end=e(m.end);m.colorInit=true}m.elem.style[k]="rgb("+Math.max(Math.min(parseInt(m.pos*(m.end[0]-m.start[0])+m.start[0],10),255),0)+","+Math.max(Math.min(parseInt(m.pos*(m.end[1]-m.start[1])+m.start[1],10),255),0)+","+Math.max(Math.min(parseInt(m.pos*(m.end[2]-m.start[2])+m.start[2],10),255),0)+")"}});var j={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,\r
+0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,\r
+211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},n=["add","remove","toggle"],p={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};b.effects.animateClass=function(l,k,m,\r
+o){if(b.isFunction(m)){o=m;m=null}return this.queue("fx",function(){var q=b(this),s=q.attr("style")||" ",r=a(f.call(this)),u,v=q.attr("className");b.each(n,function(w,y){l[y]&&q[y+"Class"](l[y])});u=a(f.call(this));q.attr("className",v);q.animate(c(r,u),k,m,function(){b.each(n,function(w,y){l[y]&&q[y+"Class"](l[y])});if(typeof q.attr("style")=="object"){q.attr("style").cssText="";q.attr("style").cssText=s}else q.attr("style",s);o&&o.apply(this,arguments)});r=b.queue(this);u=r.splice(r.length-1,1)[0];\r
+r.splice(1,0,u);b.dequeue(this)})};b.fn.extend({_addClass:b.fn.addClass,addClass:function(l,k,m,o){return k?b.effects.animateClass.apply(this,[{add:l},k,m,o]):this._addClass(l)},_removeClass:b.fn.removeClass,removeClass:function(l,k,m,o){return k?b.effects.animateClass.apply(this,[{remove:l},k,m,o]):this._removeClass(l)},_toggleClass:b.fn.toggleClass,toggleClass:function(l,k,m,o,q){return typeof k=="boolean"||k===d?m?b.effects.animateClass.apply(this,[k?{add:l}:{remove:l},m,o,q]):this._toggleClass(l,\r
+k):b.effects.animateClass.apply(this,[{toggle:l},k,m,o])},switchClass:function(l,k,m,o,q){return b.effects.animateClass.apply(this,[{add:k,remove:l},m,o,q])}});b.extend(b.effects,{version:"1.8.11",save:function(l,k){for(var m=0;m<k.length;m++)k[m]!==null&&l.data("ec.storage."+k[m],l[0].style[k[m]])},restore:function(l,k){for(var m=0;m<k.length;m++)k[m]!==null&&l.css(k[m],l.data("ec.storage."+k[m]))},setMode:function(l,k){if(k=="toggle")k=l.is(":hidden")?"show":"hide";return k},getBaseline:function(l,\r
+k){var m;switch(l[0]){case "top":m=0;break;case "middle":m=0.5;break;case "bottom":m=1;break;default:m=l[0]/k.height}switch(l[1]){case "left":l=0;break;case "center":l=0.5;break;case "right":l=1;break;default:l=l[1]/k.width}return{x:l,y:m}},createWrapper:function(l){if(l.parent().is(".ui-effects-wrapper"))return l.parent();var k={width:l.outerWidth(true),height:l.outerHeight(true),"float":l.css("float")},m=b("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",\r
+border:"none",margin:0,padding:0});l.wrap(m);m=l.parent();if(l.css("position")=="static"){m.css({position:"relative"});l.css({position:"relative"})}else{b.extend(k,{position:l.css("position"),zIndex:l.css("z-index")});b.each(["top","left","bottom","right"],function(o,q){k[q]=l.css(q);if(isNaN(parseInt(k[q],10)))k[q]="auto"});l.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return m.css(k).show()},removeWrapper:function(l){if(l.parent().is(".ui-effects-wrapper"))return l.parent().replaceWith(l);\r
+return l},setTransition:function(l,k,m,o){o=o||{};b.each(k,function(q,s){unit=l.cssUnit(s);if(unit[0]>0)o[s]=unit[0]*m+unit[1]});return o}});b.fn.extend({effect:function(l){var k=h.apply(this,arguments),m={options:k[1],duration:k[2],callback:k[3]};k=m.options.mode;var o=b.effects[l];if(b.fx.off||!o)return k?this[k](m.duration,m.callback):this.each(function(){m.callback&&m.callback.call(this)});return o.call(this,m)},_show:b.fn.show,show:function(l){if(i(l))return this._show.apply(this,arguments);\r
+else{var k=h.apply(this,arguments);k[1].mode="show";return this.effect.apply(this,k)}},_hide:b.fn.hide,hide:function(l){if(i(l))return this._hide.apply(this,arguments);else{var k=h.apply(this,arguments);k[1].mode="hide";return this.effect.apply(this,k)}},__toggle:b.fn.toggle,toggle:function(l){if(i(l)||typeof l==="boolean"||b.isFunction(l))return this.__toggle.apply(this,arguments);else{var k=h.apply(this,arguments);k[1].mode="toggle";return this.effect.apply(this,k)}},cssUnit:function(l){var k=this.css(l),\r
+m=[];b.each(["em","px","%","pt"],function(o,q){if(k.indexOf(q)>0)m=[parseFloat(k),q]});return m}});b.easing.jswing=b.easing.swing;b.extend(b.easing,{def:"easeOutQuad",swing:function(l,k,m,o,q){return b.easing[b.easing.def](l,k,m,o,q)},easeInQuad:function(l,k,m,o,q){return o*(k/=q)*k+m},easeOutQuad:function(l,k,m,o,q){return-o*(k/=q)*(k-2)+m},easeInOutQuad:function(l,k,m,o,q){if((k/=q/2)<1)return o/2*k*k+m;return-o/2*(--k*(k-2)-1)+m},easeInCubic:function(l,k,m,o,q){return o*(k/=q)*k*k+m},easeOutCubic:function(l,\r
+k,m,o,q){return o*((k=k/q-1)*k*k+1)+m},easeInOutCubic:function(l,k,m,o,q){if((k/=q/2)<1)return o/2*k*k*k+m;return o/2*((k-=2)*k*k+2)+m},easeInQuart:function(l,k,m,o,q){return o*(k/=q)*k*k*k+m},easeOutQuart:function(l,k,m,o,q){return-o*((k=k/q-1)*k*k*k-1)+m},easeInOutQuart:function(l,k,m,o,q){if((k/=q/2)<1)return o/2*k*k*k*k+m;return-o/2*((k-=2)*k*k*k-2)+m},easeInQuint:function(l,k,m,o,q){return o*(k/=q)*k*k*k*k+m},easeOutQuint:function(l,k,m,o,q){return o*((k=k/q-1)*k*k*k*k+1)+m},easeInOutQuint:function(l,\r
+k,m,o,q){if((k/=q/2)<1)return o/2*k*k*k*k*k+m;return o/2*((k-=2)*k*k*k*k+2)+m},easeInSine:function(l,k,m,o,q){return-o*Math.cos(k/q*(Math.PI/2))+o+m},easeOutSine:function(l,k,m,o,q){return o*Math.sin(k/q*(Math.PI/2))+m},easeInOutSine:function(l,k,m,o,q){return-o/2*(Math.cos(Math.PI*k/q)-1)+m},easeInExpo:function(l,k,m,o,q){return k==0?m:o*Math.pow(2,10*(k/q-1))+m},easeOutExpo:function(l,k,m,o,q){return k==q?m+o:o*(-Math.pow(2,-10*k/q)+1)+m},easeInOutExpo:function(l,k,m,o,q){if(k==0)return m;if(k==\r
+q)return m+o;if((k/=q/2)<1)return o/2*Math.pow(2,10*(k-1))+m;return o/2*(-Math.pow(2,-10*--k)+2)+m},easeInCirc:function(l,k,m,o,q){return-o*(Math.sqrt(1-(k/=q)*k)-1)+m},easeOutCirc:function(l,k,m,o,q){return o*Math.sqrt(1-(k=k/q-1)*k)+m},easeInOutCirc:function(l,k,m,o,q){if((k/=q/2)<1)return-o/2*(Math.sqrt(1-k*k)-1)+m;return o/2*(Math.sqrt(1-(k-=2)*k)+1)+m},easeInElastic:function(l,k,m,o,q){l=1.70158;var s=0,r=o;if(k==0)return m;if((k/=q)==1)return m+o;s||(s=q*0.3);if(r<Math.abs(o)){r=o;l=s/4}else l=\r
+s/(2*Math.PI)*Math.asin(o/r);return-(r*Math.pow(2,10*(k-=1))*Math.sin((k*q-l)*2*Math.PI/s))+m},easeOutElastic:function(l,k,m,o,q){l=1.70158;var s=0,r=o;if(k==0)return m;if((k/=q)==1)return m+o;s||(s=q*0.3);if(r<Math.abs(o)){r=o;l=s/4}else l=s/(2*Math.PI)*Math.asin(o/r);return r*Math.pow(2,-10*k)*Math.sin((k*q-l)*2*Math.PI/s)+o+m},easeInOutElastic:function(l,k,m,o,q){l=1.70158;var s=0,r=o;if(k==0)return m;if((k/=q/2)==2)return m+o;s||(s=q*0.3*1.5);if(r<Math.abs(o)){r=o;l=s/4}else l=s/(2*Math.PI)*Math.asin(o/\r
+r);if(k<1)return-0.5*r*Math.pow(2,10*(k-=1))*Math.sin((k*q-l)*2*Math.PI/s)+m;return r*Math.pow(2,-10*(k-=1))*Math.sin((k*q-l)*2*Math.PI/s)*0.5+o+m},easeInBack:function(l,k,m,o,q,s){if(s==d)s=1.70158;return o*(k/=q)*k*((s+1)*k-s)+m},easeOutBack:function(l,k,m,o,q,s){if(s==d)s=1.70158;return o*((k=k/q-1)*k*((s+1)*k+s)+1)+m},easeInOutBack:function(l,k,m,o,q,s){if(s==d)s=1.70158;if((k/=q/2)<1)return o/2*k*k*(((s*=1.525)+1)*k-s)+m;return o/2*((k-=2)*k*(((s*=1.525)+1)*k+s)+2)+m},easeInBounce:function(l,\r
+k,m,o,q){return o-b.easing.easeOutBounce(l,q-k,0,o,q)+m},easeOutBounce:function(l,k,m,o,q){return(k/=q)<1/2.75?o*7.5625*k*k+m:k<2/2.75?o*(7.5625*(k-=1.5/2.75)*k+0.75)+m:k<2.5/2.75?o*(7.5625*(k-=2.25/2.75)*k+0.9375)+m:o*(7.5625*(k-=2.625/2.75)*k+0.984375)+m},easeInOutBounce:function(l,k,m,o,q){if(k<q/2)return b.easing.easeInBounce(l,k*2,0,o,q)*0.5+m;return b.easing.easeOutBounce(l,k*2-q,0,o,q)*0.5+o*0.5+m}})}(jQuery);\r
+(function(b){b.effects.blind=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(e,d.options.mode||"hide"),a=d.options.direction||"vertical";b.effects.save(e,g);e.show();var c=b.effects.createWrapper(e).css({overflow:"hidden"}),h=a=="vertical"?"height":"width";a=a=="vertical"?c.height():c.width();f=="show"&&c.css(h,0);var i={};i[h]=f=="show"?a:0;c.animate(i,d.duration,d.options.easing,function(){f=="hide"&&e.hide();b.effects.restore(e,\r
+g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(e[0],arguments);e.dequeue()})})}})(jQuery);\r
+(function(b){b.effects.bounce=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(e,d.options.mode||"effect"),a=d.options.direction||"up",c=d.options.distance||20,h=d.options.times||5,i=d.duration||250;/show|hide/.test(f)&&g.push("opacity");b.effects.save(e,g);e.show();b.effects.createWrapper(e);var j=a=="up"||a=="down"?"top":"left";a=a=="up"||a=="left"?"pos":"neg";c=d.options.distance||(j=="top"?e.outerHeight({margin:true})/3:e.outerWidth({margin:true})/\r
+3);if(f=="show")e.css("opacity",0).css(j,a=="pos"?-c:c);if(f=="hide")c/=h*2;f!="hide"&&h--;if(f=="show"){var n={opacity:1};n[j]=(a=="pos"?"+=":"-=")+c;e.animate(n,i/2,d.options.easing);c/=2;h--}for(n=0;n<h;n++){var p={},l={};p[j]=(a=="pos"?"-=":"+=")+c;l[j]=(a=="pos"?"+=":"-=")+c;e.animate(p,i/2,d.options.easing).animate(l,i/2,d.options.easing);c=f=="hide"?c*2:c/2}if(f=="hide"){n={opacity:0};n[j]=(a=="pos"?"-=":"+=")+c;e.animate(n,i/2,d.options.easing,function(){e.hide();b.effects.restore(e,g);b.effects.removeWrapper(e);\r
+d.callback&&d.callback.apply(this,arguments)})}else{p={};l={};p[j]=(a=="pos"?"-=":"+=")+c;l[j]=(a=="pos"?"+=":"-=")+c;e.animate(p,i/2,d.options.easing).animate(l,i/2,d.options.easing,function(){b.effects.restore(e,g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(this,arguments)})}e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);\r
+(function(b){b.effects.clip=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right","height","width"],f=b.effects.setMode(e,d.options.mode||"hide"),a=d.options.direction||"vertical";b.effects.save(e,g);e.show();var c=b.effects.createWrapper(e).css({overflow:"hidden"});c=e[0].tagName=="IMG"?c:e;var h={size:a=="vertical"?"height":"width",position:a=="vertical"?"top":"left"};a=a=="vertical"?c.height():c.width();if(f=="show"){c.css(h.size,0);c.css(h.position,\r
+a/2)}var i={};i[h.size]=f=="show"?a:0;i[h.position]=f=="show"?0:a/2;c.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){f=="hide"&&e.hide();b.effects.restore(e,g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(e[0],arguments);e.dequeue()}})})}})(jQuery);\r
+(function(b){b.effects.drop=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right","opacity"],f=b.effects.setMode(e,d.options.mode||"hide"),a=d.options.direction||"left";b.effects.save(e,g);e.show();b.effects.createWrapper(e);var c=a=="up"||a=="down"?"top":"left";a=a=="up"||a=="left"?"pos":"neg";var h=d.options.distance||(c=="top"?e.outerHeight({margin:true})/2:e.outerWidth({margin:true})/2);if(f=="show")e.css("opacity",0).css(c,a=="pos"?-h:h);var i={opacity:f==\r
+"show"?1:0};i[c]=(f=="show"?a=="pos"?"+=":"-=":a=="pos"?"-=":"+=")+h;e.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){f=="hide"&&e.hide();b.effects.restore(e,g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(this,arguments);e.dequeue()}})})}})(jQuery);\r
+(function(b){b.effects.explode=function(d){return this.queue(function(){var e=d.options.pieces?Math.round(Math.sqrt(d.options.pieces)):3,g=d.options.pieces?Math.round(Math.sqrt(d.options.pieces)):3;d.options.mode=d.options.mode=="toggle"?b(this).is(":visible")?"hide":"show":d.options.mode;var f=b(this).show().css("visibility","hidden"),a=f.offset();a.top-=parseInt(f.css("marginTop"),10)||0;a.left-=parseInt(f.css("marginLeft"),10)||0;for(var c=f.outerWidth(true),h=f.outerHeight(true),i=0;i<e;i++)for(var j=\r
+0;j<g;j++)f.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-j*(c/g),top:-i*(h/e)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:c/g,height:h/e,left:a.left+j*(c/g)+(d.options.mode=="show"?(j-Math.floor(g/2))*(c/g):0),top:a.top+i*(h/e)+(d.options.mode=="show"?(i-Math.floor(e/2))*(h/e):0),opacity:d.options.mode=="show"?0:1}).animate({left:a.left+j*(c/g)+(d.options.mode=="show"?0:(j-Math.floor(g/2))*(c/g)),top:a.top+\r
+i*(h/e)+(d.options.mode=="show"?0:(i-Math.floor(e/2))*(h/e)),opacity:d.options.mode=="show"?1:0},d.duration||500);setTimeout(function(){d.options.mode=="show"?f.css({visibility:"visible"}):f.css({visibility:"visible"}).hide();d.callback&&d.callback.apply(f[0]);f.dequeue();b("div.ui-effects-explode").remove()},d.duration||500)})}})(jQuery);\r
+(function(b){b.effects.fade=function(d){return this.queue(function(){var e=b(this),g=b.effects.setMode(e,d.options.mode||"hide");e.animate({opacity:g},{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){d.callback&&d.callback.apply(this,arguments);e.dequeue()}})})}})(jQuery);\r
+(function(b){b.effects.fold=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(e,d.options.mode||"hide"),a=d.options.size||15,c=!!d.options.horizFirst,h=d.duration?d.duration/2:b.fx.speeds._default/2;b.effects.save(e,g);e.show();var i=b.effects.createWrapper(e).css({overflow:"hidden"}),j=f=="show"!=c,n=j?["width","height"]:["height","width"];j=j?[i.width(),i.height()]:[i.height(),i.width()];var p=/([0-9]+)%/.exec(a);if(p)a=parseInt(p[1],\r
+10)/100*j[f=="hide"?0:1];if(f=="show")i.css(c?{height:0,width:a}:{height:a,width:0});c={};p={};c[n[0]]=f=="show"?j[0]:a;p[n[1]]=f=="show"?j[1]:0;i.animate(c,h,d.options.easing).animate(p,h,d.options.easing,function(){f=="hide"&&e.hide();b.effects.restore(e,g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(e[0],arguments);e.dequeue()})})}})(jQuery);\r
+(function(b){b.effects.highlight=function(d){return this.queue(function(){var e=b(this),g=["backgroundImage","backgroundColor","opacity"],f=b.effects.setMode(e,d.options.mode||"show"),a={backgroundColor:e.css("backgroundColor")};if(f=="hide")a.opacity=0;b.effects.save(e,g);e.show().css({backgroundImage:"none",backgroundColor:d.options.color||"#ffff99"}).animate(a,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){f=="hide"&&e.hide();b.effects.restore(e,g);f=="show"&&!b.support.opacity&&\r
+this.style.removeAttribute("filter");d.callback&&d.callback.apply(this,arguments);e.dequeue()}})})}})(jQuery);\r
+(function(b){b.effects.pulsate=function(d){return this.queue(function(){var e=b(this),g=b.effects.setMode(e,d.options.mode||"show");times=(d.options.times||5)*2-1;duration=d.duration?d.duration/2:b.fx.speeds._default/2;isVisible=e.is(":visible");animateTo=0;if(!isVisible){e.css("opacity",0).show();animateTo=1}if(g=="hide"&&isVisible||g=="show"&&!isVisible)times--;for(g=0;g<times;g++){e.animate({opacity:animateTo},duration,d.options.easing);animateTo=(animateTo+1)%2}e.animate({opacity:animateTo},duration,\r
+d.options.easing,function(){animateTo==0&&e.hide();d.callback&&d.callback.apply(this,arguments)});e.queue("fx",function(){e.dequeue()}).dequeue()})}})(jQuery);\r
+(function(b){b.effects.puff=function(d){return this.queue(function(){var e=b(this),g=b.effects.setMode(e,d.options.mode||"hide"),f=parseInt(d.options.percent,10)||150,a=f/100,c={height:e.height(),width:e.width()};b.extend(d.options,{fade:true,mode:g,percent:g=="hide"?f:100,from:g=="hide"?c:{height:c.height*a,width:c.width*a}});e.effect("scale",d.options,d.duration,d.callback);e.dequeue()})};b.effects.scale=function(d){return this.queue(function(){var e=b(this),g=b.extend(true,{},d.options),f=b.effects.setMode(e,\r
+d.options.mode||"effect"),a=parseInt(d.options.percent,10)||(parseInt(d.options.percent,10)==0?0:f=="hide"?0:100),c=d.options.direction||"both",h=d.options.origin;if(f!="effect"){g.origin=h||["middle","center"];g.restore=true}h={height:e.height(),width:e.width()};e.from=d.options.from||(f=="show"?{height:0,width:0}:h);a={y:c!="horizontal"?a/100:1,x:c!="vertical"?a/100:1};e.to={height:h.height*a.y,width:h.width*a.x};if(d.options.fade){if(f=="show"){e.from.opacity=0;e.to.opacity=1}if(f=="hide"){e.from.opacity=\r
+1;e.to.opacity=0}}g.from=e.from;g.to=e.to;g.mode=f;e.effect("size",g,d.duration,d.callback);e.dequeue()})};b.effects.size=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right","width","height","overflow","opacity"],f=["position","top","bottom","left","right","overflow","opacity"],a=["width","height","overflow"],c=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],i=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],\r
+j=b.effects.setMode(e,d.options.mode||"effect"),n=d.options.restore||false,p=d.options.scale||"both",l=d.options.origin,k={height:e.height(),width:e.width()};e.from=d.options.from||k;e.to=d.options.to||k;if(l){l=b.effects.getBaseline(l,k);e.from.top=(k.height-e.from.height)*l.y;e.from.left=(k.width-e.from.width)*l.x;e.to.top=(k.height-e.to.height)*l.y;e.to.left=(k.width-e.to.width)*l.x}var m={from:{y:e.from.height/k.height,x:e.from.width/k.width},to:{y:e.to.height/k.height,x:e.to.width/k.width}};\r
+if(p=="box"||p=="both"){if(m.from.y!=m.to.y){g=g.concat(h);e.from=b.effects.setTransition(e,h,m.from.y,e.from);e.to=b.effects.setTransition(e,h,m.to.y,e.to)}if(m.from.x!=m.to.x){g=g.concat(i);e.from=b.effects.setTransition(e,i,m.from.x,e.from);e.to=b.effects.setTransition(e,i,m.to.x,e.to)}}if(p=="content"||p=="both")if(m.from.y!=m.to.y){g=g.concat(c);e.from=b.effects.setTransition(e,c,m.from.y,e.from);e.to=b.effects.setTransition(e,c,m.to.y,e.to)}b.effects.save(e,n?g:f);e.show();b.effects.createWrapper(e);\r
+e.css("overflow","hidden").css(e.from);if(p=="content"||p=="both"){h=h.concat(["marginTop","marginBottom"]).concat(c);i=i.concat(["marginLeft","marginRight"]);a=g.concat(h).concat(i);e.find("*[width]").each(function(){child=b(this);n&&b.effects.save(child,a);var o={height:child.height(),width:child.width()};child.from={height:o.height*m.from.y,width:o.width*m.from.x};child.to={height:o.height*m.to.y,width:o.width*m.to.x};if(m.from.y!=m.to.y){child.from=b.effects.setTransition(child,h,m.from.y,child.from);\r
+child.to=b.effects.setTransition(child,h,m.to.y,child.to)}if(m.from.x!=m.to.x){child.from=b.effects.setTransition(child,i,m.from.x,child.from);child.to=b.effects.setTransition(child,i,m.to.x,child.to)}child.css(child.from);child.animate(child.to,d.duration,d.options.easing,function(){n&&b.effects.restore(child,a)})})}e.animate(e.to,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e.to.opacity===0&&e.css("opacity",e.from.opacity);j=="hide"&&e.hide();b.effects.restore(e,\r
+n?g:f);b.effects.removeWrapper(e);d.callback&&d.callback.apply(this,arguments);e.dequeue()}})})}})(jQuery);\r
+(function(b){b.effects.shake=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right"];b.effects.setMode(e,d.options.mode||"effect");var f=d.options.direction||"left",a=d.options.distance||20,c=d.options.times||3,h=d.duration||d.options.duration||140;b.effects.save(e,g);e.show();b.effects.createWrapper(e);var i=f=="up"||f=="down"?"top":"left",j=f=="up"||f=="left"?"pos":"neg";f={};var n={},p={};f[i]=(j=="pos"?"-=":"+=")+a;n[i]=(j=="pos"?"+=":"-=")+a*2;p[i]=\r
+(j=="pos"?"-=":"+=")+a*2;e.animate(f,h,d.options.easing);for(a=1;a<c;a++)e.animate(n,h,d.options.easing).animate(p,h,d.options.easing);e.animate(n,h,d.options.easing).animate(f,h/2,d.options.easing,function(){b.effects.restore(e,g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(this,arguments)});e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);\r
+(function(b){b.effects.slide=function(d){return this.queue(function(){var e=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(e,d.options.mode||"show"),a=d.options.direction||"left";b.effects.save(e,g);e.show();b.effects.createWrapper(e).css({overflow:"hidden"});var c=a=="up"||a=="down"?"top":"left";a=a=="up"||a=="left"?"pos":"neg";var h=d.options.distance||(c=="top"?e.outerHeight({margin:true}):e.outerWidth({margin:true}));if(f=="show")e.css(c,a=="pos"?isNaN(h)?"-"+h:-h:h);\r
+var i={};i[c]=(f=="show"?a=="pos"?"+=":"-=":a=="pos"?"-=":"+=")+h;e.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){f=="hide"&&e.hide();b.effects.restore(e,g);b.effects.removeWrapper(e);d.callback&&d.callback.apply(this,arguments);e.dequeue()}})})}})(jQuery);\r
+(function(b){b.effects.transfer=function(d){return this.queue(function(){var e=b(this),g=b(d.options.to),f=g.offset();g={top:f.top,left:f.left,height:g.innerHeight(),width:g.innerWidth()};f=e.offset();var a=b('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(d.options.className).css({top:f.top,left:f.left,height:e.innerHeight(),width:e.innerWidth(),position:"absolute"}).animate(g,d.duration,d.options.easing,function(){a.remove();d.callback&&d.callback.apply(e[0],arguments);\r
+e.dequeue()})})}})(jQuery);\r
+(function(b){b.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var d=this,e=d.options;d.running=0;d.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix");d.headers=\r
+d.element.find(e.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){e.disabled||b(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){e.disabled||b(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){e.disabled||b(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){e.disabled||b(this).removeClass("ui-state-focus")});d.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");\r
+if(e.navigation){var g=d.element.find("a").filter(e.navigationFilter).eq(0);if(g.length){var f=g.closest(".ui-accordion-header");d.active=f.length?f:g.closest(".ui-accordion-content").prev()}}d.active=d._findActive(d.active||e.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");d.active.next().addClass("ui-accordion-content-active");d._createIcons();d.resize();d.element.attr("role","tablist");d.headers.attr("role","tab").bind("keydown.accordion",\r
+function(a){return d._keydown(a)}).next().attr("role","tabpanel");d.headers.not(d.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();d.active.length?d.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):d.headers.eq(0).attr("tabIndex",0);b.browser.safari||d.headers.find("a").attr("tabIndex",-1);e.event&&d.headers.bind(e.event.split(" ").join(".accordion ")+".accordion",function(a){d._clickHandler.call(d,a,this);a.preventDefault()})},_createIcons:function(){var d=\r
+this.options;if(d.icons){b("<span></span>").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var d=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex");\r
+this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var e=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(d.autoHeight||d.fillHeight)e.css("height","");return b.Widget.prototype.destroy.call(this)},_setOption:function(d,e){b.Widget.prototype._setOption.apply(this,arguments);d=="active"&&this.activate(e);if(d=="icons"){this._destroyIcons();\r
+e&&this._createIcons()}if(d=="disabled")this.headers.add(this.headers.next())[e?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(d){if(!(this.options.disabled||d.altKey||d.ctrlKey)){var e=b.ui.keyCode,g=this.headers.length,f=this.headers.index(d.target),a=false;switch(d.keyCode){case e.RIGHT:case e.DOWN:a=this.headers[(f+1)%g];break;case e.LEFT:case e.UP:a=this.headers[(f-1+g)%g];break;case e.SPACE:case e.ENTER:this._clickHandler({target:d.target},d.target);\r
+d.preventDefault()}if(a){b(d.target).attr("tabIndex",-1);b(a).attr("tabIndex",0);a.focus();return false}return true}},resize:function(){var d=this.options,e;if(d.fillSpace){if(b.browser.msie){var g=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}e=this.element.parent().height();b.browser.msie&&this.element.parent().css("overflow",g);this.headers.each(function(){e-=b(this).outerHeight(true)});this.headers.next().each(function(){b(this).height(Math.max(0,e-b(this).innerHeight()+\r
+b(this).height()))}).css("overflow","auto")}else if(d.autoHeight){e=0;this.headers.next().each(function(){e=Math.max(e,b(this).height("").height())}).height(e)}return this},activate:function(d){this.options.active=d;d=this._findActive(d)[0];this._clickHandler({target:d},d);return this},_findActive:function(d){return d?typeof d==="number"?this.headers.filter(":eq("+d+")"):this.headers.not(this.headers.not(d)):d===false?b([]):this.headers.filter(":eq(0)")},_clickHandler:function(d,e){var g=this.options;\r
+if(!g.disabled)if(d.target){d=b(d.currentTarget||e);e=d[0]===this.active[0];g.active=g.collapsible&&e?false:this.headers.index(d);if(!(this.running||!g.collapsible&&e)){var f=this.active;i=d.next();c=this.active.next();h={options:g,newHeader:e&&g.collapsible?b([]):d,oldHeader:this.active,newContent:e&&g.collapsible?b([]):i,oldContent:c};var a=this.headers.index(this.active[0])>this.headers.index(d[0]);this.active=e?b([]):d;this._toggle(i,c,h,e,a);f.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(g.icons.headerSelected).addClass(g.icons.header);\r
+if(!e){d.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(g.icons.header).addClass(g.icons.headerSelected);d.next().addClass("ui-accordion-content-active")}}}else if(g.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(g.icons.headerSelected).addClass(g.icons.header);this.active.next().addClass("ui-accordion-content-active");var c=this.active.next(),\r
+h={options:g,newHeader:b([]),oldHeader:g.active,newContent:b([]),oldContent:c},i=this.active=b([]);this._toggle(i,c,h)}},_toggle:function(d,e,g,f,a){var c=this,h=c.options;c.toShow=d;c.toHide=e;c.data=g;var i=function(){if(c)return c._completed.apply(c,arguments)};c._trigger("changestart",null,c.data);c.running=e.size()===0?d.size():e.size();if(h.animated){g={};g=h.collapsible&&f?{toShow:b([]),toHide:e,complete:i,down:a,autoHeight:h.autoHeight||h.fillSpace}:{toShow:d,toHide:e,complete:i,down:a,autoHeight:h.autoHeight||\r
+h.fillSpace};if(!h.proxied)h.proxied=h.animated;if(!h.proxiedDuration)h.proxiedDuration=h.duration;h.animated=b.isFunction(h.proxied)?h.proxied(g):h.proxied;h.duration=b.isFunction(h.proxiedDuration)?h.proxiedDuration(g):h.proxiedDuration;f=b.ui.accordion.animations;var j=h.duration,n=h.animated;if(n&&!f[n]&&!b.easing[n])n="slide";f[n]||(f[n]=function(p){this.slide(p,{easing:n,duration:j||700})});f[n](g)}else{if(h.collapsible&&f)d.toggle();else{e.hide();d.show()}i(true)}e.prev().attr({"aria-expanded":"false",\r
+"aria-selected":"false",tabIndex:-1}).blur();d.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(d){this.running=d?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});b.extend(b.ui.accordion,{version:"1.8.11",\r
+animations:{slide:function(d,e){d=b.extend({easing:"swing",duration:300},d,e);if(d.toHide.size())if(d.toShow.size()){var g=d.toShow.css("overflow"),f=0,a={},c={},h;e=d.toShow;h=e[0].style.width;e.width(parseInt(e.parent().width(),10)-parseInt(e.css("paddingLeft"),10)-parseInt(e.css("paddingRight"),10)-(parseInt(e.css("borderLeftWidth"),10)||0)-(parseInt(e.css("borderRightWidth"),10)||0));b.each(["height","paddingTop","paddingBottom"],function(i,j){c[j]="hide";i=(""+b.css(d.toShow[0],j)).match(/^([\d+-.]+)(.*)$/);\r
+a[j]={value:i[1],unit:i[2]||"px"}});d.toShow.css({height:0,overflow:"hidden"}).show();d.toHide.filter(":hidden").each(d.complete).end().filter(":visible").animate(c,{step:function(i,j){if(j.prop=="height")f=j.end-j.start===0?0:(j.now-j.start)/(j.end-j.start);d.toShow[0].style[j.prop]=f*a[j.prop].value+a[j.prop].unit},duration:d.duration,easing:d.easing,complete:function(){d.autoHeight||d.toShow.css("height","");d.toShow.css({width:h,overflow:g});d.complete()}})}else d.toHide.animate({height:"hide",\r
+paddingTop:"hide",paddingBottom:"hide"},d);else d.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},d)},bounceslide:function(d){this.slide(d,{easing:d.down?"easeOutBounce":"swing",duration:d.down?1E3:200})}}})})(jQuery);\r
+(function(b){var d=0;b.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var e=this,g=this.element[0].ownerDocument,f;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(a){if(!(e.options.disabled||e.element.attr("readonly"))){f=\r
+false;var c=b.ui.keyCode;switch(a.keyCode){case c.PAGE_UP:e._move("previousPage",a);break;case c.PAGE_DOWN:e._move("nextPage",a);break;case c.UP:e._move("previous",a);a.preventDefault();break;case c.DOWN:e._move("next",a);a.preventDefault();break;case c.ENTER:case c.NUMPAD_ENTER:if(e.menu.active){f=true;a.preventDefault()}case c.TAB:if(!e.menu.active)return;e.menu.select(a);break;case c.ESCAPE:e.element.val(e.term);e.close(a);break;default:clearTimeout(e.searching);e.searching=setTimeout(function(){if(e.term!=\r
+e.element.val()){e.selectedItem=null;e.search(null,a)}},e.options.delay);break}}}).bind("keypress.autocomplete",function(a){if(f){f=false;a.preventDefault()}}).bind("focus.autocomplete",function(){if(!e.options.disabled){e.selectedItem=null;e.previous=e.element.val()}}).bind("blur.autocomplete",function(a){if(!e.options.disabled){clearTimeout(e.searching);e.closing=setTimeout(function(){e.close(a);e._change(a)},150)}});this._initSource();this.response=function(){return e._response.apply(e,arguments)};\r
+this.menu=b("<ul></ul>").addClass("ui-autocomplete").appendTo(b(this.options.appendTo||"body",g)[0]).mousedown(function(a){var c=e.menu.element[0];b(a.target).closest(".ui-menu-item").length||setTimeout(function(){b(document).one("mousedown",function(h){h.target!==e.element[0]&&h.target!==c&&!b.ui.contains(c,h.target)&&e.close()})},1);setTimeout(function(){clearTimeout(e.closing)},13)}).menu({focus:function(a,c){c=c.item.data("item.autocomplete");false!==e._trigger("focus",a,{item:c})&&/^key/.test(a.originalEvent.type)&&\r
+e.element.val(c.value)},selected:function(a,c){var h=c.item.data("item.autocomplete"),i=e.previous;if(e.element[0]!==g.activeElement){e.element.focus();e.previous=i;setTimeout(function(){e.previous=i;e.selectedItem=h},1)}false!==e._trigger("select",a,{item:h})&&e.element.val(h.value);e.term=e.element.val();e.close(a);e.selectedItem=h},blur:function(){e.menu.element.is(":visible")&&e.element.val()!==e.term&&e.element.val(e.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");\r
+b.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();b.Widget.prototype.destroy.call(this)},_setOption:function(e,g){b.Widget.prototype._setOption.apply(this,arguments);e==="source"&&this._initSource();if(e==="appendTo")this.menu.element.appendTo(b(g||"body",this.element[0].ownerDocument)[0]);e==="disabled"&&\r
+g&&this.xhr&&this.xhr.abort()},_initSource:function(){var e=this,g,f;if(b.isArray(this.options.source)){g=this.options.source;this.source=function(a,c){c(b.ui.autocomplete.filter(g,a.term))}}else if(typeof this.options.source==="string"){f=this.options.source;this.source=function(a,c){e.xhr&&e.xhr.abort();e.xhr=b.ajax({url:f,data:a,dataType:"json",autocompleteRequest:++d,success:function(h){this.autocompleteRequest===d&&c(h)},error:function(){this.autocompleteRequest===d&&c([])}})}}else this.source=\r
+this.options.source},search:function(e,g){e=e!=null?e:this.element.val();this.term=this.element.val();if(e.length<this.options.minLength)return this.close(g);clearTimeout(this.closing);if(this._trigger("search",g)!==false)return this._search(e)},_search:function(e){this.pending++;this.element.addClass("ui-autocomplete-loading");this.source({term:e},this.response)},_response:function(e){if(!this.options.disabled&&e&&e.length){e=this._normalize(e);this._suggest(e);this._trigger("open")}else this.close();\r
+this.pending--;this.pending||this.element.removeClass("ui-autocomplete-loading")},close:function(e){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this.menu.element.hide();this.menu.deactivate();this._trigger("close",e)}},_change:function(e){this.previous!==this.element.val()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(e){if(e.length&&e[0].label&&e[0].value)return e;return b.map(e,function(g){if(typeof g==="string")return{label:g,value:g};return b.extend({label:g.label||\r
+g.value,value:g.value||g.label},g)})},_suggest:function(e){var g=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(g,e);this.menu.deactivate();this.menu.refresh();g.show();this._resizeMenu();g.position(b.extend({of:this.element},this.options.position));this.options.autoFocus&&this.menu.next(new b.Event("mouseover"))},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth(),this.element.outerWidth()))},_renderMenu:function(e,g){var f=this;\r
+b.each(g,function(a,c){f._renderItem(e,c)})},_renderItem:function(e,g){return b("<li></li>").data("item.autocomplete",g).append(b("<a></a>").text(g.label)).appendTo(e)},_move:function(e,g){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(e)||this.menu.last()&&/^next/.test(e)){this.element.val(this.term);this.menu.deactivate()}else this.menu[e](g);else this.search(null,g)},widget:function(){return this.menu.element}});b.extend(b.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,\r
+"\\$&")},filter:function(e,g){var f=new RegExp(b.ui.autocomplete.escapeRegex(g),"i");return b.grep(e,function(a){return f.test(a.label||a.value||a)})}})})(jQuery);\r
+(function(b){b.widget("ui.menu",{_create:function(){var d=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(e){if(b(e.target).closest(".ui-menu-item a").length){e.preventDefault();d.select(e)}});this.refresh()},refresh:function(){var d=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",\r
+-1).mouseenter(function(e){d.activate(e,b(this).parent())}).mouseleave(function(){d.deactivate()})},activate:function(d,e){this.deactivate();if(this.hasScroll()){var g=e.offset().top-this.element.offset().top,f=this.element.attr("scrollTop"),a=this.element.height();if(g<0)this.element.attr("scrollTop",f+g);else g>=a&&this.element.attr("scrollTop",f+g-a+e.height())}this.active=e.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",d,{item:e})},\r
+deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");this._trigger("blur");this.active=null}},next:function(d){this.move("next",".ui-menu-item:first",d)},previous:function(d){this.move("prev",".ui-menu-item:last",d)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(d,e,g){if(this.active){d=this.active[d+"All"](".ui-menu-item").eq(0);\r
+d.length?this.activate(g,d):this.activate(g,this.element.children(e))}else this.activate(g,this.element.children(e))},nextPage:function(d){if(this.hasScroll())if(!this.active||this.last())this.activate(d,this.element.children(".ui-menu-item:first"));else{var e=this.active.offset().top,g=this.element.height(),f=this.element.children(".ui-menu-item").filter(function(){var a=b(this).offset().top-e-g+b(this).height();return a<10&&a>-10});f.length||(f=this.element.children(".ui-menu-item:last"));this.activate(d,\r
+f)}else this.activate(d,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(d){if(this.hasScroll())if(!this.active||this.first())this.activate(d,this.element.children(".ui-menu-item:last"));else{var e=this.active.offset().top,g=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var f=b(this).offset().top-e+g-b(this).height();return f<10&&f>-10});result.length||(result=this.element.children(".ui-menu-item:first"));\r
+this.activate(d,result)}else this.activate(d,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(d){this._trigger("selected",d,{item:this.active})}})})(jQuery);\r
+(function(b){var d,e=function(f){b(":ui-button",f.target.form).each(function(){var a=b(this).data("button");setTimeout(function(){a.refresh()},1)})},g=function(f){var a=f.name,c=f.form,h=b([]);if(a)h=c?b(c).find("[name='"+a+"']"):b("[name='"+a+"']",f.ownerDocument).filter(function(){return!this.form});return h};b.widget("ui.button",{options:{disabled:null,text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",\r
+e);if(typeof this.options.disabled!=="boolean")this.options.disabled=this.element.attr("disabled");this._determineButtonType();this.hasTitle=!!this.buttonElement.attr("title");var f=this,a=this.options,c=this.type==="checkbox"||this.type==="radio",h="ui-state-hover"+(!c?" ui-state-active":"");if(a.label===null)a.label=this.buttonElement.html();if(this.element.is(":disabled"))a.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",\r
+function(){if(!a.disabled){b(this).addClass("ui-state-hover");this===d&&b(this).addClass("ui-state-active")}}).bind("mouseleave.button",function(){a.disabled||b(this).removeClass(h)}).bind("focus.button",function(){b(this).addClass("ui-state-focus")}).bind("blur.button",function(){b(this).removeClass("ui-state-focus")});c&&this.element.bind("change.button",function(){f.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(a.disabled)return false;b(this).toggleClass("ui-state-active");\r
+f.buttonElement.attr("aria-pressed",f.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",function(){if(a.disabled)return false;b(this).addClass("ui-state-active");f.buttonElement.attr("aria-pressed",true);var i=f.element[0];g(i).not(i).map(function(){return b(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(a.disabled)return false;b(this).addClass("ui-state-active");\r
+d=this;b(document).one("mouseup",function(){d=null})}).bind("mouseup.button",function(){if(a.disabled)return false;b(this).removeClass("ui-state-active")}).bind("keydown.button",function(i){if(a.disabled)return false;if(i.keyCode==b.ui.keyCode.SPACE||i.keyCode==b.ui.keyCode.ENTER)b(this).addClass("ui-state-active")}).bind("keyup.button",function(){b(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(i){i.keyCode===b.ui.keyCode.SPACE&&b(this).click()})}this._setOption("disabled",\r
+a.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?"input":"button";if(this.type==="checkbox"||this.type==="radio"){var f=this.element.parents().filter(":last"),a="label[for="+this.element.attr("id")+"]";this.buttonElement=f.find(a);if(!this.buttonElement.length){f=f.length?f.siblings():this.element.siblings();this.buttonElement=f.filter(a);if(!this.buttonElement.length)this.buttonElement=f.find(a)}this.element.addClass("ui-helper-hidden-accessible");\r
+(f=this.element.is(":checked"))&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",f)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());\r
+this.hasTitle||this.buttonElement.removeAttr("title");b.Widget.prototype.destroy.call(this)},_setOption:function(f,a){b.Widget.prototype._setOption.apply(this,arguments);if(f==="disabled")a?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var f=this.element.is(":disabled");f!==this.options.disabled&&this._setOption("disabled",f);if(this.type==="radio")g(this.element[0]).each(function(){b(this).is(":checked")?b(this).button("widget").addClass("ui-state-active").attr("aria-pressed",\r
+true):b(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var f=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only"),\r
+a=b("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(f.empty()).text(),c=this.options.icons,h=c.primary&&c.secondary,i=[];if(c.primary||c.secondary){if(this.options.text)i.push("ui-button-text-icon"+(h?"s":c.primary?"-primary":"-secondary"));c.primary&&f.prepend("<span class='ui-button-icon-primary ui-icon "+c.primary+"'></span>");c.secondary&&f.append("<span class='ui-button-icon-secondary ui-icon "+c.secondary+"'></span>");if(!this.options.text){i.push(h?"ui-button-icons-only":\r
+"ui-button-icon-only");this.hasTitle||f.attr("title",a)}}else i.push("ui-button-text-only");f.addClass(i.join(" "))}}});b.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(f,a){f==="disabled"&&this.buttons.button("option",f,a);b.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},\r
+destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");b.Widget.prototype.destroy.call(this)}})})(jQuery);\r
+(function(b,d){function e(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=\r
+"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",\r
+"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",\r
+minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};b.extend(this._defaults,this.regional[""]);this.dpDiv=b('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}function g(a,c){b.extend(a,c);for(var h in c)if(c[h]==\r
+null||c[h]==d)a[h]=c[h];return a}b.extend(b.ui,{datepicker:{version:"1.8.11"}});var f=(new Date).getTime();b.extend(e.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){g(this._defaults,a||{});return this},_attachDatepicker:function(a,c){var h=null;for(var i in this._defaults){var j=a.getAttribute("date:"+i);if(j){h=h||{};try{h[i]=eval(j)}catch(n){h[i]=j}}}i=a.nodeName.toLowerCase();\r
+j=i=="div"||i=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var p=this._newInst(b(a),j);p.settings=b.extend({},c||{},h||{});if(i=="input")this._connectDatepicker(a,p);else j&&this._inlineDatepicker(a,p)},_newInst:function(a,c){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:c,dpDiv:!c?this.dpDiv:b('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},\r
+_connectDatepicker:function(a,c){var h=b(a);c.append=b([]);c.trigger=b([]);if(!h.hasClass(this.markerClassName)){this._attachments(h,c);h.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(i,j,n){c.settings[j]=n}).bind("getData.datepicker",function(i,j){return this._get(c,j)});this._autoSize(c);b.data(a,"datepicker",c)}},_attachments:function(a,c){var h=this._get(c,"appendText"),i=this._get(c,"isRTL");c.append&&\r
+c.append.remove();if(h){c.append=b('<span class="'+this._appendClass+'">'+h+"</span>");a[i?"before":"after"](c.append)}a.unbind("focus",this._showDatepicker);c.trigger&&c.trigger.remove();h=this._get(c,"showOn");if(h=="focus"||h=="both")a.focus(this._showDatepicker);if(h=="button"||h=="both"){h=this._get(c,"buttonText");var j=this._get(c,"buttonImage");c.trigger=b(this._get(c,"buttonImageOnly")?b("<img/>").addClass(this._triggerClass).attr({src:j,alt:h,title:h}):b('<button type="button"></button>').addClass(this._triggerClass).html(j==\r
+""?h:b("<img/>").attr({src:j,alt:h,title:h})));a[i?"before":"after"](c.trigger);c.trigger.click(function(){b.datepicker._datepickerShowing&&b.datepicker._lastInput==a[0]?b.datepicker._hideDatepicker():b.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var c=new Date(2009,11,20),h=this._get(a,"dateFormat");if(h.match(/[DM]/)){var i=function(j){for(var n=0,p=0,l=0;l<j.length;l++)if(j[l].length>n){n=j[l].length;p=l}return p};c.setMonth(i(this._get(a,\r
+h.match(/MM/)?"monthNames":"monthNamesShort")));c.setDate(i(this._get(a,h.match(/DD/)?"dayNames":"dayNamesShort"))+20-c.getDay())}a.input.attr("size",this._formatDate(a,c).length)}},_inlineDatepicker:function(a,c){var h=b(a);if(!h.hasClass(this.markerClassName)){h.addClass(this.markerClassName).append(c.dpDiv).bind("setData.datepicker",function(i,j,n){c.settings[j]=n}).bind("getData.datepicker",function(i,j){return this._get(c,j)});b.data(a,"datepicker",c);this._setDate(c,this._getDefaultDate(c),\r
+true);this._updateDatepicker(c);this._updateAlternate(c);c.dpDiv.show()}},_dialogDatepicker:function(a,c,h,i,j){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=b('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);b("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};b.data(this._dialogInput[0],"datepicker",a)}g(a.settings,i||{});\r
+c=c&&c.constructor==Date?this._formatDate(a,c):c;this._dialogInput.val(c);this._pos=j?j.length?j:[j.pageX,j.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=h;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);\r
+this._showDatepicker(this._dialogInput[0]);b.blockUI&&b.blockUI(this.dpDiv);b.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var c=b(a),h=b.data(a,"datepicker");if(c.hasClass(this.markerClassName)){var i=a.nodeName.toLowerCase();b.removeData(a,"datepicker");if(i=="input"){h.append.remove();h.trigger.remove();c.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",\r
+this._doKeyUp)}else if(i=="div"||i=="span")c.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var c=b(a),h=b.data(a,"datepicker");if(c.hasClass(this.markerClassName)){var i=a.nodeName.toLowerCase();if(i=="input"){a.disabled=false;h.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(i=="div"||i=="span")c.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=b.map(this._disabledInputs,\r
+function(j){return j==a?null:j})}},_disableDatepicker:function(a){var c=b(a),h=b.data(a,"datepicker");if(c.hasClass(this.markerClassName)){var i=a.nodeName.toLowerCase();if(i=="input"){a.disabled=true;h.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(i=="div"||i=="span")c.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=b.map(this._disabledInputs,function(j){return j==a?null:\r
+j});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var c=0;c<this._disabledInputs.length;c++)if(this._disabledInputs[c]==a)return true;return false},_getInst:function(a){try{return b.data(a,"datepicker")}catch(c){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,c,h){var i=this._getInst(a);if(arguments.length==2&&typeof c=="string")return c=="defaults"?b.extend({},b.datepicker._defaults):i?c=="all"?b.extend({},\r
+i.settings):this._get(i,c):null;var j=c||{};if(typeof c=="string"){j={};j[c]=h}if(i){this._curInst==i&&this._hideDatepicker();var n=this._getDateDatepicker(a,true),p=this._getMinMaxDate(i,"min"),l=this._getMinMaxDate(i,"max");g(i.settings,j);if(p!==null&&j.dateFormat!==d&&j.minDate===d)i.settings.minDate=this._formatDate(i,p);if(l!==null&&j.dateFormat!==d&&j.maxDate===d)i.settings.maxDate=this._formatDate(i,l);this._attachments(b(a),i);this._autoSize(i);this._setDateDatepicker(a,n);this._updateDatepicker(i)}},\r
+_changeDatepicker:function(a,c,h){this._optionDatepicker(a,c,h)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,c){if(a=this._getInst(a)){this._setDate(a,c);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,c){(a=this._getInst(a))&&!a.inline&&this._setDateFromField(a,c);return a?this._getDate(a):null},_doKeyDown:function(a){var c=b.datepicker._getInst(a.target),h=true,i=c.dpDiv.is(".ui-datepicker-rtl");\r
+c._keyEvent=true;if(b.datepicker._datepickerShowing)switch(a.keyCode){case 9:b.datepicker._hideDatepicker();h=false;break;case 13:h=b("td."+b.datepicker._dayOverClass+":not(."+b.datepicker._currentClass+")",c.dpDiv);h[0]?b.datepicker._selectDay(a.target,c.selectedMonth,c.selectedYear,h[0]):b.datepicker._hideDatepicker();return false;case 27:b.datepicker._hideDatepicker();break;case 33:b.datepicker._adjustDate(a.target,a.ctrlKey?-b.datepicker._get(c,"stepBigMonths"):-b.datepicker._get(c,"stepMonths"),\r
+"M");break;case 34:b.datepicker._adjustDate(a.target,a.ctrlKey?+b.datepicker._get(c,"stepBigMonths"):+b.datepicker._get(c,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)b.datepicker._clearDate(a.target);h=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)b.datepicker._gotoToday(a.target);h=a.ctrlKey||a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)b.datepicker._adjustDate(a.target,i?+1:-1,"D");h=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)b.datepicker._adjustDate(a.target,a.ctrlKey?\r
+-b.datepicker._get(c,"stepBigMonths"):-b.datepicker._get(c,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)b.datepicker._adjustDate(a.target,-7,"D");h=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)b.datepicker._adjustDate(a.target,i?-1:+1,"D");h=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)b.datepicker._adjustDate(a.target,a.ctrlKey?+b.datepicker._get(c,"stepBigMonths"):+b.datepicker._get(c,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)b.datepicker._adjustDate(a.target,\r
++7,"D");h=a.ctrlKey||a.metaKey;break;default:h=false}else if(a.keyCode==36&&a.ctrlKey)b.datepicker._showDatepicker(this);else h=false;if(h){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var c=b.datepicker._getInst(a.target);if(b.datepicker._get(c,"constrainInput")){c=b.datepicker._possibleChars(b.datepicker._get(c,"dateFormat"));var h=String.fromCharCode(a.charCode==d?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||h<" "||!c||c.indexOf(h)>-1}},_doKeyUp:function(a){a=b.datepicker._getInst(a.target);\r
+if(a.input.val()!=a.lastVal)try{if(b.datepicker.parseDate(b.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,b.datepicker._getFormatConfig(a))){b.datepicker._setDateFromField(a);b.datepicker._updateAlternate(a);b.datepicker._updateDatepicker(a)}}catch(c){b.datepicker.log(c)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=b("input",a.parentNode)[0];if(!(b.datepicker._isDisabledDatepicker(a)||b.datepicker._lastInput==a)){var c=b.datepicker._getInst(a);\r
+b.datepicker._curInst&&b.datepicker._curInst!=c&&b.datepicker._curInst.dpDiv.stop(true,true);var h=b.datepicker._get(c,"beforeShow");g(c.settings,h?h.apply(a,[a,c]):{});c.lastVal=null;b.datepicker._lastInput=a;b.datepicker._setDateFromField(c);if(b.datepicker._inDialog)a.value="";if(!b.datepicker._pos){b.datepicker._pos=b.datepicker._findPos(a);b.datepicker._pos[1]+=a.offsetHeight}var i=false;b(a).parents().each(function(){i|=b(this).css("position")=="fixed";return!i});if(i&&b.browser.opera){b.datepicker._pos[0]-=\r
+document.documentElement.scrollLeft;b.datepicker._pos[1]-=document.documentElement.scrollTop}h={left:b.datepicker._pos[0],top:b.datepicker._pos[1]};b.datepicker._pos=null;c.dpDiv.empty();c.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});b.datepicker._updateDatepicker(c);h=b.datepicker._checkOffset(c,h,i);c.dpDiv.css({position:b.datepicker._inDialog&&b.blockUI?"static":i?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"});if(!c.inline){h=b.datepicker._get(c,"showAnim");\r
+var j=b.datepicker._get(c,"duration"),n=function(){b.datepicker._datepickerShowing=true;var p=c.dpDiv.find("iframe.ui-datepicker-cover");if(p.length){var l=b.datepicker._getBorders(c.dpDiv);p.css({left:-l[0],top:-l[1],width:c.dpDiv.outerWidth(),height:c.dpDiv.outerHeight()})}};c.dpDiv.zIndex(b(a).zIndex()+1);b.effects&&b.effects[h]?c.dpDiv.show(h,b.datepicker._get(c,"showOptions"),j,n):c.dpDiv[h||"show"](h?j:null,n);if(!h||!j)n();c.input.is(":visible")&&!c.input.is(":disabled")&&c.input.focus();b.datepicker._curInst=\r
+c}}},_updateDatepicker:function(a){var c=this,h=b.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a));var i=a.dpDiv.find("iframe.ui-datepicker-cover");i.length&&i.css({left:-h[0],top:-h[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()});a.dpDiv.find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){b(this).removeClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&b(this).removeClass("ui-datepicker-prev-hover");\r
+this.className.indexOf("ui-datepicker-next")!=-1&&b(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!c._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){b(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");b(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&b(this).addClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&b(this).addClass("ui-datepicker-next-hover")}}).end().find("."+\r
+this._dayOverClass+" a").trigger("mouseover").end();h=this._getNumberOfMonths(a);i=h[1];i>1?a.dpDiv.addClass("ui-datepicker-multi-"+i).css("width",17*i+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(h[0]!=1||h[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==b.datepicker._curInst&&b.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&\r
+a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var j=a.yearshtml;setTimeout(function(){j===a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);j=a.yearshtml=null},0)}},_getBorders:function(a){var c=function(h){return{thin:1,medium:2,thick:3}[h]||h};return[parseFloat(c(a.css("border-left-width"))),parseFloat(c(a.css("border-top-width")))]},_checkOffset:function(a,c,h){var i=a.dpDiv.outerWidth(),j=a.dpDiv.outerHeight(),n=a.input?a.input.outerWidth():\r
+0,p=a.input?a.input.outerHeight():0,l=document.documentElement.clientWidth+b(document).scrollLeft(),k=document.documentElement.clientHeight+b(document).scrollTop();c.left-=this._get(a,"isRTL")?i-n:0;c.left-=h&&c.left==a.input.offset().left?b(document).scrollLeft():0;c.top-=h&&c.top==a.input.offset().top+p?b(document).scrollTop():0;c.left-=Math.min(c.left,c.left+i>l&&l>i?Math.abs(c.left+i-l):0);c.top-=Math.min(c.top,c.top+j>k&&k>j?Math.abs(j+p):0);return c},_findPos:function(a){for(var c=this._get(this._getInst(a),\r
+"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||b.expr.filters.hidden(a));)a=a[c?"previousSibling":"nextSibling"];a=b(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var c=this._curInst;if(!(!c||a&&c!=b.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(c,"showAnim");var h=this._get(c,"duration"),i=function(){b.datepicker._tidyDialog(c);this._curInst=null};b.effects&&b.effects[a]?c.dpDiv.hide(a,b.datepicker._get(c,"showOptions"),h,i):c.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?\r
+"fadeOut":"hide"](a?h:null,i);a||i();if(a=this._get(c,"onClose"))a.apply(c.input?c.input[0]:null,[c.input?c.input.val():"",c]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(b.blockUI){b.unblockUI();b("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(b.datepicker._curInst){a=\r
+b(a.target);a[0].id!=b.datepicker._mainDivId&&a.parents("#"+b.datepicker._mainDivId).length==0&&!a.hasClass(b.datepicker.markerClassName)&&!a.hasClass(b.datepicker._triggerClass)&&b.datepicker._datepickerShowing&&!(b.datepicker._inDialog&&b.blockUI)&&b.datepicker._hideDatepicker()}},_adjustDate:function(a,c,h){a=b(a);var i=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(i,c+(h=="M"?this._get(i,"showCurrentAtPos"):0),h);this._updateDatepicker(i)}},_gotoToday:function(a){a=\r
+b(a);var c=this._getInst(a[0]);if(this._get(c,"gotoCurrent")&&c.currentDay){c.selectedDay=c.currentDay;c.drawMonth=c.selectedMonth=c.currentMonth;c.drawYear=c.selectedYear=c.currentYear}else{var h=new Date;c.selectedDay=h.getDate();c.drawMonth=c.selectedMonth=h.getMonth();c.drawYear=c.selectedYear=h.getFullYear()}this._notifyChange(c);this._adjustDate(a)},_selectMonthYear:function(a,c,h){a=b(a);var i=this._getInst(a[0]);i._selectingMonthYear=false;i["selected"+(h=="M"?"Month":"Year")]=i["draw"+(h==\r
+"M"?"Month":"Year")]=parseInt(c.options[c.selectedIndex].value,10);this._notifyChange(i);this._adjustDate(a)},_clickMonthYear:function(a){var c=this._getInst(b(a)[0]);c.input&&c._selectingMonthYear&&setTimeout(function(){c.input.focus()},0);c._selectingMonthYear=!c._selectingMonthYear},_selectDay:function(a,c,h,i){var j=b(a);if(!(b(i).hasClass(this._unselectableClass)||this._isDisabledDatepicker(j[0]))){j=this._getInst(j[0]);j.selectedDay=j.currentDay=b("a",i).html();j.selectedMonth=j.currentMonth=\r
+c;j.selectedYear=j.currentYear=h;this._selectDate(a,this._formatDate(j,j.currentDay,j.currentMonth,j.currentYear))}},_clearDate:function(a){a=b(a);this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,c){a=this._getInst(b(a)[0]);c=c!=null?c:this._formatDate(a);a.input&&a.input.val(c);this._updateAlternate(a);var h=this._get(a,"onSelect");if(h)h.apply(a.input?a.input[0]:null,[c,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();\r
+this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var c=this._get(a,"altField");if(c){var h=this._get(a,"altFormat")||this._get(a,"dateFormat"),i=this._getDate(a),j=this.formatDate(h,i,this._getFormatConfig(a));b(c).each(function(){b(this).val(j)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var c=a.getTime();a.setMonth(0);\r
+a.setDate(1);return Math.floor(Math.round((c-a)/864E5)/7)+1},parseDate:function(a,c,h){if(a==null||c==null)throw"Invalid arguments";c=typeof c=="object"?c.toString():c+"";if(c=="")return null;var i=(h?h.shortYearCutoff:null)||this._defaults.shortYearCutoff;i=typeof i!="string"?i:(new Date).getFullYear()%100+parseInt(i,10);for(var j=(h?h.dayNamesShort:null)||this._defaults.dayNamesShort,n=(h?h.dayNames:null)||this._defaults.dayNames,p=(h?h.monthNamesShort:null)||this._defaults.monthNamesShort,l=(h?\r
+h.monthNames:null)||this._defaults.monthNames,k=h=-1,m=-1,o=-1,q=false,s=function(x){(x=y+1<a.length&&a.charAt(y+1)==x)&&y++;return x},r=function(x){var C=s(x);x=new RegExp("^\\d{1,"+(x=="@"?14:x=="!"?20:x=="y"&&C?4:x=="o"?3:2)+"}");x=c.substring(w).match(x);if(!x)throw"Missing number at position "+w;w+=x[0].length;return parseInt(x[0],10)},u=function(x,C,J){x=s(x)?J:C;for(C=0;C<x.length;C++)if(c.substr(w,x[C].length).toLowerCase()==x[C].toLowerCase()){w+=x[C].length;return C+1}throw"Unknown name at position "+\r
+w;},v=function(){if(c.charAt(w)!=a.charAt(y))throw"Unexpected literal at position "+w;w++},w=0,y=0;y<a.length;y++)if(q)if(a.charAt(y)=="'"&&!s("'"))q=false;else v();else switch(a.charAt(y)){case "d":m=r("d");break;case "D":u("D",j,n);break;case "o":o=r("o");break;case "m":k=r("m");break;case "M":k=u("M",p,l);break;case "y":h=r("y");break;case "@":var B=new Date(r("@"));h=B.getFullYear();k=B.getMonth()+1;m=B.getDate();break;case "!":B=new Date((r("!")-this._ticksTo1970)/1E4);h=B.getFullYear();k=B.getMonth()+\r
+1;m=B.getDate();break;case "'":if(s("'"))v();else q=true;break;default:v()}if(h==-1)h=(new Date).getFullYear();else if(h<100)h+=(new Date).getFullYear()-(new Date).getFullYear()%100+(h<=i?0:-100);if(o>-1){k=1;m=o;do{i=this._getDaysInMonth(h,k-1);if(m<=i)break;k++;m-=i}while(1)}B=this._daylightSavingAdjust(new Date(h,k-1,m));if(B.getFullYear()!=h||B.getMonth()+1!=k||B.getDate()!=m)throw"Invalid date";return B},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",\r
+RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,c,h){if(!c)return"";var i=(h?h.dayNamesShort:null)||this._defaults.dayNamesShort,j=(h?h.dayNames:null)||this._defaults.dayNames,n=(h?h.monthNamesShort:null)||this._defaults.monthNamesShort;h=(h?h.monthNames:null)||this._defaults.monthNames;var p=function(s){(s=q+1<a.length&&\r
+a.charAt(q+1)==s)&&q++;return s},l=function(s,r,u){r=""+r;if(p(s))for(;r.length<u;)r="0"+r;return r},k=function(s,r,u,v){return p(s)?v[r]:u[r]},m="",o=false;if(c)for(var q=0;q<a.length;q++)if(o)if(a.charAt(q)=="'"&&!p("'"))o=false;else m+=a.charAt(q);else switch(a.charAt(q)){case "d":m+=l("d",c.getDate(),2);break;case "D":m+=k("D",c.getDay(),i,j);break;case "o":m+=l("o",(c.getTime()-(new Date(c.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":m+=l("m",c.getMonth()+1,2);break;case "M":m+=k("M",\r
+c.getMonth(),n,h);break;case "y":m+=p("y")?c.getFullYear():(c.getYear()%100<10?"0":"")+c.getYear()%100;break;case "@":m+=c.getTime();break;case "!":m+=c.getTime()*1E4+this._ticksTo1970;break;case "'":if(p("'"))m+="'";else o=true;break;default:m+=a.charAt(q)}return m},_possibleChars:function(a){for(var c="",h=false,i=function(n){(n=j+1<a.length&&a.charAt(j+1)==n)&&j++;return n},j=0;j<a.length;j++)if(h)if(a.charAt(j)=="'"&&!i("'"))h=false;else c+=a.charAt(j);else switch(a.charAt(j)){case "d":case "m":case "y":case "@":c+=\r
+"0123456789";break;case "D":case "M":return null;case "'":if(i("'"))c+="'";else h=true;break;default:c+=a.charAt(j)}return c},_get:function(a,c){return a.settings[c]!==d?a.settings[c]:this._defaults[c]},_setDateFromField:function(a,c){if(a.input.val()!=a.lastVal){var h=this._get(a,"dateFormat"),i=a.lastVal=a.input?a.input.val():null,j,n;j=n=this._getDefaultDate(a);var p=this._getFormatConfig(a);try{j=this.parseDate(h,i,p)||n}catch(l){this.log(l);i=c?"":i}a.selectedDay=j.getDate();a.drawMonth=a.selectedMonth=\r
+j.getMonth();a.drawYear=a.selectedYear=j.getFullYear();a.currentDay=i?j.getDate():0;a.currentMonth=i?j.getMonth():0;a.currentYear=i?j.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,c,h){var i=function(n){var p=new Date;p.setDate(p.getDate()+n);return p},j=function(n){try{return b.datepicker.parseDate(b.datepicker._get(a,"dateFormat"),n,b.datepicker._getFormatConfig(a))}catch(p){}var l=\r
+(n.toLowerCase().match(/^c/)?b.datepicker._getDate(a):null)||new Date,k=l.getFullYear(),m=l.getMonth();l=l.getDate();for(var o=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,q=o.exec(n);q;){switch(q[2]||"d"){case "d":case "D":l+=parseInt(q[1],10);break;case "w":case "W":l+=parseInt(q[1],10)*7;break;case "m":case "M":m+=parseInt(q[1],10);l=Math.min(l,b.datepicker._getDaysInMonth(k,m));break;case "y":case "Y":k+=parseInt(q[1],10);l=Math.min(l,b.datepicker._getDaysInMonth(k,m));break}q=o.exec(n)}return new Date(k,\r
+m,l)};if(c=(c=c==null||c===""?h:typeof c=="string"?j(c):typeof c=="number"?isNaN(c)?h:i(c):new Date(c.getTime()))&&c.toString()=="Invalid Date"?h:c){c.setHours(0);c.setMinutes(0);c.setSeconds(0);c.setMilliseconds(0)}return this._daylightSavingAdjust(c)},_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,c,h){var i=!c,j=a.selectedMonth,n=a.selectedYear;c=this._restrictMinMax(a,this._determineDate(a,c,new Date));a.selectedDay=\r
+a.currentDay=c.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=c.getMonth();a.drawYear=a.selectedYear=a.currentYear=c.getFullYear();if((j!=a.selectedMonth||n!=a.selectedYear)&&!h)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(i?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var c=new Date;c=this._daylightSavingAdjust(new Date(c.getFullYear(),\r
+c.getMonth(),c.getDate()));var h=this._get(a,"isRTL"),i=this._get(a,"showButtonPanel"),j=this._get(a,"hideIfNoPrevNext"),n=this._get(a,"navigationAsDateFormat"),p=this._getNumberOfMonths(a),l=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),m=p[0]!=1||p[1]!=1,o=this._daylightSavingAdjust(!a.currentDay?new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),q=this._getMinMaxDate(a,"min"),s=this._getMinMaxDate(a,"max");l=a.drawMonth-l;var r=a.drawYear;if(l<0){l+=12;r--}if(s){var u=\r
+this._daylightSavingAdjust(new Date(s.getFullYear(),s.getMonth()-p[0]*p[1]+1,s.getDate()));for(u=q&&u<q?q:u;this._daylightSavingAdjust(new Date(r,l,1))>u;){l--;if(l<0){l=11;r--}}}a.drawMonth=l;a.drawYear=r;u=this._get(a,"prevText");u=!n?u:this.formatDate(u,this._daylightSavingAdjust(new Date(r,l-k,1)),this._getFormatConfig(a));u=this._canAdjustMonth(a,-1,r,l)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+f+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+u+'"><span class="ui-icon ui-icon-circle-triangle-'+\r
+(h?"e":"w")+'">'+u+"</span></a>":j?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+u+'"><span class="ui-icon ui-icon-circle-triangle-'+(h?"e":"w")+'">'+u+"</span></a>";var v=this._get(a,"nextText");v=!n?v:this.formatDate(v,this._daylightSavingAdjust(new Date(r,l+k,1)),this._getFormatConfig(a));j=this._canAdjustMonth(a,+1,r,l)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+f+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+v+'"><span class="ui-icon ui-icon-circle-triangle-'+\r
+(h?"w":"e")+'">'+v+"</span></a>":j?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+v+'"><span class="ui-icon ui-icon-circle-triangle-'+(h?"w":"e")+'">'+v+"</span></a>";k=this._get(a,"currentText");v=this._get(a,"gotoCurrent")&&a.currentDay?o:c;k=!n?k:this.formatDate(k,v,this._getFormatConfig(a));n=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+f+'.datepicker._hideDatepicker();">'+this._get(a,\r
+"closeText")+"</button>":"";i=i?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(h?n:"")+(this._isInRange(a,v)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+f+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(h?"":n)+"</div>":"";n=parseInt(this._get(a,"firstDay"),10);n=isNaN(n)?0:n;k=this._get(a,"showWeek");v=this._get(a,"dayNames");this._get(a,"dayNamesShort");var w=this._get(a,"dayNamesMin"),y=\r
+this._get(a,"monthNames"),B=this._get(a,"monthNamesShort"),x=this._get(a,"beforeShowDay"),C=this._get(a,"showOtherMonths"),J=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var M=this._getDefaultDate(a),K="",G=0;G<p[0];G++){for(var N="",H=0;H<p[1];H++){var O=this._daylightSavingAdjust(new Date(r,l,a.selectedDay)),A=" ui-corner-all",D="";if(m){D+='<div class="ui-datepicker-group';if(p[1]>1)switch(H){case 0:D+=" ui-datepicker-group-first";A=" ui-corner-"+(h?"right":"left");break;case p[1]-\r
+1:D+=" ui-datepicker-group-last";A=" ui-corner-"+(h?"left":"right");break;default:D+=" ui-datepicker-group-middle";A="";break}D+='">'}D+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+A+'">'+(/all|left/.test(A)&&G==0?h?j:u:"")+(/all|right/.test(A)&&G==0?h?u:j:"")+this._generateMonthYearHeader(a,l,r,q,s,G>0||H>0,y,B)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var E=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(A=0;A<7;A++){var z=\r
+(A+n)%7;E+="<th"+((A+n+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+v[z]+'">'+w[z]+"</span></th>"}D+=E+"</tr></thead><tbody>";E=this._getDaysInMonth(r,l);if(r==a.selectedYear&&l==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,E);A=(this._getFirstDayOfMonth(r,l)-n+7)%7;E=m?6:Math.ceil((A+E)/7);z=this._daylightSavingAdjust(new Date(r,l,1-A));for(var P=0;P<E;P++){D+="<tr>";var Q=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(z)+"</td>";for(A=0;A<7;A++){var I=\r
+x?x.apply(a.input?a.input[0]:null,[z]):[true,""],F=z.getMonth()!=l,L=F&&!J||!I[0]||q&&z<q||s&&z>s;Q+='<td class="'+((A+n+6)%7>=5?" ui-datepicker-week-end":"")+(F?" ui-datepicker-other-month":"")+(z.getTime()==O.getTime()&&l==a.selectedMonth&&a._keyEvent||M.getTime()==z.getTime()&&M.getTime()==O.getTime()?" "+this._dayOverClass:"")+(L?" "+this._unselectableClass+" ui-state-disabled":"")+(F&&!C?"":" "+I[1]+(z.getTime()==o.getTime()?" "+this._currentClass:"")+(z.getTime()==c.getTime()?" ui-datepicker-today":\r
+""))+'"'+((!F||C)&&I[2]?' title="'+I[2]+'"':"")+(L?"":' onclick="DP_jQuery_'+f+".datepicker._selectDay('#"+a.id+"',"+z.getMonth()+","+z.getFullYear()+', this);return false;"')+">"+(F&&!C?"&#xa0;":L?'<span class="ui-state-default">'+z.getDate()+"</span>":'<a class="ui-state-default'+(z.getTime()==c.getTime()?" ui-state-highlight":"")+(z.getTime()==o.getTime()?" ui-state-active":"")+(F?" ui-priority-secondary":"")+'" href="#">'+z.getDate()+"</a>")+"</td>";z.setDate(z.getDate()+1);z=this._daylightSavingAdjust(z)}D+=\r
+Q+"</tr>"}l++;if(l>11){l=0;r++}D+="</tbody></table>"+(m?"</div>"+(p[0]>0&&H==p[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");N+=D}K+=N}K+=i+(b.browser.msie&&parseInt(b.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");a._keyEvent=false;return K},_generateMonthYearHeader:function(a,c,h,i,j,n,p,l){var k=this._get(a,"changeMonth"),m=this._get(a,"changeYear"),o=this._get(a,"showMonthAfterYear"),q='<div class="ui-datepicker-title">',\r
+s="";if(n||!k)s+='<span class="ui-datepicker-month">'+p[c]+"</span>";else{p=i&&i.getFullYear()==h;var r=j&&j.getFullYear()==h;s+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+f+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+f+".datepicker._clickMonthYear('#"+a.id+"');\">";for(var u=0;u<12;u++)if((!p||u>=i.getMonth())&&(!r||u<=j.getMonth()))s+='<option value="'+u+'"'+(u==c?' selected="selected"':"")+">"+l[u]+"</option>";s+="</select>"}o||(q+=s+(n||!(k&&\r
+m)?"&#xa0;":""));a.yearshtml="";if(n||!m)q+='<span class="ui-datepicker-year">'+h+"</span>";else{l=this._get(a,"yearRange").split(":");var v=(new Date).getFullYear();p=function(w){w=w.match(/c[+-].*/)?h+parseInt(w.substring(1),10):w.match(/[+-].*/)?v+parseInt(w,10):parseInt(w,10);return isNaN(w)?v:w};c=p(l[0]);l=Math.max(c,p(l[1]||""));c=i?Math.max(c,i.getFullYear()):c;l=j?Math.min(l,j.getFullYear()):l;for(a.yearshtml+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+f+".datepicker._selectMonthYear('#"+\r
+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+f+".datepicker._clickMonthYear('#"+a.id+"');\">";c<=l;c++)a.yearshtml+='<option value="'+c+'"'+(c==h?' selected="selected"':"")+">"+c+"</option>";a.yearshtml+="</select>";if(b.browser.mozilla)q+='<select class="ui-datepicker-year"><option value="'+h+'" selected="selected">'+h+"</option></select>";else{q+=a.yearshtml;a.yearshtml=null}}q+=this._get(a,"yearSuffix");if(o)q+=(n||!(k&&m)?"&#xa0;":"")+s;q+="</div>";return q},_adjustInstDate:function(a,c,h){var i=\r
+a.drawYear+(h=="Y"?c:0),j=a.drawMonth+(h=="M"?c:0);c=Math.min(a.selectedDay,this._getDaysInMonth(i,j))+(h=="D"?c:0);i=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(i,j,c)));a.selectedDay=i.getDate();a.drawMonth=a.selectedMonth=i.getMonth();a.drawYear=a.selectedYear=i.getFullYear();if(h=="M"||h=="Y")this._notifyChange(a)},_restrictMinMax:function(a,c){var h=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");c=h&&c<h?h:c;return c=a&&c>a?a:c},_notifyChange:function(a){var c=this._get(a,\r
+"onChangeMonthYear");if(c)c.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,c){return this._determineDate(a,this._get(a,c+"Date"),null)},_getDaysInMonth:function(a,c){return 32-this._daylightSavingAdjust(new Date(a,c,32)).getDate()},_getFirstDayOfMonth:function(a,c){return(new Date(a,c,1)).getDay()},_canAdjustMonth:function(a,c,h,i){var j=this._getNumberOfMonths(a);\r
+h=this._daylightSavingAdjust(new Date(h,i+(c<0?c:j[0]*j[1]),1));c<0&&h.setDate(this._getDaysInMonth(h.getFullYear(),h.getMonth()));return this._isInRange(a,h)},_isInRange:function(a,c){var h=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!h||c.getTime()>=h.getTime())&&(!a||c.getTime()<=a.getTime())},_getFormatConfig:function(a){var c=this._get(a,"shortYearCutoff");c=typeof c!="string"?c:(new Date).getFullYear()%100+parseInt(c,10);return{shortYearCutoff:c,dayNamesShort:this._get(a,\r
+"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,c,h,i){if(!c){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}c=c?typeof c=="object"?c:this._daylightSavingAdjust(new Date(i,h,c)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),c,this._getFormatConfig(a))}});b.fn.datepicker=\r
+function(a){if(!this.length)return this;if(!b.datepicker.initialized){b(document).mousedown(b.datepicker._checkExternalClick).find("body").append(b.datepicker.dpDiv);b.datepicker.initialized=true}var c=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return b.datepicker["_"+a+"Datepicker"].apply(b.datepicker,[this[0]].concat(c));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return b.datepicker["_"+a+"Datepicker"].apply(b.datepicker,\r
+[this[0]].concat(c));return this.each(function(){typeof a=="string"?b.datepicker["_"+a+"Datepicker"].apply(b.datepicker,[this].concat(c)):b.datepicker._attachDatepicker(this,a)})};b.datepicker=new e;b.datepicker.initialized=false;b.datepicker.uuid=(new Date).getTime();b.datepicker.version="1.8.11";window["DP_jQuery_"+f]=b})(jQuery);\r
+(function(b,d){var e={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},g={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true};b.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:{my:"center",at:"center",collision:"fit",using:function(f){var a=b(this).css(f).offset().top;a<0&&\r
+b(this).css("top",f.top-a)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var f=this,a=f.options,c=a.title||"&#160;",h=b.ui.dialog.getTitleId(f.element),i=(f.uiDialog=b("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+a.dialogClass).css({zIndex:a.zIndex}).attr("tabIndex",\r
+-1).css("outline",0).keydown(function(p){if(a.closeOnEscape&&p.keyCode&&p.keyCode===b.ui.keyCode.ESCAPE){f.close(p);p.preventDefault()}}).attr({role:"dialog","aria-labelledby":h}).mousedown(function(p){f.moveToTop(false,p)});f.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(i);var j=(f.uiDialogTitlebar=b("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(i),n=b('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role",\r
+"button").hover(function(){n.addClass("ui-state-hover")},function(){n.removeClass("ui-state-hover")}).focus(function(){n.addClass("ui-state-focus")}).blur(function(){n.removeClass("ui-state-focus")}).click(function(p){f.close(p);return false}).appendTo(j);(f.uiDialogTitlebarCloseText=b("<span></span>")).addClass("ui-icon ui-icon-closethick").text(a.closeText).appendTo(n);b("<span></span>").addClass("ui-dialog-title").attr("id",h).html(c).prependTo(j);if(b.isFunction(a.beforeclose)&&!b.isFunction(a.beforeClose))a.beforeClose=\r
+a.beforeclose;j.find("*").add(j).disableSelection();a.draggable&&b.fn.draggable&&f._makeDraggable();a.resizable&&b.fn.resizable&&f._makeResizable();f._createButtons(a.buttons);f._isOpen=false;b.fn.bgiframe&&i.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var f=this;f.overlay&&f.overlay.destroy();f.uiDialog.hide();f.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");f.uiDialog.remove();f.originalTitle&&\r
+f.element.attr("title",f.originalTitle);return f},widget:function(){return this.uiDialog},close:function(f){var a=this,c,h;if(false!==a._trigger("beforeClose",f)){a.overlay&&a.overlay.destroy();a.uiDialog.unbind("keypress.ui-dialog");a._isOpen=false;if(a.options.hide)a.uiDialog.hide(a.options.hide,function(){a._trigger("close",f)});else{a.uiDialog.hide();a._trigger("close",f)}b.ui.dialog.overlay.resize();if(a.options.modal){c=0;b(".ui-dialog").each(function(){if(this!==a.uiDialog[0]){h=b(this).css("z-index");\r
+isNaN(h)||(c=Math.max(c,h))}});b.ui.dialog.maxZ=c}return a}},isOpen:function(){return this._isOpen},moveToTop:function(f,a){var c=this,h=c.options;if(h.modal&&!f||!h.stack&&!h.modal)return c._trigger("focus",a);if(h.zIndex>b.ui.dialog.maxZ)b.ui.dialog.maxZ=h.zIndex;if(c.overlay){b.ui.dialog.maxZ+=1;c.overlay.$el.css("z-index",b.ui.dialog.overlay.maxZ=b.ui.dialog.maxZ)}f={scrollTop:c.element.attr("scrollTop"),scrollLeft:c.element.attr("scrollLeft")};b.ui.dialog.maxZ+=1;c.uiDialog.css("z-index",b.ui.dialog.maxZ);\r
+c.element.attr(f);c._trigger("focus",a);return c},open:function(){if(!this._isOpen){var f=this,a=f.options,c=f.uiDialog;f.overlay=a.modal?new b.ui.dialog.overlay(f):null;f._size();f._position(a.position);c.show(a.show);f.moveToTop(true);a.modal&&c.bind("keypress.ui-dialog",function(h){if(h.keyCode===b.ui.keyCode.TAB){var i=b(":tabbable",this),j=i.filter(":first");i=i.filter(":last");if(h.target===i[0]&&!h.shiftKey){j.focus(1);return false}else if(h.target===j[0]&&h.shiftKey){i.focus(1);return false}}});\r
+b(f.element.find(":tabbable").get().concat(c.find(".ui-dialog-buttonpane :tabbable").get().concat(c.get()))).eq(0).focus();f._isOpen=true;f._trigger("open");return f}},_createButtons:function(f){var a=this,c=false,h=b("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),i=b("<div></div>").addClass("ui-dialog-buttonset").appendTo(h);a.uiDialog.find(".ui-dialog-buttonpane").remove();typeof f==="object"&&f!==null&&b.each(f,function(){return!(c=true)});if(c){b.each(f,function(j,\r
+n){n=b.isFunction(n)?{click:n,text:j}:n;j=b('<button type="button"></button>').attr(n,true).unbind("click").click(function(){n.click.apply(a.element[0],arguments)}).appendTo(i);b.fn.button&&j.button()});h.appendTo(a.uiDialog)}},_makeDraggable:function(){function f(j){return{position:j.position,offset:j.offset}}var a=this,c=a.options,h=b(document),i;a.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(j,n){i=\r
+c.height==="auto"?"auto":b(this).height();b(this).height(b(this).height()).addClass("ui-dialog-dragging");a._trigger("dragStart",j,f(n))},drag:function(j,n){a._trigger("drag",j,f(n))},stop:function(j,n){c.position=[n.position.left-h.scrollLeft(),n.position.top-h.scrollTop()];b(this).removeClass("ui-dialog-dragging").height(i);a._trigger("dragStop",j,f(n));b.ui.dialog.overlay.resize()}})},_makeResizable:function(f){function a(j){return{originalPosition:j.originalPosition,originalSize:j.originalSize,\r
+position:j.position,size:j.size}}f=f===d?this.options.resizable:f;var c=this,h=c.options,i=c.uiDialog.css("position");f=typeof f==="string"?f:"n,e,s,w,se,sw,ne,nw";c.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:c.element,maxWidth:h.maxWidth,maxHeight:h.maxHeight,minWidth:h.minWidth,minHeight:c._minHeight(),handles:f,start:function(j,n){b(this).addClass("ui-dialog-resizing");c._trigger("resizeStart",j,a(n))},resize:function(j,n){c._trigger("resize",j,a(n))},stop:function(j,\r
+n){b(this).removeClass("ui-dialog-resizing");h.height=b(this).height();h.width=b(this).width();c._trigger("resizeStop",j,a(n));b.ui.dialog.overlay.resize()}}).css("position",i).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var f=this.options;return f.height==="auto"?f.minHeight:Math.min(f.minHeight,f.height)},_position:function(f){var a=[],c=[0,0],h;if(f){if(typeof f==="string"||typeof f==="object"&&"0"in f){a=f.split?f.split(" "):[f[0],f[1]];if(a.length===\r
+1)a[1]=a[0];b.each(["left","top"],function(i,j){if(+a[i]===a[i]){c[i]=a[i];a[i]=j}});f={my:a.join(" "),at:a.join(" "),offset:c.join(" ")}}f=b.extend({},b.ui.dialog.prototype.options.position,f)}else f=b.ui.dialog.prototype.options.position;(h=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(b.extend({of:window},f));h||this.uiDialog.hide()},_setOptions:function(f){var a=this,c={},h=false;b.each(f,function(i,j){a._setOption(i,j);if(i in e)h=true;if(i in\r
+g)c[i]=j});h&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",c)},_setOption:function(f,a){var c=this,h=c.uiDialog;switch(f){case "beforeclose":f="beforeClose";break;case "buttons":c._createButtons(a);break;case "closeText":c.uiDialogTitlebarCloseText.text(""+a);break;case "dialogClass":h.removeClass(c.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+a);break;case "disabled":a?h.addClass("ui-dialog-disabled"):h.removeClass("ui-dialog-disabled");\r
+break;case "draggable":var i=h.is(":data(draggable)");i&&!a&&h.draggable("destroy");!i&&a&&c._makeDraggable();break;case "position":c._position(a);break;case "resizable":(i=h.is(":data(resizable)"))&&!a&&h.resizable("destroy");i&&typeof a==="string"&&h.resizable("option","handles",a);!i&&a!==false&&c._makeResizable(a);break;case "title":b(".ui-dialog-title",c.uiDialogTitlebar).html(""+(a||"&#160;"));break}b.Widget.prototype._setOption.apply(c,arguments)},_size:function(){var f=this.options,a,c,h=\r
+this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(f.minWidth>f.width)f.width=f.minWidth;a=this.uiDialog.css({height:"auto",width:f.width}).height();c=Math.max(0,f.minHeight-a);if(f.height==="auto")if(b.support.minHeight)this.element.css({minHeight:c,height:"auto"});else{this.uiDialog.show();f=this.element.css("height","auto").height();h||this.uiDialog.hide();this.element.height(Math.max(f,c))}else this.element.height(Math.max(f.height-a,0));this.uiDialog.is(":data(resizable)")&&\r
+this.uiDialog.resizable("option","minHeight",this._minHeight())}});b.extend(b.ui.dialog,{version:"1.8.11",uuid:0,maxZ:0,getTitleId:function(f){f=f.attr("id");if(!f){this.uuid+=1;f=this.uuid}return"ui-dialog-title-"+f},overlay:function(f){this.$el=b.ui.dialog.overlay.create(f)}});b.extend(b.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:b.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(f){return f+".dialog-overlay"}).join(" "),create:function(f){if(this.instances.length===\r
+0){setTimeout(function(){b.ui.dialog.overlay.instances.length&&b(document).bind(b.ui.dialog.overlay.events,function(c){if(b(c.target).zIndex()<b.ui.dialog.overlay.maxZ)return false})},1);b(document).bind("keydown.dialog-overlay",function(c){if(f.options.closeOnEscape&&c.keyCode&&c.keyCode===b.ui.keyCode.ESCAPE){f.close(c);c.preventDefault()}});b(window).bind("resize.dialog-overlay",b.ui.dialog.overlay.resize)}var a=(this.oldInstances.pop()||b("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),\r
+height:this.height()});b.fn.bgiframe&&a.bgiframe();this.instances.push(a);return a},destroy:function(f){var a=b.inArray(f,this.instances);a!=-1&&this.oldInstances.push(this.instances.splice(a,1)[0]);this.instances.length===0&&b([document,window]).unbind(".dialog-overlay");f.remove();var c=0;b.each(this.instances,function(){c=Math.max(c,this.css("z-index"))});this.maxZ=c},height:function(){var f,a;if(b.browser.msie&&b.browser.version<7){f=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);\r
+a=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return f<a?b(window).height()+"px":f+"px"}else return b(document).height()+"px"},width:function(){var f,a;if(b.browser.msie&&b.browser.version<7){f=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);a=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return f<a?b(window).width()+"px":f+"px"}else return b(document).width()+"px"},resize:function(){var f=b([]);b.each(b.ui.dialog.overlay.instances,\r
+function(){f=f.add(this)});f.css({width:0,height:0}).css({width:b.ui.dialog.overlay.width(),height:b.ui.dialog.overlay.height()})}});b.extend(b.ui.dialog.overlay.prototype,{destroy:function(){b.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);\r
+(function(b){b.ui=b.ui||{};var d=/left|center|right/,e=/top|center|bottom/,g=b.fn.position,f=b.fn.offset;b.fn.position=function(a){if(!a||!a.of)return g.apply(this,arguments);a=b.extend({},a);var c=b(a.of),h=c[0],i=(a.collision||"flip").split(" "),j=a.offset?a.offset.split(" "):[0,0],n,p,l;if(h.nodeType===9){n=c.width();p=c.height();l={top:0,left:0}}else if(h.setTimeout){n=c.width();p=c.height();l={top:c.scrollTop(),left:c.scrollLeft()}}else if(h.preventDefault){a.at="left top";n=p=0;l={top:a.of.pageY,\r
+left:a.of.pageX}}else{n=c.outerWidth();p=c.outerHeight();l=c.offset()}b.each(["my","at"],function(){var k=(a[this]||"").split(" ");if(k.length===1)k=d.test(k[0])?k.concat(["center"]):e.test(k[0])?["center"].concat(k):["center","center"];k[0]=d.test(k[0])?k[0]:"center";k[1]=e.test(k[1])?k[1]:"center";a[this]=k});if(i.length===1)i[1]=i[0];j[0]=parseInt(j[0],10)||0;if(j.length===1)j[1]=j[0];j[1]=parseInt(j[1],10)||0;if(a.at[0]==="right")l.left+=n;else if(a.at[0]==="center")l.left+=n/2;if(a.at[1]==="bottom")l.top+=\r
+p;else if(a.at[1]==="center")l.top+=p/2;l.left+=j[0];l.top+=j[1];return this.each(function(){var k=b(this),m=k.outerWidth(),o=k.outerHeight(),q=parseInt(b.curCSS(this,"marginLeft",true))||0,s=parseInt(b.curCSS(this,"marginTop",true))||0,r=m+q+(parseInt(b.curCSS(this,"marginRight",true))||0),u=o+s+(parseInt(b.curCSS(this,"marginBottom",true))||0),v=b.extend({},l),w;if(a.my[0]==="right")v.left-=m;else if(a.my[0]==="center")v.left-=m/2;if(a.my[1]==="bottom")v.top-=o;else if(a.my[1]==="center")v.top-=\r
+o/2;v.left=Math.round(v.left);v.top=Math.round(v.top);w={left:v.left-q,top:v.top-s};b.each(["left","top"],function(y,B){b.ui.position[i[y]]&&b.ui.position[i[y]][B](v,{targetWidth:n,targetHeight:p,elemWidth:m,elemHeight:o,collisionPosition:w,collisionWidth:r,collisionHeight:u,offset:j,my:a.my,at:a.at})});b.fn.bgiframe&&k.bgiframe();k.offset(b.extend(v,{using:a.using}))})};b.ui.position={fit:{left:function(a,c){var h=b(window);h=c.collisionPosition.left+c.collisionWidth-h.width()-h.scrollLeft();a.left=\r
+h>0?a.left-h:Math.max(a.left-c.collisionPosition.left,a.left)},top:function(a,c){var h=b(window);h=c.collisionPosition.top+c.collisionHeight-h.height()-h.scrollTop();a.top=h>0?a.top-h:Math.max(a.top-c.collisionPosition.top,a.top)}},flip:{left:function(a,c){if(c.at[0]!=="center"){var h=b(window);h=c.collisionPosition.left+c.collisionWidth-h.width()-h.scrollLeft();var i=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,j=c.at[0]==="left"?c.targetWidth:-c.targetWidth,n=-2*c.offset[0];a.left+=\r
+c.collisionPosition.left<0?i+j+n:h>0?i+j+n:0}},top:function(a,c){if(c.at[1]!=="center"){var h=b(window);h=c.collisionPosition.top+c.collisionHeight-h.height()-h.scrollTop();var i=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,j=c.at[1]==="top"?c.targetHeight:-c.targetHeight,n=-2*c.offset[1];a.top+=c.collisionPosition.top<0?i+j+n:h>0?i+j+n:0}}}};if(!b.offset.setOffset){b.offset.setOffset=function(a,c){if(/static/.test(b.curCSS(a,"position")))a.style.position="relative";var h=b(a),\r
+i=h.offset(),j=parseInt(b.curCSS(a,"top",true),10)||0,n=parseInt(b.curCSS(a,"left",true),10)||0;i={top:c.top-i.top+j,left:c.left-i.left+n};"using"in c?c.using.call(a,i):h.css(i)};b.fn.offset=function(a){var c=this[0];if(!c||!c.ownerDocument)return null;if(a)return this.each(function(){b.offset.setOffset(this,a)});return f.call(this)}}})(jQuery);\r
+(function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");\r
+this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(e){if(e===d)return this._value();this._setOption("value",e);return this},_setOption:function(e,g){if(e==="value"){this.options.value=g;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var e=this.options.value;if(typeof e!=="number")e=0;return Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*\r
+this._value()/this.options.max},_refreshValue:function(){var e=this.value(),g=this._percentage();if(this.oldValue!==e){this.oldValue=e;this._trigger("change")}this.valueDiv.toggleClass("ui-corner-right",e===this.options.max).width(g.toFixed(0)+"%");this.element.attr("aria-valuenow",e)}});b.extend(b.ui.progressbar,{version:"1.8.11"})})(jQuery);\r
+(function(b){b.widget("ui.slider",b.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var d=this,e=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");e.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");\r
+this.range=b([]);if(e.range){if(e.range===true){this.range=b("<div></div>");if(!e.values)e.values=[this._valueMin(),this._valueMin()];if(e.values.length&&e.values.length!==2)e.values=[e.values[0],e.values[0]]}else this.range=b("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(e.range==="min"||e.range==="max")this.range.addClass("ui-slider-range-"+e.range);this.range.addClass("ui-widget-header")}b(".ui-slider-handle",this.element).length===0&&b("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");\r
+if(e.values&&e.values.length)for(;b(".ui-slider-handle",this.element).length<e.values.length;)b("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=b(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(g){g.preventDefault()}).hover(function(){e.disabled||b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")}).focus(function(){if(e.disabled)b(this).blur();\r
+else{b(".ui-slider .ui-state-focus").removeClass("ui-state-focus");b(this).addClass("ui-state-focus")}}).blur(function(){b(this).removeClass("ui-state-focus")});this.handles.each(function(g){b(this).data("index.ui-slider-handle",g)});this.handles.keydown(function(g){var f=true,a=b(this).data("index.ui-slider-handle"),c,h,i;if(!d.options.disabled){switch(g.keyCode){case b.ui.keyCode.HOME:case b.ui.keyCode.END:case b.ui.keyCode.PAGE_UP:case b.ui.keyCode.PAGE_DOWN:case b.ui.keyCode.UP:case b.ui.keyCode.RIGHT:case b.ui.keyCode.DOWN:case b.ui.keyCode.LEFT:f=\r
+false;if(!d._keySliding){d._keySliding=true;b(this).addClass("ui-state-active");c=d._start(g,a);if(c===false)return}break}i=d.options.step;c=d.options.values&&d.options.values.length?(h=d.values(a)):(h=d.value());switch(g.keyCode){case b.ui.keyCode.HOME:h=d._valueMin();break;case b.ui.keyCode.END:h=d._valueMax();break;case b.ui.keyCode.PAGE_UP:h=d._trimAlignValue(c+(d._valueMax()-d._valueMin())/5);break;case b.ui.keyCode.PAGE_DOWN:h=d._trimAlignValue(c-(d._valueMax()-d._valueMin())/5);break;case b.ui.keyCode.UP:case b.ui.keyCode.RIGHT:if(c===\r
+d._valueMax())return;h=d._trimAlignValue(c+i);break;case b.ui.keyCode.DOWN:case b.ui.keyCode.LEFT:if(c===d._valueMin())return;h=d._trimAlignValue(c-i);break}d._slide(g,a,h);return f}}).keyup(function(g){var f=b(this).data("index.ui-slider-handle");if(d._keySliding){d._keySliding=false;d._stop(g,f);d._change(g,f);b(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");\r
+this._mouseDestroy();return this},_mouseCapture:function(d){var e=this.options,g,f,a,c,h;if(e.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();g=this._normValueFromMouse({x:d.pageX,y:d.pageY});f=this._valueMax()-this._valueMin()+1;c=this;this.handles.each(function(i){var j=Math.abs(g-c.values(i));if(f>j){f=j;a=b(this);h=i}});if(e.range===true&&this.values(1)===e.min){h+=1;a=b(this.handles[h])}if(this._start(d,\r
+h)===false)return false;this._mouseSliding=true;c._handleIndex=h;a.addClass("ui-state-active").focus();e=a.offset();this._clickOffset=!b(d.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:d.pageX-e.left-a.width()/2,top:d.pageY-e.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)};this.handles.hasClass("ui-state-hover")||this._slide(d,h,g);return this._animateOff=true},_mouseStart:function(){return true},\r
+_mouseDrag:function(d){var e=this._normValueFromMouse({x:d.pageX,y:d.pageY});this._slide(d,this._handleIndex,e);return false},_mouseStop:function(d){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(d,this._handleIndex);this._change(d,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var e;\r
+if(this.orientation==="horizontal"){e=this.elementSize.width;d=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{e=this.elementSize.height;d=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}e=d/e;if(e>1)e=1;if(e<0)e=0;if(this.orientation==="vertical")e=1-e;d=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+e*d)},_start:function(d,e){var g={handle:this.handles[e],value:this.value()};if(this.options.values&&this.options.values.length){g.value=\r
+this.values(e);g.values=this.values()}return this._trigger("start",d,g)},_slide:function(d,e,g){var f;if(this.options.values&&this.options.values.length){f=this.values(e?0:1);if(this.options.values.length===2&&this.options.range===true&&(e===0&&g>f||e===1&&g<f))g=f;if(g!==this.values(e)){f=this.values();f[e]=g;d=this._trigger("slide",d,{handle:this.handles[e],value:g,values:f});this.values(e?0:1);d!==false&&this.values(e,g,true)}}else if(g!==this.value()){d=this._trigger("slide",d,{handle:this.handles[e],\r
+value:g});d!==false&&this.value(g)}},_stop:function(d,e){var g={handle:this.handles[e],value:this.value()};if(this.options.values&&this.options.values.length){g.value=this.values(e);g.values=this.values()}this._trigger("stop",d,g)},_change:function(d,e){if(!this._keySliding&&!this._mouseSliding){var g={handle:this.handles[e],value:this.value()};if(this.options.values&&this.options.values.length){g.value=this.values(e);g.values=this.values()}this._trigger("change",d,g)}},value:function(d){if(arguments.length){this.options.value=\r
+this._trimAlignValue(d);this._refreshValue();this._change(null,0)}return this._value()},values:function(d,e){var g,f,a;if(arguments.length>1){this.options.values[d]=this._trimAlignValue(e);this._refreshValue();this._change(null,d)}if(arguments.length)if(b.isArray(arguments[0])){g=this.options.values;f=arguments[0];for(a=0;a<g.length;a+=1){g[a]=this._trimAlignValue(f[a]);this._change(null,a)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(d):this.value();\r
+else return this._values()},_setOption:function(d,e){var g,f=0;if(b.isArray(this.options.values))f=this.options.values.length;b.Widget.prototype._setOption.apply(this,arguments);switch(d){case "disabled":if(e){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();\r
+this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(g=0;g<f;g+=1)this._change(null,g);this._animateOff=false;break}},_value:function(){var d=this.options.value;return d=this._trimAlignValue(d)},_values:function(d){var e,g;if(arguments.length){e=this.options.values[d];\r
+return e=this._trimAlignValue(e)}else{e=this.options.values.slice();for(g=0;g<e.length;g+=1)e[g]=this._trimAlignValue(e[g]);return e}},_trimAlignValue:function(d){if(d<=this._valueMin())return this._valueMin();if(d>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,g=(d-this._valueMin())%e;alignValue=d-g;if(Math.abs(g)*2>=e)alignValue+=g>0?e:-e;return parseFloat(alignValue.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},\r
+_refreshValue:function(){var d=this.options.range,e=this.options,g=this,f=!this._animateOff?e.animate:false,a,c={},h,i,j,n;if(this.options.values&&this.options.values.length)this.handles.each(function(p){a=(g.values(p)-g._valueMin())/(g._valueMax()-g._valueMin())*100;c[g.orientation==="horizontal"?"left":"bottom"]=a+"%";b(this).stop(1,1)[f?"animate":"css"](c,e.animate);if(g.options.range===true)if(g.orientation==="horizontal"){if(p===0)g.range.stop(1,1)[f?"animate":"css"]({left:a+"%"},e.animate);\r
+if(p===1)g.range[f?"animate":"css"]({width:a-h+"%"},{queue:false,duration:e.animate})}else{if(p===0)g.range.stop(1,1)[f?"animate":"css"]({bottom:a+"%"},e.animate);if(p===1)g.range[f?"animate":"css"]({height:a-h+"%"},{queue:false,duration:e.animate})}h=a});else{i=this.value();j=this._valueMin();n=this._valueMax();a=n!==j?(i-j)/(n-j)*100:0;c[g.orientation==="horizontal"?"left":"bottom"]=a+"%";this.handle.stop(1,1)[f?"animate":"css"](c,e.animate);if(d==="min"&&this.orientation==="horizontal")this.range.stop(1,\r
+1)[f?"animate":"css"]({width:a+"%"},e.animate);if(d==="max"&&this.orientation==="horizontal")this.range[f?"animate":"css"]({width:100-a+"%"},{queue:false,duration:e.animate});if(d==="min"&&this.orientation==="vertical")this.range.stop(1,1)[f?"animate":"css"]({height:a+"%"},e.animate);if(d==="max"&&this.orientation==="vertical")this.range[f?"animate":"css"]({height:100-a+"%"},{queue:false,duration:e.animate})}}});b.extend(b.ui.slider,{version:"1.8.11"})})(jQuery);\r
+(function(b,d){function e(){return++f}function g(){return++a}var f=0,a=0;b.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(true)},_setOption:function(c,h){if(c=="selected")this.options.collapsible&&\r
+h==this.options.selected||this.select(h);else{this.options[c]=h;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+g());return b.cookie.apply(null,[c].concat(b.makeArray(arguments)))},_ui:function(c,h){return{tab:c,panel:h,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c=\r
+b(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function h(r,u){r.css("display","");!b.support.opacity&&u.opacity&&r[0].style.removeAttribute("filter")}var i=this,j=this.options,n=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=b(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return b("a",this)[0]});this.panels=b([]);this.anchors.each(function(r,u){var v=b(u).attr("href"),w=v.split("#")[0],y;if(w&&(w===location.toString().split("#")[0]||\r
+(y=b("base")[0])&&w===y.href)){v=u.hash;u.href=v}if(n.test(v))i.panels=i.panels.add(i.element.find(i._sanitizeSelector(v)));else if(v&&v!=="#"){b.data(u,"href.tabs",v);b.data(u,"load.tabs",v.replace(/#.*$/,""));v=i._tabId(u);u.href="#"+v;u=i.element.find("#"+v);if(!u.length){u=b(j.panelTemplate).attr("id",v).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(i.panels[r-1]||i.list);u.data("destroy.tabs",true)}i.panels=i.panels.add(u)}else j.disabled.push(r)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");\r
+this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(j.selected===d){location.hash&&this.anchors.each(function(r,u){if(u.hash==location.hash){j.selected=r;return false}});if(typeof j.selected!=="number"&&j.cookie)j.selected=parseInt(i._cookie(),10);if(typeof j.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)j.selected=\r
+this.lis.index(this.lis.filter(".ui-tabs-selected"));j.selected=j.selected||(this.lis.length?0:-1)}else if(j.selected===null)j.selected=-1;j.selected=j.selected>=0&&this.anchors[j.selected]||j.selected<0?j.selected:0;j.disabled=b.unique(j.disabled.concat(b.map(this.lis.filter(".ui-state-disabled"),function(r){return i.lis.index(r)}))).sort();b.inArray(j.selected,j.disabled)!=-1&&j.disabled.splice(b.inArray(j.selected,j.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");\r
+if(j.selected>=0&&this.anchors.length){i.element.find(i._sanitizeSelector(i.anchors[j.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(j.selected).addClass("ui-tabs-selected ui-state-active");i.element.queue("tabs",function(){i._trigger("show",null,i._ui(i.anchors[j.selected],i.element.find(i._sanitizeSelector(i.anchors[j.selected].hash))[0]))});this.load(j.selected)}b(window).bind("unload",function(){i.lis.add(i.anchors).unbind(".tabs");i.lis=i.anchors=i.panels=null})}else j.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));\r
+this.element[j.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");j.cookie&&this._cookie(j.selected,j.cookie);c=0;for(var p;p=this.lis[c];c++)b(p)[b.inArray(c,j.disabled)!=-1&&!b(p).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");j.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(j.event!=="mouseover"){var l=function(r,u){u.is(":not(.ui-state-disabled)")&&u.addClass("ui-state-"+r)},k=function(r,u){u.removeClass("ui-state-"+\r
+r)};this.lis.bind("mouseover.tabs",function(){l("hover",b(this))});this.lis.bind("mouseout.tabs",function(){k("hover",b(this))});this.anchors.bind("focus.tabs",function(){l("focus",b(this).closest("li"))});this.anchors.bind("blur.tabs",function(){k("focus",b(this).closest("li"))})}var m,o;if(j.fx)if(b.isArray(j.fx)){m=j.fx[0];o=j.fx[1]}else m=o=j.fx;var q=o?function(r,u){b(r).closest("li").addClass("ui-tabs-selected ui-state-active");u.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",\r
+function(){h(u,o);i._trigger("show",null,i._ui(r,u[0]))})}:function(r,u){b(r).closest("li").addClass("ui-tabs-selected ui-state-active");u.removeClass("ui-tabs-hide");i._trigger("show",null,i._ui(r,u[0]))},s=m?function(r,u){u.animate(m,m.duration||"normal",function(){i.lis.removeClass("ui-tabs-selected ui-state-active");u.addClass("ui-tabs-hide");h(u,m);i.element.dequeue("tabs")})}:function(r,u){i.lis.removeClass("ui-tabs-selected ui-state-active");u.addClass("ui-tabs-hide");i.element.dequeue("tabs")};\r
+this.anchors.bind(j.event+".tabs",function(){var r=this,u=b(r).closest("li"),v=i.panels.filter(":not(.ui-tabs-hide)"),w=i.element.find(i._sanitizeSelector(r.hash));if(u.hasClass("ui-tabs-selected")&&!j.collapsible||u.hasClass("ui-state-disabled")||u.hasClass("ui-state-processing")||i.panels.filter(":animated").length||i._trigger("select",null,i._ui(this,w[0]))===false){this.blur();return false}j.selected=i.anchors.index(this);i.abort();if(j.collapsible)if(u.hasClass("ui-tabs-selected")){j.selected=\r
+-1;j.cookie&&i._cookie(j.selected,j.cookie);i.element.queue("tabs",function(){s(r,v)}).dequeue("tabs");this.blur();return false}else if(!v.length){j.cookie&&i._cookie(j.selected,j.cookie);i.element.queue("tabs",function(){q(r,w)});i.load(i.anchors.index(this));this.blur();return false}j.cookie&&i._cookie(j.selected,j.cookie);if(w.length){v.length&&i.element.queue("tabs",function(){s(r,v)});i.element.queue("tabs",function(){q(r,w)});i.load(i.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";\r
+b.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));return c},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var h=\r
+b.data(this,"href.tabs");if(h)this.href=h;var i=b(this).unbind(".tabs");b.each(["href","load","cache"],function(j,n){i.removeData(n+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){b.data(this,"destroy.tabs")?b(this).remove():b(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,\r
+h,i){if(i===d)i=this.anchors.length;var j=this,n=this.options;h=b(n.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,h));c=!c.indexOf("#")?c.replace("#",""):this._tabId(b("a",h)[0]);h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var p=j.element.find("#"+c);p.length||(p=b(n.panelTemplate).attr("id",c).data("destroy.tabs",true));p.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(i>=this.lis.length){h.appendTo(this.list);p.appendTo(this.list[0].parentNode)}else{h.insertBefore(this.lis[i]);\r
+p.insertBefore(this.panels[i])}n.disabled=b.map(n.disabled,function(l){return l>=i?++l:l});this._tabify();if(this.anchors.length==1){n.selected=0;h.addClass("ui-tabs-selected ui-state-active");p.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){j._trigger("show",null,j._ui(j.anchors[0],j.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[i],this.panels[i]));return this},remove:function(c){c=this._getIndex(c);var h=this.options,i=this.lis.eq(c).remove(),j=this.panels.eq(c).remove();\r
+if(i.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1<this.anchors.length?1:-1));h.disabled=b.map(b.grep(h.disabled,function(n){return n!=c}),function(n){return n>=c?--n:n});this._tabify();this._trigger("remove",null,this._ui(i.find("a")[0],j[0]));return this},enable:function(c){c=this._getIndex(c);var h=this.options;if(b.inArray(c,h.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");h.disabled=b.grep(h.disabled,function(i){return i!=c});this._trigger("enable",null,\r
+this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){c=this._getIndex(c);var h=this.options;if(c!=h.selected){this.lis.eq(c).addClass("ui-state-disabled");h.disabled.push(c);h.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this},select:function(c){c=this._getIndex(c);if(c==-1)if(this.options.collapsible&&this.options.selected!=-1)c=this.options.selected;else return this;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},\r
+load:function(c){c=this._getIndex(c);var h=this,i=this.options,j=this.anchors.eq(c)[0],n=b.data(j,"load.tabs");this.abort();if(!n||this.element.queue("tabs").length!==0&&b.data(j,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing");if(i.spinner){var p=b("span",j);p.data("label.tabs",p.html()).html(i.spinner)}this.xhr=b.ajax(b.extend({},i.ajaxOptions,{url:n,success:function(l,k){h.element.find(h._sanitizeSelector(j.hash)).html(l);h._cleanup();i.cache&&b.data(j,\r
+"cache.tabs",true);h._trigger("load",null,h._ui(h.anchors[c],h.panels[c]));try{i.ajaxOptions.success(l,k)}catch(m){}},error:function(l,k){h._cleanup();h._trigger("load",null,h._ui(h.anchors[c],h.panels[c]));try{i.ajaxOptions.error(l,k,c,j)}catch(m){}}}));h.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},\r
+url:function(c,h){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",h);return this},length:function(){return this.anchors.length}});b.extend(b.ui.tabs,{version:"1.8.11"});b.extend(b.ui.tabs.prototype,{rotation:null,rotate:function(c,h){var i=this,j=this.options,n=i._rotate||(i._rotate=function(p){clearTimeout(i.rotation);i.rotation=setTimeout(function(){var l=j.selected;i.select(++l<i.anchors.length?l:0)},c);p&&p.stopPropagation()});h=i._unrotate||(i._unrotate=!h?function(p){p.clientX&&\r
+i.rotate(null)}:function(){t=j.selected;n()});if(c){this.element.bind("tabsshow",n);this.anchors.bind(j.event+".tabs",h);n()}else{clearTimeout(i.rotation);this.element.unbind("tabsshow",n);this.anchors.unbind(j.event+".tabs",h);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
\ No newline at end of file
diff --git a/wcfsetup/install/files/js/3rdParty/jquery.min.js b/wcfsetup/install/files/js/3rdParty/jquery.min.js
new file mode 100644 (file)
index 0000000..f78f96a
--- /dev/null
@@ -0,0 +1,16 @@
+/*!
+ * jQuery JavaScript Library v1.5.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Mar 31 15:28:23 2011 -0400
+ */
+(function(a,b){function ci(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cf(a){if(!b_[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";b_[a]=c}return b_[a]}function ce(a,b){var c={};d.each(cd.concat.apply([],cd.slice(0,b)),function(){c[this]=a});return c}function b$(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bZ(){try{return new a.XMLHttpRequest}catch(b){}}function bY(){d(a).unload(function(){for(var a in bW)bW[a](0,1)})}function bS(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h==="string"&&(f[h.toLowerCase()]=a.converters[h]);l=k,k=e[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=f[m]||f["* "+k];if(!n){p=b;for(o in f){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=f[j[1]+" "+k];if(p){o=f[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&d.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bR(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bQ(a,b,c,e){if(d.isArray(b)&&b.length)d.each(b,function(b,f){c||bs.test(a)?e(a,f):bQ(a+"["+(typeof f==="object"||d.isArray(f)?b:"")+"]",f,c,e)});else if(c||b==null||typeof b!=="object")e(a,b);else if(d.isArray(b)||d.isEmptyObject(b))e(a,"");else for(var f in b)bQ(a+"["+f+"]",b[f],c,e)}function bP(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bJ,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l==="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bP(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bP(a,c,d,e,"*",g));return l}function bO(a){return function(b,c){typeof b!=="string"&&(c=b,b="*");if(d.isFunction(c)){var e=b.toLowerCase().split(bD),f=0,g=e.length,h,i,j;for(;f<g;f++)h=e[f],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bq(a,b,c){var e=b==="width"?bk:bl,f=b==="width"?a.offsetWidth:a.offsetHeight;if(c==="border")return f;d.each(e,function(){c||(f-=parseFloat(d.css(a,"padding"+this))||0),c==="margin"?f+=parseFloat(d.css(a,"margin"+this))||0:f-=parseFloat(d.css(a,"border"+this+"Width"))||0});return f}function bc(a,b){b.src?d.ajax({url:b.src,async:!1,dataType:"script"}):d.globalEval(b.text||b.textContent||b.innerHTML||""),b.parentNode&&b.parentNode.removeChild(b)}function bb(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function ba(a,b){if(b.nodeType===1){var c=b.nodeName.toLowerCase();b.clearAttributes(),b.mergeAttributes(a);if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(d.expando)}}function _(a,b){if(b.nodeType===1&&d.hasData(a)){var c=d.expando,e=d.data(a),f=d.data(b,e);if(e=e[c]){var g=e.events;f=f[c]=d.extend({},e);if(g){delete f.handle,f.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)d.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function $(a,b){return d.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Q(a,b,c){if(d.isFunction(b))return d.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return d.grep(a,function(a,d){return a===b===c});if(typeof b==="string"){var e=d.grep(a,function(a){return a.nodeType===1});if(L.test(b))return d.filter(b,e,!c);b=d.filter(b,e)}return d.grep(a,function(a,e){return d.inArray(a,b)>=0===c})}function P(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function H(a,b){return(a&&a!=="*"?a+".":"")+b.replace(t,"`").replace(u,"&")}function G(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,p=[],q=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;i<t.length;i++)g=t[i],g.origType.replace(r,"")===a.type?q.push(g.selector):t.splice(i--,1);f=d(a.target).closest(q,a.currentTarget);for(j=0,k=f.length;j<k;j++){m=f[j];for(i=0;i<t.length;i++){g=t[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,e=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,e=d(a.relatedTarget).closest(g.selector)[0];(!e||e!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){f=p[j];if(c&&f.level>c)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function E(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function y(){return!0}function x(){return!1}function i(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function h(a,c,e){if(e===b&&a.nodeType===1){e=a.getAttribute("data-"+c);if(typeof e==="string"){try{e=e==="true"?!0:e==="false"?!1:e==="null"?null:d.isNaN(e)?g.test(e)?d.parseJSON(e):e:parseFloat(e)}catch(f){}d.data(a,c,e)}else e=b}return e}var c=a.document,d=function(){function G(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(G,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x,y,z=Object.prototype.toString,A=Object.prototype.hasOwnProperty,B=Array.prototype.push,C=Array.prototype.slice,D=String.prototype.trim,E=Array.prototype.indexOf,F={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.2",length:0,size:function(){return this.length},toArray:function(){return C.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?B.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),x.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(C.apply(this,arguments),"slice",C.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:B,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){e=i[c],f=a[c];if(i===f)continue;l&&f&&(d.isPlainObject(f)||(g=d.isArray(f)))?(g?(g=!1,h=e&&d.isArray(e)?e:[]):h=e&&d.isPlainObject(e)?e:{},i[c]=d.extend(l,h,f)):f!==b&&(i[c]=f)}return i},d.extend({noConflict:function(b){a.$=f,b&&(a.jQuery=e);return d},isReady:!1,readyWait:1,ready:function(a){a===!0&&d.readyWait--;if(!d.readyWait||a!==!0&&!d.isReady){if(!c.body)return setTimeout(d.ready,1);d.isReady=!0;if(a!==!0&&--d.readyWait>0)return;x.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=d._Deferred();if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",y,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",y),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&G()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):F[z.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!A.call(a,"constructor")&&!A.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||A.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g<h;)if(c.apply(a[g++],e)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(var j=a[0];g<h&&c.call(j,g,j)!==!1;j=a[++g]){}return a},trim:D?function(a){return a==null?"":D.call(a)}:function(a){return a==null?"":(a+"").replace(j,"").replace(k,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var e=d.type(a);a.length==null||e==="string"||e==="function"||e==="regexp"||d.isWindow(a)?B.call(c,a):d.merge(c,a)}return c},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length==="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,b,c){var d=[],e;for(var f=0,g=a.length;f<g;f++)e=b(a[f],f,c),e!=null&&(d[d.length]=e);return d.concat.apply([],d)},guid:1,proxy:function(a,c,e){arguments.length===2&&(typeof c==="string"?(e=a,a=e[c],c=b):c&&!d.isFunction(c)&&(e=c,c=b)),!c&&a&&(c=function(){return a.apply(e||this,arguments)}),a&&(c.guid=a.guid=a.guid||c.guid||d.guid++);return c},access:function(a,c,e,f,g,h){var i=a.length;if(typeof c==="object"){for(var j in c)d.access(a,j,c[j],f,g,e);return a}if(e!==b){f=!h&&f&&d.isFunction(e);for(var k=0;k<i;k++)g(a[k],c,f?e.call(a[k],k,g(a[k],c)):e,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){F["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),E&&(d.inArray=function(a,b){return E.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?y=function(){c.removeEventListener("DOMContentLoaded",y,!1),d.ready()}:c.attachEvent&&(y=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",y),d.ready())});return d}(),e="then done fail isResolved isRejected promise".split(" "),f=[].slice;d.extend({_Deferred:function(){var a=[],b,c,e,f={done:function(){if(!e){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=d.type(i),j==="array"?f.done.apply(f,i):j==="function"&&a.push(i);k&&f.resolveWith(k[0],k[1])}return this},resolveWith:function(d,f){if(!e&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(d,f)}finally{b=[d,f],c=0}}return this},resolve:function(){f.resolveWith(this,arguments);return this},isResolved:function(){return c||b},cancel:function(){e=1,a=[];return this}};return f},Deferred:function(a){var b=d._Deferred(),c=d._Deferred(),f;d.extend(b,{then:function(a,c){b.done(a).fail(c);return this},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,promise:function(a){if(a==null){if(f)return f;f=a={}}var c=e.length;while(c--)a[e[c]]=b[e[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?f.call(arguments,0):c,--g||h.resolveWith(h,f.call(b,0))}}var b=arguments,c=0,e=b.length,g=e,h=e<=1&&a&&d.isFunction(a.promise)?a:d.Deferred();if(e>1){for(;c<e;c++)b[c]&&d.isFunction(b[c].promise)?b[c].promise().then(i(c),h.reject):--g;g||h.resolveWith(h,b)}else h!==a&&h.resolveWith(h,e?[a]:[]);return h.promise()}}),function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0,reliableMarginRight:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e)}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(a.style.width="1px",a.style.marginRight="0",d.support.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(a,null).marginRight,10)||0)===0),b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function");return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}}();var g=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!i(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,g=b.nodeType,h=g?d.cache:b,j=g?b[d.expando]:d.expando;if(!h[j])return;if(c){var k=e?h[j][f]:h[j];if(k){delete k[c];if(!i(k))return}}if(e){delete h[j][f];if(!i(h[j]))return}var l=h[j][f];d.support.deleteExpando||h!=a?delete h[j]:h[j]=null,l?(h[j]={},g||(h[j].toJSON=d.noop),h[j][f]=l):g&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var f=this[0].attributes,g;for(var i=0,j=f.length;i<j;i++)g=f[i].name,g.indexOf("data-")===0&&(g=g.substr(5),h(this[0],g,e[g]))}}return e}if(typeof a==="object")return this.each(function(){d.data(this,a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(c===b){e=this.triggerHandler("getData"+k[1]+"!",[k[0]]),e===b&&this.length&&(e=d.data(this[0],a),e=h(this[0],a,e));return e===b&&k[1]?this.data(k[0]):e}return this.each(function(){var b=d(this),e=[k[0],c];b.triggerHandler("setData"+k[1]+"!",e),d.data(this,a,c),b.triggerHandler("changeData"+k[1]+"!",e)})},removeData:function(a){return this.each(function(){d.removeData(this,a)})}}),d.extend({queue:function(a,b,c){if(a){b=(b||"fx")+"queue";var e=d._data(a,b);if(!c)return e||[];!e||d.isArray(c)?e=d._data(a,b,d.makeArray(c)):e.push(c);return e}},dequeue:function(a,b){b=b||"fx";var c=d.queue(a,b),e=c.shift();e==="inprogress"&&(e=c.shift()),e&&(b==="fx"&&c.unshift("inprogress"),e.call(a,function(){d.dequeue(a,b)})),c.length||d.removeData(a,b+"queue",!0)}}),d.fn.extend({queue:function(a,c){typeof a!=="string"&&(c=a,a="fx");if(c===b)return d.queue(this[0],a);return this.each(function(b){var e=d.queue(this,a,c);a==="fx"&&e[0]!=="inprogress"&&d.dequeue(this,a)})},dequeue:function(a){return this.each(function(){d.dequeue(this,a)})},delay:function(a,b){a=d.fx?d.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){d.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var j=/[\n\t\r]/g,k=/\s+/,l=/\r/g,m=/^(?:href|src|style)$/,n=/^(?:button|input)$/i,o=/^(?:button|input|object|select|textarea)$/i,p=/^a(?:rea)?$/i,q=/^(?:radio|checkbox)$/i;d.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"},d.fn.extend({attr:function(a,b){return d.access(this,a,b,!0,d.attr)},removeAttr:function(a,b){return this.each(function(){d.attr(this,a,""),this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.addClass(a.call(this,b,c.attr("class")))});if(a&&typeof a==="string"){var b=(a||"").split(k);for(var c=0,e=this.length;c<e;c++){var f=this[c];if(f.nodeType===1)if(f.className){var g=" "+f.className+" ",h=f.className;for(var i=0,j=b.length;i<j;i++)g.indexOf(" "+b[i]+" ")<0&&(h+=" "+b[i]);f.className=d.trim(h)}else f.className=a}}return this},removeClass:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.removeClass(a.call(this,b,c.attr("class")))});if(a&&typeof a==="string"||a===b){var c=(a||"").split(k);for(var e=0,f=this.length;e<f;e++){var g=this[e];if(g.nodeType===1&&g.className)if(a){var h=(" "+g.className+" ").replace(j," ");for(var i=0,l=c.length;i<l;i++)h=h.replace(" "+c[i]+" "," ");g.className=d.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,e=typeof b==="boolean";if(d.isFunction(a))return this.each(function(c){var e=d(this);e.toggleClass(a.call(this,c,e.attr("class"),b),b)});return this.each(function(){if(c==="string"){var f,g=0,h=d(this),i=b,j=a.split(k);while(f=j[g++])i=e?i:!h.hasClass(f),h[i?"addClass":"removeClass"](f)}else if(c==="undefined"||c==="boolean")this.className&&d._data(this,"__className__",this.className),this.className=this.className||a===!1?"":d._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(j," ").indexOf(b)>-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var j=i?f:0,k=i?f+1:h.length;j<k;j++){var m=h[j];if(m.selected&&(d.support.optDisabled?!m.disabled:m.getAttribute("disabled")===null)&&(!m.parentNode.disabled||!d.nodeName(m.parentNode,"optgroup"))){a=d(m).val();if(i)return a;g.push(a)}}if(i&&!g.length&&h.length)return d(h[f]).val();return g}if(q.test(c.type)&&!d.support.checkOn)return c.getAttribute("value")===null?"on":c.value;return(c.value||"").replace(l,"")}return b}var n=d.isFunction(a);return this.each(function(b){var c=d(this),e=a;if(this.nodeType===1){n&&(e=a.call(this,b,c.val())),e==null?e="":typeof e==="number"?e+="":d.isArray(e)&&(e=d.map(e,function(a){return a==null?"":a+""}));if(d.isArray(e)&&q.test(this.type))this.checked=d.inArray(c.val(),e)>=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=m.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&n.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var k=a.getAttributeNode("tabIndex");return k&&k.specified?k.value:o.test(a.nodeName)||p.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var l=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return l===null?b:l}h&&(a[c]=e);return a[c]}});var r=/\.(.*)$/,s=/^(?:textarea|input|select)$/i,t=/\./g,u=/ /g,v=/[^\w\s.|`]/g,w=function(a){return a.replace(v,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=x;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(a){return typeof d!=="undefined"&&d.event.triggered!==a.type?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=x);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),w).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))d.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=d.event.special[h]||{};for(j=f||0;j<p.length;j++){q=p[j];if(e.guid===q.guid){if(l||n.test(q.namespace))f==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(f!=null)break}}if(p.length===0||f!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&d.removeEvent(a,h,s.handle),g=null,delete t[h]}if(d.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,d.isEmptyObject(s)&&d.removeData(a,b,!0)}}},trigger:function(a,c,e){var f=a.type||a,g=arguments[3];if(!g){a=typeof a==="object"?a[d.expando]?a:d.extend(d.Event(f),a):d.Event(f),f.indexOf("!")>=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(r,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=a.type,l[m]())}catch(p){}k&&(l["on"+m]=k),d.event.triggered=b}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l<m;l++){var n=f[l];if(e||h.test(n.namespace)){c.handler=n.handler,c.data=n.data,c.handleObj=n;var o=n.handler.apply(this,k);o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[d.expando])return a;var e=a;a=d.Event(e);for(var f=this.props.length,g;f;)g=this.props[--f],a[g]=e[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=c.documentElement,i=c.body;a.pageX=a.clientX+(h&&h.scrollLeft||i&&i.scrollLeft||0)-(h&&h.clientLeft||i&&i.clientLeft||0),a.pageY=a.clientY+(h&&h.scrollTop||i&&i.scrollTop||0)-(h&&h.clientTop||i&&i.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:d.proxy,special:{ready:{setup:d.bindReady,teardown:d.noop},live:{add:function(a){d.event.add(this,H(a.origType,a.selector),d.extend({},a,{handler:G,guid:a.handler.guid}))},remove:function(a){d.event.remove(this,H(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){d.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},d.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},d.Event=function(a){if(!this.preventDefault)return new d.Event(a);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?y:x):this.type=a,this.timeStamp=d.now(),this[d.expando]=!0},d.Event.prototype={preventDefault:function(){this.isDefaultPrevented=y;var a=this.originalEvent;a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=y;var a=this.originalEvent;a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=y,this.stopPropagation()},isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x};var z=function(a){var b=a.relatedTarget;try{if(b&&b!==c&&!b.parentNode)return;while(b&&b!==this)b=b.parentNode;b!==this&&(a.type=a.data,d.event.handle.apply(this,arguments))}catch(e){}},A=function(a){a.type=a.data,d.event.handle.apply(this,arguments)};d.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){d.event.special[a]={setup:function(c){d.event.add(this,b,c&&c.selector?A:z,a)},teardown:function(a){d.event.remove(this,b,a&&a.selector?A:z)}}}),d.support.submitBubbles||(d.event.special.submit={setup:function(a,b){if(this.nodeName&&this.nodeName.toLowerCase()!=="form")d.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&d(b).closest("form").length&&E("submit",this,arguments)}),d.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&d(b).closest("form").length&&a.keyCode===13&&E("submit",this,arguments)});else return!1},teardown:function(a){d.event.remove(this,".specialSubmit")}});if(!d.support.changeBubbles){var B,C=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},D=function D(a){var c=a.target,e,f;if(s.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=C(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:D,beforedeactivate:D,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&D.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&D.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",C(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in B)d.event.add(this,c+".specialChange",B[c]);return s.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return s.test(this.nodeName)}},B=d.event.special.change.filters,B.focus=B.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function f(a){var c=d.event.fix(a);c.type=b,c.originalEvent={},d.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var e=0;d.event.special[b]={setup:function(){e++===0&&c.addEventListener(a,f,!0)},teardown:function(){--e===0&&c.removeEventListener(a,f,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i<j;i++)d.event.add(this[i],a,h,e);return this}}),d.fn.extend({unbind:function(a,b){if(typeof a!=="object"||a.preventDefault)for(var e=0,f=this.length;e<f;e++)d.event.remove(this[e],a,b);else for(var c in a)this.unbind(c,a[c]);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){d.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var c=d.Event(a);c.preventDefault(),c.stopPropagation(),d.event.trigger(c,b,this[0]);return c.result}},toggle:function(a){var b=arguments,c=1;while(c<b.length)d.proxy(a,b[c++]);return this.click(d.proxy(a,function(e){var f=(d._data(this,"lastToggle"+a.guid)||0)%c;d._data(this,"lastToggle"+a.guid,f+1),e.preventDefault();return b[f].apply(this,arguments)||!1}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var F={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};d.each(["live","die"],function(a,c){d.fn[c]=function(a,e,f,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:d(this.context);if(typeof a==="object"&&!a.preventDefault){for(var o in a)n[c](o,e,a[o],m);return this}d.isFunction(e)&&(f=e,e=b),a=(a||"").split(" ");while((h=a[i++])!=null){j=r.exec(h),k="",j&&(k=j[0],h=h.replace(r,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,h==="focus"||h==="blur"?(a.push(F[h]+k),h=h+k):h=(F[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)d.event.add(n[p],"live."+H(h,m),{data:e,selector:m,handler:f,origType:h,origHandler:f,preType:l});else n.unbind("live."+H(h,m),f)}return this}}),d.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){d.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!=="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!=="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(f){if(f===!0)continue}else g=o=!0}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b==="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1){}a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=u;typeof b==="string"&&!j.test(b)&&(b=b.toLowerCase(),d=b,g=t),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=u;typeof b==="string"&&!j.test(b)&&(b=b.toLowerCase(),d=b,g=t),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!=="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!=="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!=="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return"text"===c&&(b===c||b===null)},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||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(a===b){g=!0;return 0}if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};d.find=k,d.expr=k.selectors,d.expr[":"]=d.expr.filters,d.unique=k.uniqueSort,d.text=k.getText,d.isXMLDoc=k.isXML,d.contains=k.contains}();var I=/Until$/,J=/^(?:parents|prevUntil|prevAll)/,K=/,/,L=/^.[^:#\[\.,]*$/,M=Array.prototype.slice,N=d.expr.match.POS,O={children:!0,contents:!0,next:!0,prev:!0};d.fn.extend({find:function(a){var b=this.pushStack("","find",a),c=0;for(var e=0,f=this.length;e<f;e++){c=b.length,d.find(a,this[e],b);if(e>0)for(var g=c;g<b.length;g++)for(var h=0;h<c;h++)if(b[h]===b[g]){b.splice(g--,1);break}}return b},has:function(a){var b=d(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(d.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(Q(this,a,!1),"not",a)},filter:function(a){return this.pushStack(Q(this,a,!0),"filter",a)},is:function(a){return!!a&&d.filter(a,this).length>0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e<f;e++)i=a[e],j[i]||(j[i]=d.expr.match.POS.test(i)?d(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=N.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e<f;e++){g=this[e];while(g){if(l?l.index(g)>-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(P(c[0])||P(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=M.call(arguments);I.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!O[a]?d.unique(f):f,(this.length>1||K.test(e))&&J.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var R=/ jQuery\d+="(?:\d+|null)"/g,S=/^\s+/,T=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,U=/<([\w:]+)/,V=/<tbody/i,W=/<|&#?\w+;/,X=/<(?:script|object|embed|option|style)/i,Y=/checked\s*(?:[^=]|=\s*.checked.)/i,Z={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};Z.optgroup=Z.option,Z.tbody=Z.tfoot=Z.colgroup=Z.caption=Z.thead,Z.th=Z.td,d.support.htmlSerialize||(Z._default=[1,"div<div>","</div>"]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(R,""):null;if(typeof a!=="string"||X.test(a)||!d.support.leadingWhitespace&&S.test(a)||Z[(U.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(T,"<$1></$2>");try{for(var c=0,e=this.length;c<e;c++)this[c].nodeType===1&&(d.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(f){this.empty().append(a)}}return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(d.isFunction(a))return this.each(function(b){var c=d(this),e=c.html();c.replaceWith(a.call(this,b,e))});typeof a!=="string"&&(a=d(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;d(this).remove(),b?d(b).before(a):d(c).append(a)})}return this.length?this.pushStack(d(d.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,e){var f,g,h,i,j=a[0],k=[];if(!d.support.checkClone&&arguments.length===3&&typeof j==="string"&&Y.test(j))return this.each(function(){d(this).domManip(a,c,e,!0)});if(d.isFunction(j))return this.each(function(f){var g=d(this);a[0]=j.call(this,f,c?g.html():b),g.domManip(a,c,e)});if(this[0]){i=j&&j.parentNode,d.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?f={fragment:i}:f=d.buildFragment(a,this,k),h=f.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&d.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)e.call(c?$(this[l],g):this[l],f.cacheable||m>1&&l<n?d.clone(h,!0,!0):h)}k.length&&d.each(k,bc)}return this}}),d.buildFragment=function(a,b,e){var f,g,h,i=b&&b[0]?b[0].ownerDocument||b[0]:c;a.length===1&&typeof a[0]==="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!X.test(a[0])&&(d.support.checkClone||!Y.test(a[0]))&&(g=!0,h=d.fragments[a[0]],h&&(h!==1&&(f=h))),f||(f=i.createDocumentFragment(),d.clean(a,i,f,e)),g&&(d.fragments[a[0]]=h?f:1);return{fragment:f,cacheable:g}},d.fragments={},d.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){d.fn[a]=function(c){var e=[],f=d(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&f.length===1){f[b](this[0]);return this}for(var h=0,i=f.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){ba(a,e),f=bb(a),g=bb(e);for(h=0;f[h];++h)ba(f[h],g[h])}if(b){_(a,e);if(c){f=bb(a),g=bb(e);for(h=0;f[h];++h)_(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||W.test(i)){if(typeof i==="string"){i=i.replace(T,"<$1></$2>");var j=(U.exec(i)||["",""])[1].toLowerCase(),k=Z[j]||Z._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=V.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]==="<table>"&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&S.test(i)&&m.insertBefore(b.createTextNode(S.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bd=/alpha\([^)]*\)/i,be=/opacity=([^)]*)/,bf=/-([a-z])/ig,bg=/([A-Z]|^ms)/g,bh=/^-?\d+(?:px)?$/i,bi=/^-?\d/,bj={position:"absolute",visibility:"hidden",display:"block"},bk=["Left","Right"],bl=["Top","Bottom"],bm,bn,bo,bp=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bm(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bm)return bm(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bf,bp)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bq(a,b,e):d.swap(a,bj,function(){f=bq(a,b,e)});if(f<=0){f=bm(a,b,b),f==="0px"&&bo&&(f=bo(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bh.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return be.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bd.test(f)?f.replace(bd,e):c.filter+" "+e}}),d(function(){d.support.reliableMarginRight||(d.cssHooks.marginRight={get:function(a,b){var c;d.swap(a,{display:"inline-block"},function(){b?c=bm(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bn=function(a,c,e){var f,g,h;e=e.replace(bg,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bo=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bh.test(d)&&bi.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bm=bn||bo,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var br=/%20/g,bs=/\[\]$/,bt=/\r?\n/g,bu=/#.*$/,bv=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bw=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bx=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,by=/^(?:GET|HEAD)$/,bz=/^\/\//,bA=/\?/,bB=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bC=/^(?:select|textarea)/i,bD=/\s+/,bE=/([?&])_=[^&]*/,bF=/(^|\-)([a-z])/g,bG=function(a,b,c){return b+c.toUpperCase()},bH=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bI=d.fn.load,bJ={},bK={},bL,bM;try{bL=c.location.href}catch(bN){bL=c.createElement("a"),bL.href="",bL=bL.href}bM=bH.exec(bL.toLowerCase())||[],d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bI)return bI.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("<div>").append(c.replace(bB,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bC.test(this.nodeName)||bw.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(bt,"\r\n")}}):{name:b.name,value:c.replace(bt,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bL,isLocal:bx.test(bM[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bO(bJ),ajaxTransport:bO(bK),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bR(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bS(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bF,bG)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bv.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bu,"").replace(bz,bM[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bD),e.crossDomain==null&&(q=bH.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bM[1]||q[2]!=bM[2]||(q[3]||(q[1]==="http:"?80:443))!=(bM[3]||(bM[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bP(bJ,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!by.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(bA.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bE,"$1_="+w);e.url=x+(x===e.url?(bA.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bP(bK,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bQ(g,a[g],c,f);return e.join("&").replace(br,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bT=d.now(),bU=/(\=)\?(&|$)|\?\?/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bT++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bU.test(b.url)||f&&bU.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bU,l),b.url===j&&(f&&(k=k.replace(bU,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bV=d.now(),bW,bX;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bZ()||b$()}:bZ,bX=d.ajaxSettings.xhr(),d.support.ajax=!!bX,d.support.cors=bX&&"withCredentials"in bX,bX=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),!a.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bW[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bW||(bW={},bY()),h=bV++,g.onreadystatechange=bW[h]=c):c()},abort:function(){c&&c(0,1)}}}});var b_={},ca=/^(?:toggle|show|hide)$/,cb=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cc,cd=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(ce("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)e=this[g],f=e.style.display,!d._data(e,"olddisplay")&&f==="none"&&(f=e.style.display=""),f===""&&d.css(e,"display")==="none"&&d._data(e,"olddisplay",cf(e.nodeName));for(g=0;g<h;g++){e=this[g],f=e.style.display;if(f===""||f==="none")e.style.display=d._data(e,"olddisplay")||""}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ce("hide",3),a,b,c);for(var e=0,f=this.length;e<f;e++){var g=d.css(this[e],"display");g!=="none"&&!d._data(this[e],"olddisplay")&&d._data(this[e],"olddisplay",g)}for(e=0;e<f;e++)this[e].style.display="none";return this},_toggle:d.fn.toggle,toggle:function(a,b,c){var e=typeof a==="boolean";d.isFunction(a)&&d.isFunction(b)?this._toggle.apply(this,arguments):a==null||e?this.each(function(){var b=e?a:d(this).is(":hidden");d(this)[b?"show":"hide"]()}):this.animate(ce("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,e){var f=d.speed(b,c,e);if(d.isEmptyObject(a))return this.each(f.complete);return this[f.queue===!1?"each":"queue"](function(){var b=d.extend({},f),c,e=this.nodeType===1,g=e&&d(this).is(":hidden"),h=this;for(c in a){var i=d.camelCase(c);c!==i&&(a[i]=a[c],delete a[c],c=i);if(a[c]==="hide"&&g||a[c]==="show"&&!g)return b.complete.call(this);if(e&&(c==="height"||c==="width")){b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(d.css(this,"display")==="inline"&&d.css(this,"float")==="none")if(d.support.inlineBlockNeedsLayout){var j=cf(this.nodeName);j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)}else this.style.display="inline-block"}d.isArray(a[c])&&((b.specialEasing=b.specialEasing||{})[c]=a[c][1],a[c]=a[c][0])}b.overflow!=null&&(this.style.overflow="hidden"),b.curAnim=d.extend({},a),d.each(a,function(c,e){var f=new d.fx(h,b,c);if(ca.test(e))f[e==="toggle"?g?"show":"hide":e](a);else{var i=cb.exec(e),j=f.cur();if(i){var k=parseFloat(i[2]),l=i[3]||(d.cssNumber[c]?"":"px");l!=="px"&&(d.style(h,c,(k||1)+l),j=(k||1)/f.cur()*j,d.style(h,c,j+l)),i[1]&&(k=(i[1]==="-="?-1:1)*k+j),f.custom(j,k,l)}else f.custom(j,e,"")}});return!0})},stop:function(a,b){var c=d.timers;a&&this.queue([]),this.each(function(){for(var a=c.length-1;a>=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:ce("show",1),slideUp:ce("hide",1),slideToggle:ce("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!cc&&(cc=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||d.fx.stop()},interval:13,stop:function(){clearInterval(cc),cc=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){d.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),d.expr&&d.expr.filters&&(d.expr.filters.animated=function(a){return d.grep(d.timers,function(b){return a===b.elem}).length});var cg=/^t(?:able|d|h)$/i,ch=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?d.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,g=f.documentElement;if(!c||!d.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=f.body,i=ci(f),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||d.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||d.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:d.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);d.offset.initialize();var c,e=b.offsetParent,f=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(d.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===e&&(l+=b.offsetTop,m+=b.offsetLeft,d.offset.doesNotAddBorder&&(!d.offset.doesAddBorderForTableAndCells||!cg.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),f=e,e=b.offsetParent),d.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;d.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},d.offset={initialize:function(){var a=c.body,b=c.createElement("div"),e,f,g,h,i=parseFloat(d.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=(e==="absolute"||e==="fixed")&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=ch.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!ch.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=ci(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=ci(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window);
\ No newline at end of file
diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js
new file mode 100644 (file)
index 0000000..23169e0
--- /dev/null
@@ -0,0 +1,1403 @@
+/**\r
+ * Class and function collection for WCF\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ */\r
+\r
+/**\r
+ * Initialize WCF namespace\r
+ */\r
+var WCF = {};\r
+\r
+/**\r
+ * Extends jQuery with additional methods.\r
+ */\r
+$.extend(true, {\r
+       /**\r
+        * Escapes an ID to work with jQuery selectors.\r
+        *\r
+        * @see         http://docs.jquery.com/Frequently_Asked_Questions#How_do_I_select_an_element_by_an_ID_that_has_characters_used_in_CSS_notation.3F\r
+        * @param       string          id\r
+        * @return      string\r
+        */\r
+       wcfEscapeID: function(id) {\r
+               return id.replace(/(:|\.)/g, '\\$1');\r
+       },\r
+       \r
+       /**\r
+        * Returns true if given ID exists within DOM.\r
+        * \r
+        * @param       string          id\r
+        * @return      boolean\r
+        */\r
+       wcfIsset: function(id) {\r
+               return !!$('#' + $.wcfEscapeID(id)).length;\r
+       }\r
+});\r
+\r
+/**\r
+ * Extends jQuery's chainable methods.\r
+ */\r
+$.fn.extend({\r
+       /**\r
+        * Returns tag name of current jQuery element.\r
+        * \r
+        * @returns     string\r
+        */\r
+       getTagName: function() {\r
+               return this.get(0).tagName.toLowerCase();\r
+       },\r
+       \r
+       /**\r
+        * Returns the dimensions for current element.\r
+        * \r
+        * @see         http://api.jquery.com/hidden-selector/\r
+        * @param       string          type\r
+        * @return      object\r
+        */\r
+       getDimensions: function(type) {\r
+               var dimensions = css = {};\r
+               var wasHidden = false;\r
+               \r
+               // show element to retrieve dimensions and restore them later\r
+               if (this.is(':hidden')) {\r
+                       css = {\r
+                               display: this.css('display'),\r
+                               visibility: this.css('visibility')\r
+                       };\r
+                       \r
+                       wasHidden = true;\r
+                       \r
+                       this.css({\r
+                               display: 'block',\r
+                               visibility: 'hidden'\r
+                       });\r
+               }\r
+               \r
+               switch (type) {\r
+                       case 'inner':\r
+                               dimensions = {\r
+                                       height: this.innerHeight(),\r
+                                       width: this.innerWidth()\r
+                               };\r
+                       break;\r
+                       \r
+                       case 'outer':\r
+                               dimensions = {\r
+                                       height: this.outerHeight(),\r
+                                       width: this.innerWidth()\r
+                               };\r
+                       break;\r
+                       \r
+                       default:\r
+                               dimensions = {\r
+                                       height: this.height(),\r
+                                       width: this.width()\r
+                               };\r
+                       break;\r
+               }\r
+               \r
+               // restore previous settings\r
+               if (wasHidden) {\r
+                       this.css(css);\r
+               }\r
+               \r
+               return dimensions;\r
+       },\r
+       \r
+       /**\r
+        * Returns the offsets for current element, defaults to position\r
+        * relative to document.\r
+        * \r
+        * @see         http://api.jquery.com/hidden-selector/\r
+        * @param       string          type\r
+        * @return      object\r
+        */\r
+       getOffsets: function(type) {\r
+               var offsets = css = {};\r
+               var wasHidden = false;\r
+               \r
+               // show element to retrieve dimensions and restore them later\r
+               if (this.is(':hidden')) {\r
+                       css = {\r
+                               display: this.css('display'),\r
+                               visibility: this.css('visibility')\r
+                       };\r
+                       \r
+                       wasHidden = true;\r
+                       \r
+                       this.css({\r
+                               display: 'block',\r
+                               visibility: 'hidden'\r
+                       });\r
+               }\r
+               \r
+               switch (type) {\r
+                       case 'offset':\r
+                               offsets = this.offset();\r
+                       break;\r
+                       \r
+                       case 'position':\r
+                       default:\r
+                               offsets = this.position();\r
+                       break;\r
+               }\r
+               \r
+               // restore previous settings\r
+               if (wasHidden) {\r
+                       this.css(css);\r
+               }\r
+               \r
+               return offsets;\r
+       },\r
+       \r
+       /**\r
+        * Changes element's position to 'absolute' or 'fixed' while maintaining it's\r
+        * current position relative to viewport. Optionally removes element from\r
+        * current DOM-node and moving it into body-element (useful for drag & drop)\r
+        * \r
+        * @param       boolean         rebase\r
+        * @return      object\r
+        */\r
+       makePositioned: function(position, rebase) {\r
+               if (position != 'absolute' && position != 'fixed') {\r
+                       position = 'absolute';\r
+               }\r
+               \r
+               var $currentPosition = this.getOffsets('position');\r
+               this.css({\r
+                       position: position,\r
+                       left: $currentPosition.left,\r
+                       margin: 0,\r
+                       top: $currentPosition.top\r
+               });\r
+               \r
+               if (rebase) {\r
+                       this.remove().appentTo('body');\r
+               }\r
+               \r
+               return this;\r
+       },\r
+       \r
+       /**\r
+        * Disables a form element.\r
+        * \r
+        * @return jQuery\r
+        */\r
+       disable: function() {\r
+               return this.attr('disabled', 'disabled');\r
+       },\r
+       \r
+       /**\r
+        * Enables a form element.\r
+        * \r
+        * @return      jQuery\r
+        */\r
+       enable: function() {\r
+               return this.removeAttr('disabled');\r
+       },\r
+       \r
+       /**\r
+        * Applies a grow-effect by resizing element while moving the\r
+        * element appropriately\r
+        * \r
+        * @param       object          data\r
+        * @param       object          options\r
+        * @return      jQuery\r
+        */\r
+       wcfGrow: function(data, options) {\r
+               // create temporarily element to determine dimensions\r
+               var $tempElementID = WCF.getRandomID();\r
+               $('body').append('<div id="' + $tempElementID + '" class="wcfDimensions">' + data.content + '</div>');\r
+               var $tempElement = $('#' + $tempElementID);\r
+               \r
+               // get content dimensions\r
+               var $dimensions = $tempElement.getDimensions();\r
+               \r
+               // remove temporarily element\r
+               $tempElement.empty().remove();\r
+               \r
+               // move parent element, used if applying effect on dialogs\r
+               if (!data.parent) {\r
+                       data.parent = this;\r
+               }\r
+               \r
+               // calculate values for grow-effect\r
+               var $borderHeight = parseInt(data.parent.css('borderTopWidth')) + parseInt(data.parent.css('borderBottomWidth'));\r
+               var $borderWidth = parseInt(data.parent.css('borderLeftWidth')) + parseInt(data.parent.css('borderRightWidth'));\r
+               \r
+               var $windowDimensions = $(window).getDimensions();\r
+               var $leftOffset = Math.round(($windowDimensions.width - ($dimensions.width + $borderWidth)) / 2);\r
+               var $topOffset = Math.round(($windowDimensions.height - ($dimensions.height + $borderHeight)) / 2);\r
+               \r
+               data.parent.makePositioned('fixed', false);\r
+               data.parent.animate({\r
+                       left: $leftOffset + 'px',\r
+                       top: $topOffset + 'px'\r
+               }, options);\r
+               \r
+               return this.animate({\r
+                       height: $dimensions.height,\r
+                       width: $dimensions.width\r
+               }, options);\r
+       },\r
+       \r
+       /**\r
+        * Shows an element by sliding and fading it into viewport.\r
+        * \r
+        * @param       string          direction\r
+        * @param       object          callback\r
+        * @returns     jQuery\r
+        */\r
+       wcfDropIn: function(direction, callback) {\r
+               if (!direction) direction = 'up';\r
+               \r
+               return this.show(WCF.getEffect(this.getTagName(), 'drop'), { direction: direction }, 600, callback);\r
+       },\r
+       \r
+       /**\r
+        * Hides an element by sliding and fading it out the viewport.\r
+        * \r
+        * @param       string          direction\r
+        * @param       object          callback\r
+        * @returns     jQuery\r
+        */\r
+       wcfDropOut: function(direction, callback) {\r
+               if (!direction) direction = 'down';\r
+               \r
+               return this.hide(WCF.getEffect(this.getTagName(), 'drop'), { direction: direction }, 600, callback);\r
+       },\r
+       \r
+       /**\r
+        * Shows an element by blinding it up.\r
+        * \r
+        * @param       string          direction\r
+        * @param       object          callback\r
+        * @returns     jQuery\r
+        */\r
+       wcfBlindIn: function(direction, callback) {\r
+               if (!direction) direction = 'vertical';\r
+               \r
+               return this.show(WCF.getEffect(this.getTagName(), 'blind'), { direction: direction }, 200, callback);\r
+       },\r
+       \r
+       /**\r
+        * Hides an element by blinding it down.\r
+        * \r
+        * @param       string          direction\r
+        * @param       object          callback\r
+        * @returns     jQuery\r
+        */\r
+       wcfBlindOut: function(direction, callback) {\r
+               if (!direction) direction = 'vertical';\r
+               \r
+               return this.hide(WCF.getEffect(this.getTagName(), 'blind'), { direction: direction }, 200, callback);\r
+       },\r
+       \r
+       /**\r
+        * Highlights an element.\r
+        * \r
+        * @param       object          options\r
+        * @param       object          callback\r
+        * @returns     jQuery\r
+        */\r
+       wcfHighlight: function(options, callback) {\r
+               return this.effect('highlight', options, 600, callback);\r
+       }\r
+});\r
+\r
+/**\r
+ * WoltLab Community Framework core methods\r
+ */\r
+$.extend(WCF, {\r
+       /**\r
+        * Counter for dynamic element id's\r
+        *\r
+        * @var integer\r
+        */\r
+       _idCounter: 0,\r
+       \r
+       /**\r
+        * Shows a modal dialog with a built-in AJAX-loader.\r
+        * \r
+        * @param       string          dialogID\r
+        * @param       boolean         resetDialog\r
+        */\r
+       showAJAXDialog: function(dialogID, resetDialog) {\r
+               if (!dialogID) {\r
+                       dialogID = this.getRandomID();\r
+               }\r
+               \r
+               if (!$.wcfIsset(dialogID)) {\r
+                       $('body').append($('<div id="' + dialogID + '"></div>'));\r
+               }\r
+               \r
+               var dialog = $('#' + $.wcfEscapeID(dialogID));\r
+               \r
+               if (resetDialog) {\r
+                       dialog.empty();\r
+               }\r
+               \r
+               dialog.addClass('overlayLoading');\r
+               \r
+               var dialogOptions = arguments[2] || {};\r
+               dialog.wcfAJAXDialog(dialogOptions);\r
+       },\r
+       \r
+       /**\r
+        * Shows a modal dialog.\r
+        * @param       string          dialogID\r
+        */\r
+       showDialog: function(dialogID) {\r
+               // we cannot work with a non-existant dialog, if you wish to\r
+               // load content via AJAX, see showAJAXDialog() instead\r
+               if (!$.wcfIsset(dialogID)) return;\r
+               \r
+               var $dialog = $('#' + $.wcfEscapeID(dialogID));\r
+               \r
+               var dialogOptions = arguments[2] || {};\r
+               $dialog.wcfDialog(dialogOptions);\r
+       },\r
+       \r
+       /**\r
+        * Returns a dynamically created id.\r
+        * \r
+        * @see         https://github.com/sstephenson/prototype/blob/master/src/prototype/dom/dom.js#L1789\r
+        * @return      string\r
+        */\r
+       getRandomID: function() {\r
+               var $elementID = '';\r
+               \r
+               do {\r
+                       $elementID = 'wcf' + this._idCounter++;  \r
+               }\r
+               while ($.wcfIsset($elementID));\r
+               \r
+               return $elementID;\r
+       },\r
+       \r
+       /**\r
+        * Wrapper for $.inArray which returns boolean value instead of\r
+        * index value, similar to PHP's in_array().\r
+        * \r
+        * @param       mixed           needle\r
+        * @param       array           haystack\r
+        * @return      boolean\r
+        */\r
+       inArray: function(needle, haystack) {\r
+               return ($.inArray(needle, haystack) != -1);\r
+       },\r
+       \r
+       /**\r
+        * Adjusts effect for partially supported elements.\r
+        * \r
+        * @param       object          object\r
+        * @param       string          effect\r
+        * @return      string\r
+        */\r
+       getEffect: function(tagName, effect) {\r
+               // most effects are not properly supported on table rows, use highlight instead\r
+               if (tagName == 'tr') {\r
+                       return 'highlight';\r
+               }\r
+               \r
+               return effect;\r
+       }\r
+});\r
+\r
+/**\r
+ * Provides a simple call for periodical executed functions. Based upon\r
+ * ideas by Prototype's PeriodicalExecuter.\r
+ * \r
+ * @see                https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/periodical_executer.js\r
+ * @param      function                callback\r
+ * @param      integer                 delay\r
+ */\r
+WCF.PeriodicalExecuter = function(callback, delay) { this.init(callback, delay); };\r
+WCF.PeriodicalExecuter.prototype = {\r
+       /**\r
+        * Initializes a periodical executer.\r
+        * \r
+        * @param       function                callback\r
+        * @param       integer                 delay\r
+        */\r
+       init: function(callback, delay) {\r
+               this.callback = callback;\r
+               this.delay = delay;\r
+               this.loop = true;\r
+               \r
+               this.intervalID = setInterval($.proxy(this._execute, this), this.delay);\r
+       },\r
+       \r
+       /**\r
+        * Executes callback.\r
+        */\r
+       _execute: function() {\r
+               this.callback(this);\r
+               \r
+               if (!this.loop) {\r
+                       clearInterval(this.intervalID);\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Terminates loop.\r
+        */\r
+       stop: function() {\r
+               this.loop = false;\r
+       }\r
+};\r
+\r
+/**\r
+ * Namespace for AJAXProxies\r
+ */\r
+WCF.Action = {};\r
+\r
+/**\r
+ * Basic implementation for AJAX-based proxyies\r
+ * \r
+ * @param      object          options\r
+ */\r
+WCF.Action.Proxy = function(options) { this.init(options); };\r
+WCF.Action.Proxy.prototype = {\r
+       /**\r
+        * Initializes AJAXProxy.\r
+        * \r
+        * @param       object          options\r
+        */\r
+       init: function(options) {\r
+               // initialize default values\r
+               this.options = $.extend(true, {\r
+                       autoSend: false,\r
+                       data: { },\r
+                       after: null,\r
+                       init: null,\r
+                       failure: null,\r
+                       success: null,\r
+                       type: 'POST',\r
+                       url: 'index.php?action=AJAXProxy&t=' + SECURITY_TOKEN + SID_ARG_2ND\r
+               }, options);\r
+               \r
+               this.confirmationDialog = null;\r
+               this.loading = null;\r
+               \r
+               // send request immediately after initialization\r
+               if (this.options.autoSend) {\r
+                       this.sendRequest();\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Sends an AJAX request.\r
+        */\r
+       sendRequest: function() {\r
+               this._init();\r
+               \r
+               $.ajax({\r
+                       data: this.options.data,\r
+                       dataType: 'json',\r
+                       type: this.options.type,\r
+                       url: this.options.url,\r
+                       success: $.proxy(this._success, this),\r
+                       error: $.proxy(this._failure, this)\r
+               });\r
+       },\r
+       \r
+       /**\r
+        * Fires before request is send, displays global loading status.\r
+        */\r
+       _init: function() {\r
+               if ($.isFunction(this.options.init)) {\r
+                       this.options.init();\r
+               }\r
+               \r
+               $('<div id="actionProxyLoading" style="display: none;">Loading …</div>').appendTo($('body'));\r
+               this.loading = $('#actionProxyLoading');\r
+               this.loading.wcfDropIn();\r
+       },\r
+       \r
+       /**\r
+        * Handles AJAX errors.\r
+        * \r
+        * @param       object          jqXHR\r
+        * @param       string          textStatus\r
+        * @param       string          errorThrown\r
+        */\r
+       _failure: function(jqXHR, textStatus, errorThrown) {\r
+               try {\r
+                       var data = $.parseJSON(jqXHR.responseText);\r
+                       \r
+                       // call child method if applicable\r
+                       if ($.isFunction(this.options.failure)) {\r
+                               this.options.failure(jqXHR, textStatus, errorThrown, data);\r
+                       }\r
+                       \r
+                       var $randomID = WCF.getRandomID();\r
+                       $('<div id="' + $randomID + '" title="HTTP/1.0 ' + jqXHR.status + ' ' + errorThrown + '"><p>Der Server antwortete: ' + data.message + '.</p></div>').wcfDialog();\r
+               }\r
+               // failed to parse JSON\r
+               catch (e) {\r
+                       var $randomID = WCF.getRandomID();\r
+                       $('<div id="' + $randomID + '" title="HTTP/1.0 ' + jqXHR.status + ' ' + errorThrown + '"><p>Der Server antwortete: ' + jqXHR.responseText + '.</p></div>').wcfDialog();\r
+               }\r
+               \r
+               this._after();\r
+       },\r
+       \r
+       /**\r
+        * Handles successful AJAX requests.\r
+        * \r
+        * @param       object          data\r
+        * @param       string          textStatus\r
+        * @param       object          jqXHR\r
+        */\r
+       _success: function(data, textStatus, jqXHR) {\r
+               // call child method if applicable\r
+               if ($.isFunction(this.options.success)) {\r
+                       this.options.success(data, textStatus, jqXHR);\r
+               }\r
+               \r
+               this._after();\r
+       },\r
+       \r
+       /**\r
+        * Fires after an AJAX request, hides global loading status.\r
+        */\r
+       _after: function() {\r
+               if ($.isFunction(this.options.after)) {\r
+                       this.options.after();\r
+               }\r
+               \r
+               this.loading.wcfDropOut('up');\r
+       },\r
+       \r
+       /**\r
+        * Sets options, MUST be used to set parameters before sending request\r
+        * if calling from child classes.\r
+        * \r
+        * @param       string          optionName\r
+        * @param       mixed           optionData\r
+        */\r
+       setOption: function(optionName, optionData) {\r
+               this.options[optionName] = optionData;\r
+       }\r
+};\r
+\r
+/**\r
+ * Basic implementation for simple proxy access using bound elements.\r
+ * \r
+ * @param      object          options\r
+ * @param      object          callbacks\r
+ */\r
+WCF.Action.SimpleProxy = function(options, callbacks) { this.init(options, callbacks); };\r
+WCF.Action.SimpleProxy.prototype = {\r
+       /**\r
+        * Initializes SimpleProxy.\r
+        * \r
+        * @param       object          options\r
+        * @param       object          callbacks\r
+        */\r
+       init: function(options, callbacks) {\r
+               /**\r
+                * action-specific options\r
+                */\r
+               this.options = $.extend(true, {\r
+                       action: '',\r
+                       className: '',\r
+                       elements: null,\r
+                       eventName: 'click'\r
+               }, options);\r
+               \r
+               /**\r
+                * proxy-specific options\r
+                */\r
+               this.callbacks = $.extend(true, {\r
+                       after: null,\r
+                       failure: null,\r
+                       init: null,\r
+                       success: null\r
+               }, callbacks);\r
+               \r
+               if (!this.options.elements) return;\r
+               \r
+               // initialize proxy\r
+               this.proxy = new WCF.Action.Proxy(this.callbacks);\r
+               \r
+               // bind event listener\r
+               this.options.elements.each($.proxy(function(index, element) {\r
+                       $(element).bind(this.options.eventName, $.proxy(this._handleEvent, this));\r
+               }, this));\r
+       },\r
+       \r
+       /**\r
+        * Handles event actions.\r
+        * \r
+        * @param       object          event\r
+        */\r
+       _handleEvent: function(event) {\r
+               this.proxy.setOption('data', {\r
+                       actionName: this.options.action,\r
+                       className: this.options.className,\r
+                       objectIDs: [ $(event.target).data('objectID') ]\r
+               });\r
+               \r
+               this.proxy.sendRequest();\r
+       }\r
+};\r
+\r
+/**\r
+ * Basic implementation for AJAXProxy-based deletion.\r
+ * \r
+ * @param      string          className\r
+ * @param      jQuery          containerList\r
+ */\r
+WCF.Action.Delete = function(className, containerList) { this.init(className, containerList); };\r
+WCF.Action.Delete.prototype = {\r
+       /**\r
+        * Initializes 'delete'-Proxy.\r
+        * \r
+        * @param       string          className\r
+        * @param       jQuery          containerList\r
+        */\r
+       init: function(className, containerList) {\r
+               if (!containerList.length) return;\r
+               this.containerList = containerList;\r
+               this.className = className;\r
+               \r
+               // initialize proxy\r
+               var options = {\r
+                       success: $.proxy(this._success, this)\r
+               };\r
+               this.proxy = new WCF.Action.Proxy(options);\r
+               \r
+               // bind event listener\r
+               this.containerList.each($.proxy(function(index, container) {\r
+                       $(container).find('.deleteButton').bind('click', $.proxy(this._click, this));\r
+               }, this));\r
+       },\r
+       \r
+       /**\r
+        * Sends AJAX request.\r
+        * \r
+        * @param       object          event\r
+        */\r
+       _click: function(event) {\r
+               var $target = $(event.target);\r
+               \r
+               if ($target.data('confirmMessage')) {\r
+                       if (confirm($target.data('confirmMessage'))) {\r
+                               this._sendRequest($target);\r
+                       }\r
+               }\r
+               else {\r
+                       this._sendRequest($target);\r
+               }\r
+               \r
+       },\r
+       \r
+       _sendRequest: function(object) {\r
+               this.proxy.setOption('data', {\r
+                       actionName: 'delete',\r
+                       className: this.className,\r
+                       objectIDs: [ $(object).data('objectID') ]\r
+               });\r
+               \r
+               this.proxy.sendRequest();\r
+       },\r
+       \r
+       /**\r
+        * Deletes items from containers.\r
+        * \r
+        * @param       object          data\r
+        * @param       string          textStatus\r
+        * @param       object          jqXHR\r
+        */\r
+       _success: function(data, textStatus, jqXHR) {\r
+               // remove items\r
+               this.containerList.each(function(index, container) {\r
+                       var $objectID = $(container).find('.deleteButton').data('objectID');\r
+                       if (WCF.inArray($objectID, data.objectIDs)) {\r
+                               $(container).wcfBlindOut('up', function() {\r
+                                       $(container).empty().remove();\r
+                               }, container);\r
+                       }\r
+               });\r
+       }\r
+};\r
+\r
+/**\r
+ * Basic implementation for AJAXProxy-based toggle actions.\r
+ * \r
+ * @param      string          className\r
+ * @param      jQuery          containerList\r
+ */\r
+WCF.Action.Toggle = function(className, containerList) { this.init(className, containerList); };\r
+WCF.Action.Toggle.prototype = {\r
+       /**\r
+        * Initializes 'toggle'-Proxy\r
+        * \r
+        * @param       string          className\r
+        * @param       jQuery          containerList\r
+        */\r
+       init: function(className, containerList) {\r
+               if (!containerList.length) return;\r
+               this.containerList = containerList;\r
+               this.className = className;\r
+               \r
+               // initialize proxy\r
+               var options = {\r
+                       success: $.proxy(this._success, this)\r
+               };\r
+               this.proxy = new WCF.Action.Proxy(options);\r
+               \r
+               // bind event listener\r
+               this.containerList.each($.proxy(function(index, container) {\r
+                       $(container).find('.toggleButton').bind('click', $.proxy(this._click, this));\r
+               }, this));\r
+       },\r
+       \r
+       /**\r
+        * Sends AJAX request.\r
+        * \r
+        * @param       object          event\r
+        */\r
+       _click: function(event) {\r
+               this.proxy.setOption('data', {\r
+                       actionName: 'toggle',\r
+                       className: this.className,\r
+                       objectIDs: [ $(event.target).data('objectID') ]\r
+               });\r
+               \r
+               this.proxy.sendRequest();\r
+       },\r
+       \r
+       /**\r
+        * Toggles status icons.\r
+        * \r
+        * @param       object          data\r
+        * @param       string          textStatus\r
+        * @param       object          jqXHR\r
+        */\r
+       _success: function(data, textStatus, jqXHR) {\r
+               // remove items\r
+               this.containerList.each(function(index, container) {\r
+                       var $toggleButton = $(container).find('.toggleButton');\r
+                       if (WCF.inArray($toggleButton.data('objectID'), data.objectIDs)) {\r
+                               $(container).wcfHighlight();\r
+                               \r
+                               // toggle icon source\r
+                               $toggleButton.attr('src', function() {\r
+                                       if (this.src.match(/enabled(S|M|L)\.png$/)) {\r
+                                               return this.src.replace(/enabled(S|M|L)\.png$/, 'disabled$1\.png');\r
+                                       }\r
+                                       else {\r
+                                               return this.src.replace(/disabled(S|M|L)\.png$/, 'enabled$1\.png');\r
+                                       }\r
+                               });\r
+                               // toogle icon title\r
+                               $toggleButton.attr('title', function() {\r
+                                       if (this.src.match(/enabled(S|M|L)\.png$/)) {\r
+                                               return $(this).data('disableMessage');\r
+                                       }\r
+                                       else {\r
+                                               return $(this).data('enableMessage');\r
+                                       }\r
+                               });\r
+                       }\r
+               });\r
+       }\r
+};\r
+\r
+/**\r
+ * Namespace for date-related functions.\r
+ */\r
+WCF.Date = {};\r
+\r
+/**\r
+ * Provides utility functions for date operations.\r
+ */\r
+WCF.Date.Util = {\r
+       /**\r
+        * Returns UTC timestamp, if date is not given, current time will be used.\r
+        * \r
+        * @param       Date            date\r
+        * @return      integer\r
+        */\r
+       gmdate: function(date) {\r
+               var $date = (date) ? date : new Date();\r
+               \r
+               return Math.round(Date.UTC(\r
+                       $date.getUTCFullYear(),\r
+                       $date.getUTCMonth(),\r
+                       $date.getUTCDay(),\r
+                       $date.getUTCHours(),\r
+                       $date.getUTCMinutes(),\r
+                       $date.getUTCSeconds()\r
+               ) / 1000);\r
+       },\r
+       \r
+       /**\r
+        * Returns a Date object with precise offset (including timezone and local timezone).\r
+        * Parameter timestamp must be in miliseconds!\r
+        * \r
+        * @param       integer         timestamp\r
+        * @param       integer         offset\r
+        * @return      Date\r
+        */\r
+       getTimezoneDate: function(timestamp, offset) {\r
+               var $date = new Date(timestamp);\r
+               var $localOffset = $date.getTimezoneOffset() * -1 * 60000;\r
+               \r
+               return new Date((timestamp - $localOffset - offset));\r
+       }\r
+};\r
+\r
+/**\r
+ * Handles relative time designations.\r
+ */\r
+WCF.Date.Time = function() { this.init(); };\r
+WCF.Date.Time.prototype = {\r
+       /**\r
+        * Initializes relative datetimes.\r
+        */\r
+       init: function() {\r
+               // initialize variables\r
+               this.elements = $('time.datetime');\r
+               this.timestamp = 0;\r
+               \r
+               // calculate relative datetime on init\r
+               this._refresh();\r
+               \r
+               // re-calculate relative datetime every minute\r
+               new WCF.PeriodicalExecuter($.proxy(this._refresh, this), 60000);\r
+       },\r
+       \r
+       /**\r
+        * Refreshes relative datetime for each element.\r
+        */\r
+       _refresh: function() {\r
+               // TESTING ONLY!\r
+               var $date = new Date();\r
+               this.timestamp = ($date.getTime() - $date.getMilliseconds()) / 1000;\r
+               // TESTING ONLY!\r
+               \r
+               this.elements.each($.proxy(this._refreshElement, this));\r
+       },\r
+       \r
+       /**\r
+        * Refreshes relative datetime for current element.\r
+        * \r
+        * @param       integer         index\r
+        * @param       object          element\r
+        */\r
+       _refreshElement: function(index, element) {\r
+               if (!$(element).attr('title')) {\r
+                       $(element).attr('title', $(element).text());\r
+               }\r
+               \r
+               var $timestamp = $(element).data('timestamp');\r
+               var $date = $(element).data('date');\r
+               var $time = $(element).data('time');\r
+               var $offset = $(element).data('offset');\r
+               \r
+               // timestamp is less than 60 minutes ago (display 1 hour ago rather than 60 minutes ago)\r
+               if (this.timestamp < ($timestamp + 3540)) {\r
+                       var $minutes = Math.round((this.timestamp - $timestamp) / 60);\r
+                       $(element).text(eval(WCF.Language.get('wcf.global.date.relative.minutes')));\r
+               }\r
+               // timestamp is less than 24 hours ago\r
+               else if (this.timestamp < ($timestamp + 86400)) {\r
+                       var $hours = Math.round((this.timestamp - $timestamp) / 3600);\r
+                       $(element).text(eval(WCF.Language.get('wcf.global.date.relative.hours')));\r
+               }\r
+               // timestamp is less than a week ago\r
+               else if (this.timestamp < ($timestamp + 604800)) {\r
+                       var $days = Math.round((this.timestamp - $timestamp) / 86400);\r
+                       var $string = eval(WCF.Language.get('wcf.global.date.relative.pastDays'));\r
+               \r
+                       // get day of week\r
+                       var $dateObj = WCF.Date.Util.getTimezoneDate(($timestamp * 1000), $offset);\r
+                       var $dow = $dateObj.getDay();\r
+                       \r
+                       $(element).text($string.replace(/\%day\%/, WCF.Language.get('__days')[$dow]).replace(/\%time\%/, $time));\r
+               }\r
+               // timestamp is between ~700 million years BC and last week\r
+               else {\r
+                       var $string = WCF.Language.get('wcf.global.date.dateTimeFormat');\r
+                       $(element).text($string.replace(/\%date\%/, $date).replace(/\%time\%/, $time));\r
+               }\r
+       }\r
+};\r
+\r
+/**\r
+ * Hash-like dictionary. Based upon idead from Prototype's hash\r
+ * \r
+ * @see        https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/hash.js\r
+ */\r
+WCF.Dictionary = function() { this.init(); };\r
+WCF.Dictionary.prototype = {\r
+       /**\r
+        * Initializes a new dictionary.\r
+        */\r
+       init: function() {\r
+               this.variables = { };\r
+       },\r
+       \r
+       /**\r
+        * Adds an entry.\r
+        * \r
+        * @param       string          key\r
+        * @param       mixed           value\r
+        */\r
+       add: function(key, value) {\r
+               this.variables[key] = value;\r
+       },\r
+       \r
+       /**\r
+        * Adds a traditional object to current dataset.\r
+        * \r
+        * @param       object          object\r
+        */\r
+       addObject: function(object) {\r
+               for (var $key in object) {\r
+                       this.add($key, object[$key]);\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Adds a dictionary to current dataset.\r
+        * \r
+        * @param       object          dictionary\r
+        */\r
+       addDictionary: function(dictionary) {\r
+               dictionary.each($.proxy(function(pair) {\r
+                       this.add(pair.key, pair.value);\r
+               }, this));\r
+       },\r
+       \r
+       /**\r
+        * Retrieves the value of an entry or returns null if key is not found.\r
+        * \r
+        * @param       string          key\r
+        * @returns     mixed\r
+        */\r
+       get: function(key) {\r
+               if (this.isset(key)) {\r
+                       return this.variables[key];\r
+               }\r
+               \r
+               return null;\r
+       },\r
+       \r
+       /**\r
+        * Returns true if given key is a valid entry.\r
+        * \r
+        * @param       string          key\r
+        */\r
+       isset: function(key) {\r
+               return this.variables.hasOwnProperty(key);\r
+       },\r
+       \r
+       /**\r
+        * Removes an entry.\r
+        * \r
+        * @param       string          key\r
+        */\r
+       remove: function(key) {\r
+               delete this.variables[key];\r
+       },\r
+       \r
+       /**\r
+        * Iterates through dictionary.\r
+        * \r
+        * Usage:\r
+        *      var $hash = new WCF.Dictionary();\r
+        *      $hash.add('foo', 'bar');\r
+        *      $hash.each(function(pair) {\r
+        *              // alerts:      foo = bar\r
+        *              alert(pair.key + ' = ' + pair.value);\r
+        *      });\r
+        * \r
+        * @param       function        callback\r
+        */\r
+       each: function(callback) {\r
+               if (!$.isFunction(callback)) {\r
+                       return;\r
+               }\r
+               \r
+               for (var $key in this.variables) {\r
+                       var $value = this.variables[$key];\r
+                       var $pair = {\r
+                               key: $key,\r
+                               value: $value\r
+                       };\r
+                       \r
+                       callback($pair);\r
+               }\r
+       }\r
+};\r
+\r
+/**\r
+ * Global language storage.\r
+ * \r
+ * @see        WCF.Dictionary\r
+ */\r
+WCF.Language = {\r
+       _variables: new WCF.Dictionary(),\r
+       \r
+       /**\r
+        * @see WCF.Dictionary.addObject()\r
+        */\r
+       add: function(key, value) {\r
+               this._variables.add(key, value);\r
+       },\r
+       \r
+       /**\r
+        * @see WCF.Dictionary.addObject()\r
+        */\r
+       addObject: function(object) {\r
+               this._variables.addObject(object);\r
+       },\r
+       \r
+       /**\r
+        * Retrieves a variable.\r
+        * \r
+        * @param       string          key\r
+        * @return      mixed\r
+        */\r
+       get: function(key) {\r
+               return this._variables.get(key);\r
+       }\r
+};\r
+\r
+/**\r
+ * String utilities.\r
+ */\r
+WCF.String = {\r
+       /**\r
+        * Makes a string's first character uppercase\r
+        * \r
+        * @param       string          string\r
+        * @return      string\r
+        */\r
+       ucfirst: function(string) {\r
+               return string.substring(0, 1).toUpperCase() + string.substring(1);\r
+       }\r
+};\r
+\r
+/**\r
+ * Basic implementation for WCF TabMenus. Use the data attributes 'active' to specify the\r
+ * tab which should be shown on init. Furthermore you may specify a 'store' data-attribute\r
+ * which will be filled with the currently selected tab.\r
+ */\r
+WCF.TabMenu = {\r
+       /**\r
+        * Initializes all TabMenus\r
+        */\r
+       init: function() {\r
+               $('.tabMenuContainer').each(function(index, tabMenu) {\r
+                       if (!$(tabMenu).attr('id')) {\r
+                               var $randomID = WCF.getRandomID();\r
+                               $(tabMenu).attr('id', $randomID);\r
+                       }\r
+                       \r
+                       // init jQuery UI TabMenu\r
+                       $(tabMenu).wcfTabs({\r
+                               select: function(event, ui) {\r
+                                       var $panel = $(ui.panel);\r
+                                       var $container = $panel.closest('.tabMenuContainer');\r
+                                       \r
+                                       // store currently selected item\r
+                                       if ($container.data('store')) {\r
+                                               if ($.wcfIsset($container.data('store'))) {\r
+                                                       $('#' + $container.data('store')).attr('value', $panel.attr('id'));\r
+                                               }\r
+                                       }\r
+                               }\r
+                       });\r
+                       \r
+                       // display active item on init\r
+                       if ($(tabMenu).data('active')) {\r
+                               $(tabMenu).find('.tabMenuContent').each(function(index, tabMenuItem) {\r
+                                       if ($(tabMenuItem).attr('id') == $(tabMenu).data('active')) {\r
+                                               $(tabMenu).wcfTabs('select', index);\r
+                                       }\r
+                               });\r
+                       }\r
+               });\r
+       }\r
+};\r
+\r
+/**\r
+ * Toggles options.\r
+ * \r
+ * @param      string          element\r
+ * @param      array           showItems\r
+ * @param      array           hideItems\r
+ */\r
+WCF.ToggleOptions = function(element, showItems, hideItems) { this.init(element, showItems, hideItems); };\r
+WCF.ToggleOptions.prototype = {\r
+       /**\r
+        * target item\r
+        * \r
+        * @var jQuery\r
+        */\r
+       _element: null,\r
+       \r
+       /**\r
+        * list of items to be shown\r
+        * \r
+        * @var array\r
+        */\r
+       _showItems: [],\r
+       \r
+       /**\r
+        * list of items to be hidden\r
+        * \r
+        * @var array\r
+        */\r
+       _hideItems: [],\r
+       \r
+       /**\r
+        * Initializes option toggle.\r
+        * \r
+        * @param       string          element\r
+        * @param       array           showItems\r
+        * @param       array           hideItems\r
+        */\r
+       init: function(element, showItems, hideItems) {\r
+               this._element = $('#' + element);\r
+               this._showItems = showItems;\r
+               this._hideItems = hideItems;\r
+               \r
+               // bind event\r
+               this._element.click($.proxy(this._toggle, this));\r
+               \r
+               // execute toggle on init\r
+               this._toggle();\r
+       },\r
+       \r
+       /**\r
+        * Toggles items.\r
+        */\r
+       _toggle: function() {\r
+               if (!this._element.attr('checked')) return;\r
+               \r
+               for (var $i = 0, $length = this._showItems.length; $i < $length; $i++) {\r
+                       var $item = this._showItems[$i];\r
+                       \r
+                       $('#' + $item).show();\r
+               }\r
+               \r
+               for (var $i = 0, $length = this._hideItems.length; $i < $length; $i++) {\r
+                       var $item = this._hideItems[$i];\r
+                       \r
+                       $('#' + $item).hide();\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * Basic implementation for WCF dialogs.\r
+ */\r
+$.widget('ui.wcfDialog', $.ui.dialog, {\r
+       _init: function() {\r
+               this.options.autoOpen = true;\r
+               this.options.close = function(event, ui) {\r
+                       $(this).parent('.ui-dialog').wcfDropOut('down', $.proxy(function() {\r
+                               $(this).parent('.ui-dialog').empty().remove();\r
+                       }, this));\r
+               };\r
+               this.options.height = 'auto';\r
+               this.options.minHeight = 0;\r
+               this.options.modal = true;\r
+               this.options.width = 'auto';\r
+               \r
+               $.ui.dialog.prototype._init.apply(this, arguments);\r
+       }\r
+});\r
+\r
+/**\r
+ * Basic implementation for WCF dialogs loading content\r
+ * via AJAX before calling dialog itself.\r
+ */\r
+$.widget('ui.wcfAJAXDialog', $.ui.dialog, {\r
+       /**\r
+        * Indicates wether callback was already executed\r
+        * \r
+        * @var boolean\r
+        */\r
+       _callbackExecuted: false,\r
+       \r
+       /**\r
+        * Initializes AJAX-request to fetch content.\r
+        */\r
+       _init: function() {\r
+               if (this.options.ajax) {\r
+                       this._loadContent();\r
+               }\r
+               \r
+               // force dialog to be placed centered\r
+               this.options.position = {\r
+                       my: 'center center',\r
+                       at: 'center center'\r
+               };\r
+               \r
+               // dialog should display a spinner-like image, thus immediately fire up dialog\r
+               this.options.autoOpen = true;\r
+               this.options.width = 'auto';\r
+               this.options.minHeight = 80;\r
+               \r
+               // disable ability to move dialog\r
+               this.options.resizable = false;\r
+               this.options.draggable = false;\r
+               \r
+               this.options.modal = true;\r
+               this.options.hide = {\r
+                       effect: 'drop',\r
+                       direction: 'down'\r
+               };\r
+               \r
+               this.options.close = function(event, ui) {\r
+                       // loading ajax content seems to block properly closing\r
+                       $(this).parent('.ui-dialog').empty().remove();\r
+               };\r
+               \r
+               if (this.options.preventClose) {\r
+                       this.options.closeOnEscape = false;\r
+               }\r
+               \r
+               $.ui.dialog.prototype._init.apply(this, arguments);\r
+               \r
+               // remove complete node instead of removing node-by-node\r
+               if (this.options.hideTitle && this.options.preventClose) {\r
+                       this.element.parent('.ui-dialog').find('div.ui-dialog-titlebar').empty().remove();\r
+               }\r
+               else {\r
+                       if (this.options.hideTitle) {\r
+                               // remove title element\r
+                               $('#ui-dialog-title-' + this.element.attr('id')).empty().remove();\r
+                       }\r
+                       \r
+                       if (this.options.preventClose) {\r
+                               // remove close-button\r
+                               this.element.parent('.ui-dialog').find('a.ui-dialog-titlebar-close').empty().remove();\r
+                       }\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Loads content via AJAX.\r
+        * \r
+        * @todo        Enforce JSON\r
+        */\r
+       _loadContent: function() {\r
+               var $type = 'GET';\r
+               if (this.options.ajax.type) {\r
+                       $type = this.options.ajax.type;\r
+                       \r
+                       if (this.options.ajax.type != 'GET' && this.options.ajax.type != 'POST') {\r
+                               $type = 'GET';\r
+                       }\r
+               }\r
+               \r
+               var $data = this.options.ajax.data || {};\r
+               \r
+               $.ajax({\r
+                       url: this.options.ajax.url,\r
+                       context: this,\r
+                       dataType: 'json',\r
+                       type: $type,\r
+                       data: $data,\r
+                       success: $.proxy(this._createDialog, this),\r
+                       error: function(transport) {\r
+                               alert(transport.responseText);\r
+                       }\r
+               });\r
+       },\r
+       \r
+       /**\r
+        * Inserts content.\r
+        * \r
+        * @param       string          data\r
+        */\r
+       _createDialog: function(data) {\r
+               data.ignoreTemplate = true;\r
+               this.element.data('responseData', data);\r
+               \r
+               this.element.wcfGrow({\r
+                       content: data.template,\r
+                       parent: this.element.parent('.ui-dialog')\r
+               }, {\r
+                       duration: 600,\r
+                       complete: $.proxy(function(data) {\r
+                               this.element.css({\r
+                                       height: 'auto'\r
+                               });\r
+                               \r
+                               // prevent double execution due to two complete-calls (two times animate)\r
+                               if (this._callbackExecuted) {\r
+                                       return;\r
+                               }\r
+                               \r
+                               this._callbackExecuted = true;\r
+                               \r
+                               this.element.removeClass('overlayLoading');\r
+                               this.element.html(this.element.data('responseData').template);\r
+                               \r
+                               if (this.options.ajax.success) {\r
+                                       this.options.ajax.success();\r
+                               }\r
+                       }, this)\r
+               });\r
+       },\r
+       \r
+       /**\r
+        * Redraws dialog, should be executed everytime content is changed.\r
+        */\r
+       redraw: function() {\r
+               var $dimensions = this.element.getDimensions();\r
+               \r
+               if ($dimensions.height > 200) {\r
+                       this.element.wcfGrow({\r
+                               content: this.element.html(),\r
+                               parent: this.element.parent('.ui-dialog')\r
+                       }, {\r
+                               duration: 600,\r
+                               complete: function() {\r
+                                       $(this).css({ height: 'auto' });\r
+                               }\r
+                       });\r
+               }\r
+       }\r
+});\r
+\r
+/**\r
+ * Workaround for ids containing a dot ".", until jQuery UI devs learn\r
+ * to properly escape ids ... (it took 18 months until they finally\r
+ * fixed it!)\r
+ * \r
+ * @see        http://bugs.jqueryui.com/ticket/4681\r
+ */\r
+$.widget('ui.wcfTabs', $.ui.tabs, {\r
+       _init: function() {\r
+               $.ui.dialog.prototype._init.apply(this, arguments);\r
+       },\r
+       \r
+       _sanitizeSelector: function(hash) {\r
+               return hash.replace(/([:\.])/g, '\\$1');\r
+       }\r
+});\r
+\r
+/**\r
+ * Encapsulate eval() within an own function to prevent problems\r
+ * with optimizing and minifiny JS.\r
+ * \r
+ * @param      mixed           expression\r
+ * @returns    mixed\r
+ */\r
+function wcfEval(expression) {\r
+       return eval(expression);\r
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/language/.htaccess b/wcfsetup/install/files/language/.htaccess
new file mode 100644 (file)
index 0000000..3418e55
--- /dev/null
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/action/AJAXProxyAction.class.php b/wcfsetup/install/files/lib/acp/action/AJAXProxyAction.class.php
new file mode 100644 (file)
index 0000000..4b1d619
--- /dev/null
@@ -0,0 +1,15 @@
+<?php\r
+namespace wcf\acp\action;\r
+\r
+/**\r
+ * Copy of the default implementation for object-actions using the AJAX-API.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.action\r
+ * @category   Community Framework\r
+ */\r
+class AJAXProxyAction extends \wcf\action\AJAXProxyAction { }\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/action/InstallPackageAction.class.php b/wcfsetup/install/files/lib/acp/action/InstallPackageAction.class.php
new file mode 100644 (file)
index 0000000..70158c2
--- /dev/null
@@ -0,0 +1,158 @@
+<?php\r
+namespace wcf\acp\action;\r
+use wcf\action\AbstractDialogAction;\r
+use wcf\data\package\installation\queue\PackageInstallationQueue;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\package\PackageInstallationDispatcher;\r
+use wcf\system\WCF;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Handles an AJAX-based package installation.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.action\r
+ * @category   Community Framework\r
+ */\r
+class InstallPackageAction extends AbstractDialogAction {\r
+       /**\r
+        * current node\r
+        *\r
+        * @var string\r
+        */\r
+       public $node = '';\r
+       \r
+       /**\r
+        * PackageInstallationDispatcher object\r
+        *\r
+        * @var PackageInstallationDispatcher\r
+        */\r
+       public $installation = null;\r
+       \r
+       /**\r
+        * PackageInstallationQueue object\r
+        *\r
+        * @var PackageInstallationQueue\r
+        */\r
+       public $queue = null;\r
+       \r
+       /**\r
+        * current queue id\r
+        *\r
+        * @var integer\r
+        */\r
+       public $queueID = 0;\r
+       \r
+       // system\r
+       public $templateName = 'packageInstallationStep';\r
+       \r
+       /**\r
+        * @see Action::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_POST['node'])) $this->node = StringUtil::trim($_POST['node']);\r
+               if (isset($_POST['queueID'])) $this->queueID = intval($_POST['queueID']);\r
+               $this->queue = new PackageInstallationQueue($this->queueID);\r
+               \r
+               if (!$this->queue->queueID) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               \r
+               $this->installation = new PackageInstallationDispatcher($this->queue);\r
+       }\r
+       \r
+       /**\r
+        * Executes installation based upon nodes.\r
+        */\r
+       protected function stepInstall() {\r
+               $step = $this->installation->install($this->node);\r
+               \r
+               if ($step->hasDocument()) {\r
+                       $this->data = array(\r
+                               'innerTemplate' => $step->getTemplate(),\r
+                               'node' => $step->getNode(),\r
+                               'progress' => $this->installation->nodeBuilder->calculateProgress($this->node),\r
+                               'step' => 'install'\r
+                       );\r
+               }\r
+               else {\r
+                       if ($step->getNode() == '') {\r
+                               // perform final actions\r
+                               $queueID = $this->installation->completeSetup();\r
+                               \r
+                               // begin with next queue\r
+                               if ($queueID) {\r
+                                       $this->data = array(\r
+                                               'progress' => 100,\r
+                                               'queueID' => $queueID,\r
+                                               'step' => 'prepare'\r
+                                       );\r
+                                       return;\r
+                               }\r
+                               \r
+                               // no more queues, show success\r
+                               $this->data = array(\r
+                                       'progress' => 100,\r
+                                       'step' => 'success'\r
+                               );\r
+                               return;\r
+                       }\r
+                       \r
+                       // continue with next node\r
+                       $this->data = array(\r
+                               'step' => 'install',\r
+                               'node' => $step->getNode(),\r
+                               'progress' => $this->installation->nodeBuilder->calculateProgress($this->node)\r
+                       );\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Prepares the installation process.\r
+        */\r
+       protected function stepPrepare() {\r
+               // update package information\r
+               $this->installation->updatePackage();\r
+               \r
+               // clean-up previously created nodes\r
+               $this->installation->nodeBuilder->purgeNodes();\r
+               \r
+               // create node tree\r
+               $this->installation->nodeBuilder->buildNodes();\r
+               $nextNode = $this->installation->nodeBuilder->getNextNode();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'queue' => $this->queue\r
+               ));\r
+               \r
+               $this->data = array(\r
+                       'template' => WCF::getTPL()->fetch($this->templateName),\r
+                       'step' => 'install',\r
+                       'node' => $nextNode,\r
+                       'currentAction' => WCF::getLanguage()->get('wcf.package.installation.step.installing'),\r
+                       'progress' => 0\r
+               );\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractDialogAction::validateStep()\r
+        */\r
+       protected function validateStep() {\r
+               switch ($this->step) {\r
+                       case 'install':\r
+                       case 'prepare':\r
+                               continue;\r
+                       break;\r
+                       \r
+                       default:\r
+                               throw new IllegalLinkException();\r
+                       break;\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/action/LogoutAction.class.php b/wcfsetup/install/files/lib/acp/action/LogoutAction.class.php
new file mode 100644 (file)
index 0000000..5124754
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+namespace wcf\acp\action;\r
+use wcf\action\AbstractSecureAction;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\WCF;\r
+use wcf\util\HeaderUtil;\r
+\r
+/**\r
+ * Does the user logout in the admin control panel.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.action\r
+ * @category   Community Framework\r
+ */\r
+class LogoutAction extends AbstractSecureAction {\r
+       /**\r
+        * @see Action::execute()\r
+        */\r
+       public function execute() {\r
+               parent::execute();\r
+               \r
+               // validate\r
+               if (!WCF::getUser()->userID) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               \r
+               // do logout\r
+               WCF::getSession()->delete();\r
+               \r
+               $this->executed();\r
+               \r
+               // forward to index page\r
+               // warning: if doLogout() writes a cookie this is buggy in MS IIS\r
+               HeaderUtil::redirect('index.php'.SID_ARG_1ST);\r
+               exit;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/action/OptionExportAction.class.php b/wcfsetup/install/files/lib/acp/action/OptionExportAction.class.php
new file mode 100644 (file)
index 0000000..360be38
--- /dev/null
@@ -0,0 +1,55 @@
+<?php\r
+namespace wcf\acp\action;\r
+use wcf\action\AbstractAction;\r
+use wcf\data\option\Option;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Exports the options to an XML.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.action\r
+ * @category   Community Framework\r
+ */\r
+class OptionExportAction extends AbstractAction {\r
+       /**\r
+        * @see AbstractAction::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.system.canEditOption');\r
+       \r
+       /**\r
+        * @see Action::execute();\r
+        */\r
+       public function execute() {\r
+               parent::execute();\r
+               \r
+               // header\r
+               @header('Content-type: text/xml');\r
+               \r
+               // file name\r
+               @header('Content-disposition: attachment; filename="options.xml"');\r
+                       \r
+               // no cache headers\r
+               @header('Pragma: no-cache');\r
+               @header('Expires: 0');\r
+               \r
+               // content\r
+               echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<options>\n";\r
+               \r
+               $options = Option::getOptions();\r
+               foreach ($options as $option) {\r
+                       echo "\t<option>\n";\r
+                       echo "\t\t<name><![CDATA[".StringUtil::escapeCDATA($option['optionName'])."]]></name>\n";\r
+                       echo "\t\t<value><![CDATA[".StringUtil::escapeCDATA($option['optionValue'])."]]></value>\n";\r
+                       echo "\t</option>\n";\r
+               }\r
+               \r
+               echo '</options>';\r
+               $this->executed();\r
+               exit;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/action/UninstallPackageAction.class.php b/wcfsetup/install/files/lib/acp/action/UninstallPackageAction.class.php
new file mode 100644 (file)
index 0000000..6fff5ee
--- /dev/null
@@ -0,0 +1,150 @@
+<?php\r
+namespace wcf\acp\action;\r
+use wcf\action\AbstractDialogAction;\r
+use wcf\data\package\Package;\r
+use wcf\data\package\installation\queue\PackageInstallationQueue;\r
+use wcf\data\package\installation\queue\PackageInstallationQueueEditor;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\package\PackageUninstallationDispatcher;\r
+use wcf\system\WCF;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Handles an AJAX-based package uninstallation.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.action\r
+ * @category   Community Framework\r
+ */\r
+class UninstallPackageAction extends InstallPackageAction {\r
+       /**\r
+        * active package id\r
+        *\r
+        * @var integer\r
+        */\r
+       protected $packageID = 0;\r
+       \r
+       // system\r
+       public $templateName = 'packageUninstallationStep';\r
+       \r
+       /**\r
+        * @see Action::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               AbstractDialogAction::readParameters();\r
+               \r
+               if (isset($_POST['node'])) $this->node = StringUtil::trim($_POST['node']);\r
+               \r
+               if (isset($_POST['packageID'])) {\r
+                       $this->packageID = intval($_POST['packageID']);\r
+               }\r
+               else {\r
+                       if (isset($_POST['queueID'])) $this->queueID = intval($_POST['queueID']);\r
+                       $this->queue = new PackageInstallationQueue($this->queueID);\r
+                       \r
+                       if (!$this->queue->queueID) {\r
+                               throw new IllegalLinkException();\r
+                       }\r
+                       \r
+                       $this->installation = new PackageUninstallationDispatcher($this->queue);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Prepares the uninstallation process.\r
+        */\r
+       protected function stepPrepare() {\r
+               $package = new Package($this->packageID);\r
+               if (!$package->packageID) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               \r
+               if (PackageUninstallationDispatcher::hasDependencies($package->packageID)) {\r
+                       throw new SystemException('hasDependencies');\r
+               }\r
+               else {\r
+                       // get new process no\r
+                       $processNo = PackageInstallationQueue::getNewProcessNo();\r
+                       \r
+                       // create queue\r
+                       $queue = PackageInstallationQueueEditor::create(array(\r
+                               'processNo' => $processNo,\r
+                               'userID' => WCF::getUser()->userID,\r
+                               'packageName' => $package->getName(),\r
+                               'packageID' => $package->packageID,\r
+                               'action' => 'uninstall',\r
+                               'cancelable' => 0\r
+                       ));\r
+                       \r
+                       // initialize uninstallation\r
+                       $this->installation = new PackageUninstallationDispatcher($queue);\r
+                       \r
+                       $this->installation->nodeBuilder->purgeNodes();\r
+                       $this->installation->nodeBuilder->buildNodes();\r
+                       \r
+                       WCF::getTPL()->assign(array(\r
+                               'queue' => $queue\r
+                       ));\r
+                       \r
+                       $this->data = array(\r
+                               'template' => WCF::getTPL()->fetch($this->templateName),\r
+                               'step' => 'uninstall',\r
+                               'node' => $this->installation->nodeBuilder->getNextNode(),\r
+                               'currentAction' => WCF::getLanguage()->get('wcf.package.installation.step.uninstalling'),\r
+                               'progress' => 0,\r
+                               'queueID' => $queue->queueID\r
+                       );\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Uninstalls node components and returns next node.\r
+        *\r
+        * @param       string          $node\r
+        * @return      string\r
+        */\r
+       public function stepUninstall() {\r
+               $node = $this->installation->uninstall($this->node);\r
+               \r
+               if ($node == '') {\r
+                       // remove node data\r
+                       $this->installation->nodeBuilder->purgeNodes();\r
+                       \r
+                       // TODO: Show 'success' template at this point\r
+                       $this->data = array(\r
+                               'progress' => 100,\r
+                               'step' => 'success'\r
+                       );\r
+                       return;\r
+               }\r
+               \r
+               // continue with next node\r
+               $this->data = array(\r
+                       'step' => 'uninstall',\r
+                       'node' => $node,\r
+                       'progress' => $this->installation->nodeBuilder->calculateProgress($this->node)\r
+               );\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractDialogAction::validateStep()\r
+        */\r
+       protected function validateStep() {\r
+               switch ($this->step) {\r
+                       case 'prepare':\r
+                       case 'uninstall':\r
+                               continue;\r
+                       break;\r
+                       \r
+                       default:\r
+                               die(print_r($_POST, true));\r
+                               throw new IllegalLinkException();\r
+                       break;\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/ACPForm.class.php b/wcfsetup/install/files/lib/acp/form/ACPForm.class.php
new file mode 100644 (file)
index 0000000..6157178
--- /dev/null
@@ -0,0 +1,34 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\form\AbstractForm;\r
+\r
+/**\r
+ * Provides a default implementation for the show method in acp forms.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class ACPForm extends AbstractForm {\r
+       /**\r
+        * Active acp menu item.\r
+        * \r
+        * @var string\r
+        */\r
+       public $activeMenuItem = '';\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               // enable menu item\r
+               if (!empty($this->activeMenuItem)) ACPMenu::getInstance()->setActiveMenuItem($this->activeMenuItem);\r
+               \r
+               parent::show();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/AbstractOptionListForm.class.php b/wcfsetup/install/files/lib/acp/form/AbstractOptionListForm.class.php
new file mode 100644 (file)
index 0000000..59f6726
--- /dev/null
@@ -0,0 +1,379 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\option\category\OptionCategory;\r
+use wcf\data\option\Option;\r
+use wcf\form\AbstractForm;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\exception\SystemException;\r
+use wcf\util\ClassUtil;\r
+\r
+/**\r
+ * This class provides default implementations for a list of options.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractOptionListForm extends AbstractForm {\r
+       /**\r
+        * @see AbstractForm::$errorField\r
+        */\r
+       public $errorField = array();\r
+       \r
+       /**\r
+        * @see AbstractForm::$errorType\r
+        */\r
+       public $errorType = array();\r
+\r
+       /**\r
+        * cache name\r
+        * @var string\r
+        */\r
+       public $cacheName = 'option-';\r
+       \r
+       /**\r
+        * cache class name\r
+        * @var string\r
+        */\r
+       public $cacheClass = 'wcf\system\cache\CacheBuilderOption';\r
+\r
+       /**\r
+        * list of all option categories\r
+        * @var array<OptionCategory>\r
+        */\r
+       public $cachedCategories = array();\r
+       \r
+       /**\r
+        * list of all options\r
+        * @var array<Option>\r
+        */\r
+       public $cachedOptions = array();\r
+       \r
+       /**\r
+        * category structure\r
+        * @var array\r
+        */\r
+       public $cachedCategoryStructure = array();\r
+       \r
+       /**\r
+        * option structure\r
+        * @var array\r
+        */\r
+       public $cachedOptionToCategories = array();\r
+       \r
+       /**\r
+        * raw option values\r
+        * @var array<mixed>\r
+        */\r
+       public $rawValues = array();\r
+       \r
+       /**\r
+        * option values\r
+        * @var array<mixed>\r
+        */\r
+       public $optionValues = array();\r
+       \r
+       /**\r
+        * Name of the active option category.\r
+        * @var string\r
+        */\r
+       public $categoryName = '';\r
+       \r
+       /**\r
+        * Options of the active category.\r
+        * @var array<Option>\r
+        */\r
+       public $options = array();\r
+       \r
+       /**\r
+        * Type object cache.\r
+        * @var array\r
+        */\r
+       public $typeObjects = array();\r
+               \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['values']) && is_array($_POST['values'])) $this->rawValues = $_POST['values'];\r
+       }\r
+\r
+       /**\r
+        * Returns an object of the requested option type.\r
+        * \r
+        * @param       string                  $type\r
+        * @return      OptionType\r
+        */\r
+       protected function getTypeObject($type) {\r
+               if (!isset($this->typeObjects[$type])) {\r
+                       $className = 'wcf\system\option\OptionType'.ucfirst($type);\r
+                       \r
+                       // validate class\r
+                       if (!class_exists($className)) {\r
+                               throw new SystemException("unable to find class '".$className."'", 11001);\r
+                       }\r
+                       if (!ClassUtil::isInstanceOf($className, 'wcf\system\option\OptionType')) {\r
+                               throw new SystemException("'".$className."' should implement OptionType");\r
+                       }\r
+                       // create instance\r
+                       $this->typeObjects[$type] = new $className();\r
+               }\r
+               \r
+               return $this->typeObjects[$type];\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               foreach ($this->options as $option) {\r
+                       try {\r
+                               $this->validateOption($option);\r
+                       }\r
+                       catch (UserInputException $e) {\r
+                               $this->errorType[$e->getField()] = $e->getType();\r
+                       }\r
+               }\r
+               \r
+               if (count($this->errorType) > 0) {\r
+                       throw new UserInputException('options', $this->errorType);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Validates an option.\r
+        * \r
+        * @param       Option          $option\r
+        */\r
+       protected function validateOption(Option $option) {\r
+               // get type object\r
+               $typeObj = $this->getTypeObject($option->optionType);\r
+               \r
+               // get new value\r
+               $newValue = isset($this->rawValues[$option->optionName]) ? $this->rawValues[$option->optionName] : null;\r
+                               \r
+               // get save value\r
+               $this->optionValues[$option->optionName] = $typeObj->getData($option, $newValue);\r
+                               \r
+               // validate with pattern\r
+               if ($option->validationPattern) {\r
+                       if (!preg_match('~'.$option->validationPattern.'~', $this->optionValues[$option->optionName])) {\r
+                               throw new UserInputException($option->optionName, 'validationFailed');\r
+                       }\r
+               }\r
+               \r
+               // validate by type object\r
+               $typeObj->validate($option, $newValue);\r
+       }\r
+       \r
+       /**\r
+        * Gets all options and option categories from cache.\r
+        */\r
+       protected function readCache() {\r
+               // init cache\r
+               $cacheName = $this->cacheName.PACKAGE_ID;\r
+               CacheHandler::getInstance()->addResource($cacheName, WCF_DIR.'cache/cache.'.$cacheName.'.php', $this->cacheClass);\r
+               \r
+               // get cache contents\r
+               $this->cachedCategories = CacheHandler::getInstance()->get($cacheName, 'categories');\r
+               $this->cachedOptions = CacheHandler::getInstance()->get($cacheName, 'options');\r
+               $this->cachedCategoryStructure = CacheHandler::getInstance()->get($cacheName, 'categoryStructure');\r
+               $this->cachedOptionToCategories = CacheHandler::getInstance()->get($cacheName, 'optionToCategories');\r
+               \r
+               // get active options\r
+               $this->loadActiveOptions($this->categoryName);\r
+       }\r
+       \r
+       /**\r
+        * Creates a list of all active options.\r
+        * \r
+        * @param       string          $parentCategoryName\r
+        */\r
+       protected function loadActiveOptions($parentCategoryName) {\r
+               if (!isset($this->cachedCategories[$parentCategoryName]) || static::checkCategory($this->cachedCategories[$parentCategoryName])) {\r
+                       if (isset($this->cachedOptionToCategories[$parentCategoryName])) {\r
+                               foreach ($this->cachedOptionToCategories[$parentCategoryName] as $optionName) {\r
+                                       if (static::checkOption($this->cachedOptions[$optionName])) {\r
+                                               $this->options[$optionName] = $this->cachedOptions[$optionName];\r
+                                       }\r
+                               }\r
+                       }\r
+                       if (isset($this->cachedCategoryStructure[$parentCategoryName])) {\r
+                               foreach ($this->cachedCategoryStructure[$parentCategoryName] as $categoryName) {\r
+                                       $this->loadActiveOptions($categoryName);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Checks the required permissions and options of a category.\r
+        * \r
+        * @param       OptionCategory          $category\r
+        * @return      boolean\r
+        */\r
+       protected static function checkCategory(OptionCategory $category) {\r
+               if ($category->permissions) {\r
+                       $hasPermission = false;\r
+                       $permissions = explode(',', $category->permissions);\r
+                       foreach ($permissions as $permission) {\r
+                               if (WCF::getSession()->getPermission($permission)) {\r
+                                       $hasPermission = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       if (!$hasPermission) return false;\r
+                       \r
+               }\r
+               if ($category->options) {\r
+                       $hasEnabledOption = false;\r
+                       $options = explode(',', strtoupper($category->options));\r
+                       foreach ($options as $option) {\r
+                               if (defined($option) && constant($option)) {\r
+                                       $hasEnabledOption = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       if (!$hasEnabledOption) return false;\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       protected function getFormElement($type, Option $option) {\r
+               return $this->getTypeObject($type)->getFormElement($option, (isset($this->optionValues[$option->optionName]) ? $this->optionValues[$option->optionName] : null));\r
+       }\r
+       \r
+       /**\r
+        * Checks the required permissions and options of an option.\r
+        * \r
+        * @param       Option          $option\r
+        * @return      boolean\r
+        */\r
+       protected static function checkOption(Option $option) {\r
+               if ($option->permissions) {\r
+                       $hasPermission = false;\r
+                       $permissions = explode(',', $option->permissions);\r
+                       foreach ($permissions as $permission) {\r
+                               if (WCF::getSession()->getPermission($permission)) {\r
+                                       $hasPermission = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       if (!$hasPermission) return false;\r
+                       \r
+               }\r
+               if ($option->options) {\r
+                       $hasEnabledOption = false;\r
+                       $options = explode(',', strtoupper($option->options));\r
+                       foreach ($options as $option) {\r
+                               if (defined($option) && constant($option)) {\r
+                                       $hasEnabledOption = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       if (!$hasEnabledOption) return false;\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Returns the tree of options.\r
+        * \r
+        * @param       string          $parentCategoryName\r
+        * @param       integer         $level\r
+        * @return      array\r
+        */\r
+       protected function getOptionTree($parentCategoryName = '', $level = 0) {\r
+               $tree = array();\r
+               \r
+               if (isset($this->cachedCategoryStructure[$parentCategoryName])) {\r
+                       // get super categories\r
+                       foreach ($this->cachedCategoryStructure[$parentCategoryName] as $superCategoryName) {\r
+                               $superCategoryObject = $this->cachedCategories[$superCategoryName];\r
+                               $superCategory = array(\r
+                                       'object' => $superCategoryObject,\r
+                                       'categories' => array(),\r
+                                       'options' => array()\r
+                               );\r
+                               \r
+                               if (static::checkCategory($superCategoryObject)) {\r
+                                       if ($level <= 1) {\r
+                                               $superCategory['categories'] = $this->getOptionTree($superCategoryName, $level + 1);\r
+                                       }\r
+                                       if ($level > 1 || count($superCategory['categories']) == 0) {\r
+                                               $superCategory['options'] = $this->getCategoryOptions($superCategoryName);\r
+                                       }\r
+                                       else {\r
+                                               $superCategory['options'] = $this->getCategoryOptions($superCategoryName, false);\r
+                                       }\r
+                                       \r
+                                       if (count($superCategory['categories']) > 0 || count($superCategory['options']) > 0) {\r
+                                               $tree[] = $superCategory;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       \r
+               return $tree;\r
+       }\r
+       \r
+       /**\r
+        * Returns a list with the options of a specific option category.\r
+        * \r
+        * @param       string          $categoryName\r
+        * @param       boolean         $inherit\r
+        * @return      array\r
+        */\r
+       protected function getCategoryOptions($categoryName = '', $inherit = true) {\r
+               $children = array();\r
+               \r
+               // get sub categories\r
+               if ($inherit && isset($this->cachedCategoryStructure[$categoryName])) {\r
+                       foreach ($this->cachedCategoryStructure[$categoryName] as $subCategoryName) {\r
+                               $children = array_merge($children, $this->getCategoryOptions($subCategoryName));\r
+                       }\r
+               }\r
+               \r
+               // get options\r
+               if (isset($this->cachedOptionToCategories[$categoryName])) {\r
+                       $i = 0;\r
+                       $last = count($this->cachedOptionToCategories[$categoryName]) - 1;\r
+                       foreach ($this->cachedOptionToCategories[$categoryName] as $optionName) {\r
+                               if (!isset($this->options[$optionName]) || !$this->checkOption($this->options[$optionName])) continue;\r
+                               \r
+                               // get option object\r
+                               $option = $this->options[$optionName];\r
+                               \r
+                               // get form element html\r
+                               $html = $this->getFormElement($option->optionType, $option);\r
+                               \r
+                               // add option to list\r
+                               $children[] = array(\r
+                                       'object' => $option,\r
+                                       'html' => $html\r
+                               );\r
+                               \r
+                               $i++;\r
+                       }\r
+               }\r
+               \r
+               return $children;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/CronjobAddForm.class.php b/wcfsetup/install/files/lib/acp/form/CronjobAddForm.class.php
new file mode 100644 (file)
index 0000000..9ba9efa
--- /dev/null
@@ -0,0 +1,179 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\cronjob\CronjobAction;\r
+use wcf\data\package\Package;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\WCF;\r
+use wcf\util\CronjobUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the cronjobs add form.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class CronjobAddForm extends ACPForm {\r
+       /**\r
+        * @see AbstractPage::$templateName\r
+        */\r
+       public $templateName = 'cronjobAdd';\r
+       \r
+       /**\r
+        * @see ACPForm::$activeMenuItem\r
+        */\r
+       public $activeMenuItem = 'wcf.acp.menu.link.cronjobs.add';\r
+       \r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.system.cronjobs.canAddCronjob');\r
+       \r
+       /**\r
+        * cronjob class name\r
+        * @var string\r
+        */\r
+       public $className = '';\r
+       \r
+       /**\r
+        * cronjob package id\r
+        * @var integer\r
+        */\r
+       public $packageID = PACKAGE_ID;\r
+       \r
+       /**\r
+        * cronjob description\r
+        * @var string\r
+        */\r
+       public $description = '';\r
+       \r
+       /**\r
+        * execution time (min)\r
+        * @var string\r
+        */\r
+       public $startMinute = '*';\r
+       \r
+       /**\r
+        * execution time (hour)\r
+        * @var string\r
+        */\r
+       public $startHour = '*';\r
+       \r
+       /**\r
+        * execution time (day of month)\r
+        * @var string\r
+        */\r
+       public $startDom = '*';\r
+       \r
+       /**\r
+        * execution time (month)\r
+        * @var string\r
+        */\r
+       public $startMonth = '*';\r
+       \r
+       /**\r
+        * execution time (day of week)\r
+        * @var string\r
+        */\r
+       public $startDow = '*';\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['className'])) $this->className = StringUtil::trim($_POST['className']);\r
+               if (isset($_POST['description'])) $this->description = StringUtil::trim($_POST['description']);\r
+               if (isset($_POST['startMinute'])) $this->startMinute = StringUtil::replace(' ', '', $_POST['startMinute']);\r
+               if (isset($_POST['startHour'])) $this->startHour = StringUtil::replace(' ', '', $_POST['startHour']);\r
+               if (isset($_POST['startDom'])) $this->startDom = StringUtil::replace(' ', '', $_POST['startDom']);\r
+               if (isset($_POST['startMonth'])) $this->startMonth = StringUtil::replace(' ', '', $_POST['startMonth']);\r
+               if (isset($_POST['startDow'])) $this->startDow = StringUtil::replace(' ', '', $_POST['startDow']);\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               // validate class name\r
+               if (empty($this->className)) {\r
+                       throw new UserInputException('className');\r
+               }\r
+               \r
+               if (!class_exists($this->className)) {\r
+                       throw new UserInputException('className', 'doesNotExist');\r
+               }\r
+               \r
+               try {\r
+                       CronjobUtil::validate($this->startMinute, $this->startHour, $this->startDom, $this->startMonth, $this->startDow);\r
+               } \r
+               catch (SystemException $e) {\r
+                       // extract field name\r
+                       $fieldName = '';\r
+                       if (preg_match("/cronjob attribute '(.*)'/", $e->getMessage(), $match)) {\r
+                               $fieldName = $match[1];\r
+                       }\r
+                       \r
+                       throw new UserInputException($fieldName, 'notValid');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // save cronjob\r
+               $data = array(\r
+                       'className' => $this->className,\r
+                       'packageID' => $this->packageID,\r
+                       'description' => $this->description,\r
+                       'startMinute' => $this->startMinute,\r
+                       'startHour' => $this->startHour,\r
+                       'startDom' => $this->startDom,\r
+                       'startMonth' => $this->startMonth,\r
+                       'startDow' => $this->startDow\r
+               );\r
+               \r
+               $cronjobAction = new CronjobAction(array(), 'create', array('data' => $data));\r
+               $cronjobAction->executeAction();\r
+               $this->saved();\r
+               \r
+               // reset values\r
+               $this->className = $this->description = '';\r
+               $this->startMinute = $this->startHour = $this->startDom = $this->startMonth = $this->startDow = '*';\r
+               \r
+               // show success.\r
+               WCF::getTPL()->assign(array(\r
+                       'success' => true\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'className' => $this->className,\r
+                       'description' => $this->description,\r
+                       'startMinute' => $this->startMinute,\r
+                       'startHour' => $this->startHour,\r
+                       'startDom' => $this->startDom,\r
+                       'startMonth' => $this->startMonth,\r
+                       'startDow' => $this->startDow,\r
+                       'action' => 'add'\r
+               ));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/CronjobEditForm.class.php b/wcfsetup/install/files/lib/acp/form/CronjobEditForm.class.php
new file mode 100644 (file)
index 0000000..edaf6dc
--- /dev/null
@@ -0,0 +1,115 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\cronjob\Cronjob;\r
+use wcf\data\cronjob\CronjobAction;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Shows the cronjobs edit form.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class CronjobEditForm extends CronjobAddForm {\r
+       /**\r
+        * @see ACPForm::$activeMenuItem\r
+        */\r
+       public $activeMenuItem = 'wcf.acp.menu.link.cronjobs';\r
+       \r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.system.cronjobs.canEditCronjob');\r
+       \r
+       /**\r
+        * cronjob id\r
+        * \r
+        * @var integer\r
+        */\r
+       public $cronjobID = 0;\r
+       \r
+       /**\r
+        * cronjob object\r
+        *\r
+        * @var Cronjob\r
+        */\r
+       public $cronjob = null;\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['cronjobID'])) $this->cronjobID = intval($_REQUEST['cronjobID']);\r
+               $this->cronjob = new Cronjob($this->cronjobID);\r
+               if (!$cronjob->cronjobID) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               \r
+               $this->packageID = $this->cronjob->packageID;\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               ACPForm::save();\r
+               \r
+               // update cronjob\r
+               $data = array(\r
+                       'className' => $this->className,\r
+                       'description' => $this->description,\r
+                       'startMinute' => $this->startMinute,\r
+                       'startHour' => $this->startHour,\r
+                       'startDom' => $this->startDom,\r
+                       'startMonth' => $this->startMonth,\r
+                       'startDow' => $this->startDow\r
+               );\r
+               \r
+               $cronjobAction = new CronjobAction(array($this->cronjobID), 'update', array('data' => $data));\r
+               $cronjobAction->executeAction();\r
+               \r
+               $this->saved();\r
+               \r
+               // show success\r
+               WCF::getTPL()->assign(array(\r
+                       'success' => true\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               if (!count($_POST)) {\r
+                       $this->className = $this->cronjob->className;\r
+                       $this->description = $this->cronjob->description;\r
+                       $this->startMinute = $this->cronjob->startMinute;\r
+                       $this->startHour = $this->cronjob->startHour;\r
+                       $this->startDom = $this->cronjob->startDom;\r
+                       $this->startMonth = $this->cronjob->startMonth;\r
+                       $this->startDow = $this->cronjob->startDow;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'cronjobID' => $this->cronjobID,\r
+                       'action' => 'edit'\r
+               ));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php
new file mode 100644 (file)
index 0000000..5db0735
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\language\server\LanguageServerAction;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\system\exception\UserInputException;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the language server add form.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class LanguageServerAddForm extends ACPForm {
+       /**
+        * @see wcf\page\AbstractPage::$templateName
+        */
+       public $templateName = 'languageServerAdd';
+       
+       /**
+        * @see wcf\acp\form\ACPForm::$activeMenuItem
+        */
+       public $activeMenuItem = 'wcf.acp.menu.link.language.server.add';
+       
+       /**
+        * @see wcf\page\AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.language.canEditServer');
+       
+       /**
+        * server url
+        * @var string
+        */
+       public $server = '';
+       
+       /**
+        * @see wcf\form\Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_POST['server'])) $this->server = StringUtil::trim($_POST['server']);
+       }
+       
+       /**
+        * @see wcf\form\Form::validate()
+        */
+       public function validate() {
+               parent::validate();
+               
+               if (empty($this->server)) {
+                       throw new UserInputException('server');
+               }
+               
+               if (!PackageUpdateServer::isValidServerURL($this->server)) {
+                       throw new UserInputException('server', 'notValid');
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               parent::save();
+               
+               // save server
+               $languageServerAction = new LanguageServerAction(array(), 'create', array('data' => array(
+                       'serverURL' => $this->server
+               )));
+               $languageServerAction->executeAction();
+               $this->saved();
+               
+               // reset values
+               $this->server = '';
+               
+               // show success message
+               WCF::getTPL()->assign('success', true);
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'server' => $this->server,
+                       'action' => 'add'
+               ));
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function show() {
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php
new file mode 100644 (file)
index 0000000..567bc18
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\language\server\LanguageServer;
+use wcf\data\language\server\LanguageServerAction;
+use wcf\form\AbstractForm;
+use wcf\system\WCF;
+use wcf\system\exception\IllegalLinkException;
+
+/**
+ * Shows the language server edit form.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class LanguageServerEditForm extends LanguageServerAddForm {
+       /**
+        * @see wcf\acp\form\ACPForm::$activeMenuItem
+        */
+       public $activeMenuItem = 'wcf.acp.menu.link.language.server';
+       
+       /**
+        * language server id
+        * @var integer
+        */
+       public $languageServerID = 0;
+       
+       /**
+        * active language server
+        * @var wcf\data\language\server\LanguageServer
+        */
+       public $languageServer = null;
+       
+       /**
+        * @see wcf\page\Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_REQUEST['languageServerID'])) $this->languageServerID = intval($_REQUEST['languageServerID']);
+               $this->languageServer = new LanguageServer($this->languageServerID);
+               if (!$this->languageServer->languageServerID) {
+                       throw new IllegalLinkException();
+               }
+       }
+       
+       /**
+        * @see wcf\form\Form::save()
+        */
+       public function save() {
+               AbstractForm::save();
+               
+               // save server
+               $languageServerAction = new LanguageServerAction(array($this->languageServerID), 'update', array('data' => array(
+                       'serverURL' => $this->server
+               )));
+               $languageServerAction->executeAction();
+               $this->saved();
+               
+               // show success message
+               WCF::getTPL()->assign('success', true);
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               if (!count($_POST)) {
+                       $this->server = $this->languageServer->serverURL;
+               }
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+                       
+               WCF::getTPL()->assign(array(
+                       'languageServerID' => $this->languageServerID,
+                       'languageServer' => $this->languageServer,
+                       'action' => 'edit'
+               ));
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/form/LoginForm.class.php b/wcfsetup/install/files/lib/acp/form/LoginForm.class.php
new file mode 100644 (file)
index 0000000..4422a2a
--- /dev/null
@@ -0,0 +1,157 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\user\User;\r
+use wcf\form\AbstractForm;\r
+use wcf\system\auth\UserAuth;\r
+use wcf\system\exception\PermissionDeniedException;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\WCF;\r
+use wcf\util\HeaderUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the acp login form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class LoginForm extends AbstractForm {\r
+       /**\r
+        * @see AbstractPage::$templateName\r
+        */\r
+       public $templateName = 'login';\r
+       \r
+       /**\r
+        * given login username\r
+        * @var string\r
+        */\r
+       public $username = '';\r
+       \r
+       /**\r
+        * given login password\r
+        * @var string\r
+        */\r
+       public $password = '';\r
+       \r
+       /**\r
+        * user object\r
+        * @var User\r
+        */\r
+       public $user;\r
+       \r
+       /**\r
+        * given forward url\r
+        * @var string\r
+        */\r
+       public $url = null;\r
+       \r
+       /**\r
+        * Creates a new LoginForm object.\r
+        */\r
+       public function __construct() {\r
+               if (WCF::getUser()->userID) {\r
+                       throw new PermissionDeniedException();\r
+               }\r
+               \r
+               parent::__construct();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (!empty($_REQUEST['url'])) $this->url = $_REQUEST['url'];\r
+       }\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']);\r
+               if (isset($_POST['password'])) $this->password = $_POST['password'];\r
+       }\r
+       \r
+       /**\r
+        * Validates the user access data.\r
+        */\r
+       protected function validateUser() {\r
+               $this->user = UserAuth::getInstance()->loginManually($this->username, $this->password);\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               // error handling\r
+               if (empty($this->username)) {\r
+                       throw new UserInputException('username');\r
+               }\r
+               \r
+               if (empty($this->password)) {\r
+                       throw new UserInputException('password');\r
+               }\r
+               \r
+               $this->validateUser();\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // change user\r
+               WCF::getSession()->changeUser($this->user);\r
+               $this->saved();\r
+               \r
+               if (!empty($this->url)) {\r
+                       // append session\r
+                       if (StringUtil::indexOf($this->url, '?') !== false) $this->url .= SID_ARG_2ND_NOT_ENCODED;\r
+                       else $this->url .= SID_ARG_1ST;\r
+                       HeaderUtil::redirect($this->url);\r
+               }\r
+               else {\r
+                       HeaderUtil::redirect('index.php'.SID_ARG_1ST);\r
+               }\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+\r
+               // get preferred username\r
+               if (!count($_POST)) {\r
+                       if (isset($_COOKIE[COOKIE_PREFIX.'userID'])) {\r
+                               $user = new User(intval($_COOKIE[COOKIE_PREFIX.'userID']));\r
+                               if ($user->userID) $this->username = $user->username;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'username' => $this->username,\r
+                       'password' => $this->password,\r
+                       'url' => $this->url\r
+               ));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/MasterPasswordForm.class.php b/wcfsetup/install/files/lib/acp/form/MasterPasswordForm.class.php
new file mode 100644 (file)
index 0000000..886b1af
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+namespace wcf\acp\form;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\HeaderUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the master password form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class MasterPasswordForm extends ACPForm {
+       /**
+        * @see AbstractPage::$templateName
+        */
+       public $templateName = 'masterPassword';
+       
+       /**
+        * master password
+        *
+        * @var string
+        */
+       public $masterPassword = '';
+       
+       /**
+        * forward url
+        *
+        * @var string
+        */
+       public $url = '';
+       
+       /**
+        * @see Page::readParameters()
+        */     
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (file_exists(WCF_DIR.'acp/masterPassword.inc.php')) {
+                       require_once(WCF_DIR.'acp/masterPassword.inc.php');
+               }
+       }
+
+       /**
+        * @see Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_POST['masterPassword'])) $this->masterPassword = $_POST['masterPassword'];
+               if (isset($_POST['url'])) $this->url = $_POST['url'];
+       }
+       
+       /**
+        * @see Form::validate()
+        */
+       public function validate() {
+               parent::validate();
+               
+               if (empty($this->masterPassword)) {
+                       throw new UserInputException('masterPassword');
+               }
+               
+               // check password
+               if (StringUtil::getSaltedHash($this->masterPassword, MASTER_PASSWORD_SALT) != MASTER_PASSWORD) {
+                       throw new UserInputException('masterPassword', 'invalid');
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               parent::save();
+               
+               // update session
+               WCF::getSession()->register('masterPassword', 1);
+               WCF::getSession()->update();
+               WCF::getSession()->disableUpdate();
+               
+               // forward
+               if (empty($this->url)) {
+                       $this->url = 'index.php?page=Index'.SID_ARG_2ND_NOT_ENCODED;
+               }
+               HeaderUtil::redirect($this->url, false);
+               exit;
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               if (!count($_POST)) {
+                       $this->url = WCF::getSession()->requestURI;
+               }
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'masterPassword' => $this->masterPassword,
+                       'url' => $this->url
+               ));
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/MasterPasswordInitForm.class.php b/wcfsetup/install/files/lib/acp/form/MasterPasswordInitForm.class.php
new file mode 100644 (file)
index 0000000..eb72b9e
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+namespace wcf\acp\form;
+use wcf\system\WCF;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\UserInputException;
+use wcf\system\io\File;
+use wcf\util\MathUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the master password init form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class MasterPasswordInitForm extends MasterPasswordForm {
+       /**
+        * @see AbstractPage::$templateName
+        */
+       public $templateName = 'masterPasswordInit';
+
+       /**
+        * master password confirm
+        * 
+        * @var string
+        */
+       public $confirmMasterPassword = '';
+       
+       /**
+        * @see Page::readParameters()
+        */     
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (defined('MASTER_PASSWORD') && defined('MASTER_PASSWORD_SALT')) {
+                       throw new IllegalLinkException();
+               }
+       }
+       
+       /**
+        * @see Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_POST['confirmMasterPassword'])) $this->confirmMasterPassword = $_POST['confirmMasterPassword'];
+       }
+       
+       /**
+        * @see Form::validate()
+        */
+       public function validate() {
+               ACPForm::validate();
+               
+               if (empty($this->masterPassword)) {
+                       throw new UserInputException('masterPassword');
+               }
+               
+               // check password security
+               if (StringUtil::length($this->masterPassword) < 8) {
+                       throw new UserInputException('masterPassword', 'notSecure');
+               }
+               // digits
+               if (!preg_match('![0-9]+!', $this->masterPassword)) {
+                       throw new UserInputException('masterPassword', 'notSecure');
+               }
+               // latin characters (lower-case)
+               if (!preg_match('![a-z]+!', $this->masterPassword)) {
+                       throw new UserInputException('masterPassword', 'notSecure');
+               }
+               // latin characters (upper-case)
+               if (!preg_match('![A-Z]+!', $this->masterPassword)) {
+                       throw new UserInputException('masterPassword', 'notSecure');
+               }
+               // special characters
+               if (!preg_match('![^A-Za-z0-9]+!', $this->masterPassword)) {
+                       throw new UserInputException('masterPassword', 'notSecure');
+               }
+               
+               // search for identical admin passwords
+               $sql = "SELECT  password, salt
+                       FROM    wcf".WCF_N."_user
+                       WHERE   userID IN (
+                                       SELECT  userID
+                                       FROM    wcf".WCF_N."_user_to_group
+                                       WHERE   groupID = 4
+                               )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       if (StringUtil::getDoubleSaltedHash($this->masterPassword, $row['salt']) == $row['password']) {
+                               throw new UserInputException('masterPassword', 'notSecure');
+                       }
+               }
+               
+               // confirm master password
+               if (empty($this->confirmMasterPassword)) {
+                       throw new UserInputException('confirmMasterPassword');
+               }
+               
+               if ($this->confirmMasterPassword != $this->masterPassword) {
+                       throw new UserInputException('confirmMasterPassword', 'notEqual');
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               // generate salt
+               $salt = StringUtil::getRandomID();
+
+               // write master password file
+               $file = new File(WCF_DIR.'acp/masterPassword.inc.php');
+               $file->write("<?php
+/** MASTER PASSWORD STORAGE
+DO NOT EDIT THIS FILE */
+define('MASTER_PASSWORD', '".StringUtil::getSaltedHash($this->masterPassword, $salt)."');
+define('MASTER_PASSWORD_SALT', '".$salt."');
+?>");
+               $file->close();
+               @chmod(WCF_DIR.'acp/masterPassword.inc.php', 0777);
+               
+               parent::save();
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'confirmMasterPassword' => $this->confirmMasterPassword,
+                       'exampleMasterPassword' => StringUtil::getRandomPassword(12)
+               ));
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/form/OptionForm.class.php b/wcfsetup/install/files/lib/acp/form/OptionForm.class.php
new file mode 100644 (file)
index 0000000..f078e32
--- /dev/null
@@ -0,0 +1,154 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\option\category\OptionCategory;\r
+use wcf\data\option\OptionAction;\r
+use wcf\data\option\Option;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\WCF;\r
+use wcf\system\WCFACP;\r
+\r
+/**\r
+ * Shows the option edit form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class OptionForm extends AbstractOptionListForm {\r
+       /**\r
+        * @see AbstractPage::$templateName;\r
+        */\r
+       public $templateName = 'option';\r
+       \r
+       /**\r
+        * category option\r
+        * @var OptionCategory\r
+        */\r
+       public $category = null;\r
+       \r
+       /**\r
+        * category id\r
+        * @var integer\r
+        */\r
+       public $categoryID = 0;\r
+       \r
+       /**\r
+        * active tab menu item name\r
+        * @var string\r
+        */\r
+       public $activeTabMenuItem = '';\r
+       \r
+       /**\r
+        * the option tree\r
+        * @var array\r
+        */\r
+       public $optionTree = array();\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['categoryID'])) $this->categoryID = intval($_REQUEST['categoryID']);\r
+               $this->category = new OptionCategory($this->categoryID);\r
+               if (!isset($this->category->categoryID)) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               $this->categoryName = $this->category->categoryName;\r
+       }\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['activeTabMenuItem'])) $this->activeTabMenuItem = $_POST['activeTabMenuItem'];\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // save options\r
+               $saveOptions = array();\r
+               foreach ($this->options as $option) {\r
+                       $saveOptions[$option->optionID] = $this->optionValues[$option->optionName];\r
+               }\r
+               $optionAction = new OptionAction(array(), 'updateAll', array('data' => $saveOptions));\r
+               $optionAction->executeAction();\r
+               $this->saved();\r
+               \r
+               // show succes message\r
+               WCF::getTPL()->assign('success', true);\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               if (!count($_POST)) {\r
+                       // get option values\r
+                       foreach ($this->options as $option) {\r
+                               $this->optionValues[$option->optionName] = $option->optionValue;\r
+                       }\r
+               }\r
+               $this->optionTree = $this->getOptionTree($this->category->categoryName);\r
+               if (!count($_POST)) {\r
+                       $this->activeTabMenuItem = $this->optionTree[0]['object']->categoryName;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'category' => $this->category,\r
+                       'optionTree' => $this->optionTree,\r
+                       'activeTabMenuItem' => $this->activeTabMenuItem\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Form::show()\r
+        */\r
+       public function show() {\r
+               // set active menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.option.category.'.$this->category->categoryName);\r
+               \r
+               // check permission\r
+               WCF::getSession()->checkPermission(array('admin.system.canEditOption'));\r
+\r
+               if ($this->category->categoryName == 'module') {\r
+                       // check master password\r
+                       WCFACP::checkMasterPassword();\r
+               }\r
+               \r
+               // get options and categories from cache\r
+               $this->readCache();\r
+               \r
+               // show form\r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractOptionListForm::checkOption()\r
+        */\r
+       protected static function checkOption(Option $option) {\r
+               if (!parent::checkOption($option)) return false;\r
+               return ($option->hidden != 1);\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/OptionImportForm.class.php b/wcfsetup/install/files/lib/acp/form/OptionImportForm.class.php
new file mode 100644 (file)
index 0000000..448179a
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+namespace wcf\acp\form;
+use wcf\acp\option\Options;
+use wcf\data\option\OptionAction;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCFACP;
+use wcf\util\XML;
+
+/**
+ * Shows the option import form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class OptionImportForm extends ACPForm {
+       /**
+        * @see AbstractPage::$templateName
+        */
+       public $templateName = 'optionImport';
+       
+       /**
+        * @see ACPForm::$activeMenuItem
+        */
+       public $activeMenuItem = 'wcf.acp.menu.link.option.importAndExport';
+       
+       /**
+        * @see AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.system.canEditOption');
+       
+       /**
+        * upload file data
+        * @var array
+        */
+       public $optionImport = null;
+       
+       /**
+        * list of options
+        * @var array
+        */
+       public $options = array();
+       
+       /**
+        * @see Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_FILES['optionImport'])) $this->optionImport = $_FILES['optionImport'];
+       }
+       
+       /**
+        * @see Form::validate()
+        */
+       public function validate() {
+               parent::validate();
+               
+               // upload
+               if ($this->optionImport && $this->optionImport['error'] != 4) {
+                       if ($this->optionImport['error'] != 0) {
+                               throw new UserInputException('optionImport', 'uploadFailed');
+                       }
+                       
+                       try {
+                               $xml = new XML($this->optionImport['tmp_name']);
+                               $optionsXML = $xml->getElementTree('options');
+                               foreach ($optionsXML['children'] as $option) {
+                                       $name = $value = '';
+                                       foreach ($option['children'] as $optionData) {
+                                               switch ($optionData['name']) {
+                                                       case 'name':
+                                                               $name = $optionData['cdata'];
+                                                               break;
+                                                       case 'value':
+                                                               $value = $optionData['cdata'];
+                                                               break;
+                                               }
+                                       }
+                                       
+                                       if (!empty($name)) {
+                                               $this->options[$name] = $value;
+                                       }
+                               }
+                       }
+                       catch (SystemException $e) {
+                               throw new UserInputException('optionImport', 'importFailed');
+                       }
+               }
+               else {
+                       throw new UserInputException('optionImport');
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               parent::save();
+               
+               // save
+               $optionAction = new OptionAction(array(), 'import', array('data' => $this->options));
+               $optionAction->executeAction();
+               $this->saved();
+               
+               // show success message
+               WCF::getTPL()->assign('success', true);
+       }
+       
+       /**
+        * @see Page::show()
+        */
+       public function show() {
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               parent::show();
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/PackageStartInstallForm.class.php b/wcfsetup/install/files/lib/acp/form/PackageStartInstallForm.class.php
new file mode 100644 (file)
index 0000000..91403d3
--- /dev/null
@@ -0,0 +1,227 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\package\Package;\r
+use wcf\data\package\installation\queue\PackageInstallationQueue;\r
+use wcf\data\package\installation\queue\PackageInstallationQueueEditor;\r
+use wcf\system\WCF;\r
+use wcf\system\WCFACP;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\package\PackageArchive;\r
+use wcf\system\package\PackageInstallationDispatcher;\r
+use wcf\util\FileUtil;\r
+use wcf\util\HeaderUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the package install and update form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class PackageStartInstallForm extends ACPForm {\r
+       public $templateName = 'packageStartInstall';\r
+       public $activeMenuItem = 'wcf.acp.menu.link.package.install';\r
+               \r
+       public $packageID = 0;\r
+       public $package = null;\r
+       public $downloadPackage = '';\r
+       public $uploadPackage = '';\r
+       public $archive = null;\r
+       public $queue = null;\r
+       \r
+       /**\r
+        * @see Form::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['activePackageID'])) {\r
+                       $this->packageID = intval($_REQUEST['activePackageID']);\r
+                       if ($this->packageID != 0) {\r
+                               try {\r
+                                       $this->package = new Package($this->packageID);\r
+                               }\r
+                               catch (SystemException $e) {\r
+                                       throw new IllegalLinkException();\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['downloadPackage'])) $this->downloadPackage = StringUtil::trim($_POST['downloadPackage']);\r
+               if (isset($_FILES['uploadPackage'])) $this->uploadPackage = $_FILES['uploadPackage'];\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               if (!empty($this->uploadPackage['name'])) {\r
+                       $this->validateUploadPackage();\r
+               }\r
+               else if (!empty($this->downloadPackage)) {\r
+                       $this->validateDownloadPackage();\r
+               }\r
+               else {\r
+                       throw new UserInputException('uploadPackage');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Validates the upload package input.\r
+        */\r
+       protected function validateUploadPackage() {\r
+               if (empty($this->uploadPackage['tmp_name'])) {\r
+                       throw new UserInputException('uploadPackage', 'uploadFailed');\r
+               }\r
+               \r
+               // get filename\r
+               $this->uploadPackage['name'] = FileUtil::getTemporaryFilename('package_', preg_replace('!^.*(?=\.(?:tar\.gz|tgz|tar)$)!i', '', basename($this->uploadPackage['name'])));\r
+               \r
+               if (!@move_uploaded_file($this->uploadPackage['tmp_name'], $this->uploadPackage['name'])) {\r
+                       throw new UserInputException('uploadPackage', 'uploadFailed');\r
+               }\r
+               \r
+               $this->archive = new PackageArchive($this->uploadPackage['name'], $this->package);\r
+               $this->validateArchive('uploadPackage');\r
+       }\r
+       \r
+       /**\r
+        * Validates the download package input.\r
+        */\r
+       protected function validateDownloadPackage() {\r
+               if (FileUtil::isURL($this->downloadPackage)) {\r
+                       // download package\r
+                       $this->archive = new PackageArchive($this->downloadPackage, $this->package);\r
+                       \r
+                       try {\r
+                               $this->downloadPackage = $this->archive->downloadArchive();\r
+                               //$this->archive->downloadArchive();\r
+                       }\r
+                       catch (SystemException $e) {\r
+                               throw new UserInputException('downloadPackage', 'notFound');\r
+                       }\r
+               }\r
+               else {\r
+                       // probably local path\r
+                       if (!file_exists($this->downloadPackage)) {\r
+                               throw new UserInputException('downloadPackage', 'notFound');\r
+                       }\r
+                       \r
+                       $this->archive = new PackageArchive($this->downloadPackage, $this->package);\r
+               }\r
+               \r
+               $this->validateArchive('downloadPackage');\r
+       }\r
+       \r
+       /**\r
+        * Validates the package archive.\r
+        *\r
+        * @param       string          $type           upload or download package\r
+        */\r
+       protected function validateArchive($type) {\r
+               // try to open the archive\r
+               try {\r
+                       // TODO: Exceptions thrown within openArchive() are discarded, resulting in\r
+                       // the meaningless message 'not a valid package'\r
+                       $this->archive->openArchive();\r
+               }\r
+               catch (SystemException $e) {\r
+                       throw new UserInputException($type, 'noValidPackage');\r
+               }\r
+               \r
+               // validate php requirements\r
+               $errors = PackageInstallationDispatcher::validatePHPRequirements($this->archive->getPhpRequirements());\r
+               if (count($errors)) {\r
+                       WCF::getTPL()->assign('phpRequirements', $errors);\r
+                       throw new UserInputException($type, 'phpRequirements');\r
+               }\r
+               \r
+               // check update or install support\r
+               if ($this->package !== null) {\r
+                       if (!$this->archive->isValidUpdate()) {\r
+                               throw new UserInputException($type, 'noValidUpdate');\r
+                       }\r
+               }\r
+               else {\r
+                       if (!$this->archive->isValidInstall()) {\r
+                               throw new UserInputException($type, 'noValidInstall');\r
+                       }\r
+                       elseif ($this->archive->isAlreadyInstalled()) {\r
+                               throw new UserInputException($type, 'uniqueAlreadyInstalled');\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // get new process no\r
+               $processNo = PackageInstallationQueue::getNewProcessNo();\r
+               \r
+               // obey foreign key\r
+               $packageID = ($this->packageID) ? $this->packageID : null;\r
+               \r
+               // insert queue\r
+               $this->queue = PackageInstallationQueueEditor::create(array(\r
+                       'processNo' => $processNo,\r
+                       'userID' => WCF::getUser()->userID,\r
+                       'package' => $this->archive->getPackageInfo('name'),\r
+                       'packageName' => $this->archive->getPackageInfo('packageName'),\r
+                       'packageID' => $packageID,\r
+                       'archive' => (!empty($this->uploadPackage['tmp_name']) ? $this->uploadPackage['name'] : $this->downloadPackage),\r
+                       'action' => ($this->package != null ? 'update' : 'install'),\r
+                       'confirmInstallation' => 1,\r
+                       'cancelable' => ($this->package != null ? 0 : 1)\r
+               ));\r
+               \r
+               $this->saved();\r
+               \r
+               // open queue\r
+               HeaderUtil::redirect('index.php?page=Package&action=openQueue&processNo='.$processNo.''.SID_ARG_2ND_NOT_ENCODED);\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'packageID' => $this->packageID,\r
+                       'package' => $this->package\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               if ($this->action == 'install') WCF::getSession()->checkPermission(array('admin.system.package.canInstallPackage'));\r
+               else WCF::getSession()->checkPermission(array('admin.system.package.canUpdatePackage'));\r
+               \r
+               // check master password\r
+               WCFACP::checkMasterPassword();\r
+               \r
+               parent::show();\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/PackageUpdateAuthForm.class.php b/wcfsetup/install/files/lib/acp/form/PackageUpdateAuthForm.class.php
new file mode 100644 (file)
index 0000000..81928c0
--- /dev/null
@@ -0,0 +1,261 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\data\package\update\server\PackageUpdateServerEditor;
+use wcf\system\package\PackageUpdateAuthorizationRequiredException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the package update authentification form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class PackageUpdateAuthForm extends ACPForm {
+       public $templateName = 'packageUpdateAuth';
+       public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canInstallPackage');
+       public $activeMenuItem = 'wcf.acp.menu.link.package';
+       
+       public $exception;
+       public $loginUsername = '';
+       public $loginPassword = '';
+       public $saveAuthData = 0;
+       
+       public $packageUpdateServerID = 0;
+       public $url = '';
+       public $eader = '';
+       public $realm = '';
+       public $message = '';
+       
+       public $postParameters = '';
+       public $getParameters = '';
+       
+       protected static $reservedParameters = array('s', 'packageID', 'page', 'form', 'action', 'packageUpdateServerID', 'loginUsername', 'loginPassword', 'saveAuthData', 'requestedPage', 'requestedForm', 'requestedAction');
+       
+       /**
+        * Creates a new PackageUpdateAuthForm object.
+        * 
+        * @param       PackageUpdateAuthorizationRequiredException     $exception
+        */
+       public function __construct(PackageUpdateAuthorizationRequiredException $exception = null) {
+               $this->exception = $exception;
+               if ($this->exception !== null) {
+                       $this->packageUpdateServerID = $this->exception->getPackageUpdateServerID();
+                       $this->url = $this->exception->getURL();
+                       $this->header = $this->exception->getResponseHeader();
+                       
+                       // get message
+                       $this->message = $this->exception->getResponseContent();
+                       
+                       // find out response charset
+                       if (preg_match('/charset=([a-z0-9\-]+)/i', $this->header, $match)) {
+                               $charset = strtoupper($match[1]);
+                               if ($charset != 'UTF-8') $this->message = @StringUtil::convertEncoding($charset, 'UTF-8', $this->message);
+                       }
+                       
+                       // format message
+                       $this->message = nl2br(preg_replace("/\n{3,}/", "\n\n", StringUtil::unifyNewlines(StringUtil::trim(strip_tags($this->message)))));
+               }
+               
+               parent::__construct();
+       }
+       
+       /**
+        * @see Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_REQUEST['loginUsername'])) $this->loginUsername = $_REQUEST['loginUsername'];
+               if (isset($_REQUEST['loginPassword'])) $this->loginPassword = $_REQUEST['loginPassword'];
+               if (isset($_REQUEST['saveAuthData'])) $this->saveAuthData = intval($_REQUEST['saveAuthData']);
+               if ($this->packageUpdateServerID == 0 && isset($_REQUEST['packageUpdateServerID'])) $this->packageUpdateServerID = intval($_REQUEST['packageUpdateServerID']);
+               
+               if (!empty($_REQUEST['requestedPage']) || !empty($_REQUEST['requestedForm']) || !empty($_REQUEST['requestedAction'])) {
+                       // get update server
+                       $updateServer = new PackageUpdateServer($this->packageUpdateServerID);
+                       if (!$updateServer->packageUpdateServerID) {
+                               throw new IllegalLinkException();
+                       }
+                       
+                       // update update server
+                       if ($this->saveAuthData) {
+                               $updateServerEditor = new PackageUpdateServerEditor($updateServer);
+                               $updateServerEditor->update(array(
+                                       'loginUsername' => $this->loginUsername,
+                                       'loginPassword' => $this->loginPassword
+                               ));
+                       }
+                       
+                       // save auth data in session
+                       $authData = array(
+                               'authType' => 'Basic',
+                               'loginUsername' => $this->loginUsername,
+                               'loginPassword' => $this->loginPassword
+                       );
+                       
+                       // session data
+                       $packageUpdateAuthData = WCF::getSession()->getVar('packageUpdateAuthData');
+                       if ($packageUpdateAuthData === null) $packageUpdateAuthData = array();
+                       $packageUpdateAuthData[$this->packageUpdateServerID] = $authData;
+                       WCF::getSession()->register('packageUpdateAuthData', $packageUpdateAuthData);
+                       
+                       // remove form=PackageUpdateAuth
+                       unset($_REQUEST['form'], $_GET['form'], $_POST['form']);
+                       
+                       // set page/form/action
+                       if (!empty($_REQUEST['requestedPage'])) {
+                               $_POST['page'] = $_REQUEST['requestedPage'];
+                       }
+                       else if (!empty($_REQUEST['requestedForm'])) {
+                               $_POST['form'] = $_REQUEST['requestedForm'];
+                       }
+                       else {
+                               $_POST['action'] = $_REQUEST['requestedAction'];
+                       }
+                       
+                       // remove requestedPage...
+                       unset($_REQUEST['requestedPage'], $_REQUEST['requestedForm'], $_REQUEST['requestedAction']);
+                       
+                       // start request handler
+                       
+                       /**
+                        * TODO: This is not working anymore, find a solution!
+                        */
+                       
+                       global $packageDirs;
+                       RequestHandler::handle(ArrayUtil::appendSuffix(!empty($packageDirs) ? $packageDirs : array(WCF_DIR), 'lib/acp/'));
+                       exit;
+               }
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               // extract realm
+               if (preg_match('/realm="(.*?)"/i', $this->header, $match)) {
+                       $this->realm = $match[1];
+               }
+               
+               // get existing auth data
+               if ($this->packageUpdateServerID) {
+                       $updateServer = new PackageUpdateServer($this->packageUpdateServerID);
+                       $authData = $updateServer->getAuthData();
+                       if (isset($authData['loginUsername'])) $this->loginUsername = $authData['loginUsername'];
+                       if (isset($authData['loginPassword'])) $this->loginPassword = $authData['loginPassword'];
+                       
+                       if (isset($authData['loginUsername']) || isset($authData['loginPassword'])) {
+                               $this->errorField = 'loginPassword';
+                               $this->errorType = 'invalid';
+                       }
+               }
+               
+               $this->buildPostParameters();
+               $this->buildGetParameters();
+               
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'loginUsername' => $this->loginUsername,
+                       'loginPassword' => $this->loginPassword,
+                       'saveAuthData' => $this->saveAuthData,
+                       'packageUpdateServerID' => $this->packageUpdateServerID,
+                       'url' => $this->url,
+                       'realm' => $this->realm,
+                       'message' => $this->message,
+                       'requestMethod' => WCF::getSession()->requestMethod,
+                       'postParameters' => $this->postParameters,
+                       'getParameters' => $this->getParameters
+               ));
+       }
+       
+       /**
+        * Builds a list of POST parameters.
+        */
+       protected function buildPostParameters() {
+               $postParameters = array();
+               
+               if (isset($_POST['page'])) $postParameters['requestedPage'] = $_POST['page'];
+               if (isset($_POST['form'])) $postParameters['requestedForm'] = $_POST['form'];
+               if (isset($_POST['action'])) $postParameters['requestedAction'] = $_POST['action'];
+               
+               foreach ($_POST as $key => $value) {
+                       if (!in_array($key, self::$reservedParameters)) {
+                               $postParameters[$key] = $value;
+                       }
+               }
+               
+               $this->buildPostParametersList($postParameters);
+       }
+       
+       /**
+        * Builds a list of POST parameters.
+        * 
+        * @param       array           $parameters
+        * @param       string          $prefix
+        */
+       protected function buildPostParametersList($parameters, $prefix = '') {
+               foreach ($parameters as $key => $value) {
+                       $key = StringUtil::encodeHTML($key);
+                       if (is_array($value)) {
+                               $this->buildPostParametersList($value, (!empty($prefix) ? $prefix."[".$key."]" : $key));
+                       }
+                       else {
+                               $this->postParameters .= '<input type="hidden" name="'.(!empty($prefix) ? $prefix."[".$key."]" : $key).'" value="'.StringUtil::encodeHTML($value).'" />';
+                       }
+               }
+       }
+       
+       /**
+        * Builds a list of GET parameters.
+        */
+       protected function buildGetParameters() {
+               $getParameters = array();
+               
+               if (isset($_GET['page'])) $getParameters['requestedPage'] = $_GET['page'];
+               if (isset($_GET['form'])) $getParameters['requestedForm'] = $_GET['form'];
+               if (isset($_GET['action'])) $getParameters['requestedAction'] = $_GET['action'];
+               
+               foreach ($_GET as $key => $value) {
+                       if (!in_array($key, self::$reservedParameters)) {
+                               $getParameters[$key] = $value;
+                       }
+               }
+               
+               $this->buildPostParametersList($getParameters);
+       }
+       
+       /**
+        * Builds a list of GET parameters.
+        * 
+        * @param       array           $parameters
+        * @param       string          $prefix 
+        */
+       protected function buildGetParametersList($parameters, $prefix = '') {
+               foreach ($parameters as $key => $value) {
+                       $key = rawurlencode($key);
+                       if (is_array($value)) {
+                               $this->buildGetParametersList($value, (!empty($prefix) ? $prefix."[".$key."]" : $key));
+                       }
+                       else {
+                               if (!empty($this->getParameters)) $this->getParameters .= '&';
+                               $this->getParameters .= (!empty($prefix) ? $prefix."[".$key."]" : $key).'='.rawurlencode($value);
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/form/PackageUpdateForm.class.php b/wcfsetup/install/files/lib/acp/form/PackageUpdateForm.class.php
new file mode 100644 (file)
index 0000000..34aacce
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+namespace wcf\acp\form;
+use wcf\system\exception\SystemException;
+use wcf\system\exception\UserInputException;
+use wcf\system\package\PackageUpdateDispatcher;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\util\HeaderUtil;
+
+/**
+ * Shows the package update confirmation form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class PackageUpdateForm extends ACPForm {
+       public $templateName = 'packageUpdate';
+       public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canInstallPackage');
+       public $activeMenuItem = 'wcf.acp.menu.link.package';
+       
+       public $updates = array();
+       public $excludedPackages = array();
+       public $packageInstallationStack = array();
+       public $packageUpdate = null;
+       
+       /**
+        * @see Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_POST['updates']) && is_array($_POST['updates'])) $this->updates = $_POST['updates'];
+       }
+       
+       /**
+        * @see Form::validate()
+        */
+       public function validate() {
+               parent::validate();
+               
+               if (!count($this->updates)) {
+                       throw new UserInputException('updates');
+               }
+               
+               // build update stack
+               $this->packageUpdate = PackageUpdateDispatcher::prepareInstallation($this->updates, array(), isset($_POST['send']));
+               try {
+                       $this->packageUpdate->buildPackageInstallationStack();
+                       $this->excludedPackages = $this->packageUpdate->getExcludedPackages();
+                       if (count($this->excludedPackages)) {
+                               throw new UserInputException('excludedPackages');
+                       }
+               }
+               catch (SystemException $e) {
+                       // show detailed error message
+                       throw new UserInputException('updates', $e);
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               if (isset($_POST['send'])) {
+                       parent::save();
+                       
+                       // save stack
+                       $processNo = $this->packageUpdate->savePackageInstallationStack();
+                       $this->saved();
+                       
+                       // open queue
+                       HeaderUtil::redirect('index.php?page=Package&action=openQueue&processNo='.$processNo.''.SID_ARG_2ND_NOT_ENCODED);
+                       exit;
+               }
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               // get installation stack
+               if ($this->packageInstallationStack !== null && $this->packageUpdate !== null) {
+                       $this->packageInstallationStack = $this->packageUpdate->getPackageInstallationStack();
+               }
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'updates' => $this->updates,
+                       'packageInstallationStack' => $this->packageInstallationStack,
+                       'excludedPackages' => $this->excludedPackages
+               ));
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function show() {
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/form/PackageUpdateSearchForm.class.php b/wcfsetup/install/files/lib/acp/form/PackageUpdateSearchForm.class.php
new file mode 100644 (file)
index 0000000..17cad2b
--- /dev/null
@@ -0,0 +1,226 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\data\search\SearchEditor;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\UserInputException;
+use wcf\system\package\PackageUpdateDispatcher;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\util\HeaderUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the package update search form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class PackageUpdateSearchForm extends ACPForm {
+       public $templateName = 'packageUpdateSearch';
+       public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canInstallPackage');
+       public $activeMenuItem = 'wcf.acp.menu.link.package.database';
+       
+       public $packageUpdateServerIDs = array();
+       public $packageName = '';
+       public $author = '';
+       public $searchDescription = 0;
+       public $plugin = 1;
+       public $standalone = 1;
+       public $other = 0;
+       public $ignoreUniques = 1;
+       
+       public $updateServers = array();
+       public $packageUpdateIDs = '';
+       
+       /**
+        * @see Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               $this->ignoreUniques = $this->plugin = $this->standalone = 0;
+               if (isset($_POST['packageUpdateServerIDs']) && is_array($_POST['packageUpdateServerIDs'])) $this->packageUpdateServerIDs = ArrayUtil::toIntegerArray($_POST['packageUpdateServerIDs']);
+               if (isset($_POST['packageName'])) $this->packageName = StringUtil::trim($_POST['packageName']);
+               if (isset($_POST['author'])) $this->author = StringUtil::trim($_POST['author']);
+               if (isset($_POST['searchDescription'])) $this->searchDescription = intval($_POST['searchDescription']);
+               if (isset($_POST['plugin'])) $this->plugin = intval($_POST['plugin']);
+               if (isset($_POST['standalone'])) $this->standalone = intval($_POST['standalone']);
+               if (isset($_POST['other'])) $this->other = intval($_POST['other']);
+               if (isset($_POST['ignoreUniques'])) $this->ignoreUniques = intval($_POST['ignoreUniques']);
+       }
+       
+       /**
+        * @see Form::validate()
+        */
+       public function validate() {
+               parent::validate();
+
+               // refresh package database
+               PackageUpdateDispatcher::refreshPackageDatabase($this->packageUpdateServerIDs);
+               
+               // build conditions
+               $conditions = new PreparedStatementConditionBuilder();
+               // update servers
+               if (count($this->packageUpdateServerIDs)) $conditions->add("packageUpdateServerID IN (?)", array($this->packageUpdateServerIDs));
+               // name
+               if (!empty($this->packageName)) {
+                       $condition = "packageName LIKE ?";
+                       $parameters = array('%'.$this->packageName.'%');
+                       
+                       if ($this->searchDescription) {
+                               $condition .= " OR packageDescription LIKE ?";
+                               $parameters[] = '%'.$this->packageName.'%';
+                       }
+                       
+                       $conditions->add('('.$condition.')', $parameters);
+               }
+               // author
+               if (!empty($this->author)) $conditions->add("author LIKE ?", array($this->author));
+               // ignore already installed uniques
+               if ($this->ignoreUniques == 1) $conditions->add("package NOT IN (SELECT package FROM wcf".WCF_N."_package WHERE isUnique = 1)");
+               // package type
+               if (($this->plugin == 0 || $this->standalone == 0 || $this->other == 0) && ($this->plugin == 1 || $this->standalone == 1 || $this->other == 1)) {
+                       if ($this->standalone == 1) {
+                               $condition = 'standalone = 1';
+                               if ($this->plugin == 1) {
+                                       $condition .= " OR plugin IN (SELECT package FROM wcf".WCF_N."_package)";
+                               }
+                               else if ($this->other == 1) { 
+                                       $condition .= " OR plugin = ''";
+                               }
+                               
+                               $conditions->add('('.$condition.')');
+                       }
+                       else if ($this->plugin == 1) {
+                               $condition = "plugin IN (SELECT package FROM wcf".WCF_N."_package)";
+                               if ($this->other == 1) { 
+                                       $condition .= " OR standalone = 0";
+                               }
+                               
+                               $conditions->add('('.$condition.')');
+                       }
+                       else if ($this->other) {
+                               $conditions->add("(standalone = 0 AND plugin = '')");
+                       }
+               }
+               
+               // search package database
+               $packages = array();
+               $packageUpdateIDs = array();
+               $sql = "SELECT  package, packageUpdateID
+                       FROM    wcf".WCF_N."_package_update
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql, 1000);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $packageUpdateIDs[] = $row['packageUpdateID'];
+                       
+                       if (!isset($packages[$row['package']])) $packages[$row['package']] = array();
+                       $packages[$row['package']][$row['packageUpdateID']] = array();
+               }
+               
+               if (empty($packageUpdateIDs)) {
+                       throw new UserInputException('packageName');
+               }
+               
+               // remove duplicates
+               $condition = '';
+               $statementParameters = array();
+               foreach ($packageUpdateIDs as $packageUpdateID) {
+                       if (!empty($condition)) $condition .= ',';
+                       $condition .= '?';
+                       $statementParameters[] = $packageUpdateID;
+               }
+               
+               $sql = "SELECT          puv.packageVersion, pu.package, pu.packageUpdateID
+                       FROM            wcf".WCF_N."_package_update_version puv
+                       LEFT JOIN       wcf".WCF_N."_package_update pu
+                       ON              (pu.packageUpdateID = puv.packageUpdateID)
+                       WHERE           puv.packageUpdateID IN (".$condition.")";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($statementParameters);
+               while ($row = $statement->fetchArray()) {
+                       $packages[$row['package']][$row['packageUpdateID']][] = $row['packageVersion'];
+               }
+               
+               foreach ($packages as $identifier => $packageUpdates) {
+                       if (count($packageUpdates) > 1) {
+                               foreach ($packageUpdates as $packageUpdateID => $versions) {
+                                       usort($versions, array('wcf\data\package\Package', 'compareVersion'));
+                                       $packageUpdates[$packageUpdateID] = array_pop($versions);
+                               }
+                               
+                               uasort($packageUpdates, array('wcf\data\package\Package', 'compareVersion'));
+                       }
+                       
+                       $keys = array_keys($packageUpdates);
+                       if (!empty($this->packageUpdateIDs)) $this->packageUpdateIDs .= ',';
+                       $this->packageUpdateIDs .= array_pop($keys);
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               parent::save();
+               
+               // save search
+               $search = SearchEditor::create(array(
+                       'userID' => WCF::getUser()->userID,
+                       'searchData' => $this->packageUpdateServerIDs,
+                       'searchTime' => TIME_NOW,
+                       'searchType' => 'packages'
+               ));
+               
+               $this->saved();
+               
+               // forward
+               HeaderUtil::redirect('index.php?page=PackageUpdateSearchResult&searchID='.$search->searchID.''.SID_ARG_2ND_NOT_ENCODED);
+               exit;
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               $this->updateServers = PackageUpdateServer::getActiveUpdateServers();
+       }
+
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'updateServers' => $this->updateServers,
+                       'packageName' => $this->packageName,
+                       'searchDescription' => $this->searchDescription,
+                       'author' => $this->author,
+                       'standalone' => $this->standalone,
+                       'plugin' => $this->plugin,
+                       'other' => $this->other,
+                       'packageUpdateServerIDs' => $this->packageUpdateServerIDs,
+                       'ignoreUniques' => $this->ignoreUniques
+               ));
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function show() {
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/form/UpdateServerAddForm.class.php b/wcfsetup/install/files/lib/acp/form/UpdateServerAddForm.class.php
new file mode 100644 (file)
index 0000000..015c33a
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\data\package\update\server\PackageUpdateServerAction;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\system\exception\UserInputException;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the server add form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class UpdateServerAddForm extends ACPForm {
+       /**
+        * @see AbstractPage::$templateName
+        */
+       public $templateName = 'updateServerAdd';
+       
+       /**
+        * @see ACPForm::$activeMenuItem
+        */
+       public $activeMenuItem = 'wcf.acp.menu.link.package.server.add';
+       
+       /**
+        * @see AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.system.package.canEditServer');
+       
+       /**
+        * server url
+        * @var string
+        */
+       public $server = '';
+       
+       /**
+        * server login username
+        * @var string
+        */
+       public $loginUsername = '';
+       
+       /**
+        * server login password
+        * @var string
+        */
+       public $loginPassword = '';
+       
+       /**
+        * @see Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_POST['server'])) $this->server = StringUtil::trim($_POST['server']);
+               if (isset($_POST['loginUsername'])) $this->loginUsername = $_POST['loginUsername'];
+               if (isset($_POST['loginPassword'])) $this->loginPassword = $_POST['loginPassword'];
+       }
+       
+       /**
+        * @see Form::validate()
+        */
+       public function validate() {
+               parent::validate();
+               
+               if (empty($this->server)) {
+                       throw new UserInputException('server');
+               }
+               
+               if (!PackageUpdateServer::isValidServerURL($this->server)) {
+                       throw new UserInputException('server', 'notValid');
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               parent::save();
+               
+               // save server
+               $updateServerAction = new PackageUpdateServerAction(array(), 'create', array('data' => array(
+                       'server' => $this->server,
+                       'loginUsername' => $this->loginUsername,
+                       'loginPassword' => $this->loginPassword
+               )));
+               $updateServer = $updateServerAction->executeAction();
+               $this->saved();
+               
+               // reset values
+               $this->server = $this->loginUsername = $this->loginPassword = '';
+               
+               // show success message
+               WCF::getTPL()->assign('success', true);
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'server' => $this->server,
+                       'loginUsername' => $this->loginUsername,
+                       'loginPassword' => $this->loginPassword,
+                       'action' => 'add'
+               ));
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function show() {
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               parent::show();
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/UpdateServerEditForm.class.php b/wcfsetup/install/files/lib/acp/form/UpdateServerEditForm.class.php
new file mode 100644 (file)
index 0000000..6a3e71f
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\data\package\update\server\PackageUpdateServerAction;
+use wcf\form\AbstractForm;
+use wcf\system\WCF;
+use wcf\system\exception\IllegalLinkException;
+
+/**
+ * Shows the server edit form.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class UpdateServerEditForm extends UpdateServerAddForm {
+       /**
+        * @see ACPForm::$activeMenuItem
+        */
+       public $activeMenuItem = 'wcf.acp.menu.link.package.server';
+       
+       /**
+        * update server id
+        * @var integer
+        */
+       public $packageUpdateServerID = 0;
+       
+       /**
+        * active package update server
+        * @var PackageUpdateServer
+        */
+       public $updateServer = null;
+       
+       /**
+        * @see Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_REQUEST['packageUpdateServerID'])) $this->packageUpdateServerID = intval($_REQUEST['packageUpdateServerID']);
+               $this->updateServer = new PackageUpdateServer($this->packageUpdateServerID);
+               if (!$this->updateServer->packageUpdateServerID) {
+                       throw new IllegalLinkException();
+               }
+       }
+       
+       /**
+        * @see Form::save()
+        */
+       public function save() {
+               AbstractForm::save();
+               
+               // save server
+               $updateServerAction = new PackageUpdateServerAction(array($this->packageUpdateServerID), 'update', array('data' => array(
+                       'server' => $this->server,
+                       'loginUsername' => $this->loginUsername,
+                       'loginPassword' => $this->loginPassword
+               )));
+               $updateServerAction->executeAction();
+               $this->saved();
+               
+               // show success message
+               WCF::getTPL()->assign('success', true);
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               if (!count($_POST)) {
+                       $this->server = $this->updateServer->server;
+                       $this->loginUsername = $this->updateServer->loginUsername;
+                       $this->loginPassword = $this->updateServer->loginPassword;
+               }
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+                       
+               WCF::getTPL()->assign(array(
+                       'packageUpdateServerID' => $this->packageUpdateServerID,
+                       'packageUpdateServer' => $this->updateServer,
+                       'action' => 'edit'
+               ));
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/UserAddForm.class.php b/wcfsetup/install/files/lib/acp/form/UserAddForm.class.php
new file mode 100644 (file)
index 0000000..5359377
--- /dev/null
@@ -0,0 +1,341 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\option\Option;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\data\user\UserAction;\r
+use wcf\form\AbstractForm;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\language\LanguageFactory;\r
+use wcf\system\WCF;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\StringUtil;\r
+use wcf\util\UserUtil;\r
+\r
+/**\r
+ * Shows the user add form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserAddForm extends UserOptionListForm {\r
+       /**\r
+        * @see AbstractPage::$templateName\r
+        */\r
+       public $templateName = 'userAdd';\r
+       \r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.user.canAddUser');\r
+       \r
+       /**\r
+        * name of the active menu item\r
+        * @var string\r
+        */\r
+       public $menuItemName = 'wcf.acp.menu.link.user.add';\r
+       \r
+       /**\r
+        * username\r
+        * @var string\r
+        */\r
+       public $username = '';\r
+       \r
+       /**\r
+        * email address\r
+        * @var string\r
+        */\r
+       public $email = '';\r
+       \r
+       /**\r
+        * confirmed email address\r
+        * @var string\r
+        */\r
+       public $confirmEmail = '';\r
+       \r
+       /**\r
+        * user password\r
+        * @var string\r
+        */\r
+       public $password = '';\r
+       \r
+       /**\r
+        * confirmed user password\r
+        * @var string\r
+        */\r
+       public $confirmPassword = '';\r
+       \r
+       /**\r
+        * user group ids\r
+        * @var array<integer>\r
+        */\r
+       public $groupIDs = array();\r
+       \r
+       /**\r
+        * language id\r
+        * @var integer\r
+        */\r
+       public $languageID = 0;\r
+       \r
+       /**\r
+        * visible languages\r
+        * @var array<integer>\r
+        */\r
+       public $visibleLanguages = array();\r
+       \r
+       /**\r
+        * additional fields\r
+        * @var array<mixed>\r
+        */\r
+       public $additionalFields = array();\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']); \r
+               if (isset($_POST['email'])) $this->email = StringUtil::trim($_POST['email']);\r
+               if (isset($_POST['confirmEmail'])) $this->confirmEmail = StringUtil::trim($_POST['confirmEmail']);\r
+               if (isset($_POST['password'])) $this->password = $_POST['password'];\r
+               if (isset($_POST['confirmPassword'])) $this->confirmPassword = $_POST['confirmPassword'];\r
+               if (isset($_POST['groupIDs']) && is_array($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);\r
+               if (isset($_POST['visibleLanguages']) && is_array($_POST['visibleLanguages'])) $this->visibleLanguages = ArrayUtil::toIntegerArray($_POST['visibleLanguages']);\r
+               if (isset($_POST['languageID'])) $this->languageID = intval($_POST['languageID']);\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               // validate static user options \r
+               try {\r
+                       $this->validateUsername($this->username); \r
+               }\r
+               catch (UserInputException $e) {\r
+                       $this->errorType[$e->getField()] = $e->getType();\r
+               }\r
+               \r
+               try {\r
+                       $this->validateEmail($this->email, $this->confirmEmail); \r
+               }\r
+               catch (UserInputException $e) {\r
+                       $this->errorType[$e->getField()] = $e->getType();\r
+               }\r
+               \r
+               try {\r
+                       $this->validatePassword($this->password, $this->confirmPassword);\r
+               }\r
+               catch (UserInputException $e) {\r
+                       $this->errorType[$e->getField()] = $e->getType();\r
+               }\r
+               \r
+               // validate user groups\r
+               if (count($this->groupIDs) > 0) {\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("groupID IN (?)", array($this->groupIDs));\r
+                       $conditions->add("groupType NOT IN (?)", array(array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS)));\r
+                       \r
+                       $sql = "SELECT  groupID\r
+                               FROM    wcf".WCF_N."_user_group\r
+                               ".$conditions;\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       $this->groupIDs = array();\r
+                       while ($row = $statement->fetchArray()) {\r
+                               if (UserGroup::isAccessibleGroup(array($row['groupID']))) {\r
+                                       $this->groupIDs[] = $row['groupID'];\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // validate user language\r
+               $language = LanguageFactory::getLanguage($this->languageID);\r
+               if (!$language->languageID) {\r
+                       // use default language\r
+                       $this->languageID = LanguageFactory::getDefaultLanguageID();\r
+               }\r
+               \r
+               // validate visible languages\r
+               foreach ($this->visibleLanguages as $key => $visibleLanguage) {\r
+                       $language = LanguageFactory::getLanguage($visibleLanguage);\r
+                       if (!$language->languageID || !$language->hasContent) {\r
+                               unset($this->visibleLanguages[$key]);\r
+                       }\r
+               }\r
+               if (!count($this->visibleLanguages) && ($language = LanguageFactory::getLanguage($this->languageID)) && $language->hasContent) {\r
+                       $this->visibleLanguages[] = $this->languageID;\r
+               }\r
+               \r
+               // validate dynamic options\r
+               parent::validate();\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               AbstractForm::save();\r
+               \r
+               // create\r
+               $saveOptions = array();\r
+               foreach ($this->options as $option) {\r
+                       $saveOptions[$option->optionID] = $this->optionValues[$option->optionName];\r
+               }\r
+               $this->additionalFields['languageID'] = $this->languageID;\r
+               $data = array(\r
+                       'data' => array_merge($this->additionalFields, array(\r
+                               'username' => $this->username,\r
+                               'email' => $this->email,\r
+                               'password' => $this->password,\r
+                       )),\r
+                       'groups' => $this->groupIDs,\r
+                       'languages' => $this->visibleLanguages,\r
+                       'options' => $saveOptions\r
+               );\r
+               $userAction = new UserAction(array(), 'create', $data);\r
+               $userAction->executeAction();\r
+               $this->saved();\r
+               \r
+               // show empty add form\r
+               WCF::getTPL()->assign(array(\r
+                       'success' => true\r
+               ));\r
+               \r
+               // reset values\r
+               $this->username = $this->email = $this->confirmEmail = $this->password = $this->confirmPassword = '';\r
+               $this->groupIDs = array();\r
+               $this->languageID = $this->getDefaultFormLanguageID();\r
+               $this->optionValues = array();\r
+       }\r
+       \r
+       /**\r
+        * Throws a UserInputException if the username is not unique or not valid.\r
+        * \r
+        * @param       string          $username\r
+        */\r
+       protected function validateUsername($username) {\r
+               if (empty($username)) {\r
+                       throw new UserInputException('username');\r
+               }\r
+               \r
+               // check for forbidden chars (e.g. the ",")\r
+               if (!UserUtil::isValidUsername($username)) {\r
+                       throw new UserInputException('username', 'notValid');\r
+               }\r
+               \r
+               // Check if username exists already.\r
+               if (!UserUtil::isAvailableUsername($username)) {\r
+                       throw new UserInputException('username', 'notUnique');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Throws a UserInputException if the email is not unique or not valid.\r
+        * \r
+        * @param       string          $email\r
+        * @param       string          $confirmEmail\r
+        */\r
+       protected function validateEmail($email, $confirmEmail) {\r
+               if (empty($email)) {    \r
+                       throw new UserInputException('email');\r
+               }\r
+               \r
+               // check for valid email (one @ etc.)\r
+               if (!UserUtil::isValidEmail($email)) {\r
+                       throw new UserInputException('email', 'notValid');\r
+               }\r
+               \r
+               // Check if email exists already.\r
+               if (!UserUtil::isAvailableEmail($email)) {\r
+                       throw new UserInputException('email', 'notUnique');\r
+               }\r
+               \r
+               // check confirm input\r
+               if (StringUtil::toLowerCase($email) != StringUtil::toLowerCase($confirmEmail)) {\r
+                       throw new UserInputException('confirmEmail', 'notEqual');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Throws a UserInputException if the password is not valid.\r
+        * \r
+        * @param       string          $password\r
+        * @param       string          $confirmPassword\r
+        */\r
+       protected function validatePassword($password, $confirmPassword) {\r
+               if (empty($password)) {\r
+                       throw new UserInputException('password');\r
+               }\r
+               \r
+               // check confirm input\r
+               if ($password != $confirmPassword) {\r
+                       throw new UserInputException('confirmPassword', 'notEqual');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               $this->optionTree = $this->getOptionTree();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'username' => $this->username,\r
+                       'email' => $this->email,\r
+                       'confirmEmail' => $this->confirmEmail,\r
+                       'password' => $this->password,\r
+                       'confirmPassword' => $this->confirmPassword,\r
+                       'groupIDs' => $this->groupIDs,\r
+                       'optionTree' => $this->optionTree,\r
+                       'availableGroups' => $this->getAvailableGroups(),\r
+                       'availableLanguages' => $this->getAvailableLanguages(),\r
+                       'languageID' => $this->languageID,\r
+                       'visibleLanguages' => $this->visibleLanguages,\r
+                       'availableContentLanguages' => $this->getAvailableContentLanguages(),\r
+                       'action' => 'add'\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               // set active menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem($this->menuItemName);\r
+               \r
+               // get the default langauge id\r
+               $this->languageID = $this->getDefaultFormLanguageID();\r
+               \r
+               // get user options and categories from cache\r
+               $this->readCache();\r
+               \r
+               // show form\r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractOptionListForm::checkOption()\r
+        */\r
+       protected static function checkOption(Option $option) {\r
+               if (!parent::checkOption($option)) return false;\r
+               \r
+               return ($option->editable != 1 && $option->editable != 4 && !$option->disabled);\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/UserAssignToGroupForm.class.php b/wcfsetup/install/files/lib/acp/form/UserAssignToGroupForm.class.php
new file mode 100644 (file)
index 0000000..4b55abf
--- /dev/null
@@ -0,0 +1,139 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\data\user\UserEditor;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\exception\PermissionDeniedException;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\session\SessionHandler;\r
+use wcf\system\WCF;\r
+use wcf\util\ArrayUtil;\r
+\r
+/**\r
+ * Shows the assign user to group form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserAssignToGroupForm extends ACPForm {\r
+       public $templateName = 'userAssignToGroup';\r
+       public $activeMenuItem = 'wcf.acp.menu.link.user.management';\r
+       public $neededPermissions = array('admin.user.canEditUser');\r
+       \r
+       public $userIDs = array();\r
+       public $groupIDs = array();\r
+       public $users = array();\r
+       public $groups = array();\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['userIDs'])) $this->userIDs = ArrayUtil::toIntegerArray(explode(',', $_POST['userIDs']));\r
+               if (isset($_POST['groupIDs']) && is_array($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               if (empty($this->userIDs)) throw new IllegalLinkException();\r
+               \r
+               // groups\r
+               foreach ($this->groupIDs as $groupID) {\r
+                       $group = new UserGroup($groupID);\r
+                       if (!$group->groupID) throw new UserInputException('groupIDs');\r
+                       if (!$group->isAccessible()) {\r
+                               throw new PermissionDeniedException();\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               $conditions = new PreparedStatementConditionBuilder();\r
+               $conditions->add("userID IN (?)", array($this->userIDs));\r
+               \r
+               $sql = "SELECT  userID, groupID\r
+                       FROM    wcf".WCF_N."_user_to_group\r
+                       ".$conditions;\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute($conditions->getParameters());\r
+               \r
+               $groups = array();\r
+               while ($row = $statement->fetchArray()) {\r
+                       $groups[$row['userID']][] = $row['groupID'];\r
+               }\r
+               \r
+               foreach ($this->users as $user) {\r
+                       if (!UserGroup::isAccessibleGroup($groups[$user->userID])) {\r
+                               throw new PermissionDeniedException();\r
+                       }\r
+                       \r
+                       $userEditor = new UserEditor($user);\r
+                       $userEditor->addToGroups($groups[$user->userID], false, false);\r
+               }\r
+               \r
+               // TODO: Implement unmarkAll()\r
+               //UserEditor::unmarkAll();\r
+               SessionHandler::resetSessions($this->userIDs);\r
+               $this->saved();\r
+               WCF::getTPL()->assign('message', 'wcf.acp.user.assignToGroup.success');\r
+               WCF::getTPL()->display('success');\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               if (!count($_POST)) {\r
+                       // get marked user ids\r
+                       $markedUsers = WCF::getSession()->getVar('markedUsers');\r
+                       if (is_array($markedUsers)) {\r
+                               $this->userIDs = $markedUsers;\r
+                       }\r
+                       if (empty($this->userIDs)) throw new IllegalLinkException();\r
+               }\r
+               \r
+               $this->users = User::getUsers($this->userIDs);\r
+               $this->readGroups();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'users' => $this->users,\r
+                       'userIDs' => $this->userIDs,\r
+                       'groupIDs' => $this->groupIDs,\r
+                       'groups' => $this->groups\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * Get a list of available groups.\r
+        */\r
+       protected function readGroups() {\r
+               $this->groups = UserGroup::getAccessibleGroups(array(), array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/UserEditForm.class.php b/wcfsetup/install/files/lib/acp/form/UserEditForm.class.php
new file mode 100644 (file)
index 0000000..8d60b83
--- /dev/null
@@ -0,0 +1,201 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\user\User;\r
+use wcf\data\user\UserAction;\r
+use wcf\data\user\UserEditor;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\form\AbstractForm;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\exception\PermissionDeniedException;\r
+use wcf\system\WCF;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the user edit form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserEditForm extends UserAddForm {\r
+       /**\r
+        * @see UserAddForm::$menuItemName\r
+        */\r
+       public $menuItemName = 'wcf.acp.menu.link.user.management';\r
+       \r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.user.canEditUser');\r
+       \r
+       /**\r
+        * user id\r
+        * @var integer\r
+        */\r
+       public $userID = 0;\r
+       \r
+       /**\r
+        * user editor object\r
+        * @var UserEditor\r
+        */\r
+       public $user = null;\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['userID'])) {\r
+                       $this->userID = intval($_REQUEST['userID']);\r
+                       $user = new User($this->userID);\r
+                       if (!$user->userID) {\r
+                               throw new IllegalLinkException();\r
+                       }\r
+                       \r
+                       $this->user = new UserEditor($user);\r
+                       if (!UserGroup::isAccessibleGroup($this->user->getGroupIDs())) {\r
+                               throw new PermissionDeniedException();\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (!WCF::getSession()->getPermission('admin.user.canEditPassword')) $this->password = $this->confirmPassword = '';\r
+               if (!WCF::getSession()->getPermission('admin.user.canEditMailAddress')) $this->email = $this->confirmEmail = $this->user->email;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               if (!count($_POST)) {\r
+                       // get visible languages\r
+                       $this->readVisibleLanguages();\r
+                       \r
+                       // default values\r
+                       $this->readDefaultValues();\r
+               }\r
+               \r
+               parent::readData();\r
+       }\r
+       \r
+       /**\r
+        * Gets the selected languages.\r
+        */\r
+       protected function readVisibleLanguages() {\r
+               $this->visibleLanguages = $this->user->getLanguageIDs();\r
+       }\r
+       \r
+       /**\r
+        * Gets the default values.\r
+        */\r
+       protected function readDefaultValues() {\r
+               $this->username = $this->user->username;\r
+               $this->email = $this->confirmEmail = $this->user->email;\r
+               $this->groupIDs = $this->user->getGroupIDs();\r
+               $this->languageID = $this->user->languageID;\r
+               \r
+               foreach ($this->options as $option) {\r
+                       $value = $this->user->{'userOption'.$option->optionID};\r
+                       if ($value !== null) {\r
+                               $this->optionValues[$option->optionName] = $value;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'userID' => $this->user->userID,\r
+                       'action' => 'edit',\r
+                       'url' => '',\r
+                       'markedUsers' => 0,\r
+                       'user' => $this->user\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               AbstractForm::save();\r
+               \r
+               // add default groups\r
+               $defaultGroups = UserGroup::getAccessibleGroups(array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS));\r
+               $oldGroupIDs = $this->user->getGroupIDs();\r
+               foreach ($oldGroupIDs as $oldGroupID) {\r
+                       if (isset($defaultGroups[$oldGroupID])) {\r
+                               $this->groupIDs[] = $oldGroupID;\r
+                       }\r
+               }\r
+               $this->groupIDs = array_unique($this->groupIDs);\r
+               \r
+               // save user\r
+               $saveOptions = array();\r
+               foreach ($this->options as $option) {\r
+                       $saveOptions[$option->optionID] = $this->optionValues[$option->optionName];\r
+               }\r
+               $this->additionalFields['languageID'] = $this->languageID;\r
+               $data = array(\r
+                       'data' => array_merge($this->additionalFields, array(\r
+                               'username' => $this->username,\r
+                               'email' => $this->email,\r
+                               'password' => $this->password,\r
+                       )),\r
+                       'groups' => $this->groupIDs,\r
+                       'languages' => $this->visibleLanguages,\r
+                       'options' => $saveOptions\r
+               );\r
+               $userAction = new UserAction(array($this->userID), 'update', $data);\r
+               $userAction->executeAction();\r
+               \r
+               $this->saved();\r
+               \r
+               // reset password\r
+               $this->password = $this->confirmPassword = '';\r
+       \r
+               // show success message\r
+               WCF::getTPL()->assign('success', true);\r
+       }\r
+       \r
+       /**\r
+        * @see UserAddForm::validateUsername()\r
+        */\r
+       protected function validateUsername($username) {\r
+               if (StringUtil::toLowerCase($this->user->username) != StringUtil::toLowerCase($username)) {\r
+                       parent::validateUsername($username);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see UserAddForm::validateEmail()\r
+        */\r
+       protected function validateEmail($email, $confirmEmail) {\r
+               if (StringUtil::toLowerCase($this->user->email) != StringUtil::toLowerCase($email)) {\r
+                       parent::validateEmail($email, $this->confirmEmail);     \r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see UserAddForm::validatePassword()\r
+        */\r
+       protected function validatePassword($password, $confirmPassword) {\r
+               if (!empty($password) || !empty($confirmPassword)) {\r
+                       parent::validatePassword($password, $confirmPassword);\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/UserEmailAddressExportForm.class.php b/wcfsetup/install/files/lib/acp/form/UserEmailAddressExportForm.class.php
new file mode 100644 (file)
index 0000000..163ca5e
--- /dev/null
@@ -0,0 +1,133 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\user\User;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\WCF;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the export user mail addresses form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserEmailAddressExportForm extends ACPForm {\r
+       public $templateName = 'userEmailAddressExport';\r
+       public $activeMenuItem = 'wcf.acp.menu.link.user.management';\r
+       public $neededPermissions = array('admin.user.canMailUser');\r
+       \r
+       public $fileType = 'csv';\r
+       public $userIDs = array();\r
+       public $separator = ',';\r
+       public $textSeparator = '"'; \r
+       public $users = array();\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['fileType']) && $_POST['fileType'] == 'xml') $this->fileType = $_POST['fileType'];\r
+               if (isset($_POST['userIDs'])) $this->userIDs = ArrayUtil::toIntegerArray(explode(',', $_POST['userIDs']));\r
+               if (isset($_POST['separator'])) $this->separator = $_POST['separator'];\r
+               if (isset($_POST['textSeparator'])) $this->textSeparator = $_POST['textSeparator'];\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               if (empty($this->userIDs)) throw new IllegalLinkException();\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // send content type\r
+               header('Content-Type: text/'.$this->fileType.'; charset=UTF-8');\r
+               header('Content-Disposition: attachment; filename="export.'.$this->fileType.'"');\r
+               \r
+               if ($this->fileType == 'xml') {\r
+                       echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<addresses>\n";\r
+               }\r
+               \r
+               $conditions = new PreparedStatementConditionBuilder();\r
+               $conditions->add("userID IN (?)", array($this->userIDs));\r
+               \r
+               // count users\r
+               $sql = "SELECT  COUNT(*) AS count\r
+                       FROM    wcf".WCF_N."_user\r
+                       ".$conditions;\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute($conditions->getParameters());\r
+               $count = $statement->fetchArray();\r
+               \r
+               // get users\r
+               $sql = "SELECT          email\r
+                       FROM            wcf".WCF_N."_user\r
+                       ".$conditions."\r
+                       ORDER BY        email";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute($conditions->getParameters());\r
+               \r
+               $i = 0;\r
+               while ($row = WCF::getDB()->fetchArray($result)) {\r
+                       if ($this->fileType == 'xml') echo "<address><![CDATA[".StringUtil::escapeCDATA($row['email'])."]]></address>\n";\r
+                       else echo $this->textSeparator . $row['email'] . $this->textSeparator . ($i < $count['count'] ? $this->separator : '');\r
+                       $i++;\r
+               }\r
+               \r
+               if ($this->fileType == 'xml') {\r
+                       echo "</addresses>";\r
+               }\r
+               \r
+               // TODO: Implement unmarkAll()\r
+               //UserEditor::unmarkAll();\r
+               $this->saved();\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               if (!count($_POST)) {\r
+                       // get marked user ids\r
+                       $markedUsers = WCF::getSession()->getVar('markedUsers');\r
+                       if (is_array($markedUsers)) $this->userIDs = implode(',', $markedUsers);\r
+                       if (empty($this->userIDs)) throw new IllegalLinkException();\r
+               }\r
+               \r
+               $this->users = User::getUsers($this->userIDs);\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'users' => $this->users,\r
+                       'userIDs' => $this->userIDs,\r
+                       'separator' => $this->separator,\r
+                       'textSeparator' => $this->textSeparator,\r
+                       'fileType' => $this->fileType\r
+               ));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/UserGroupAddForm.class.php b/wcfsetup/install/files/lib/acp/form/UserGroupAddForm.class.php
new file mode 100644 (file)
index 0000000..cd93e05
--- /dev/null
@@ -0,0 +1,229 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\data\user\group\UserGroupAction;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\WCF;\r
+use wcf\system\WCFACP;\r
+use wcf\util\ClassUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the group add form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupAddForm extends AbstractOptionListForm {\r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.user.canAddGroup');\r
+       \r
+       /**\r
+        * @see AbstractPage::$templateName\r
+        */\r
+       public $templateName = 'userGroupAdd';\r
+       \r
+       /**\r
+        * name of the active acp menu item\r
+        * @var string\r
+        */\r
+       public $menuItemName = 'wcf.acp.menu.link.group.add';\r
+       \r
+       /**\r
+        * @see AbstractOptionListForm::$cacheName\r
+        */\r
+       public $cacheName = 'user_group-option-';\r
+       \r
+       /**\r
+        * active tab menu item name\r
+        * @var string\r
+        */\r
+       public $activeTabMenuItem = '';\r
+       \r
+       /**\r
+        * active sub tab menu item name\r
+        * @var string\r
+        */\r
+       public $activeSubTabMenuItem = '';\r
+       \r
+       /**\r
+        * the option tree\r
+        * @var array\r
+        */\r
+       public $optionTree = array();\r
+       \r
+       /**\r
+        * group name\r
+        * @var string\r
+        */\r
+       public $groupName = '';\r
+       \r
+       /**\r
+        * additional fields\r
+        * @var array\r
+        */\r
+       public $additionalFields = array();\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['groupName'])) $this->groupName = StringUtil::trim($_POST['groupName']);\r
+               if (isset($_POST['activeTabMenuItem'])) $this->activeTabMenuItem = $_POST['activeTabMenuItem'];\r
+               if (isset($_POST['activeSubTabMenuItem'])) $this->activeSubTabMenuItem = $_POST['activeSubTabMenuItem'];\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               // validate dynamic options\r
+               parent::validate();\r
+               \r
+               // validate group name\r
+               try {\r
+                       if (empty($this->groupName)) {\r
+                               throw new UserInputException('groupName');\r
+                       }\r
+               }\r
+               catch (UserInputException $e) {\r
+                       $this->errorType[$e->getField()] = $e->getType();\r
+               }\r
+       \r
+               if (count($this->errorType) > 0) {\r
+                       throw new UserInputException('groupName', $this->errorType);\r
+               }               \r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // get default group\r
+               $defaultGroup = UserGroup::getGroupByType(UserGroup::EVERYONE);\r
+               $saveOptions = array();\r
+               foreach ($this->options as $option) {\r
+                       if ($this->optionValues[$option->optionName] != $defaultGroup->getGroupOption($option->optionName)) {\r
+                               $saveOptions[$option->optionID] = $this->optionValues[$option->optionName];\r
+                       }\r
+               }\r
+               \r
+               $data = array(\r
+                       'data' => array_merge($this->additionalFields, array('groupName' => $this->groupName)),\r
+                       'options' => $saveOptions\r
+               );\r
+               $groupAction = new UserGroupAction(array(), 'create', $data);\r
+               $groupAction->executeAction();\r
+               $this->saved();\r
+               \r
+               // show success message\r
+               WCF::getTPL()->assign(array(\r
+                       'success' => true\r
+               ));\r
+               \r
+               // reset values\r
+               $this->groupName = '';\r
+               $this->optionValues = array();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               AbstractOptionListForm::readData();\r
+               \r
+               if (!count($_POST)) {\r
+                       $this->groupName = $this->group->groupName;\r
+                       \r
+                       // get default values\r
+                       if ($this->group->groupType != UserGroup::EVERYONE) {\r
+                               $defaultGroup = UserGroup::getGroupByType(UserGroup::EVERYONE);\r
+                               foreach ($this->options as $option) {\r
+                                       $value = $defaultGroup->getGroupOption($option->optionName);\r
+                                       if ($value !== null) {\r
+                                               $this->optionValues[$option->optionName] = $value;\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       \r
+                       \r
+                       foreach ($this->options as $option) {\r
+                               $value = $this->group->getGroupOption($option->optionName);\r
+                               if ($value !== null) {\r
+                                       $this->optionValues[$option->optionName] = $value;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               $this->optionTree = $this->getOptionTree();\r
+               if (!count($_POST)) {\r
+                       $this->activeTabMenuItem = $this->optionTree[0]['object']->categoryName;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'groupName' => $this->groupName,\r
+                       'optionTree' => $this->optionTree,\r
+                       'action' => 'add',\r
+                       'activeTabMenuItem' => $this->activeTabMenuItem,\r
+                       'activeSubTabMenuItem' => $this->activeSubTabMenuItem\r
+               ));\r
+       }\r
+\r
+       /**\r
+        * @see Form::show()\r
+        */\r
+       public function show() {\r
+               // set active menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem($this->menuItemName);\r
+               \r
+               // check master password\r
+               WCFACP::checkMasterPassword();\r
+               \r
+               // get user options and categories from cache\r
+               $this->readCache();\r
+               \r
+               // show form\r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractOptionListForm::getTypeObject()\r
+        */\r
+       protected function getTypeObject($type) {\r
+               if (!isset($this->typeObjects[$type])) {\r
+                       $className = 'wcf\system\option\group\GroupOptionType'.ucfirst($type);\r
+                       \r
+                       // create instance\r
+                       if (!class_exists($className)) {\r
+                               throw new SystemException("unable to find class '".$className."'", 11001);\r
+                       }\r
+                       if (!ClassUtil::isInstanceOf($className, 'wcf\system\option\group\GroupOptionType')) {\r
+                               throw new SystemException("'".$className."' should implement GroupOptionType", 11001);\r
+                       }\r
+                       $this->typeObjects[$type] = new $className();\r
+               }\r
+               \r
+               return $this->typeObjects[$type];\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/UserGroupEditForm.class.php b/wcfsetup/install/files/lib/acp/form/UserGroupEditForm.class.php
new file mode 100644 (file)
index 0000000..9cac024
--- /dev/null
@@ -0,0 +1,144 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\acp\session\ACPSession;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\data\user\group\UserGroupAction;\r
+use wcf\data\user\group\UserGroupEditor;\r
+use wcf\form\AbstractForm;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\exception\PermissionDeniedException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Shows the group edit form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupEditForm extends UserGroupAddForm {\r
+       /**\r
+        * @see UserGroupAddForm::$menuItemName\r
+        */\r
+       public $menuItemName = 'wcf.acp.menu.link.group';\r
+       \r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.user.canEditGroup');\r
+       \r
+       /**\r
+        * group id\r
+        * @var integer\r
+        */\r
+       public $groupID = 0;\r
+       \r
+       /**\r
+        * group editor object\r
+        * @var GroupEditor\r
+        */\r
+       public $group = null;\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               // get group\r
+               if (isset($_REQUEST['groupID'])) $this->groupID = intval($_REQUEST['groupID']);\r
+               $group = new UserGroup($this->groupID);\r
+               if (!$group->groupID) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               if (!$group->isAccessible()) {\r
+                       throw new PermissionDeniedException();\r
+               }\r
+               \r
+               $this->group = new UserGroupEditor($group);\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               if (!count($_POST)) {\r
+                       $this->groupName = $this->group->groupName;\r
+                       \r
+                       // get default values\r
+                       if ($this->group->groupType != UserGroup::EVERYONE) {\r
+                               $defaultGroup = UserGroup::getGroupByType(UserGroup::EVERYONE);\r
+                               foreach ($this->options as $option) {\r
+                                       $value = $defaultGroup->getGroupOption($option->optionName);\r
+                                       if ($value !== null) {\r
+                                               $this->optionValues[$option->optionName] = $value;\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       foreach ($this->options as $option) {\r
+                               $value = $this->group->getGroupOption($option->optionName);\r
+                               if ($value !== null) {\r
+                                       $this->optionValues[$option->optionName] = $value;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               parent::readData();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'groupID' => $this->group->groupID,\r
+                       'action' => 'edit'\r
+               ));\r
+               \r
+               // add warning when the initiator is in the group\r
+               if ($this->group->isMember($this->groupID)) {\r
+                       WCF::getTPL()->assign('warningSelfEdit', true);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               AbstractForm::save();\r
+               \r
+               // save group\r
+               $saveOptions = array();\r
+               if ($this->group->groupType == UserGroup::EVERYONE) {\r
+                       foreach ($this->options as $option) {\r
+                               $saveOptions[$option->optionID] = $this->optionValues[$option->optionName];\r
+                       }\r
+               }\r
+               else {\r
+                       // get default group\r
+                       $defaultGroup = UserGroup::getGroupByType(UserGroup::EVERYONE);\r
+                       foreach ($this->options as $option) {\r
+                               if ($this->optionValues[$option->optionName] != $defaultGroup->getGroupOption($option->optionName)) {\r
+                                       $saveOptions[$option->optionID] = $this->optionValues[$option->optionName];\r
+                               }\r
+                       }\r
+               }\r
+               $data = array(\r
+                       'data' => array_merge(array('groupName' => $this->groupName), $this->additionalFields),\r
+                       'options' => $saveOptions\r
+               );\r
+               $groupAction = new UserGroupAction(array($this->groupID), 'update', $data);\r
+               $groupAction->executeAction();\r
+               $this->saved();\r
+               \r
+               // show success message\r
+               WCF::getTPL()->assign('success', true);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/UserMailForm.class.php b/wcfsetup/install/files/lib/acp/form/UserMailForm.class.php
new file mode 100644 (file)
index 0000000..a58e234
--- /dev/null
@@ -0,0 +1,166 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\data\user\UserList;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\StringUtil;\r
+use wcf\system\WCF;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\exception\UserInputException;\r
+\r
+/**\r
+ * Shows the user mail form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserMailForm extends ACPForm {\r
+       // system\r
+       public $templateName = 'userMail';\r
+       public $neededPermissions = array('admin.user.canMailUser');\r
+       \r
+       // parameters\r
+       public $userIDs = array();\r
+       public $groupIDs = array();\r
+       public $subject = '';\r
+       public $text = '';\r
+       public $from = '';\r
+       public $users = array();\r
+       public $groups = array();\r
+       public $enableHTML = 0;\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               $this->activeMenuItem = ($this->action == 'all' ? 'wcf.acp.menu.link.user.mail' : ($this->action == 'group' ? 'wcf.acp.menu.link.group.mail' : 'wcf.acp.menu.link.user.management'));\r
+       }\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['userIDs'])) $this->userIDs = ArrayUtil::toIntegerArray(explode(',', $_POST['userIDs']));\r
+               if (isset($_POST['groupIDs']) && is_array($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);\r
+               if (isset($_POST['subject'])) $this->subject = StringUtil::trim($_POST['subject']);\r
+               if (isset($_POST['text'])) $this->text = StringUtil::trim($_POST['text']);\r
+               if (isset($_POST['from'])) $this->from = StringUtil::trim($_POST['from']);\r
+               if (isset($_POST['enableHTML'])) $this->enableHTML = intval($_POST['enableHTML']);\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               parent::validate();\r
+               \r
+               if ($this->action == 'group') {\r
+                       if (!count($this->groupIDs)) {\r
+                               throw new UserInputException('groupIDs');\r
+                       }\r
+               }\r
+               if ($this->action == '') {\r
+                       if (empty($this->userIDs)) throw new IllegalLinkException();\r
+               }\r
+               \r
+               if (empty($this->subject)) {\r
+                       throw new UserInputException('subject');\r
+               }\r
+               \r
+               if (empty($this->text)) {\r
+                       throw new UserInputException('text');\r
+               }\r
+               \r
+               if (empty($this->from)) {\r
+                       throw new UserInputException('from');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // save config in session\r
+               $userMailData = WCF::getSession()->getVar('userMailData');\r
+               if ($userMailData === null) $userMailData = array();\r
+               $mailID = count($userMailData);\r
+               $userMailData[$mailID] = array(\r
+                       'action' => $this->action,\r
+                       'userIDs' => $this->userIDs,\r
+                       'groupIDs' => implode(',', $this->groupIDs),\r
+                       'subject' => $this->subject,\r
+                       'text' => $this->text,\r
+                       'from' => $this->from,\r
+                       'enableHTML' => $this->enableHTML\r
+               );\r
+               WCF::getSession()->register('userMailData', $userMailData);\r
+               $this->saved();\r
+               \r
+               // show worker template\r
+               WCF::getTPL()->assign(array(\r
+                       'pageTitle' => WCF::getLanguage()->get(($this->action == 'all' ? 'wcf.acp.user.sendMail.all' : ($this->action == 'group' ? 'wcf.acp.user.sendMail.group' : 'wcf.acp.user.sendMail'))),\r
+                       'url' => 'index.php?action=UserMail&mailID='.$mailID.''.SID_ARG_2ND_NOT_ENCODED\r
+               ));\r
+               WCF::getTPL()->display('worker');\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               if (!count($_POST)) {\r
+                       // get marked user ids\r
+                       if (empty($this->action)) {\r
+                               $markedUsers = WCF::getSession()->getVar('markedUsers');\r
+                               if (is_array($markedUsers)) $this->userIDs = implode(',', $markedUsers);\r
+                               if (empty($this->userIDs)) throw new IllegalLinkException();\r
+                       }\r
+                       \r
+                       if (MAIL_USE_FORMATTED_ADDRESS) $this->from = MAIL_FROM_NAME . ' <' . MAIL_FROM_ADDRESS . '>';\r
+                       else $this->from = MAIL_FROM_ADDRESS;\r
+               }\r
+               \r
+               if (!empty($this->userIDs)) {\r
+                       $userList = new UserList();\r
+                       $userList->getConditionBuilder()->add("user.userID IN (?)", array($this->userIDs));\r
+                       $userList->sqlOrderBy = "user.username ASC";\r
+                       $userList->readObjects();\r
+                       \r
+                       $this->users = $userList->getObjects();\r
+               }\r
+               \r
+               $this->groups = UserGroup::getAccessibleGroups(array(), array(UserGroup::GUESTS, UserGroup::EVERYONE));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'users' => $this->users,\r
+                       'groups' => $this->groups,\r
+                       'userIDs' => $this->userIDs,\r
+                       'groupIDs' => $this->groupIDs,\r
+                       'subject' => $this->subject,\r
+                       'text' => $this->text,\r
+                       'from' => $this->from,\r
+                       'enableHTML' => $this->enableHTML\r
+               ));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/form/UserOptionListForm.class.php b/wcfsetup/install/files/lib/acp/form/UserOptionListForm.class.php
new file mode 100644 (file)
index 0000000..9a13c80
--- /dev/null
@@ -0,0 +1,89 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\data\option\Option;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\system\WCF;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\language\LanguageFactory;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * This class provides default implementations for a list of dynamic user options.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+abstract class UserOptionListForm extends AbstractOptionListForm {\r
+       /**\r
+        * @see AbstractOptionListForm::$cacheName\r
+        */\r
+       public $cacheName = 'user-option-';\r
+       \r
+       /**\r
+        * Returns a list of all available user groups.\r
+        * \r
+        * @return      array\r
+        */\r
+       protected function getAvailableGroups() {\r
+               return UserGroup::getAccessibleGroups(array(), array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS));\r
+       }\r
+       \r
+       /**\r
+        * Returns a list of all available languages.\r
+        * \r
+        * @return      array\r
+        */\r
+       protected function getAvailableLanguages() {\r
+               $availableLanguages = array();\r
+               foreach (LanguageFactory::getAvailableLanguages(PACKAGE_ID) as $language) {\r
+                       $availableLanguages[$language['languageID']] = WCF::getLanguage()->get('wcf.global.language.'.$language['languageCode']);       \r
+               }\r
+               \r
+               // sort languages\r
+               StringUtil::sort($availableLanguages);\r
+               \r
+               return $availableLanguages;\r
+       }\r
+       \r
+       /**\r
+        * Returns a list of all available content languages.\r
+        * \r
+        * @return      array\r
+        */\r
+       public static function getAvailableContentLanguages() {\r
+               $availableLanguages = array();\r
+               foreach (LanguageFactory::getAvailableContentLanguages(PACKAGE_ID) as $language) {\r
+                       $availableLanguages[$language['languageID']] = WCF::getLanguage()->get('wcf.global.language.'.$language['languageCode']);       \r
+               }\r
+               \r
+               // sort languages\r
+               StringUtil::sort($availableLanguages);\r
+               \r
+               return $availableLanguages;\r
+       }\r
+       \r
+       /**\r
+        * Returns the default-form language id    \r
+        * \r
+        * @return      integer         $languageID\r
+        */\r
+       protected function getDefaultFormLanguageID() {\r
+               return LanguageFactory::getDefaultLanguageID();\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractOptionListForm::validateOption()\r
+        */\r
+       protected function validateOption(Option $option) {\r
+               parent::validateOption($option);\r
+\r
+               if ($option->required && empty($this->optionValues[$option->optionName])) {\r
+                       throw new UserInputException($option->optionName);\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/UserSearchForm.class.php b/wcfsetup/install/files/lib/acp/form/UserSearchForm.class.php
new file mode 100644 (file)
index 0000000..7330059
--- /dev/null
@@ -0,0 +1,310 @@
+<?php\r
+namespace wcf\acp\form;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\option\Option;\r
+use wcf\data\search\SearchEditor;\r
+use wcf\form\AbstractForm;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\event\EventHandler;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\wcf;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\HeaderUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the user search form.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.form\r
+ * @category   Community Framework\r
+ */\r
+class UserSearchForm extends UserOptionListForm {\r
+       /**\r
+        * @see wcf\page\AbstractPage::$templateName\r
+        */\r
+       public $templateName = 'userSearch';\r
+       \r
+       /**\r
+        * active menu item name\r
+        * @var string\r
+        */\r
+       public $menuItemName = 'wcf.acp.menu.link.user.search';\r
+       \r
+       /**\r
+        * @see AbstractPage::$neededPermissions\r
+        */\r
+       public $neededPermissions = array('admin.user.canSearchUser');\r
+       \r
+       /**\r
+        * username \r
+        * @var string\r
+        */\r
+       public $username = '';\r
+       \r
+       /**\r
+        * email address\r
+        * @var string\r
+        */\r
+       public $email = '';\r
+       \r
+       /**\r
+        * user id\r
+        * @var integer\r
+        */\r
+       public $userID = 0;\r
+\r
+       /**\r
+        * group ids\r
+        * @var array<integer>\r
+        */\r
+       public $groupIDs = array();\r
+       \r
+       /**\r
+        * true to invert the given group ids\r
+        * @var boolean\r
+        */\r
+       public $invertGroupIDs = 0;\r
+       \r
+       /**\r
+        * language ids\r
+        * @var array<integer>\r
+        */\r
+       public $languageIDs = array();\r
+       \r
+       /**\r
+        * matches\r
+        * @var array<integer>\r
+        */\r
+       public $matches = array();\r
+       \r
+       /**\r
+        * condtion builder object\r
+        * @var wcf\system\database\condition\PreparedStatementConditionBuilder\r
+        */\r
+       public $conditions = null;\r
+       \r
+       /**\r
+        * search id\r
+        * @var integer\r
+        */\r
+       public $searchID = 0;\r
+       \r
+       /**\r
+        * sort field\r
+        * @var string\r
+        */\r
+       public $sortField = 'username';\r
+       \r
+       /**\r
+        * sort order\r
+        * @var string\r
+        */\r
+       public $sortOrder = 'ASC';\r
+       \r
+       /**\r
+        * results per page\r
+        * @var integer\r
+        */\r
+       public $itemsPerPage = 50;\r
+       \r
+       /**\r
+        * shown columns\r
+        * @var array<string>\r
+        */\r
+       public $columns = array('email', 'registrationDate');\r
+       \r
+       /**\r
+        * number of results\r
+        * @var integer\r
+        */\r
+       public $maxResults = 0;\r
+       \r
+       /**\r
+        * @see wcf\form\Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               parent::readFormParameters();\r
+               \r
+               if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']);\r
+               if (isset($_POST['email'])) $this->email = StringUtil::trim($_POST['email']);\r
+               if (isset($_POST['userID'])) $this->userID = intval($_POST['userID']);\r
+               if (isset($_POST['groupIDs']) && is_array($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);\r
+               if (isset($_POST['languageIDs']) && is_array($_POST['languageIDs'])) $this->languageIDs = ArrayUtil::toIntegerArray($_POST['languageIDs']);\r
+               if (isset($_POST['invertGroupIDs'])) $this->invertGroupIDs = intval($_POST['invertGroupIDs']);\r
+               \r
+               if (isset($_POST['itemsPerPage'])) $this->itemsPerPage = intval($_POST['itemsPerPage']);\r
+               if (isset($_POST['sortField'])) $this->sortField = $_POST['sortField'];\r
+               if (isset($_POST['sortOrder'])) $this->sortOrder = $_POST['sortOrder'];\r
+               if (isset($_POST['columns']) && is_array($_POST['columns'])) $this->columns = $_POST['columns'];\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\page\Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               $this->optionTree = $this->getCategoryOptions('profile');\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\page\Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'username' => $this->username,\r
+                       'email' => $this->email,\r
+                       'userID' => $this->userID,\r
+                       'groupIDs' => $this->groupIDs,\r
+                       'languageIDs' => $this->languageIDs,\r
+                       'optionTree' => $this->optionTree,\r
+                       'availableGroups' => $this->getAvailableGroups(),\r
+                       'availableLanguages' => $this->getAvailablelanguages(),\r
+                       'invertGroupIDs' => $this->invertGroupIDs,\r
+                       'sortField' => $this->sortField,\r
+                       'sortOrder' => $this->sortOrder,\r
+                       'itemsPerPage' => $this->itemsPerPage,\r
+                       'columns' => $this->columns\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\form\Form::show()\r
+        */\r
+       public function show() {\r
+               // set active menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem($this->menuItemName);\r
+               \r
+               // get user options and categories from cache\r
+               $this->readCache();\r
+               \r
+               // show form\r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\form\Form::save()\r
+        */     \r
+       public function save() {\r
+               parent::save();\r
+               \r
+               // store search result in database\r
+               $data = serialize(array(\r
+                       'matches' => $this->matches,\r
+                       'itemsPerPage' => $this->itemsPerPage,\r
+                       'columns' => $this->columns\r
+               ));\r
+               \r
+               $search = SearchEditor::create(array(\r
+                       'userID' => WCF::getUser()->userID,\r
+                       'searchData' => $data,\r
+                       'searchTime' => TIME_NOW,\r
+                       'searchType' => 'users'\r
+               ));\r
+               \r
+               // get new search id\r
+               $this->searchID = $search->searchID;\r
+               $this->saved();\r
+               \r
+               // forward to result page\r
+               HeaderUtil::redirect('index.php?page=UserList&searchID='.$this->searchID.'&sortField='.rawurlencode($this->sortField).'&sortOrder='.rawurlencode($this->sortOrder).''.SID_ARG_2ND_NOT_ENCODED);\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\form\Form::validate()\r
+        */\r
+       public function validate() {\r
+               AbstractForm::validate();\r
+               \r
+               // do search\r
+               $this->search();\r
+               \r
+               if (count($this->matches) == 0) {\r
+                       throw new UserInputException('search', 'noMatches');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Search for users which fit to the search values.\r
+        */\r
+       protected function search() {\r
+               $this->matches = array();\r
+               $sql = "SELECT          user_table.userID\r
+                       FROM            wcf".WCF_N."_user user_table\r
+                       LEFT JOIN       wcf".WCF_N."_user_option_value option_value \r
+                       ON              (option_value.userID = user_table.userID)";\r
+               \r
+               // build search condition\r
+               $this->conditions = new PreparedStatementConditionBuilder(); \r
+               \r
+               // static fields\r
+               $this->buildStaticConditions();\r
+               \r
+               // dynamic fields\r
+               $this->buildDynamicConditions();\r
+               \r
+               // call buildConditions event\r
+               EventHandler::getInstance()->fireAction($this, 'buildConditions');\r
+\r
+               // do search\r
+               $statement = WCF::getDB()->prepareStatement($sql.$this->conditions, $this->maxResults);\r
+               $statement->execute($this->conditions->getParameters());\r
+               while ($row = $statement->fetchArray()) {\r
+                       $this->matches[] = $row['userID'];      \r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Builds the static conditions.\r
+        */\r
+       protected function buildStaticConditions() {\r
+               if (!empty($this->username)) {\r
+                       $this->conditions->add("user_table.username LIKE ?", array('%'.addcslashes($this->username, '_%').'%'));\r
+               }\r
+               if (!empty($this->userID)) {\r
+                       $this->conditions->add("user_table.userID LIKE ?", array('%'.$this->userID.'%'));\r
+               }\r
+               if (!empty($this->email)) {\r
+                       $this->conditions->add("user_table.email LIKE ?", array('%'.addcslashes($this->email, '_%').'%'));\r
+               }\r
+               if (count($this->groupIDs)) {\r
+                       $this->conditions->add("user_table.userID ".($this->invertGroupIDs == 1 ? 'NOT ' : '')."IN (SELECT userID FROM wcf".WCF_N."_user_to_group WHERE groupID IN (?))", array($this->groupIDs));\r
+               }\r
+               if (count($this->languageIDs)) {\r
+                       $this->conditions->add("user_table.languageID IN (?)", array($this->languageIDs));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Builds the dynamic conditions.\r
+        */\r
+       protected function buildDynamicConditions() {\r
+               foreach ($this->options as $option) {\r
+                       $value = isset($this->values[$option->optionName]) ? $this->values[$option->optionName] : null;\r
+                       $condition = $this->getTypeObject($option->optionType)->getCondition($option, $value);\r
+                       if ($condition !== false) $this->conditions->add($condition);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\system\option\SearchableOptionType::getSearchFormElement()\r
+        */\r
+       protected function getFormElement($type, Option $option) {\r
+               return $this->getTypeObject($type)->getSearchFormElement($option);\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\acp\form\DynamicOptionListForm::checkOption()\r
+        */\r
+       protected static function checkOption(Option $option) {\r
+               return ($option->searchable == 1 && !$option->disabled && ($option->visible == 3 || $option->visible < 2));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/form/UsersMassProcessingForm.class.php b/wcfsetup/install/files/lib/acp/form/UsersMassProcessingForm.class.php
new file mode 100644 (file)
index 0000000..f58bc83
--- /dev/null
@@ -0,0 +1,403 @@
+<?php
+namespace wcf\acp\form;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\data\user\UserEditor;
+use wcf\data\user\group\UserGroup;
+use wcf\form\AbstractForm;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\event\EventHandler;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\exception\UserInputException;
+use wcf\util\ArrayUtil;
+use wcf\util\StringUtil;
+               
+/**
+ * Shows the users mass processing form.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class UsersMassProcessingForm extends UserOptionListForm {
+       // system
+       public $templateName = 'usersMassProcessing';
+       public $neededPermissions = array('admin.user.canEditUser', 'admin.user.canDeleteUser', 'admin.user.canMailUser');
+       
+       // parameters
+       public $username = '';
+       public $email = '';
+       public $groupIDArray = array();
+       public $languageIDArray = array();
+       public $invertGroupIDs = 0;
+       
+       // assign to group
+       public $assignToGroupIDArray = array();
+       
+       // export mail address
+       public $fileType = 'csv';
+       public $separator = ',';
+       public $textSeparator = '"'; 
+       
+       // send mail
+       public $subject = '';
+       public $text = '';
+       public $from = '';
+       public $enableHTML = 0;
+       
+       // data
+       public $availableGroups = array();
+       public $availableLanguages = array();
+       public $options = array();
+       public $availableActions = array('sendMail', 'exportMailAddress', 'assignToGroup', 'delete');
+       public $affectedUsers = 0;
+       
+       /**
+        * conditions builder object.
+        * 
+        * @var wcf\system\database\condition\PreparedStatementConditionBuilder
+        */
+       public $conditions = null;
+       
+       /**
+        * @see wcf\form\Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']);
+               if (isset($_POST['email'])) $this->email = StringUtil::trim($_POST['email']);
+               if (isset($_POST['groupIDArray']) && is_array($_POST['groupIDArray'])) $this->groupIDArray = ArrayUtil::toIntegerArray($_POST['groupIDArray']);
+               if (isset($_POST['languageIDArray']) && is_array($_POST['languageIDArray'])) $this->languageIDArray = ArrayUtil::toIntegerArray($_POST['languageIDArray']);
+               if (isset($_POST['invertGroupIDs'])) $this->invertGroupIDs = intval($_POST['invertGroupIDs']);
+               // assign to group
+               if (isset($_POST['assignToGroupIDArray']) && is_array($_POST['assignToGroupIDArray'])) $this->assignToGroupIDArray = ArrayUtil::toIntegerArray($_POST['assignToGroupIDArray']);
+               // export mail address
+               if (isset($_POST['fileType']) && $_POST['fileType'] == 'xml') $this->fileType = $_POST['fileType'];
+               if (isset($_POST['separator'])) $this->separator = $_POST['separator'];
+               if (isset($_POST['textSeparator'])) $this->textSeparator = $_POST['textSeparator'];
+               // send mail
+               if (isset($_POST['subject'])) $this->subject = StringUtil::trim($_POST['subject']);
+               if (isset($_POST['text'])) $this->text = StringUtil::trim($_POST['text']);
+               if (isset($_POST['from'])) $this->from = StringUtil::trim($_POST['from']);
+               if (isset($_POST['enableHTML'])) $this->enableHTML = intval($_POST['enableHTML']);
+       }
+       
+       /**
+        * @see wcf\form\Form::validate()
+        */
+       public function validate() {
+               AbstractForm::validate();
+
+               // action
+               if (!in_array($this->action, $this->availableActions)) {
+                       throw new UserInputException('action');
+               }
+               
+               // assign to group
+               if ($this->action == 'assignToGroup') {
+                       if (!count($this->assignToGroupIDArray)) {
+                               throw new UserInputException('assignToGroupIDArray');
+                       }
+               }
+               
+               // send mail
+               if ($this->action == 'sendMail') {
+                       if (empty($this->subject)) {
+                               throw new UserInputException('subject');
+                       }
+                       
+                       if (empty($this->text)) {
+                               throw new UserInputException('text');
+                       }
+                       
+                       if (empty($this->from)) {
+                               throw new UserInputException('from');
+                       }
+               }
+       }
+       
+       /**
+        * @see wcf\form\Form::save()
+        */
+       public function save() {
+               parent::save();
+               
+               // build conditions
+               $this->conditions = new PreparedStatementConditionBuilder();
+               // static fields
+               if (!empty($this->username)) {
+                       $this->conditions->add("user.username LIKE ?", array('%'.addcslashes($this->username, '_%').'%'));
+               }
+               if (!empty($this->email)) {
+                       $this->conditions->add("user.email LIKE ?", array('%'.addcslashes($this->email, '_%').'%'));
+               }
+               if (count($this->groupIDArray) > 0) {
+                       $this->conditions->add("user.userID ".($this->invertGroupIDs == 1 ? 'NOT ' : '')."IN (SELECT userID FROM wcf".WCF_N."_user_to_group WHERE groupID IN (?))", array($this->groupIDArray));
+               }
+               if (count($this->languageIDArray) > 0) {
+                       $this->conditions->add("user.languageID IN (?)", array($this->languageIDArray));
+               }
+               
+               // dynamic fields
+               foreach ($this->activeOptions as $name => $option) {
+                       $value = isset($this->values[$option['optionName']]) ? $this->values[$option['optionName']] : null;
+                       $this->getTypeObject($option['optionType'])->getCondition($this->conditions, $option, $value);
+               }
+
+               // call buildConditions event
+               EventHandler::getInstance()->fireAction($this, 'buildConditions');
+               
+               // execute action
+               switch ($this->action) {
+                       case 'sendMail':
+                               WCF::getSession()->checkPermission(array('admin.user.canMailUser'));
+                               // get user ids
+                               $userIDArray = array();
+                               $sql = "SELECT          user.userID
+                                       FROM            wcf".WCF_N."_user
+                                       LEFT JOIN       wcf".WCF_N."_user_option_value option_value
+                                       ON              (option_value.userID = user.userID)".
+                                       $this->conditions;
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute($this->conditions->getParameters());
+                               while ($row = $statement->fetchArray()) {
+                                       $userIDArray[] = $row['userID'];
+                                       $this->affectedUsers++;
+                               }
+
+                               // save config in session
+                               $userMailData = WCF::getSession()->getVar('userMailData');
+                               if ($userMailData === null) $userMailData = array();
+                               $mailID = count($userMailData);
+                               $userMailData[$mailID] = array(
+                                       'action' => '',
+                                       'userIDs' => implode(',', $userIDArray),
+                                       'groupIDs' => '',
+                                       'subject' => $this->subject,
+                                       'text' => $this->text,
+                                       'from' => $this->from,
+                                       'enableHTML' => $this->enableHTML
+                               );
+                               WCF::getSession()->register('userMailData', $userMailData);
+                               $this->saved();
+                               
+                               // show worker template
+                               WCF::getTPL()->assign(array(
+                                       'pageTitle' => WCF::getLanguage()->get('wcf.acp.user.sendMail'),
+                                       'url' => 'index.php?action=UserMail&mailID='.$mailID.''.SID_ARG_2ND_NOT_ENCODED
+                               ));
+                               WCF::getTPL()->display('worker');
+                               exit;
+                               break;
+                               
+                       case 'exportMailAddress':
+                               WCF::getSession()->checkPermission(array('admin.user.canMailUser'));
+                               // send content type
+                               header('Content-Type: text/'.$this->fileType.'; charset=UTF-8');
+                               header('Content-Disposition: attachment; filename="export.'.$this->fileType.'"');
+                               
+                               if ($this->fileType == 'xml') {
+                                       echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<addresses>\n";
+                               }
+                               
+                               // count users
+                               $sql = "SELECT          COUNT(*) AS count
+                                       FROM            wcf".WCF_N."_user user
+                                       LEFT JOIN       wcf".WCF_N."_user_option_value option_value
+                                       ON              (option_value.userID = user.userID)
+                                       ".$this->conditions;
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute($this->conditions->getParameters());
+                               $count = $statement->fetchArray();
+                               
+                               // get users
+                               $sql = "SELECT          user.email
+                                       FROM            wcf".WCF_N."_user user
+                                       LEFT JOIN       wcf".WCF_N."_user_option_value option_value
+                                       ON              (option_value.userID = user.userID)
+                                       ".$this->conditions."
+                                       ORDER BY        user.email";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute($this->conditions->getParameters());
+                               
+                               $i = 0;
+                               while ($row = $statement->fetchArray()) {
+                                       if ($this->fileType == 'xml') echo "<address><![CDATA[".StringUtil::escapeCDATA($row['email'])."]]></address>\n";
+                                       else echo $this->textSeparator . $row['email'] . $this->textSeparator . ($i < $count['count'] ? $this->separator : '');
+                                       $i++;
+                                       $this->affectedUsers++;
+                               }
+                               
+                               if ($this->fileType == 'xml') {
+                                       echo "</addresses>";
+                               }
+                               $this->saved();
+                               exit;
+                               break;
+                               
+                       case 'assignToGroup':
+                               WCF::getSession()->checkPermission(array('admin.user.canEditUser'));
+                               
+                               $userIDArray = $this->fetchUsers(function($userID, array $userData) {
+                                       $user = new UserEditor(new User(null, $row));
+                                       $user->addToGroups($this->assignToGroupIDArray, false, false);
+                               });
+                               
+                               Session::resetSessions($userIDArray);
+                               break;
+                               
+                       case 'delete':
+                               WCF::getSession()->checkPermission(array('admin.user.canDeleteUser'));
+                               
+                               $userIDArray = $this->fetchUsers();
+                               
+                               UserEditor::deleteUsers($userIDArray);
+                               break;
+               }
+               $this->saved();
+               
+               WCF::getTPL()->assign('affectedUsers', $this->affectedUsers);
+       }
+       
+       protected function fetchUsers($loopFunction = null) {
+               // select users
+               $sql = "SELECT  user.*
+                       FROM    wcf".WCF_N."_user user
+                       LEFT JOIN       wcf".WCF_N."_user_option_value option_value
+                       ON              (option_value.userID = user.userID)
+                       ".$this->conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->conditions->getParameters()));
+               
+               $users = array();
+               while ($row = $statement->fetchArray()) {
+                       $users[$row['userID']] = $row;
+               }
+               
+               // select group ids
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("userID = ?", array(array_keys($users)));
+               
+               $sql = "SELECT  userID, groupID
+                       FROM    wcf".WCF_N."_user_to_group
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               
+               $groupIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       if (!is_array($groupIDs[$row['userID']])) {
+                               $groupIDs[$row['userID']] = array();
+                       }
+                       
+                       $groupIDs[$row['userID']][] = $row['groupID'];
+               }
+               
+               
+               foreach ($users as $userID => $userData) {
+                       if (!UserGroup::isAccessibleGroup($groupIDs[$userID])) {
+                               throw new PermissionDeniedException();
+                       }
+                       
+                       if ($loopFunction !== null) {
+                               $loopFunction($userID, $userData);
+                       }
+                       
+                       $userIDArray[] = $userID;
+                       $this->affectedUsers++;
+               }
+               
+               return $userIDArray;
+       }
+       
+       /**
+        * @see wcf\page\Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               if (!count($_POST)) {
+                       if (MAIL_USE_FORMATTED_ADDRESS) $this->from = MAIL_FROM_NAME . ' <' . MAIL_FROM_ADDRESS . '>';
+                       else $this->from = MAIL_FROM_ADDRESS;
+               }
+               
+               $this->availableGroups = $this->getAvailableGroups();
+               $this->availableLanguages = $this->getAvailableLanguages();
+               
+               foreach ($this->activeOptions as $name => $option) {
+                       if (isset($this->values[$name])) {
+                               $this->activeOptions[$name]['optionValue'] = $this->values[$name];
+                       }
+               }
+               
+               $this->options = $this->getCategoryOptions('profile');
+       }
+       
+       /**
+        * @see wcf\page\Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'username' => $this->username,
+                       'email' => $this->email,
+                       'groupIDArray' => $this->groupIDArray,
+                       'languageIDArray' => $this->languageIDArray,
+                       'invertGroupIDs' => $this->invertGroupIDs,
+                       'availableGroups' => $this->availableGroups,
+                       'availableLanguages' => $this->availableLanguages,
+                       'options' => $this->options,
+                       'availableActions' => $this->availableActions,
+                       // assign to group
+                       'assignToGroupIDArray' => $this->assignToGroupIDArray,
+                       // export mail address
+                       'separator' => $this->separator,
+                       'textSeparator' => $this->textSeparator,
+                       'fileType' => $this->fileType,
+                       // send mail
+                       'subject' => $this->subject,
+                       'text' => $this->text,
+                       'from' => $this->from,
+                       'enableHTML' => $this->enableHTML
+               ));
+       }
+       
+       /**
+        * @see wcf\form\Form::show()
+        */
+       public function show() {
+               // set active menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.user.massProcessing');
+               
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               // get user options and categories from cache
+               $this->readCache();
+               
+               // show form
+               parent::show();
+       }
+       
+       /**
+        * @see wcf\system\option\SearchableOptionType::getSearchFormElement()
+        */
+       protected function getFormElement($type, &$optionData) {
+               return $this->getTypeObject($type)->getSearchFormElement($optionData);
+       }
+       
+       /**
+        * @see wcf\acp\form\DynamicOptionListForm::checkOption()
+        */
+       protected function checkOption($optionName) {
+               $option = $this->cachedOptions[$optionName];
+               return ($option['searchable'] == 1 && !$option['disabled'] && ($option['visible'] == 3 || $option['visible'] < 2));
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/ACPSessionLogListPage.class.php b/wcfsetup/install/files/lib/acp/page/ACPSessionLogListPage.class.php
new file mode 100644 (file)
index 0000000..6ef08ee
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\page\SortablePage;
+use wcf\system\WCF;
+
+/**
+ * Shows a list of log sessions.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class ACPSessionLogListPage extends SortablePage {
+       /**
+        * @see wcf\page\AbstractPage::$templateName
+        */
+       public $templateName = 'acpSessionLogList';
+       
+       /**
+        * @see wcf\page\AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.system.canViewLog');
+       
+       /**
+        * @see wcf\page\SortablePage::$defaultSortField
+        */
+       public $defaultSortField = 'lastActivityTime';
+       
+       /**
+        * @see wcf\page\SortablePage::$defaultSortOrder
+        */
+       public $defaultSortOrder = 'DESC';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$objectListClassName
+        */
+       public $objectListClassName = 'wcf\data\acp\session\log\ACPSessionLogList';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::readObjects()
+        */
+       public function readObjects() {
+               $this->sqlOrderBy = (($this->sortField != 'accesses' && $this->sortField != 'username') ? 'acp_session_log.' : '').$this->sortField." ".$this->sortOrder;
+               
+               parent::readObjects();
+       }
+       
+       /**
+        * @see wcf\page\SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'sessionLogID':
+                       case 'username':
+                       case 'ipAddress':
+                       case 'userAgent':
+                       case 'time':
+                       case 'lastActivityTime':
+                       case 'accesses': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+       
+       /**
+        * @see wcf\page\Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'sessionLogs' => $this->objectList->getObjects()
+               ));
+       }
+       
+       /**
+        * @see wcf\page\Page::show()
+        */
+       public function show() {
+               // enable menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.log.session');
+               
+               parent::show();
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/page/ACPSessionLogPage.class.php b/wcfsetup/install/files/lib/acp/page/ACPSessionLogPage.class.php
new file mode 100644 (file)
index 0000000..7094e11
--- /dev/null
@@ -0,0 +1,127 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\data\acp\session\log\ACPSessionLog;
+use wcf\page\SortablePage;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\WCF;
+
+/**
+ * Shows the details of a logged sessions.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class ACPSessionLogPage extends SortablePage {
+       /**
+        * @see wcf\page\AbstractPage::$templateName
+        */
+       public $templateName = 'acpSessionLog';
+       
+       /**
+        * @see wcf\page\AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.system.canViewLog');
+       
+       /**
+        * @see wcf\page\SortablePage::$defaultSortField
+        */
+       public $defaultSortField = 'time';
+       
+       /**
+        * session log id
+        *
+        * @var integer
+        */
+       public $sessionLogID = 0;
+       
+       /**
+        * session log object
+        *
+        * @var wcf\data\acp\session\log\ACPSessionLog
+        */
+       public $sessionLog = null;
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$objectListClassName
+        */
+       public $objectListClassName = 'wcf\data\acp\session\access\log\ACPSessionAccessLogList';
+       
+       /**
+        * @see wcf\page\Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               // get session log
+               if (isset($_REQUEST['sessionLogID'])) $this->sessionLogID = intval($_REQUEST['sessionLogID']);
+               $this->sessionLog = new ACPSessionLog($this->sessionLogID);
+               if (!$this->sessionLog->sessionLogID) {
+                       throw new IllegalLinkException();
+               }
+       }
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::initObjectList()
+        */
+       protected function initObjectList() {
+               parent::initObjectList();
+               
+               $this->objectList->getConditionBuilder()->add('sessionLogID = ?', array($this->sessionLogID));
+       }
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::readObjects()
+        */     
+       protected function readObjects() {
+               $this->sqlOrderBy = ($this->sortField != 'packageName' ? 'acp_session_access_log.' : '').$this->sortField." ".$this->sortOrder;
+               
+               parent::readObjects();
+       }
+       
+       /**
+        * @see wcf\page\SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'sessionAccessLogID':
+                       case 'ipAddress':
+                       case 'time':
+                       case 'requestURI':
+                       case 'requestMethod':
+                       case 'className':
+                       case 'packageName': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+       
+       /**
+        * @see wcf\page\Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'sessionAccessLogs' => $this->objectList->getObjects(),
+                       'sessionLogID' => $this->sessionLogID,
+                       'sessionLog' => $this->sessionLog
+               ));
+       }
+       
+       /**
+        * @see wcf\page\Page::show()
+        */
+       public function show() {
+               // enable menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.log.session');
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/CacheListPage.class.php b/wcfsetup/install/files/lib/acp/page/CacheListPage.class.php
new file mode 100644 (file)
index 0000000..b2b2861
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\page\AbstractPage;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\cache\source\MemcacheAdapter;
+use wcf\system\cache\CacheHandler;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Shows a list of all cache resources.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class CacheListPage extends AbstractPage {
+       // system
+       public $templateName = 'cacheList';
+       public $neededPermissions = array('admin.system.canViewLog');
+       public $cleared = 0;
+       
+       /**
+        * contains a list of cache resources
+        *
+        * @var array
+        */
+       public $caches = array();
+       
+       /**
+        * contains general cache information
+        *
+        * @var array
+        */
+       public $cacheData = array();
+       
+       /**
+        * @see Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_REQUEST['cleared'])) $this->cleared = intval($_REQUEST['cleared']);
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               // init cache data
+               $this->cacheData = array(
+                       'source' => get_class(CacheHandler::getInstance()->getCacheSource()),
+                       'version' => '',
+                       'size' => 0,
+                       'files' => 0
+               );
+               
+               // filesystem cache
+               if ($this->cacheData['source'] == 'wcf\system\cache\source\DiskCacheSource') {
+                       // set version
+                       $this->cacheData['version'] = WCF_VERSION;
+                       
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+                       $conditions->add("standalone = ?", array(1));
+                       
+                       // get package dirs
+                       $sql = "SELECT  packageDir
+                               FROM    wcf".WCF_N."_package
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               $packageDir = FileUtil::getRealPath(WCF_DIR.$row['packageDir']);
+                               $cacheDir = $packageDir.'cache';
+                               if (file_exists($cacheDir)) {
+                                       $this->caches[$cacheDir] = array();
+
+                                       // get files in cache directory
+                                       $files = glob($cacheDir.'/*.php');
+                                       // get additional file information
+                                       if (is_array($files)) {
+                                               foreach ($files as $file) {
+                                                       $filesize = filesize($file);
+                                                       $this->caches[$cacheDir][] = array(
+                                                               'filename' => basename($file),
+                                                               'filesize' => $filesize,
+                                                               'mtime' => filemtime($file),
+                                                               'perm' => substr(sprintf('%o', fileperms($file)), -3),
+                                                               'writable' => is_writable($file)
+                                                       );
+                                                       
+                                                       $this->cacheData['files']++;
+                                                       $this->cacheData['size'] += $filesize;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               // memcache
+               else if ($this->cacheData['source'] == 'wcf\system\cache\source\MemcacheCacheSource') {
+                       // get version
+                       $this->cacheData['version'] = MemcacheAdapter::getInstance()->getMemcache()->getVersion();
+                       
+                       // get stats
+                       $stats = MemcacheAdapter::getInstance()->getMemcache()->getStats();
+                       $this->cacheData['files'] = $stats['curr_items'];
+                       $this->cacheData['size'] = $stats['bytes'];
+               }
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'caches' => $this->caches,
+                       'cacheData' => $this->cacheData,
+                       'cleared' => $this->cleared
+               ));
+       }
+       
+       /**
+        * @see Page::show()
+        */
+       public function show() {
+               // enable menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.log.cache');
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/CronjobListPage.class.php b/wcfsetup/install/files/lib/acp/page/CronjobListPage.class.php
new file mode 100644 (file)
index 0000000..2d915f1
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\page\SortablePage;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+
+/**
+ * Shows information about configured cron jobs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class CronjobListPage extends SortablePage {
+       /**
+        * @see wcf\page\AbstractPage::$templateName
+        */
+       public $templateName = 'cronjobList';
+       
+       /**
+        * @see wcf\page\AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.system.cronjobs.canEditCronjob', 'admin.system.cronjobs.canDeleteCronjob', 'admin.system.cronjobs.canEnableDisableCronjob');
+       
+       /**
+        * @see wcf\page\SortablePage::$defaultSortField
+        */
+       public $defaultSortField = 'description';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$objectListClassName
+        */     
+       public $objectListClassName = 'wcf\data\cronjob\CronjobList';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::readObjects()
+        */     
+       public function readObjects() {
+               $this->objectList->getConditionBuilder()->add("cronjob.packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+               $this->sqlOrderBy = "cronjob.".$this->sortField." ".$this->sortOrder;
+               
+               parent::readObjects();
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'cronjobs' => $this->objectList->getObjects()
+               ));
+       }
+       
+       /**
+        * @see wcf\page\SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'description':
+                       case 'cronjobID':
+                       case 'nextExec':
+                       case 'startMinute':
+                       case 'startHour':
+                       case 'startDom':
+                       case 'startMonth':
+                       case 'startDow': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+       
+       /**
+        * @see wcf\page\Page::show()
+        */
+       public function show() {
+               // set active menu item.
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.cronjobs.view');
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/CronjobLogListPage.class.php b/wcfsetup/install/files/lib/acp/page/CronjobLogListPage.class.php
new file mode 100644 (file)
index 0000000..281062d
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\page\SortablePage;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+
+/**
+ * Shows cron jobs log information.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class CronjobLogListPage extends SortablePage {
+       /**
+        * @see wcf\page\AbstractPage::$templateName
+        */
+       public $templateName = 'cronjobLogList';
+       
+       /**
+        * @see wcf\page\AbstractPage::$neededPermissions
+        */
+       public $neededPermissions = array('admin.system.cronjobs.canEditCronjob');
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$itemsPerPage
+        */
+       public $itemsPerPage = 100;
+       
+       /**
+        * @see wcf\page\SortablePage::$defaultSortField
+        */
+       public $defaultSortField = 'execTime';
+       
+       /**
+        * @see wcf\page\SortablePage::$defaultSortOrder
+        */
+       public $defaultSortOrder = 'DESC';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$objectListClassName
+        */     
+       public $objectListClassName = 'wcf\data\cronjob\log\CronjobLogList';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::initObjectList()
+        */
+       protected function initObjectList() {
+               parent::initObjectList();
+               
+               $this->objectList->sqlSelects = "cronjob.*";
+               $this->objectList->sqlJoins = "LEFT JOIN wcf".WCF_N."_cronjob cronjob ON (cronjob.cronjobID = cronjob_log.cronjobID)";
+               $this->objectList->getConditionBuilder()->add("cronjob_log.cronjobID IN (SELECT cronjobID FROM wcf".WCF_N."_cronjob WHERE packageID IN (?))", array(PackageDependencyHandler::getDependencies()));
+       }
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::readObjects()
+        */
+       protected function readObjects() {
+               $this->sqlOrderBy = (($this->sortField == 'classPath' || $this->sortField == 'description') ? 'cronjob.' : 'cronjob_log.').$this->sortField." ".$this->sortOrder;
+               
+               parent::readObjects();
+       }
+       
+       /**
+        * @see wcf\page\Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'cronjobLogs' => $this->objectList->getObjects()
+               ));
+       }
+       
+       /**
+        * @see wcf\page\SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'cronjobID':
+                       case 'classPath':
+                       case 'description':
+                       case 'execTime':
+                       case 'success': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+       
+       /**
+        * @see wcf\page\Page::show()
+        */
+       public function show() {
+               // set active menu item.
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.cronjobs.showLog');
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/IndexPage.class.php b/wcfsetup/install/files/lib/acp/page/IndexPage.class.php
new file mode 100644 (file)
index 0000000..cbcf11f
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+namespace wcf\acp\page;\r
+use wcf\page\AbstractPage;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\package\PackageInstallationDispatcher;\r
+use wcf\system\WCF;\r
+use wcf\system\WCFACP;\r
+\r
+/**\r
+ * Shows the welcome page in admin control panel.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.page\r
+ * @category   Community Framework\r
+ */\r
+class IndexPage extends AbstractPage {\r
+       // system\r
+       public $templateName = 'index';\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               $wcfPackageID = WCFACP::getWcfPackageID();\r
+               // check package installation queue\r
+               if ($wcfPackageID == 0) {\r
+                       $queueID = PackageInstallationDispatcher::checkPackageInstallationQueue();\r
+                       \r
+                       if ($queueID) {\r
+                               WCF::getTPL()->assign(array(\r
+                                       'queueID' => $queueID\r
+                               ));\r
+                               WCF::getTPL()->display('packageInstallationSetup');\r
+                               exit;\r
+                       }\r
+               }\r
+               \r
+               /*\r
+               if (WCFACP::getWcfPackageID() == PACKAGE_ID) {\r
+                       $packages = CacheHandler::getInstance()->get('packages');\r
+                       foreach ($packages as $packageID => $package) {\r
+                               break;\r
+                       }\r
+                       \r
+                       if (isset($packageID) && $packageID != PACKAGE_ID) {\r
+                               HeaderUtil::redirect('../'.$packages[$packageID]['packageDir'].'acp/index.php'.SID_ARG_1ST, false);\r
+                               exit;\r
+                       }\r
+               }\r
+               */\r
+               \r
+               // show page\r
+               parent::show();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php b/wcfsetup/install/files/lib/acp/page/LanguageServerListPage.class.php
new file mode 100644 (file)
index 0000000..d0b0bca
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+namespace wcf\acp\page;
+use wcf\acp\page\util\menu\ACPMenu;
+use wcf\page\SortablePage;
+use wcf\system\WCF;
+
+/**
+ * Shows information about available language servers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class LanguageServerListPage extends SortablePage {
+       // system
+       public $templateName = 'languageServerList';
+       public $neededPermissions = array('admin.language.canEditServer');
+       public $defaultSortField = 'serverURL';
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$objectListClassName
+        */     
+       public $objectListClassName = 'wcf\data\language\server\LanguageServerList';
+       
+       /**
+        * @see wcf\page\Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'languageServers' => $this->objectList->getObjects()
+               ));
+       }
+       
+       /**
+        * @see wcf\page\Page::show()
+        */
+       public function show() {
+               // enable menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.language.server.view');
+               
+               parent::show();
+       }
+       
+       /**
+        * @see wcf\page\SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'languageServerID':
+                       case 'serverURL': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/PackageAutoUpdateListPage.class.php b/wcfsetup/install/files/lib/acp/page/PackageAutoUpdateListPage.class.php
new file mode 100644 (file)
index 0000000..04ac3f5
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\page\AbstractPage;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\system\package\PackageUpdateDispatcher;
+
+/**
+ * Shows the list of available updates for installed packages.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class PackageAutoUpdateListPage extends AbstractPage {
+       public $templateName = 'packageAutoUpdateList';
+       public $neededPermissions = array('admin.system.package.canUpdatePackage');
+       
+       public $availableUpdates = array();
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (!count($_POST)) {
+                       // refresh package database
+                       PackageUpdateDispatcher::refreshPackageDatabase();
+               }
+               
+               // get updatable packages
+               $this->availableUpdates = PackageUpdateDispatcher::getAvailableUpdates();
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'availableUpdates' => $this->availableUpdates
+               ));
+       }
+       
+       /**
+        * @see Page::show()
+        */
+       public function show() {
+               // set active menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.autoupdate');
+               
+               // check master password
+               WCFACP::checkMasterPassword();
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php b/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php
new file mode 100644 (file)
index 0000000..701c144
--- /dev/null
@@ -0,0 +1,95 @@
+<?php\r
+namespace wcf\acp\page;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\package\PackageList;\r
+use wcf\page\SortablePage;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Shows a list of all installed packages.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.page\r
+ * @category   Community Framework\r
+ */\r
+class PackageListPage extends SortablePage {\r
+       // system\r
+       public $templateName = 'packageList';\r
+       public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canUninstallPackage');\r
+       public $itemsPerPage = 50;\r
+       public $defaultSortField = 'packageType';\r
+       public $defaultSortOrder = 'DESC';\r
+       \r
+       /**\r
+        * list of packages\r
+        * \r
+        * @var PackageList\r
+        */\r
+       public $packageList = null;\r
+       \r
+       /**\r
+        * class name for DatabaseObjectList\r
+        * \r
+        * @var string\r
+        */     \r
+       public $objectListClassName = 'wcf\data\package\PackageList';\r
+       \r
+       /**\r
+        * @see wcf\page\MuletipleLinkPage::readObjects()\r
+        */     \r
+       protected function readObjects() {\r
+               $this->sqlOrderBy = 'package.'.($this->sortField == 'packageType' ? 'standalone '.$this->sortOrder.', package.parentPackageID '.$this->sortOrder : $this->sortField.' '.$this->sortOrder).($this->sortField != 'packageName' ? ', package.packageName ASC' : '');\r
+               \r
+               parent::readObjects();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign('packages', $this->objectList->getObjects());\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               // enable menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.package.view');\r
+               \r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see SortablePage::validateSortField()\r
+        */\r
+       public function validateSortField() {\r
+               parent::validateSortField();\r
+               \r
+               switch ($this->sortField) {\r
+                       case 'packageID':\r
+                       case 'package':\r
+                       case 'packageDir':\r
+                       case 'packageName':\r
+                       case 'instanceNo':\r
+                       case 'packageDescription':\r
+                       case 'packageVersion':\r
+                       case 'packageDate':\r
+                       case 'packageURL':\r
+                       case 'parentPackageID':\r
+                       case 'isUnique':\r
+                       case 'standalone':\r
+                       case 'author':\r
+                       case 'authorURL':\r
+                       case 'installDate':\r
+                       case 'updateDate': break;\r
+                       default: $this->sortField = $this->defaultSortField;\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/page/PackagePage.class.php b/wcfsetup/install/files/lib/acp/page/PackagePage.class.php
new file mode 100644 (file)
index 0000000..afdb5f8
--- /dev/null
@@ -0,0 +1,78 @@
+<?php\r
+namespace wcf\acp\page;\r
+use wcf\data\package\installation\queue\PackageInstallationQueue;\r
+use wcf\page\AbstractPage;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\package\PackageInstallationDispatcher;\r
+use wcf\system\package\PackageUninstallationDispatcher;\r
+use wcf\system\WCF;\r
+use wcf\system\WCFACP;\r
+\r
+/**\r
+ * Handles all request on the package.php script\r
+ * and executes the requested action.\r
+ * TODO: split this page into separate pages / actions\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.page\r
+ * @category   Community Framework\r
+ */\r
+class PackagePage extends AbstractPage {\r
+       const DO_NOT_LOG = true;\r
+       public $parentQueueID = 0;\r
+       public $processNo = 0;\r
+       public $queueID = 0;\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['parentQueueID'])) $this->parentQueueID = intval($_REQUEST['parentQueueID']);\r
+               if (isset($_REQUEST['processNo'])) $this->processNo = intval($_REQUEST['processNo']);\r
+               if (isset($_REQUEST['queueID'])) $this->queueID = intval($_REQUEST['queueID']);\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               parent::show();\r
+\r
+               // check master password\r
+               WCFACP::checkMasterPassword();\r
+               \r
+               switch ($this->action) {\r
+                       case 'install':\r
+                       case 'update':\r
+                               if ($this->action == 'install') WCF::getSession()->checkPermission(array('admin.system.package.canInstallPackage'));\r
+                               else WCF::getSession()->checkPermission(array('admin.system.package.canUpdatePackage'));\r
+                               \r
+                               $queue = new PackageInstallationQueue($this->queueID);\r
+                               $dispatcher = new PackageInstallationDispatcher($queue);\r
+                               $dispatcher->beginInstallation();\r
+                       break;\r
+                               \r
+                       case 'rollback':\r
+                               die('ROLLBACK');\r
+                               WCF::getSession()->checkPermission(array('admin.system.package.canInstallPackage'));\r
+                               require_once(WCF_DIR.'lib/acp/package/PackageInstallationRollback.class.php');\r
+                               new PackageInstallationRollback($this->queueID);\r
+                       break;\r
+                       \r
+                       case 'openQueue':\r
+                               PackageInstallationDispatcher::openQueue($this->parentQueueID, $this->processNo);\r
+                       break;\r
+                               \r
+                       case 'startUninstall':\r
+                               WCF::getSession()->checkPermission(array('admin.system.package.canUninstallPackage'));\r
+                               PackageUninstallationDispatcher::checkDependencies();\r
+                       break;\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/page/PackageUpdateSearchResultPage.class.php b/wcfsetup/install/files/lib/acp/page/PackageUpdateSearchResultPage.class.php
new file mode 100644 (file)
index 0000000..ae8e212
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\data\package\Package;
+use wcf\data\search\Search;
+use wcf\page\SortablePage;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\WCF;
+
+/**
+ * Shows the list of package update search results.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class PackageUpdateSearchResultPage extends SortablePage {
+       public $templateName = 'packageUpdateSearchResult';
+       public $defaultSortField = 'packageName';
+       public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canInstallPackage');
+       
+       public $searchID = 0;
+       
+       /**
+        * search object
+        * @var wcf\data\search\Search
+        */
+       public $search = null;
+       public $packages = array();
+       
+       /**
+        * @see Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_REQUEST['searchID'])) $this->searchID = intval($_REQUEST['searchID']);
+               
+               // get search data
+               $conditions = new PrepareStatementConditionBuilder();
+               $conditions->add("searchID = ?", array($this->searchID));
+               $conditions->add("userID = ?", array(WCF::getUser()->userID));
+               $conditions->add("searchType = ?", array('packages'));
+               
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_search
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               
+               $this->search = new Search(null, $statement->fetchArray());
+               if (empty($this->search->searchID)) {
+                       throw new IllegalLinkException();
+               }
+       }
+       
+       /**
+        * @see Page::readData()
+        */
+       public function readData() {
+               parent::readData();
+               
+               // read packages
+               $this->readPackages();
+       }
+       
+       /**
+        * @see MultipleLinkPage::countItems()
+        */
+       public function countItems() {
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("packageUpdateID IN (?)", array(explode(',', $this->search->searchData)));
+               
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_package_update
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               $row = $statement->fetchArray();
+               
+               return $row['count'];
+       }
+       
+       /**
+        * @see SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'package':
+                       case 'packageName':
+                       case 'author': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+       
+       /**
+        * Gets a list of packages.
+        */
+       protected function readPackages() {
+               if ($this->items) {
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("packageUpdateID IN (?)", array(explode(',', $this->search->searchData)));
+                       
+                       $sql = "SELECT          *
+                               FROM            wcf".WCF_N."_package_update
+                               ".$conditions."
+                               ORDER BY        ".$this->sortField." ".$this->sortOrder;
+                       $statement = WCF::getDB()->prepareStatement($sql, $this->itemsPerPage, ($this->pageNo - 1) * $this->itemsPerPage);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               // default values
+                               $row['isUnique'] = 0;
+                               $row['updatableInstances'] = array();
+                               $row['packageVersions'] = array();
+                               $row['packageVersion'] = '1.0.0';
+                               $row['instances'] = 0;
+                               
+                               // get package versions
+                               $sql = "SELECT  packageVersion
+                                       FROM    wcf".WCF_N."_package_update_version
+                                       WHERE   packageUpdateID IN (
+                                                       SELECT  packageUpdateID
+                                                       FROM    wcf".WCF_N."_package_update
+                                                       WHERE   package = ?
+                                               )";
+                               $statement2 = WCF::getDB()->prepareStatement($sql);
+                               $statement2->execute(array($row['package']));
+                               while ($row2 = $statement2->fetchArray()) {
+                                       $row['packageVersions'][] = $row2['packageVersion'];
+                               }
+                               
+                               if (count($row['packageVersions'])) {
+                                       // remove duplicates
+                                       $row['packageVersions'] = array_unique($row['packageVersions']);
+                                       // sort versions
+                                       usort($row['packageVersions'], array('wcf\data\package\Package', 'compareVersion'));
+                                       // take lastest version
+                                       $row['packageVersion'] = end($row['packageVersions']);
+                               }
+                                       
+                               // get installed instances
+                               $sql = "SELECT  package.*, CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                                       FROM    wcf".WCF_N."_package package
+                                       WHERE   package.package = ?";
+                               $statement2 = WCF::getDB()->prepareStatement($sql);
+                               $statement2->execute(array($row['package']));
+                               while ($row2 = $statement2->fetchArray()) {
+                                       $row['instances']++;
+
+                                       // is already installed unique?
+                                       if ($row2['isUnique'] == 1) $row['isUnique'] = 1;
+                                       
+                                       // check update support
+                                       if (Package::compareVersion($row2['packageVersion'], $row['packageVersion'], '<')) {
+                                               $row['updatableInstances'][] = $row2;
+                                       }
+                               }
+                               
+                               $this->packages[] = $row;
+                       }
+               }
+       }
+       
+       /**
+        * @see Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'searchID' => $this->searchID,
+                       'packages' => $this->packages,
+                       'selectedPackages' => array()
+               ));
+       }
+       
+       /**
+        * @see Page::show()
+        */
+       public function show() {
+               // set active menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.package.database');
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/PackageViewPage.class.php b/wcfsetup/install/files/lib/acp/page/PackageViewPage.class.php
new file mode 100644 (file)
index 0000000..0d195a6
--- /dev/null
@@ -0,0 +1,78 @@
+<?php\r
+namespace wcf\acp\page;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\package\Package;\r
+use wcf\page\AbstractPage;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Shows all information about an installed package.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.page\r
+ * @category   Community Framework\r
+ */\r
+class PackageViewPage extends AbstractPage {\r
+       public $package;\r
+       public $packageID = 0;\r
+       public $templateName = 'packageView';\r
+       public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canUninstallPackage');\r
+       public $requiredPackages = array();\r
+       public $dependentPackages = array();\r
+       public $dependencies = array();\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['activePackageID'])) $this->packageID = intval($_REQUEST['activePackageID']);\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               // get package data\r
+               try {\r
+                       $this->package = new Package($this->packageID);\r
+                       $this->requiredPackages = $this->package->getRequiredPackages();\r
+                       $this->dependentPackages = $this->package->getDependentPackages();\r
+                       $this->dependencies = $this->package->getDependencies();\r
+               }\r
+               catch (SystemException $e) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'requiredPackages' => $this->requiredPackages,\r
+                       'dependentPackages' => $this->dependentPackages,\r
+                       'dependencies' => $this->dependencies,\r
+                       'package' => $this->package\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               // enable menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.package');\r
+               \r
+               parent::show();\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/page/UpdateServerListPage.class.php b/wcfsetup/install/files/lib/acp/page/UpdateServerListPage.class.php
new file mode 100644 (file)
index 0000000..f0c8c89
--- /dev/null
@@ -0,0 +1,86 @@
+<?php\r
+namespace wcf\acp\page;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\page\SortablePage;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Shows information about available update package servers.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.page\r
+ * @category   Community Framework\r
+ */\r
+class UpdateServerListPage extends SortablePage {\r
+       // system\r
+       public $templateName = 'updateServerList';\r
+       public $neededPermissions = array('admin.system.package.canEditServer');\r
+       public $defaultSortField = 'serverURL';\r
+       public $deletedPackageUpdateServerID = 0;\r
+       \r
+       /**\r
+        * @see wcf\page\MultipleLinkPage::$objectListClassName\r
+        */     \r
+       public $objectListClassName = 'wcf\data\package\update\server\PackageUpdateServerList';\r
+       \r
+       /**\r
+        * @see wcf\page\Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_REQUEST['deletedPackageUpdateServerID'])) $this->deletedPackageUpdateServerID = intval($_REQUEST['deletedPackageUpdateServerID']);\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\page\MultipleLinkPage::readObjects()\r
+        */     \r
+       public function readObjects() {\r
+               $this->sqlOrderBy = ($this->sortField != 'packages' ? 'package_update_server.' : '') . $this->sortField.' '.$this->sortOrder;\r
+               \r
+               parent::readObjects();\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\page\Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'updateServers' => $this->objectList->getObjects(),\r
+                       'deletedPackageUpdateServerID' => $this->deletedPackageUpdateServerID\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\page\Page::show()\r
+        */\r
+       public function show() {\r
+               // enable menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.package.server.view');\r
+               \r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see wcf\page\SortablePage::validateSortField()\r
+        */\r
+       public function validateSortField() {\r
+               parent::validateSortField();\r
+               \r
+               switch ($this->sortField) {\r
+                       case 'packageUpdateServerID':\r
+                       case 'serverURL':\r
+                       case 'status':\r
+                       case 'errorMessage':\r
+                       case 'lastUpdateTime':\r
+                       case 'packages': break;\r
+                       default: $this->sortField = $this->defaultSortField;\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/acp/page/UserGroupListPage.class.php b/wcfsetup/install/files/lib/acp/page/UserGroupListPage.class.php
new file mode 100644 (file)
index 0000000..998c6de
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+namespace wcf\acp\page;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\page\SortablePage;
+use wcf\system\WCF;
+
+/**
+ * Shows a list of all user groups.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.page
+ * @category   Community Framework
+ */
+class UserGroupListPage extends SortablePage {
+       // system
+       public $templateName = 'userGroupList';
+       public $deletedGroups = 0;
+       public $defaultSortField = 'groupName';
+       public $neededPermissions = array('admin.user.canEditGroup', 'admin.user.canDeleteGroup');
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::$objectListClassName
+        */     
+       public $objectListClassName = 'wcf\data\user\group\UserGroupList';
+       
+       /**
+        * @see wcf\page\Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               // detect group deletion
+               if (isset($_REQUEST['deletedGroups'])) {
+                       $this->deletedGroups = intval($_REQUEST['deletedGroups']);
+               }
+       }
+       
+       /**
+        * @see wcf\page\SortablePage::validateSortField()
+        */
+       public function validateSortField() {
+               parent::validateSortField();
+               
+               switch ($this->sortField) {
+                       case 'groupID':
+                       case 'groupName':
+                       case 'groupType':
+                       case 'members': break;
+                       default: $this->sortField = $this->defaultSortField;
+               }
+       }
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::initObjectList()
+        */     
+       protected function initObjectList() {
+               parent::initObjectList();
+               
+               $this->objectList->sqlSelects .= "(SELECT COUNT(*) FROM wcf".WCF_N."_user_to_group WHERE groupID = user_group.groupID) AS members";
+       }
+       
+       /**
+        * @see wcf\page\MultipleLinkPage::readObjects()
+        */
+       protected function readObjects() {
+               $this->sqlOrderBy = ($this->sortField != 'members' ? 'user_group.' : '').$this->sortField." ".$this->sortOrder;
+               
+               parent::readObjects();
+       }
+       
+       /**
+        * @see wcf\page\Page::assignVariables()
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign(array(
+                       'groups' => $this->objectList->getObjects(),
+                       'deletedGroups' => $this->deletedGroups
+               ));
+       }
+       
+       /**
+        * @see Page::show()
+        */
+       public function show() {
+               // enable menu item
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.group.view');
+               
+               parent::show();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/acp/page/UserListPage.class.php b/wcfsetup/install/files/lib/acp/page/UserListPage.class.php
new file mode 100644 (file)
index 0000000..2b8627b
--- /dev/null
@@ -0,0 +1,316 @@
+<?php\r
+namespace wcf\acp\page;\r
+use wcf\system\menu\acp\ACPMenu;\r
+use wcf\data\user\User;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\page\SortablePage;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\event\EventHandler;\r
+use wcf\system\WCF;\r
+use wcf\util\DateUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Shows the result of a user search.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage acp.page\r
+ * @category   Community Framework\r
+ */\r
+class UserListPage extends SortablePage {\r
+       // system\r
+       public $itemsPerPage = 50;\r
+       public $defaultSortField = 'username';\r
+       public $templateName = 'userList';\r
+       public $neededPermissions = array('admin.user.canSearchUser');\r
+       \r
+       // parameters\r
+       public $searchID = 0;\r
+       \r
+       // data\r
+       public $userIDs = array();\r
+       public $markedUsers = array();\r
+       public $users = array();\r
+       public $url = '';\r
+       public $columns = array('email', 'registrationDate');\r
+       public $outputObjects = array();\r
+       public $options = array();\r
+       public $columnValues = array();\r
+       public $columnHeads = array();\r
+       public $sqlConditions = '';\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               $this->conditions = new PreparedStatementConditionBuilder();\r
+               \r
+               if (!empty($_REQUEST['searchID'])) {\r
+                       $this->searchID = intval($_REQUEST['searchID']);\r
+                       if ($this->searchID) $this->readSearchResult();\r
+                       if (!count($this->userIDs)) {\r
+                               throw new IllegalLinkException();\r
+                       }\r
+                       $this->conditions->add("user_table.userID IN (?)", array($this->userIDs));\r
+               }\r
+               \r
+               // get user options\r
+               $this->readUserOptions();\r
+       }\r
+       \r
+       /**\r
+        * @see SortablePage::validateSortField()\r
+        */\r
+       public function validateSortField() {\r
+               parent::validateSortField();\r
+               \r
+               switch ($this->sortField) {\r
+                       case 'email':\r
+                       case 'userID':\r
+                       case 'registrationDate':\r
+                       case 'username': break;\r
+                       default: \r
+                               if (!isset($this->options[$this->sortField])) {\r
+                                       $this->sortField = $this->defaultSortField;\r
+                               }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               // get marked users\r
+               $this->markedUsers = WCF::getSession()->getVar('markedUsers');\r
+               if ($this->markedUsers == null || !is_array($this->markedUsers)) $this->markedUsers = array();\r
+               \r
+               // get columns heads\r
+               $this->readColumnsHeads();\r
+               \r
+               // get users\r
+               $this->readUsers();\r
+               \r
+               // build page url\r
+               $this->url = 'index.php?page=UserList&searchID='.$this->searchID.'&action='.rawurlencode($this->action).'&pageNo='.$this->pageNo.'&sortField='.$this->sortField.'&sortOrder='.$this->sortOrder.''.SID_ARG_2ND_NOT_ENCODED;\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'users' => $this->users,\r
+                       'searchID' => $this->searchID,\r
+                       'markedUsers' => count($this->markedUsers),\r
+                       'url' => $this->url,\r
+                       'columnHeads' => $this->columnHeads,\r
+                       'columnValues' => $this->columnValues\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               // set active menu item\r
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.user.'.($this->searchID ? 'search' : 'list'));\r
+               \r
+               parent::show();\r
+       }\r
+       \r
+       /**\r
+        * @see MultipleLinkPage::countItems()\r
+        */\r
+       public function countItems() {\r
+               // call countItems event\r
+               EventHandler::getInstance()->fireAction($this, 'countItems');\r
+\r
+               $sql = "SELECT  COUNT(*) AS count\r
+                       FROM    wcf".WCF_N."_user user_table\r
+                       ".$this->conditions;\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute($this->conditions->getParameters());\r
+               $row = $statement->fetchArray();\r
+               return $row['count'];\r
+       }\r
+       \r
+       /**\r
+        * Gets the list of results.\r
+        */\r
+       protected function readUsers() {\r
+               // get user ids\r
+               $userIDs = array();\r
+               $sql = "SELECT          user_table.userID\r
+                       FROM            wcf".WCF_N."_user user_table\r
+                       ".(isset($this->options[$this->sortField]) ? "LEFT JOIN wcf".WCF_N."_user_option_value user_option_value ON (user_option_value.userID = user.userID)" : '')."\r
+                       ".$this->conditions."\r
+                       ORDER BY        ".(($this->sortField != 'email' && isset($this->options[$this->sortField])) ? 'user_option_value.userOption'.$this->options[$this->sortField]['optionID'] : $this->sortField)." ".$this->sortOrder;\r
+               $statement = WCF::getDB()->prepareStatement($sql, $this->itemsPerPage, ($this->pageNo - 1) * $this->itemsPerPage);\r
+               $statement->execute($this->conditions->getParameters());\r
+               while ($row = $statement->fetchArray()) {\r
+                       $userIDs[] = $row['userID'];\r
+               }\r
+               \r
+               // get user data\r
+               if (count($userIDs)) {\r
+                       $userToGroups = array();\r
+                       \r
+                       // get group ids\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("user_table.userID IN (?)", array($userIDs));\r
+                       \r
+                       $sql = "SELECT  userID, groupID\r
+                               FROM    wcf".WCF_N."_user_to_group user_table\r
+                               ".$conditions;\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $userToGroups[$row['userID']][] = $row['groupID'];\r
+                       }\r
+                       \r
+                       $sql = "SELECT          option_value.*, user_table.*\r
+                               FROM            wcf".WCF_N."_user user_table\r
+                               LEFT JOIN       wcf".WCF_N."_user_option_value option_value\r
+                               ON              (option_value.userID = user_table.userID)\r
+                               ".$conditions."\r
+                               ORDER BY        ".(($this->sortField != 'email' && isset($this->options[$this->sortField])) ? 'option_value.userOption'.$this->options[$this->sortField]['optionID'] : 'user_table.'.$this->sortField)." ".$this->sortOrder;\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $row['groupIDs'] = implode(',', $userToGroups[$row['userID']]);\r
+                               $accessible = UserGroup::isAccessibleGroup($userToGroups[$row['userID']]);\r
+                               $row['accessible'] = $accessible;\r
+                               $row['deletable'] = ($accessible && WCF::getSession()->getPermission('admin.user.canDeleteUser') && $row['userID'] != WCF::getUser()->userID) ? 1 : 0;\r
+                               $row['editable'] = ($accessible && WCF::getSession()->getPermission('admin.user.canEditUser')) ? 1 : 0;\r
+                               $row['isMarked'] = intval(in_array($row['userID'], $this->markedUsers));\r
+                               \r
+                               $this->users[] = new User(null, $row);\r
+                       }\r
+                       \r
+                       // get special columns\r
+                       foreach ($this->users as $key => $user) {\r
+                               foreach ($this->columns as $column) {\r
+                                       if (isset($this->options[$column])) {\r
+                                               if ($this->options[$column]['outputClass']) {\r
+                                                       $outputObj = $this->getOutputObject($this->options[$column]['outputClass']);\r
+                                                       $this->columnValues[$user->userID][$column] = $outputObj->getOutput($user, $this->options[$column], $user->{$column});\r
+                                               }\r
+                                               else {\r
+                                                       $this->columnValues[$user->userID][$column] = StringUtil::encodeHTML($user->{$column});\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               switch ($column) {\r
+                                                       case 'email':\r
+                                                               $this->columnValues[$user->userID][$column] = '<a href="mailto:'.StringUtil::encodeHTML($user->email).'">'.StringUtil::encodeHTML($user->email).'</a>';\r
+                                                               break;\r
+                                                       case 'registrationDate':\r
+                                                               $this->columnValues[$user->userID][$column] = DateUtil::format(DateUtil::getDateTimeByTimestamp($user->{$column}), DateUtil::DATE_FORMAT);\r
+                                                               break;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Gets the result of the search with the given search id.\r
+        */\r
+       protected function readSearchResult() {\r
+               // get user search from database\r
+               $sql = "SELECT  searchData\r
+                       FROM    wcf".WCF_N."_search\r
+                       WHERE   searchID = ?\r
+                               AND userID = ?\r
+                               AND searchType = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array(\r
+                       $this->searchID,\r
+                       WCF::getUser()->userID,\r
+                       'users'\r
+               ));\r
+               $search = $statement->fetchArray();\r
+               if (!isset($search['searchData'])) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               \r
+               $data = unserialize($search['searchData']);\r
+               $this->userIDs = $data['matches'];\r
+               $this->itemsPerPage = $data['itemsPerPage'];\r
+               $this->columns = $data['columns'];\r
+               unset($data);\r
+       }\r
+       \r
+       /**\r
+        * Gets the user options from cache.\r
+        */\r
+       protected function readUserOptions() {\r
+               // add cache resource\r
+               $cacheName = 'user-option-'.PACKAGE_ID;\r
+               CacheHandler::getInstance()->addResource($cacheName, WCF_DIR.'cache/cache.'.$cacheName.'.php', 'wcf\system\cache\CacheBuilderOption');\r
+               \r
+               // get options\r
+               $this->options = CacheHandler::getInstance()->get($cacheName, 'options');\r
+       }\r
+       \r
+       /**\r
+        * Reads the column heads.\r
+        */\r
+       protected function readColumnsHeads() {\r
+               foreach ($this->columns as $column) {\r
+                       if (isset($this->options[$column])) {\r
+                               $this->columnHeads[$column] = 'wcf.user.option.'.$column;\r
+                       }\r
+                       else {\r
+                               $this->columnHeads[$column] = 'wcf.user.'.$column;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns an object of the requested option output type.\r
+        * \r
+        * @param       string                  $type\r
+        * @return      UserOptionOutput\r
+        */\r
+       protected function getOutputObject($className) {\r
+               if (!isset($this->outputObjects[$className])) {\r
+                       // include class file\r
+                       $classPath = WCF_DIR.'lib/data/user/option/'.$className.'.class.php';\r
+                       if (!file_exists($classPath)) {\r
+                               throw new SystemException("unable to find class file '".$classPath."'", 11000);\r
+                       }\r
+                       require_once($classPath);\r
+                       \r
+                       // create instance\r
+                       if (!class_exists($className)) {\r
+                               throw new SystemException("unable to find class '".$className."'", 11001);\r
+                       }\r
+                       $this->outputObjects[$className] = new $className();\r
+               }\r
+               \r
+               return $this->outputObjects[$className];\r
+       }\r
+\r
+       /**\r
+        * @see wcf\page\MultipleLinkPage::initObjectList()\r
+        */             \r
+       protected function initObjectList() { }\r
+       \r
+       /**\r
+        * @see wcf\page\MultipleLinkPage::readObjects()\r
+        */     \r
+       protected function readObjects() { }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/action/AJAXProxyAction.class.php b/wcfsetup/install/files/lib/action/AJAXProxyAction.class.php
new file mode 100644 (file)
index 0000000..8316911
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+namespace wcf\action;\r
+use wcf\system\exception\AJAXException;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\ClassUtil;\r
+use wcf\util\JSON;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Default implementation for object-actions using the AJAX-API.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage action\r
+ * @category   Community Framework\r
+ */\r
+class AJAXProxyAction extends AbstractSecureAction {\r
+       /**\r
+        * class name\r
+        * @var string\r
+        */\r
+       protected $className = '';\r
+       \r
+       /**\r
+        * action name\r
+        * @var string\r
+        */\r
+       protected $actionName = '';\r
+       \r
+       /**\r
+        * list of object ids\r
+        * @var array<integer>\r
+        */\r
+       protected $objectIDs = array();\r
+       \r
+       /**\r
+        * additional parameters\r
+        * @var array<mixed>\r
+        */\r
+       protected $parameters = array();\r
+       \r
+       /**\r
+        * object action\r
+        * @var DatabaseObjectAction\r
+        */\r
+       protected $objectAction = null;\r
+       \r
+       /**\r
+        * results of the executed action\r
+        * @var mixed\r
+        */\r
+       protected $response = null;\r
+       \r
+       /**\r
+        * @see AbstractAction::_construct()\r
+        */\r
+       public function __construct() {\r
+               try {\r
+                       parent::__construct();\r
+               }\r
+               catch (\Exception $e) {\r
+                       if ($e instanceof AJAXException) {\r
+                               throw $e;\r
+                       }\r
+                       else {\r
+                               throw new AJAXException($e->getMessage());\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Action::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_POST['className'])) {\r
+                       $this->className = StringUtil::trim($_POST['className']);\r
+               }\r
+               if (isset($_POST['actionName'])) {\r
+                       $this->actionName = StringUtil::trim($_POST['actionName']);\r
+               }\r
+               if (isset($_POST['objectIDs'])) {\r
+                       if (is_array($_POST['objectIDs'])) $this->objectIDs = ArrayUtil::toIntegerArray($_POST['objectIDs']);\r
+               }\r
+               if (isset($_POST['parameters'])) {\r
+                       if (is_array($_POST['parameters'])) $this->parameters = $parameters;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Action::execute()\r
+        */\r
+       public function execute() {\r
+               parent::execute();\r
+               \r
+               // validate class name\r
+               if (!class_exists($this->className)) {\r
+                       throw new AJAXException("unknown class '".$this->className."'");\r
+               }\r
+               if (!ClassUtil::isInstanceOf($this->className, 'wcf\data\DatabaseObjectAction')) {\r
+                       throw new AJAXException("'".$this->className."' should implement DatabaseObjectAction");\r
+               }\r
+               \r
+               // create object action instance\r
+               $this->objectAction = new $this->className($this->objectIDs, $this->actionName, $this->parameters);\r
+               \r
+               // validate action\r
+               try {\r
+                       $this->objectAction->validateAction();\r
+               }\r
+               catch (ValidateActionException $e) {\r
+                       throw new AJAXException("validation failed: ".$e->getMessage());\r
+               }\r
+               \r
+               // execute action\r
+               try {\r
+                       $this->response = $this->objectAction->executeAction();\r
+               }\r
+               catch (\Exception $e) {\r
+                       throw new AJAXException('unknown exception caught: '.$e->getMessage());\r
+               }\r
+               $this->executed();\r
+               \r
+               // send JSON-encoded response\r
+               header('Content-type: application/json');\r
+               echo JSON::encode($this->response);\r
+               exit;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/action/AbstractAction.class.php b/wcfsetup/install/files/lib/action/AbstractAction.class.php
new file mode 100644 (file)
index 0000000..02578ca
--- /dev/null
@@ -0,0 +1,79 @@
+<?php\r
+namespace wcf\action;\r
+use wcf\system\event\EventHandler;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * This class provides default implementations for the Action interface.\r
+ * This includes the call of the default event listeners for an action: readParameters and execute.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage action\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractAction implements Action {\r
+       /**\r
+        * Needed modules to execute this action.\r
+        * \r
+        * @var array<string>\r
+        */\r
+       public $neededModules = array();\r
+       \r
+       /**\r
+        * Needed permissions to execute this action.\r
+        * \r
+        * @var array<string>\r
+        */\r
+       public $neededPermissions = array();\r
+       \r
+       /**\r
+        * Creates a new AbstractAction object.\r
+        * Calls the methods readParameters() and execute() automatically.\r
+        */\r
+       public function __construct() {\r
+               // call default methods\r
+               $this->readParameters();\r
+               $this->execute();\r
+       }\r
+       \r
+       /**\r
+        * @see Action::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               // call readParameters event\r
+               EventHandler::getInstance()->fireAction($this, 'readParameters');\r
+       }\r
+       \r
+       /**\r
+        * @see Action::execute()\r
+        */\r
+       public function execute() {\r
+               // check modules\r
+               if (count($this->neededModules)) {\r
+                       foreach ($this->neededModules as $module) {\r
+                               if (!defined($module) || !constant($module)) throw new IllegalLinkException();\r
+                       }\r
+               }\r
+               \r
+               // check permission\r
+               if (count($this->neededPermissions)) {\r
+                       WCF::getSession()->checkPermission($this->neededPermissions);\r
+               }\r
+               \r
+               // call execute event\r
+               EventHandler::getInstance()->fireAction($this, 'execute');\r
+       }\r
+       \r
+       /**\r
+        * Calls the 'executed' event after the successful execution of this action.\r
+        * This functions won't called automatically. You must do this manually, if you inherit AbstractAction.\r
+        */\r
+       protected function executed() {\r
+               EventHandler::getInstance()->fireAction($this, 'executed');\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/action/AbstractAjaxAction.class.php b/wcfsetup/install/files/lib/action/AbstractAjaxAction.class.php
new file mode 100644 (file)
index 0000000..5322212
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+namespace wcf\action;\r
+\r
+/**\r
+ * Provides method to send JSON-encoded responses.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage action\r
+ * @category   Community Framework\r
+ */\r
+class AbstractAjaxAction extends AbstractAction {\r
+       /**\r
+        * Sends a JSON-encoded response.\r
+        * \r
+        * @param       array           $data\r
+        */\r
+       protected function sendJsonResponse(array $data) {\r
+               $json = JSON::encode($data);\r
+               \r
+               // send JSON response\r
+               header('Content-type: application/json');\r
+               echo $json;\r
+               exit;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/action/AbstractDialogAction.class.php b/wcfsetup/install/files/lib/action/AbstractDialogAction.class.php
new file mode 100644 (file)
index 0000000..4eb0b97
--- /dev/null
@@ -0,0 +1,73 @@
+<?php\r
+namespace wcf\action;\r
+use wcf\system\exception\AJAXException;\r
+use wcf\util\JSON;\r
+use wcf\util\StringUtil;\r
+\r
+abstract class AbstractDialogAction extends AbstractSecureAction {\r
+       /**\r
+        * current step\r
+        *\r
+        * @var string\r
+        */\r
+       public $step = '';\r
+       \r
+       /**\r
+        * template name\r
+        *\r
+        * @var string\r
+        */\r
+       public $templateName = '';\r
+       \r
+       /**\r
+        * response data\r
+        *\r
+        * @var array\r
+        */\r
+       public $data = array();\r
+       \r
+       /**\r
+        * @see Action::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (empty($this->templateName)) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+               \r
+               if (isset($_REQUEST['step'])) {\r
+                       $this->step = StringUtil::trim($_REQUEST['step']);\r
+                       \r
+                       // append step as part of template name\r
+                       $this->templateName .= StringUtil::firstCharToUpperCase($this->step);\r
+               }\r
+               \r
+               $this->validateStep();\r
+       }\r
+       \r
+       public final function execute() {\r
+               parent::execute();\r
+               \r
+               $methodName = 'step' . StringUtil::firstCharToUpperCase($this->step);\r
+               if (!method_exists($this, $methodName)) {\r
+                       throw new AJAXException("Class '".get_class($this)."' does not implement the required method '".$methodName."'");\r
+               }\r
+               \r
+               // execute step\r
+               $this->{$methodName}();\r
+               \r
+               $this->executed();\r
+               \r
+               // send JSON-encoded response\r
+               header('Content-type: application/json');\r
+               echo JSON::encode($this->data);\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * Validates current dialog step.\r
+        */\r
+       abstract protected function validateStep();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/action/AbstractSecureAction.class.php b/wcfsetup/install/files/lib/action/AbstractSecureAction.class.php
new file mode 100644 (file)
index 0000000..891a115
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace wcf\action;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\WCF;
+
+/**
+ * Extends AbstractAction by a function to validate a given security token.
+ * A missing or invalid token will be result in a throw of a IllegalLinkException.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage action
+ * @category   Community Framework
+ */
+abstract class AbstractSecureAction extends AbstractAction {
+       /**
+        * @see Action::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               // check security token
+               $this->checkSecurityToken();
+       }
+       
+       /**
+        * Validates the security token.
+        */
+       protected function checkSecurityToken() {
+               if (!isset($_REQUEST['t']) || !WCF::getSession()->checkSecurityToken($_REQUEST['t'])) {
+                       throw new IllegalLinkException();
+               }
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/action/AbstractSecureObjectAction.class.php b/wcfsetup/install/files/lib/action/AbstractSecureObjectAction.class.php
new file mode 100644 (file)
index 0000000..dbbe80e
--- /dev/null
@@ -0,0 +1,90 @@
+<?php\r
+namespace wcf\action;\r
+\r
+/**\r
+ * Abstract handler for object-actions using the AJAX-API.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage action\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractSecureObjectAction extends AbstractAction {\r
+       protected $action = '';\r
+       protected $actionClass = '';\r
+       protected $actionData = array();\r
+       protected $data = array();\r
+       protected $objectAction = null;\r
+       protected $objectIDs = array();\r
+               \r
+       /**\r
+        * @see Action::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               if (isset($_POST['actionClass'])) {\r
+                       $this->actionClass = StringUtil::trim($_POST['actionClass']);\r
+               }\r
+               if (isset($_POST['data'])) {\r
+                       $data = json_decode($_POST['data'], true);\r
+                       if (is_array($data)) $this->data = $data;\r
+               }\r
+               if (isset($_POST['objectIDs'])) {\r
+                       $objectIDs = json_decode($_POST['objectIDs']);\r
+                       if (is_array($objectIDs)) $this->objectIDs = ArrayUtil::toIntegerArray($objectIDs);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see         Action::execute()\r
+        * @todo        Add validation for $actionClass, $data and $objectIDs,\r
+        *              possibly with some kind of derived exception maintaining\r
+        *              a js-readable output (do not use printable exception!)\r
+        */\r
+       public function execute() {\r
+               parent::execute();\r
+               \r
+               $className = $this->actionClass.'Action';\r
+               $classPath = $this->getClassPath().$this->actionClass.'Action.class.php';\r
+               \r
+               require_once($classPath);\r
+               $this->objectAction = new $className($this->objectIDs, $this->action, $this->actionData);\r
+       }\r
+       \r
+       /**\r
+        * Executes chosen action. This method is not called automatically,\r
+        * you must call this method in any derived class.\r
+        */\r
+       protected function executeAction() {\r
+               $this->objectAction->validateAction();\r
+               $this->objectAction->executeAction();\r
+               \r
+               $this->handleResult();\r
+       }\r
+       \r
+       /**\r
+        * Returns class path based upon object action's name (excluding Action-suffix)\r
+        * \r
+        * @return      string\r
+        */\r
+       protected function getClassPath() {\r
+               $directories = array();\r
+               $components = preg_split('~(?<=[a-z])(?=[A-Z])~', $this->actionClass);\r
+               \r
+               foreach ($components as $part) {\r
+                       $directories[] = StringUtil::toLowerCase($part);\r
+               }\r
+               \r
+               $path = WCF_DIR . 'lib/data/' . implode('/', $directories);\r
+               return FileUtil::addTrailingSlash($path);\r
+       }\r
+       \r
+       /**\r
+        * Handles action result, derived classes must implement this but leave it empty.\r
+        */\r
+       abstract protected function handleResult();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/action/Action.class.php b/wcfsetup/install/files/lib/action/Action.class.php
new file mode 100644 (file)
index 0000000..490879e
--- /dev/null
@@ -0,0 +1,26 @@
+<?php\r
+namespace wcf\action;\r
+\r
+/**\r
+ * All action classes should implement this interface.\r
+ * An action executes a user input without showing a result page or a form. \r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage action\r
+ * @category   Community Framework\r
+ */\r
+interface Action {\r
+       /**\r
+        * Reads the given parameters.\r
+        */\r
+       public function readParameters();\r
+       \r
+       /**\r
+        * Executes this action.\r
+        */\r
+       public function execute();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/core.functions.php b/wcfsetup/install/files/lib/core.functions.php
new file mode 100644 (file)
index 0000000..0d74b84
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+/**\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @category   Community Framework\r
+ */\r
+// set exception handler\r
+set_exception_handler(array('wcf\system\WCF', 'handleException'));\r
+\r
+// set php error handler\r
+set_error_handler(array('wcf\system\WCF', 'handleError'), E_ALL);\r
+\r
+// set shutdown function\r
+register_shutdown_function(array('wcf\system\WCF', 'destruct'));\r
+\r
+// set autoload function\r
+spl_autoload_register(array('wcf\system\WCF', 'autoload'));\r
+\r
+// define escape string shortcut\r
+function escapeString($string) {\r
+       return wcf\system\WCF::getDB()->escapeString($string);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php b/wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php
new file mode 100644 (file)
index 0000000..a6a6ae5
--- /dev/null
@@ -0,0 +1,311 @@
+<?php
+namespace wcf\data;
+
+use wcf\system\event\EventHandler;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\exception\ValidateActionException;
+use wcf\system\WCF;
+use wcf\util\ClassUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Default implementation for DatabaseObject-related actions.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+abstract class AbstractDatabaseObjectAction implements DatabaseObjectAction {
+       /**
+        * pending action
+        *
+        * @var string
+        */
+       protected $action = '';
+       
+       /**
+        * object editor class name
+        *
+        * @var string
+        */
+       protected $className = '';
+       
+       /**
+        * list of object ids
+        *
+        * @var array<integer>
+        */
+       protected $objectIDs = array();
+       
+       /**
+        * list of objects
+        *
+        * @var array<DatabaseObjectEditor>
+        */
+       protected $objects = array();
+       
+       /**
+        * multi-dimensional array of parameters required by an action
+        *
+        * @var array<array>
+        */
+       protected $parameters = array();
+       
+       /**
+        * list of permissions required to create objects
+        *
+        * @var array
+        */
+       protected $permissionsCreate = array();
+       
+       /**
+        * list of permissions required to delete objects
+        *
+        * @var array
+        */
+       protected $permissionsDelete = array();
+       
+       /**
+        * list of permissions required to update objects
+        *
+        * @var array
+        */
+       protected $permissionsUpdate = array();
+       
+       /**
+        * values returned by executed action
+        *
+        * @var mixed
+        */
+       protected $returnValues = null;
+       
+       /**
+        * Initialized a new DatabaseObject-related action.
+        *
+        * @param       array           $objectIDs
+        * @param       string          $action
+        * @param       array           $parameters
+        */
+       public function __construct(array $objectIDs, $action, array $parameters = array()) {
+               $this->objectIDs = $objectIDs;
+               $this->action = $action;
+               $this->parameters = $parameters;
+               
+               // fire event action
+               EventHandler::getInstance()->fireAction($this, 'initializeAction');
+       }
+       
+       /**
+        * @see DatabaseObjectAction::validateAction()
+        */
+       public function validateAction() {
+               // validate action name
+               if (!method_exists($this, $this->getActionName())) {
+                       throw new ValidateActionException("unknown action '".$this->getActionName()."'");
+               }
+               
+               $actionName = 'validate'.StringUtil::firstCharToUpperCase($this->getActionName());
+               if (!method_exists($this, $actionName)) {
+                       throw new ValidateActionException("validation of action '".$this->getActionName()."' failed");
+               }
+               
+               // execute action
+               call_user_func_array(array($this, $actionName), $this->getParameters());
+       }
+       
+       /**
+        * @see DatabaseObjectAction::executeAction()
+        */
+       public function executeAction() {
+               // execute action
+               if (method_exists($this, $this->getActionName())) {
+                       $this->returnValues = call_user_func_array(array($this, $this->getActionName()), $this->getParameters());
+               }
+               
+               // reset cache
+               if (ClassUtil::isInstanceOf($this->className, 'wcf\data\EditableCachedObject')) {
+                       call_user_func(array($this->className, 'resetCache'));
+               }
+               
+               // fire event action
+               EventHandler::getInstance()->fireAction($this, 'finalizeAction');
+               
+               return $this->getReturnValues();
+       }
+       
+       /**
+        * @see DatabaseObjectAction::getActionName()
+        */
+       public function getActionName() {
+               return $this->action;
+       }
+       
+       /**
+        * @see DatabaseObjectAction::getObjectIDs()
+        */
+       public function getObjectIDs() {
+               return $this->objectIDs;
+       }
+       
+       /**
+        * @see DatabaseObjectAction::getParameters()
+        */
+       public function getParameters() {
+               return $this->parameters;
+       }
+       
+       /**
+        * @see DatabaseObjectAction::getReturnValues()
+        */
+       public function getReturnValues() {
+               return array(
+                       'objectIDs' => $this->getObjectIDs(),
+                       'returnValues' => $this->returnValues
+               );
+       }
+       
+       /**
+        * Validates permissions and parameters.
+        */
+       public function validateCreate() {
+               // validate permissions
+               if (is_array($this->permissionsCreate) && count($this->permissionsCreate)) {
+                       try {
+                               WCF::getSession()->checkPermission($this->permissionsCreate);
+                       }
+                       catch (PermissionDeniedException $e) {
+                               throw new ValidateActionException('Insufficient permissions');
+                       }
+               }
+               else {
+                       throw new ValidateActionException('Insufficient permissions');
+               }
+       }
+       
+       /**
+        * Validates permissions and parameters.
+        */
+       public function validateDelete() {
+               // validate permissions
+               if (is_array($this->permissionsDelete) && count($this->permissionsDelete)) {
+                       try {
+                               WCF::getSession()->checkPermission($this->permissionsDelete);
+                       }
+                       catch (PermissionDeniedException $e) {
+                               throw new ValidateActionException('Insufficient permissions');
+                       }
+               }
+               else {
+                       throw new ValidateActionException('Insufficient permissions');
+               }
+               
+               // read data
+               $this->readObjects();
+               
+               if (!count($this->objects)) {
+                       throw new ValidateActionException('Invalid object id');
+               }
+       }
+       
+       /**
+        * Validates permissions and parameters.
+        */
+       public function validateUpdate() {
+               // validate permissions
+               if (is_array($this->permissionsUpdate) && count($this->permissionsUpdate)) {
+                       try {
+                               WCF::getSession()->checkPermission($this->permissionsUpdate);
+                       }
+                       catch (PermissionDeniedException $e) {
+                               throw new ValidateActionException('Insufficient permissions');
+                       }
+               }
+               else {
+                       throw new ValidateActionException('Insufficient permissions');
+               }
+               
+               // read data
+               $this->readObjects();
+               
+               if (!count($this->objects)) {
+                       throw new ValidateActionException('Invalid object id');
+               }
+       }
+       
+       /**
+        * Creates a new data.
+        *
+        * @return      DatabaseObject
+        */
+       public function create() {
+               // create data
+               return call_user_func(array($this->className, 'create'), $this->parameters['data']);
+       }
+       
+       /**
+        * Deletes data.
+        * Returns the number of deleted data.
+        *
+        * @return      integer
+        */
+       public function delete() {
+               if (!count($this->objects)) {
+                       $this->readObjects();
+               }
+               
+               // get index name
+               $indexName = call_user_func(array($this->className, 'getDatabaseTableIndexName'));
+               
+               // get ids
+               $objectIDs = array();
+               foreach ($this->objects as $object) {
+                       $objectIDs[] = $object->__get($indexName);
+               }
+               
+               // execute action
+               return call_user_func(array($this->className, 'deleteAll'), $objectIDs);
+       }
+       
+       /**
+        * Updates data.
+        */
+       public function update() {
+               if (!count($this->objects)) {
+                       $this->readObjects();
+               }
+               
+               foreach ($this->objects as $object) {
+                       $object->update($this->parameters['data']);
+               }
+       }
+       
+       /**
+        * Reads data by data id.
+        */
+       protected function readObjects() {
+               if (!count($this->objectIDs)) {
+                       return;
+               }
+               
+               // get base class
+               $baseClass = call_user_func(array($this->className, 'getBaseClass'));
+               
+               // get db information
+               $tableName = call_user_func(array($this->className, 'getDatabaseTableName'));
+               $indexName = call_user_func(array($this->className, 'getDatabaseTableIndexName'));
+               
+               // get objects
+               $sql = "SELECT  *
+                       FROM    ".$tableName."
+                       WHERE   ".$indexName." IN (".str_repeat('?,', count($this->objectIDs) - 1)."?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($this->objectIDs);
+               while ($object = $statement->fetchObject($baseClass)) {
+                       $this->objects[] = new $this->className($object);
+               }
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/DatabaseObject.class.php b/wcfsetup/install/files/lib/data/DatabaseObject.class.php
new file mode 100644 (file)
index 0000000..07e639c
--- /dev/null
@@ -0,0 +1,189 @@
+<?php\r
+namespace wcf\data;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Abstract class for all data holder classes.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data\r
+ * @category   Community Framework\r
+ */\r
+abstract class DatabaseObject implements StorableObject {\r
+       /**\r
+        * database table for this object\r
+        * @var string\r
+        */\r
+       protected static $databaseTableName = '';\r
+       \r
+       /**\r
+        * indicates if database table index is an identity column\r
+        * @var boolean \r
+        */     \r
+       protected static $databaseTableIndexIsIdentity = true;\r
+       \r
+       /**\r
+        * name of the primary index column\r
+        * @var string\r
+        */\r
+       protected static $databaseTableIndexName = '';\r
+       \r
+       /**\r
+        * sort field\r
+        * @var mixed\r
+        */\r
+       protected static $sortBy = null;\r
+       \r
+       /**\r
+        * sort order\r
+        * @var mixed\r
+        */\r
+       protected static $sortOrder = null;\r
+       \r
+       /**\r
+        * object data\r
+        * @var array\r
+        */\r
+       protected $data = null;\r
+       \r
+       /**\r
+        * Creates a new instance of the DatabaseObject class.\r
+        * Stores object data.\r
+        *  \r
+        * @param       mixed                   $id\r
+        * @param       array                   $row\r
+        * @param       DatabaseObject          $object\r
+        */\r
+       public function __construct($id, array $row = null, DatabaseObject $object = null) {\r
+               if ($id !== null) {\r
+                       $sql = "SELECT  *\r
+                               FROM    ".static::getDatabaseTableName()."\r
+                               WHERE   ".static::getDatabaseTableIndexName()." = ?";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute(array($id));\r
+                       $row = $statement->fetchArray();\r
+                       \r
+                       // enforce data type 'array'\r
+                       if ($row === false) $row = array();\r
+               }\r
+               else if ($object !== null) {\r
+                       $row = $object->data;\r
+               }\r
+               \r
+               $this->handleData($row);\r
+       }\r
+       \r
+       /**\r
+        * Stores the data of a database row.\r
+        * \r
+        * @param       array           $data\r
+        */\r
+       protected function handleData($data) {\r
+               // provide a logical false value for - assumed numeric - primary index\r
+               if (!isset($data[static::getDatabaseTableIndexName()])) {\r
+                       $data[static::getDatabaseTableIndexName()] = 0;\r
+               }\r
+               \r
+               $this->data = $data;\r
+       }\r
+\r
+       /**\r
+        * @see StorableObject::__get()\r
+        */\r
+       public function __get($name) {\r
+               if (isset($this->data[$name])) {\r
+                       return $this->data[$name];\r
+               }\r
+               else {\r
+                       return null;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see StorableObject::__isset()\r
+        */\r
+       public function __isset($name) {\r
+               return isset($this->data[$name]);\r
+       }\r
+       \r
+       /**\r
+        * @see StorableObject::getDatabaseTableName()\r
+        */\r
+       public static function getDatabaseTableName() {\r
+               return 'wcf'.WCF_N.'_'.static::$databaseTableName;\r
+       }\r
+       \r
+       /**\r
+        * @see StorableObject::getDatabaseTableAlias()\r
+        */\r
+       public static function getDatabaseTableAlias() {\r
+               return static::$databaseTableName;\r
+       }\r
+       \r
+       /**\r
+        * @see StorableObject::getDatabaseTableIndexIsIdentity()\r
+        */     \r
+       public static function getDatabaseTableIndexIsIdentity() {\r
+               return static::$databaseTableIndexIsIdentity;\r
+       }\r
+       \r
+       /**\r
+        * @see StorableObject::getDatabaseTableIndexName()\r
+        */\r
+       public static function getDatabaseTableIndexName() {\r
+               return static::$databaseTableIndexName;\r
+       }\r
+       \r
+       /**\r
+        * Sorts a list of database objects.\r
+        *\r
+        * @param       array<DatabaseObject>   $objects\r
+        * @param       mixed                   $sortBy\r
+        * @param       string                  $sortOrder\r
+        * @return      boolean\r
+        */\r
+       public static function sort(&$objects, $sortBy, $sortOrder = 'ASC') {\r
+               static::$sortBy = (!is_array($sortBy) ? array($sortBy) : $sortBy);\r
+               static::$sortOrder = (!is_array($sortOrder) ? array($sortOrder) : $sortOrder);\r
+               return uasort($objects, array('static', 'compareObjects'));\r
+       }\r
+       \r
+       /**\r
+        * Compares to database objects.\r
+        *\r
+        * @param       DatabaseObject          $objectA\r
+        * @param       DatabaseObject          $objectB\r
+        * @return      float\r
+        */\r
+       protected static function compareObjects($objectA, $objectB) {\r
+               foreach (static::$sortBy as $key => $sortBy) {\r
+                       $sortOrder = (isset(static::$sortOrder[$key]) ? static::$sortOrder[$key] : 'ASC');\r
+                       if (is_numeric($objectA->$sortBy) && is_numeric($objectB->$sortBy)) {\r
+                               if ($objectA->$sortBy > $objectB->$sortBy) {\r
+                                       return ($sortOrder == 'ASC' ? 1 : 0);\r
+                               }\r
+                               else if ($objectA->$sortBy < $objectB->$sortBy) {\r
+                                       return ($sortOrder == 'ASC' ? 0 : 1);\r
+                               }\r
+                       }\r
+                       else {\r
+                               if ($sortOrder == 'ASC') {\r
+                                       $result =  strcoll($objectA->$sortBy, $objectB->$sortBy);\r
+                               }\r
+                               else {\r
+                                       $result = strcoll($objectB->$sortBy, $objectA->$sortBy);\r
+                               }\r
+                               \r
+                               if ($result != 0.0) {\r
+                                       return $result;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               return 0;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/DatabaseObjectAction.class.php b/wcfsetup/install/files/lib/data/DatabaseObjectAction.class.php
new file mode 100644 (file)
index 0000000..eadacbf
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+namespace wcf\data;
+
+/**
+ * Default interface for DatabaseObject-related actions.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+interface DatabaseObjectAction {
+       /**
+        * Executes the previously chosen action.
+        */
+       public function executeAction();
+       
+       /**
+        * Validates action-related parameters.
+        */
+       public function validateAction();
+       
+       /**
+        * Returns active action name.
+        * 
+        * @return      string
+        */
+       public function getActionName();
+       
+       /**
+        * Returns DatabaseObject-related object ids.
+        * 
+        * @return      array<integer>
+        */
+       public function getObjectIDs();
+       
+       /**
+        * Returns action-related parameters.
+        * 
+        * @return      array<array>
+        */
+       public function getParameters();
+       
+       /**
+        * Returns results returned by active action.
+        * 
+        * @return      mixed
+        */
+       public function getReturnValues();
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/DatabaseObjectDecorator.class.php b/wcfsetup/install/files/lib/data/DatabaseObjectDecorator.class.php
new file mode 100644 (file)
index 0000000..2576953
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+namespace wcf\data;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Basic implementation for object decorators.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+abstract class DatabaseObjectDecorator extends DatabaseObject {
+       /**
+        * name of the base class
+        * @var string
+        */
+       protected static $baseClass = '';
+       
+       /**
+        * the object being decorated
+        * @var DatabaseObject
+        */
+       protected $object = null;
+       
+       /**
+        * Creates a new DatabaseObjectDecorator object.
+        * 
+        * @param       DatabaseObject          $object
+        */
+       public function __construct(DatabaseObject $object) {
+               if (empty(static::$baseClass)) {
+                       throw new SystemException('Base class not specified');
+               }
+               
+               if (!($object instanceof static::$baseClass)) {
+                       throw new SystemException('Object does not match '.static::$baseClass);
+               }
+               
+               $this->object = $object;
+       }
+       
+       /**
+        * @see DatabaseObject::__get()
+        */
+       public function __get($name) {
+               return $this->object->__get($name);
+       }
+       
+       /**
+        * @see DatabaseObject::__isset()
+        */
+       public function __isset($name) {
+               return $this->object->__isset($name);
+       }
+       
+       /**
+        * Delegates inaccessible methods calls to the decorated object.
+        *  
+        * @param       string          $name
+        * @param       array           $arguments
+        * @return      mixed
+        */
+       public function __call($name, $arguments) {
+               if (!method_exists($this->object, $name)) {
+                       throw new SystemException("unknown method '".$name."'");
+               }
+               
+               return call_user_func_array(array($this->object, $name), $arguments);
+       }
+       
+       /**
+        * @see StorableObject::getDatabaseTableName()
+        */
+       public static function getDatabaseTableName() {
+               return call_user_func(array(static::$baseClass, 'getDatabaseTableName'));
+       }
+       
+       /**
+        * @see StorableObject::getDatabaseTableIndexIsIdentity()
+        */
+       public static function getDatabaseTableIndexIsIdentity() {
+               return call_user_func(array(static::$baseClass, 'getDatabaseTableIndexIsIdentity'));
+       }
+       
+       /**
+        * @see StorableObject::getDatabaseTableIndexName()
+        */
+       public static function getDatabaseTableIndexName() {
+               return call_user_func(array(static::$baseClass, 'getDatabaseTableIndexName'));
+       }
+       
+       /**
+        * Returns the name of the base class.
+        * 
+        * @return string
+        */
+       public static function getBaseClass() {
+               return static::$baseClass;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php b/wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php
new file mode 100644 (file)
index 0000000..d0932d8
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+namespace wcf\data;
+use wcf\system\WCF;
+
+/**
+ * Basic implementation for object editors following the decorator pattern.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+abstract class DatabaseObjectEditor extends DatabaseObjectDecorator implements EditableObject {
+       /**
+        * @see EditableObject::create()
+        */
+       public static function create(array $parameters = array()) {
+               $keys = $values = '';
+               $statementParameters = array();
+               foreach ($parameters as $key => $value) {
+                       if (!empty($keys)) {
+                               $keys .= ',';
+                               $values .= ',';
+                       }
+                       
+                       $keys .= $key;
+                       $values .= '?';
+                       $statementParameters[] = $value;
+               }
+               
+               // save object
+               $sql = "INSERT INTO     ".static::getDatabaseTableName()."
+                                       (".$keys.")
+                       VALUES          (".$values.")";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($statementParameters);
+               
+               // return new object
+               if (static::getDatabaseTableIndexIsIdentity()) {
+                       $id = WCF::getDB()->getInsertID(static::getDatabaseTableName(), static::getDatabaseTableIndexName());
+               }
+               else {
+                       $id = $parameters[static::getDatabaseTableIndexName()];
+               }
+               return new static::$baseClass($id);
+       }
+       
+       /**
+        * @see EditableObject::update()
+        */
+       public function update(array $parameters = array()) {
+               if (!count($parameters)) return;
+               
+               $updateSQL = '';
+               $statementParameters = array();
+               foreach ($parameters as $key => $value) {
+                       if (!empty($updateSQL)) $updateSQL .= ', ';
+                       $updateSQL .= $key . ' = ?';
+                       $statementParameters[] = $value;
+               }
+               $statementParameters[] = $this->__get(static::getDatabaseTableIndexName());
+               
+               $sql = "UPDATE  ".static::getDatabaseTableName()."
+                       SET     ".$updateSQL."
+                       WHERE   ".static::getDatabaseTableIndexName()." = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($statementParameters);
+       }
+       
+       /**
+        * @see EditableObject::delete()
+        */
+       public function delete() {
+               static::deleteAll(array($this->__get(static::getDatabaseTableIndexName())));
+       }
+       
+       /**
+        * @see EditableObject::deleteAll()
+        */
+       public static function deleteAll(array $objectIDs = array()) {
+               $sql = "DELETE FROM     ".static::getDatabaseTableName()."
+                       WHERE           ".static::getDatabaseTableIndexName()." = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($objectIDs as $objectID) {
+                       $statement->execute(array($objectID));
+               }
+               
+               return count($objectIDs);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/DatabaseObjectList.class.php b/wcfsetup/install/files/lib/data/DatabaseObjectList.class.php
new file mode 100644 (file)
index 0000000..d871a62
--- /dev/null
@@ -0,0 +1,213 @@
+<?php
+namespace wcf\data;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * Abstract class for a list of database objects.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+abstract class DatabaseObjectList {
+       /**
+        * object class name
+        * 
+        * @var string
+        */
+       public $className = '';
+       
+       /**
+        * result objects
+        * 
+        * @var array<wcf\data\DatabaseObject>
+        */
+       public $objects = array();
+       
+       /**
+        * result object ids
+        * 
+        * @var array<integer>
+        */
+       public $objectIDs = null; 
+       
+       /**
+        * sql offset
+        *
+        * @var integer
+        */
+       public $sqlOffset = 0;
+       
+       /**
+        * sql limit
+        *
+        * @var integer
+        */
+       public $sqlLimit = 20;
+       
+       /**
+        * sql order by statement
+        *
+        * @var string
+        */
+       public $sqlOrderBy = '';
+       
+       /**
+        * sql select parameters
+        *
+        * @var string
+        */
+       public $sqlSelects = '';
+       
+       /**
+        * sql select joins which are necessary for where statements
+        *
+        * @var string
+        */
+       public $sqlConditionJoins = '';
+       
+       /**
+        * sql select joins
+        *
+        * @var string
+        */
+       public $sqlJoins = '';
+       
+       /**
+        * sql conditions
+        *
+        * @var wcf\system\database\util\PreparedStatementConditionBuilder
+        */
+       protected $conditionBuilder = null;
+       
+       /**
+        * Creates a new DatabaseObjectList object.
+        */
+       public function __construct() {
+               $this->conditionBuilder = new PreparedStatementConditionBuilder();
+       }
+       
+       /**
+        * Counts the number of objects.
+        * 
+        * @return      integer
+        */
+       public function countObjects() {
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    ".$this->getDatabaseTableName()." ".$this->getDatabaseTableAlias()."
+                       ".$this->sqlConditionJoins."
+                       ".$this->getConditionBuilder()->__toString();
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($this->getConditionBuilder()->getParameters());
+               $row = $statement->fetchArray();
+               return $row['count'];
+       }
+       
+       /**
+        * Reads the object ids from database.
+        */
+       public function readObjectIDs() {
+               $this->objectIDs = array();
+               $sql = "SELECT  ".$this->getDatabaseTableAlias().".".$this->getDatabaseTableIndexName()." AS objectID
+                       FROM    ".$this->getDatabaseTableName()." ".$this->getDatabaseTableAlias()."
+                               ".$this->sqlConditionJoins."
+                               ".$this->getConditionBuilder()->__toString()."
+                               ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
+               $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
+               $statement->execute($this->getConditionBuilder()->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $this->objectIDs[] = $row['objectID'];
+               }
+       }
+       
+       /**
+        * Reads the objects from database.
+        */
+       public function readObjects() {
+               if ($this->objectIDs !== null) {
+                       if (!count($this->objectIDs)) {
+                               return;
+                       }
+                       
+                       $sql = "SELECT  ".(!empty($this->sqlSelects) ? $this->sqlSelects.',' : '')."
+                                       ".$this->getDatabaseTableAlias().".*
+                               FROM    ".$this->getDatabaseTableName()." ".$this->getDatabaseTableAlias()."
+                                       ".$this->sqlJoins."
+                               WHERE   ".$this->getDatabaseTableAlias().".".$this->getDatabaseTableIndexName()." IN (?".str_repeat(',?', count($this->objectIDs)).")
+                                       ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($this->objectIDs);
+                       $this->objects = $statement->fetchObjects($this->className);
+               }
+               else {
+                       $sql = "SELECT  ".(!empty($this->sqlSelects) ? $this->sqlSelects.',' : '')."
+                                       ".$this->getDatabaseTableAlias().".*
+                               FROM    ".$this->getDatabaseTableName()." ".$this->getDatabaseTableAlias()."
+                                       ".$this->sqlJoins."
+                                       ".$this->getConditionBuilder()->__toString()."
+                                       ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
+                       $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
+                       $statement->execute($this->getConditionBuilder()->getParameters());
+                       $this->objects = $statement->fetchObjects($this->className);
+               }
+       }
+       
+       /**
+        * Returns the object ids of the list.
+        * 
+        * @return      array<integer>
+        */
+       public function getObjectIDs() {
+               return $this->objectIDs;
+       }
+       
+       /**
+        * Returns the objects of the list.
+        * 
+        * @return      array<wcf\data\DatabaseObject>
+        */
+       public function getObjects() {
+               return $this->objects;
+       }
+       
+       /**
+        * Returns the condition builder object.
+        * 
+        * @return      wcf\system\database\util\PreparedStatementConditionBuilder
+        */
+       public function getConditionBuilder() {
+               return $this->conditionBuilder;
+       }
+       
+       /**
+        * Returns the name of the database table.
+        * 
+        * @return string
+        */
+       public function getDatabaseTableName() {
+               return call_user_func(array($this->className, 'getDatabaseTableName'));
+       }
+       
+       /**
+        * Returns the name of the database table.
+        * 
+        * @return string
+        */
+       public function getDatabaseTableIndexName() {
+               return call_user_func(array($this->className, 'getDatabaseTableIndexName'));
+       }
+       
+       /**
+        * Returns the name of the database table alias.
+        * 
+        * @return string
+        */
+       public function getDatabaseTableAlias() {
+               return call_user_func(array($this->className, 'getDatabaseTableAlias'));
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/EditableCachedObject.class.php b/wcfsetup/install/files/lib/data/EditableCachedObject.class.php
new file mode 100644 (file)
index 0000000..bee2ccf
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+namespace wcf\data;
+
+/**
+ * Abstract class for all cached data holder objects.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+interface EditableCachedObject extends EditableObject {
+       /**
+        * Resets the cache of this object type.
+        */
+       public static function resetCache();
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/EditableObject.class.php b/wcfsetup/install/files/lib/data/EditableObject.class.php
new file mode 100644 (file)
index 0000000..c6a04d5
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+namespace wcf\data;
+
+/**
+ * Abstract class for all data holder classes.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+interface EditableObject extends StorableObject {
+       /**
+        * Creates a new object.
+        * 
+        * @param       array           $parameters
+        * @return      StorableObject
+        */
+       public static function create(array $parameters = array());
+       
+       /**
+        * Updates this object.
+        * 
+        * @param       array           $parameters
+        */
+       public function update(array $parameters = array());
+       
+       /**
+        * Deletes this object.
+        */
+       public function delete();
+       
+       /**
+        * Deletes all given objects.
+        * 
+        * @param       array           $objectIDs
+        * @return      integer
+        */
+       public static function deleteAll(array $objectIDs = array());
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/StorableObject.class.php b/wcfsetup/install/files/lib/data/StorableObject.class.php
new file mode 100644 (file)
index 0000000..48ff27f
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+namespace wcf\data;
+
+/**
+ * Abstract class for all data holder classes.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data
+ * @category   Community Framework
+ */
+interface StorableObject {
+       /**
+        * Returns the value of a variable in object data.
+        * 
+        * @param       string          $name           variable name
+        * @return      mixed           value
+        */
+       public function __get($name);
+       
+       /**
+        * Determines if a variable is set and is not NULL.
+        * 
+        * @param       string          $name           variable name
+        * @return      boolean
+        */
+       public function __isset($name);
+       
+       /**
+        * Returns the name of the database table.
+        * 
+        * @return string
+        */
+       public static function getDatabaseTableName();
+       
+       /**
+        * Returns the alias of the database table.
+        * 
+        * @return      string
+        */
+       public static function getDatabaseTableAlias();
+       
+       /**
+        * Returns true if database table index is an identity column.
+        * 
+        * @return      boolean
+        */
+       public static function getDatabaseTableIndexIsIdentity();
+       
+       /**
+        * Returns the name of the database table index.
+        * 
+        * @return string
+        */
+       public static function getDatabaseTableIndexName();
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItem.class.php b/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItem.class.php
new file mode 100644 (file)
index 0000000..1ec29e9
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\data\acp\menu\item;
+use wcf\data\DatabaseObject;
+use wcf\system\menu\TreeMenuItem;
+use wcf\system\request\LinkHandler;
+
+/**
+ * Represents an ACP menu item.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.menu.item
+ * @category   Community Framework
+ */
+class ACPMenuItem extends DatabaseObject implements TreeMenuItem {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_menu_item';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'menuItemID';
+       
+       /**
+        * @see TreeMenuItem::getLink()
+        */
+       public function getLink() {
+               return LinkHandler::getInstance()->getLink($this->menuItemLink);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemAction.class.php b/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemAction.class.php
new file mode 100644 (file)
index 0000000..281dead
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\menu\item;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes ACP menu item-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.menu.item\r
+ * @category   Community Framework\r
+ */\r
+class ACPMenuItemAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\acp\menu\item\ACPMenuItemEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemEditor.class.php b/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemEditor.class.php
new file mode 100644 (file)
index 0000000..3694a80
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\acp\menu\item;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit ACP menu items.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.menu.item
+ * @category   Community Framework
+ */
+class ACPMenuItemEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\menu\item\ACPMenuItem';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemList.class.php b/wcfsetup/install/files/lib/data/acp/menu/item/ACPMenuItemList.class.php
new file mode 100644 (file)
index 0000000..b6c1671
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\menu\item;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of ACP menu items.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.menu.item\r
+ * @category   Community Framework\r
+ */\r
+class ACPMenuItemList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\acp\menu\item\ACPMenuItem';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/ACPSession.class.php b/wcfsetup/install/files/lib/data/acp/session/ACPSession.class.php
new file mode 100644 (file)
index 0000000..0ce512b
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+namespace wcf\data\acp\session;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+
+/**
+ * Represents an ACP session.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session
+ * @category   Community Framework
+ */
+class ACPSession extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_session';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexIsIdentity
+        */
+       protected static $databaseTableIndexIsIdentity = false;
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'sessionID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/acp/session/ACPSessionAction.class.php b/wcfsetup/install/files/lib/data/acp/session/ACPSessionAction.class.php
new file mode 100644 (file)
index 0000000..6ebc0a5
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\session;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes ACP session-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.session\r
+ * @category   Community Framework\r
+ */\r
+class ACPSessionAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\acp\session\ACPSessionEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/ACPSessionEditor.class.php b/wcfsetup/install/files/lib/data/acp/session/ACPSessionEditor.class.php
new file mode 100644 (file)
index 0000000..c8fcf9f
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+namespace wcf\data\acp\session;
+use wcf\data\DatabaseObjectEditor;
+use wcf\system\WCF;
+
+/**
+ * Provides functions to edit ACP sessions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session
+ * @category   Community Framework
+ */
+class ACPSessionEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\session\ACPSession';
+       
+       /**
+        * @see DatabaseObjectEditor::create()
+        */
+       public static function create(array $parameters = array()) {
+               if (isset($parameters['userID']) && !$parameters['userID']) {
+                       $parameters['userID'] = null;
+               }
+               if (isset($parameters['packageID']) && !$parameters['packageID']) {
+                       $parameters['packageID'] = null;
+               }
+               
+               return parent::create($parameters);
+       }
+       
+       /**
+        * @see DatabaseObjectEditor::create()
+        */
+       public function update(array $parameters = array()) {
+               if (isset($parameters['userID']) && !$parameters['userID']) {
+                       $parameters['userID'] = null;
+               }
+               if (isset($parameters['packageID']) && !$parameters['packageID']) {
+                       $parameters['packageID'] = null;
+               }
+               
+               return parent::update($parameters);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/acp/session/ACPSessionList.class.php b/wcfsetup/install/files/lib/data/acp/session/ACPSessionList.class.php
new file mode 100644 (file)
index 0000000..4798476
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+namespace wcf\data\acp\session;\r
+\r
+/**\r
+ * Represents a list of ACP sessions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.session\r
+ * @category   Community Framework\r
+ */\r
+class ACPSessionList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\acp\session\ACPSession';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLog.class.php b/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLog.class.php
new file mode 100644 (file)
index 0000000..8d3e172
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+namespace wcf\data\acp\session\access\log;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a session access log entry.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.access.log
+ * @category   Community Framework
+ */
+class ACPSessionAccessLog extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_session_access_log';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'sessionAccessLogID';
+       
+       /**
+        * Returns true, if the URI of this log entry is protected.
+        *
+        * @return      boolean
+        */
+       public function hasProtectedURI() {
+               if ($this->requestMethod != 'GET' || !preg_match('/(\?|&)(page|form)=/', $this->requestURI)) {
+                       return true;
+               }
+               
+               return false;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogAction.class.php b/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogAction.class.php
new file mode 100644 (file)
index 0000000..e4157ff
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\session\access\log;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes ACP session access log-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.session.access.log\r
+ * @category   Community Framework\r
+ */\r
+class ACPSessionAccessLogAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\acp\session\access\log\ACPSessionAccessLogEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogEditor.class.php b/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogEditor.class.php
new file mode 100644 (file)
index 0000000..871cd81
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\acp\session\access\log;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit ACP session access logs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.access.log
+ * @category   Community Framework
+ */
+class ACPSessionAccessLogEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\session\access\log\ACPSessionAccessLog';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogList.class.php b/wcfsetup/install/files/lib/data/acp/session/access/log/ACPSessionAccessLogList.class.php
new file mode 100644 (file)
index 0000000..bdc5954
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+namespace wcf\data\acp\session\access\log;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of access logs.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.access.log
+ * @category   Community Framework
+ */
+class ACPSessionAccessLogList extends DatabaseObjectList {
+       /**
+        * @see DatabaseObjectList::$className
+        */
+       public $className = 'wcf\data\acp\session\access\log\ACPSessionAccessLog';
+       
+       /**
+        * @see DatabaseObjectList::readObjects()
+        */
+       public function readObjects() {
+               if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
+               $this->sqlSelects .= "CASE WHEN package.instanceName <> '' THEN package.instanceName ELSE package.packageName END AS packageName";
+               $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_package package ON (package.packageID = ".$this->getDatabaseTableAlias().".packageID)";
+               
+               parent::readObjects();
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionData.class.php b/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionData.class.php
new file mode 100644 (file)
index 0000000..c008590
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+namespace wcf\data\acp\session\data;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+
+/**
+ * Represents ACP session data.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.data
+ * @category   Community Framework
+ */
+class ACPSessionData extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_session_data';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexIsIdentity
+        */
+       protected static $databaseTableIndexIsIdentity = false;
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'sessionID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataAction.class.php b/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataAction.class.php
new file mode 100644 (file)
index 0000000..588e914
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\session\data;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes ACP session data-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.session.data\r
+ * @category   Community Framework\r
+ */\r
+class ACPSessionDataAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\acp\session\data\ACPSessionDataEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataEditor.class.php b/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataEditor.class.php
new file mode 100644 (file)
index 0000000..dfb0238
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\acp\session\data;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit ACP session data.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.data
+ * @category   Community Framework
+ */
+class ACPSessionDataEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\session\data\ACPSessionData';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataList.class.php b/wcfsetup/install/files/lib/data/acp/session/data/ACPSessionDataList.class.php
new file mode 100644 (file)
index 0000000..b54387a
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\session\data;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of ACP session data.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.session.data\r
+ * @category   Community Framework\r
+ */\r
+class ACPSessionDataList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\acp\session\data\ACPSessionData';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLog.class.php b/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLog.class.php
new file mode 100644 (file)
index 0000000..216c064
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+namespace wcf\data\acp\session\log;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+
+/**
+ * Represents a session log entry.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.log
+ * @category   Community Framework
+ */
+class ACPSessionLog extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_session_log';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'sessionLogID';
+       
+       /**
+        * @see DatabaseObject::__construct()
+        */
+       public function __construct($id, array $row = null, DatabaseObject $object = null) {
+               if ($id !== null) {
+                       $sql = "SELECT          acp_session_log.*, user_table.username, acp_session.sessionID AS active
+                               FROM            wcf".WCF_N."_acp_session_log acp_session_log
+                               LEFT JOIN       wcf".WCF_N."_acp_session acp_session
+                               ON              (acp_session.sessionID = acp_session_log.sessionID)
+                               LEFT JOIN       wcf".WCF_N."_user user_table
+                               ON              (user_table.userID = acp_session_log.userID)
+                               WHERE           acp_session_log.sessionLogID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($id));
+                       $row = $statement->fetchArray();
+               }
+               else if ($object !== null) {
+                       $row = $object->data;
+               }
+               
+               $this->handleData($row);
+       }
+       
+       /**
+        * Returns true, if this session is active.
+        *
+        * @return      boolean
+        */
+       public function isActive() {
+               if ($this->active && $this->lastActivityTime > TIME_NOW - SESSION_TIMEOUT) {
+                       return 1;
+               }
+               
+               return 0;
+       }
+       
+       /**
+        * Returns true, if this session is the active user session.
+        *
+        * @return      boolean
+        */
+       public function isActiveUserSession() {
+               if ($this->isActive() && $this->sessionID == WCF::getSession()->sessionID) {
+                       return 1;
+               }
+               
+               return 0;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogAction.class.php b/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogAction.class.php
new file mode 100644 (file)
index 0000000..7c410a7
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\session\log;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes ACP session log-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.session.log\r
+ * @category   Community Framework\r
+ */\r
+class ACPSessionLogAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\acp\session\log\ACPSessionLogEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogEditor.class.php b/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogEditor.class.php
new file mode 100644 (file)
index 0000000..bb0bde9
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\acp\session\log;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit ACP session logs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.log
+ * @category   Community Framework
+ */
+class ACPSessionLogEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\session\log\ACPSessionLog';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogList.class.php b/wcfsetup/install/files/lib/data/acp/session/log/ACPSessionLogList.class.php
new file mode 100644 (file)
index 0000000..53779c5
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\data\acp\session\log;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of session log entries.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.session.log
+ * @category   Community Framework
+ */
+class ACPSessionLogList extends DatabaseObjectList {
+       /**
+        * @see DatabaseObjectList::$className
+        */
+       public $className = 'wcf\data\acp\session\log\ACPSessionLog';
+       
+       /**
+        * @see DatabaseObjectList::readObjects()
+        */
+       public function readObjects() {
+               if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
+               $this->sqlSelects .= "  user_table.username, acp_session.sessionID AS active,
+                                       (SELECT COUNT(*) FROM wcf".WCF_N."_acp_session_access_log WHERE sessionLogID = ".$this->getDatabaseTableAlias().".sessionLogID) AS accesses";
+               
+               $this->sqlJoins .= "    LEFT JOIN wcf".WCF_N."_user user_table ON (user_table.userID = ".$this->getDatabaseTableAlias().".userID)
+                                       LEFT JOIN wcf".WCF_N."_acp_session acp_session ON (acp_session.sessionID = ".$this->getDatabaseTableAlias().".sessionID)";
+               
+               parent::readObjects();
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/template/ACPTemplate.class.php b/wcfsetup/install/files/lib/data/acp/template/ACPTemplate.class.php
new file mode 100644 (file)
index 0000000..1253411
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\acp\template;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents an ACP template.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.template
+ * @category   Community Framework
+ */
+class ACPTemplate extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_template';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'templateID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/template/ACPTemplateAction.class.php b/wcfsetup/install/files/lib/data/acp/template/ACPTemplateAction.class.php
new file mode 100644 (file)
index 0000000..5f8a593
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\data\acp\template;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes ACP templates-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.template\r
+ * @category   Community Framework\r
+ */\r
+class ACPTemplateAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\acp\template\ACPTemplateEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.template.canAddTemplate');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.template.canDeleteTemplate');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.template.canUpdateTemplate');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/template/ACPTemplateEditor.class.php b/wcfsetup/install/files/lib/data/acp/template/ACPTemplateEditor.class.php
new file mode 100644 (file)
index 0000000..9704189
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\acp\template;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit ACP templates.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.template
+ * @category   Community Framework
+ */
+class ACPTemplateEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\template\ACPTemplate';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/acp/template/ACPTemplateList.class.php b/wcfsetup/install/files/lib/data/acp/template/ACPTemplateList.class.php
new file mode 100644 (file)
index 0000000..07a543b
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\acp\template;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of ACP templates.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.template\r
+ * @category   Community Framework\r
+ */\r
+class ACPTemplateList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\acp\template\ACPTemplate';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/application/Application.class.php b/wcfsetup/install/files/lib/data/application/Application.class.php
new file mode 100644 (file)
index 0000000..b84f2ec
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\application;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents an application.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application
+ * @category   Community Framework
+ */
+class Application extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'application';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'packageID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/ApplicationAction.class.php b/wcfsetup/install/files/lib/data/application/ApplicationAction.class.php
new file mode 100644 (file)
index 0000000..981406e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\application;
+use wcf\data\AbstractDatabaseObjectAction;
+
+/**
+ * Executes application-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application
+ * @category   Community Framework
+ */
+class ApplicationAction extends AbstractDatabaseObjectAction {
+       /**
+        * @see AbstractDatabaseObjectAction::$className
+        */
+       protected $className = 'wcf\data\application\ApplicationEditor';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/ApplicationEditor.class.php b/wcfsetup/install/files/lib/data/application/ApplicationEditor.class.php
new file mode 100644 (file)
index 0000000..8400239
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\application;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit applications.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application
+ * @category   Community Framework
+ */
+class ApplicationEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\application\Application';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/ApplicationList.class.php b/wcfsetup/install/files/lib/data/application/ApplicationList.class.php
new file mode 100644 (file)
index 0000000..04c302a
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\application;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of applications.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application
+ * @category   Community Framework
+ */
+class ApplicationList extends DatabaseObjectList {
+       /**
+        * @see DatabaseObjectList::$className
+        */
+       public $className = 'wcf\data\application\Application';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/group/ApplicationGroup.class.php b/wcfsetup/install/files/lib/data/application/group/ApplicationGroup.class.php
new file mode 100644 (file)
index 0000000..30cf743
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\application\group;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents an application group.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application.group
+ * @category   Community Framework
+ */
+class ApplicationGroup extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'application_group';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'groupID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php b/wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php
new file mode 100644 (file)
index 0000000..c0de8e7
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\application\group;
+use wcf\data\AbstractDatabaseObjectAction;
+
+/**
+ * Executes application group-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application.group
+ * @category   Community Framework
+ */
+class ApplicationGroupAction extends AbstractDatabaseObjectAction {
+       /**
+        * @see AbstractDatabaseObjectAction::$className
+        */
+       protected $className = 'wcf\data\application\group\ApplicationGroupEditor';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/group/ApplicationGroupEditor.class.php b/wcfsetup/install/files/lib/data/application/group/ApplicationGroupEditor.class.php
new file mode 100644 (file)
index 0000000..884ac4c
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\application\group;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit application groups.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application.group
+ * @category   Community Framework
+ */
+class ApplicationGroupEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\application\group\ApplicationGroup';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/application/group/ApplicationGroupList.class.php b/wcfsetup/install/files/lib/data/application/group/ApplicationGroupList.class.php
new file mode 100644 (file)
index 0000000..d4b3513
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\application\group;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of application groups.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.application.group
+ * @category   Community Framework
+ */
+class ApplicationGroupList extends DatabaseObjectList {
+       /**
+        * @see DatabaseObjectList::$className
+        */
+       public $className = 'wcf\data\application\group\ApplicationGroup';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListener.class.php b/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListener.class.php
new file mode 100644 (file)
index 0000000..4256934
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\cleanup\listener;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a cleanup listener.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.cleanup.listener
+ * @category   Community Framework
+ */
+class CleanupListener extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'cleanup_listener';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'listenerID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerAction.class.php b/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerAction.class.php
new file mode 100644 (file)
index 0000000..a057e1e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\cleanup\listener;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes cleanup listener-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.cleanup.listener\r
+ * @category   Community Framework\r
+ */\r
+class CleanupListenerAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\cleanup\listener\CleanupListenerEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerEditor.class.php b/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerEditor.class.php
new file mode 100644 (file)
index 0000000..60b61fd
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\cleanup\listener;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit cleanup listeners.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.cleanup.listener
+ * @category   Community Framework
+ */
+class CleanupListenerEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       public $baseClass = 'wcf\data\cleanup\listener\CleanupListener';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerList.class.php b/wcfsetup/install/files/lib/data/cleanup/listener/CleanupListenerList.class.php
new file mode 100644 (file)
index 0000000..eebda13
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\cleanup\listener;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of cleanup listener.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.cleanup.listener\r
+ * @category   Community Framework\r
+ */\r
+class CleanupListenerList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\cleanup\listener\CleanupListener';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/core/object/CoreObject.class.php b/wcfsetup/install/files/lib/data/core/object/CoreObject.class.php
new file mode 100644 (file)
index 0000000..78d6c37
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\core\object;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a core object.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.core.object
+ * @category   Community Framework
+ */
+class CoreObject extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'core_object';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'objectID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/core/object/CoreObjectAction.class.php b/wcfsetup/install/files/lib/data/core/object/CoreObjectAction.class.php
new file mode 100644 (file)
index 0000000..90c2210
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\core\object;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes core object-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.core.object\r
+ * @category   Community Framework\r
+ */\r
+class CoreObjectAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\core\object\CoreObjectEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/core/object/CoreObjectEditor.class.php b/wcfsetup/install/files/lib/data/core/object/CoreObjectEditor.class.php
new file mode 100644 (file)
index 0000000..eb036f9
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\core\object;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit core objects.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.core.object
+ * @category   Community Framework
+ */
+class CoreObjectEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\core\object\CoreObject';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/core/object/CoreObjectList.class.php b/wcfsetup/install/files/lib/data/core/object/CoreObjectList.class.php
new file mode 100644 (file)
index 0000000..672006e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\core\object;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of core objects.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.event\r
+ * @category   Community Framework\r
+ */\r
+class CoreObjectList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\core\object\CoreObject';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cronjob/Cronjob.class.php b/wcfsetup/install/files/lib/data/cronjob/Cronjob.class.php
new file mode 100644 (file)
index 0000000..4f04cf1
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+namespace wcf\data\cronjob;
+use wcf\data\DatabaseObject;
+use wcf\util\CronjobUtil;
+use wcf\system\WCF;
+
+/**
+ * Represents a cronjob.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.cronjob
+ * @category   Community Framework
+ */
+class Cronjob extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'cronjob';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'cronjobID';
+       
+       /**
+        * Cronjob is available for execution.
+        */
+       const READY = 0;
+       
+       /**
+        * Cronjob is currently processed, preventing multiple execution.
+        */
+       const PENDING = 1;
+       
+       /**
+        * Cronjob is being executed.
+        */
+       const EXECUTING = 2;
+       
+       /**
+        * Returns timestamp of next execution.
+        * 
+        * @param       integer         $timeBase
+        * @return      integer
+        */
+       public function getNextExec($timeBase = null) {
+               if ($timeBase === null) {
+                       if ($this->lastExec) {
+                               $timeBase = $this->lastExec;
+                       }
+                       else {
+                               // first time setup
+                               $timeBase = TIME_NOW;
+                       }
+               }
+               
+               $nextExec = CronjobUtil::calculateNextExec(
+                       $this->startMinute,
+                       $this->startHour,
+                       $this->startDom,
+                       $this->startMonth,
+                       $this->startDow,
+                       $timeBase
+               );
+               
+               return $nextExec;
+       }
+       
+       /**
+        * Returns true if current user may edit this cronjob.
+        * 
+        * @return      boolean
+        */
+       public function isEditable() {
+               return (WCF::getSession()->getPermission('admin.system.cronjobs.canEditCronjob') && $this->canBeEdited);
+       }
+       
+       /**
+        * Returns true if current user may delete this cronjob.
+        * 
+        * @return      boolean
+        */
+       public function isDeletable() {
+               return (WCF::getSession()->getPermission('admin.system.cronjobs.canDeleteCronjob') && $this->canBeEdited);
+       }
+       
+       /**
+        * Returns true if current user may enable or disable this cronjob.
+        * 
+        * @return      true
+        */
+       public function canBeDisabled() {
+               return (WCF::getSession()->getPermission('admin.system.cronjobs.canEnableDisableCronjob') && $this->canBeDisabled);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/cronjob/CronjobAction.class.php b/wcfsetup/install/files/lib/data/cronjob/CronjobAction.class.php
new file mode 100644 (file)
index 0000000..ae216b9
--- /dev/null
@@ -0,0 +1,103 @@
+<?php\r
+namespace wcf\data\cronjob;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes cronjob-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.cronjob\r
+ * @category   Community Framework\r
+ */\r
+class CronjobAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\cronjob\CronjobEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.system.cronjobs.canAddCronjob');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.system.cronjobs.canDeleteCronjob');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.system.cronjobs.canEditCronjob');\r
+       \r
+       /**\r
+        * Validates permissions and parameters\r
+        */\r
+       public function validateDelete() {\r
+               parent::validateDelete();\r
+               \r
+               foreach ($this->objects as $cronjob) {\r
+                       if (!$cronjob->isDeletable()) {\r
+                               throw new ValidateActionException('Insufficient permissions');\r
+                       } \r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Validates permissions and parameters\r
+        */\r
+       public function validateUpdate() {\r
+               parent::validateUpdate();\r
+               \r
+               foreach ($this->objects as $cronjob) {\r
+                       if (!$cronjob->isEditable()) {\r
+                               throw new ValidateActionException('Insufficient permissions');\r
+                       } \r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Validates permissions and parameters\r
+        */\r
+       public function validateToggle() {\r
+               parent::validateUpdate();\r
+               \r
+               foreach ($this->objects as $cronjob) {\r
+                       if (!$cronjob->canBeDisabled()) {\r
+                               throw new ValidateActionException('Insufficient permissions');\r
+                       } \r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Toggles status.\r
+        */\r
+       public function toggle() {\r
+               foreach ($this->objects as $cronjob) {\r
+                       $newStatus = ($cronjob->active) ? 0 : 1;\r
+                       $cronjob->update(array('active' => $newStatus));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Validates permissions and parameters\r
+        */\r
+       public function validateExecute() {\r
+               parent::validateUpdate();\r
+       }\r
+       \r
+       /**\r
+        * Executes cronjobs.\r
+        */\r
+       public function execute() {\r
+               // TODO: implement me\r
+               foreach ($this->objects as $cronjob) {\r
+                       \r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php b/wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php
new file mode 100644 (file)
index 0000000..35e3ebc
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+namespace wcf\data\cronjob;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\EditableCachedObject;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * Provides functions to edit cronjobs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.cronjob
+ * @category   Community Framework
+ */
+class CronjobEditor extends DatabaseObjectEditor implements EditableCachedObject {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\cronjob\Cronjob';
+       
+       /**
+        * @see EditableCachedObject::resetCache()
+        */
+       public static function resetCache() {
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.cronjobs-*');
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cronjob/CronjobList.class.php b/wcfsetup/install/files/lib/data/cronjob/CronjobList.class.php
new file mode 100644 (file)
index 0000000..dbf7e03
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\cronjob;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of cronjobs.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.cronjob\r
+ * @category   Community Framework\r
+ */\r
+class CronjobList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\cronjob\Cronjob';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cronjob/log/CronjobLog.class.php b/wcfsetup/install/files/lib/data/cronjob/log/CronjobLog.class.php
new file mode 100644 (file)
index 0000000..7bc30cf
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\cronjob\log;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a croniob log.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.cronjob.log
+ * @category   Community Framework
+ */
+class CronjobLog extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'cronjob_log';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'cronjobLogID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cronjob/log/CronjobLogAction.class.php b/wcfsetup/install/files/lib/data/cronjob/log/CronjobLogAction.class.php
new file mode 100644 (file)
index 0000000..22ac177
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\cronjob\log;
+use wcf\data\AbstractDatabaseObjectAction;
+
+/**
+ * Executes cronjob log-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.menu.item
+ * @category   Community Framework
+ */
+class CronjobLogAction extends AbstractDatabaseObjectAction {
+       /**
+        * @see AbstractDatabaseObjectAction::$className
+        */
+       protected $className = 'wcf\data\cronjob\log\CronjobLogEditor';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/cronjob/log/CronjobLogEditor.class.php b/wcfsetup/install/files/lib/data/cronjob/log/CronjobLogEditor.class.php
new file mode 100644 (file)
index 0000000..a0f0494
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+namespace wcf\data\cronjob\log;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit cronjob logs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.item
+ * @category   Community Framework
+ */
+class CronjobLogEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\cronjob\log\CronjobLog';
+       
+       /**
+        * Deletes the cronjob log.
+        */
+       public static function clearLogs($packageID = PACKAGE_ID) {
+               // delete logs
+               $sql = "DELETE FROM     wcf".WCF_N."_cronjobs_log
+                       WHERE           cronjobID IN (
+                                               SELECT  cronjobID
+                                               FROM    wcf".WCF_N."_cronjobs cronjobs,
+                                                       wcf".WCF_N."_package_dependency package_dependency
+                                               WHERE   cronjobs.packageID = package_dependency.dependency
+                                                       AND package_dependency.packageID = ?
+                                       )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($packageID);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/cronjob/log/CronjobLogList.class.php b/wcfsetup/install/files/lib/data/cronjob/log/CronjobLogList.class.php
new file mode 100644 (file)
index 0000000..5a5877f
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\cronjob\log;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of cronjob log entries.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.acp.menu.item\r
+ * @category   Community Framework\r
+ */\r
+class CronjobLogList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\cronjob\log\CronjobLog';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/event/listener/EventListener.class.php b/wcfsetup/install/files/lib/data/event/listener/EventListener.class.php
new file mode 100644 (file)
index 0000000..a81135b
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\event\listener;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents an event listener.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.event.listener
+ * @category   Community Framework
+ */
+class EventListener extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'event_listener';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'listenerID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/event/listener/EventListenerAction.class.php b/wcfsetup/install/files/lib/data/event/listener/EventListenerAction.class.php
new file mode 100644 (file)
index 0000000..8ca028e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\event\listener;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes event listener-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.event\r
+ * @category   Community Framework\r
+ */\r
+class EventListenerAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\event\listener\EventListenerEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/event/listener/EventListenerEditor.class.php b/wcfsetup/install/files/lib/data/event/listener/EventListenerEditor.class.php
new file mode 100644 (file)
index 0000000..3996729
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\event\listener;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit event listener.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.event.listener
+ * @category   Community Framework
+ */
+class EventListenerEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       public static $baseClass = 'wcf\data\event\listener\EventListener';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/event/listener/EventListenerList.class.php b/wcfsetup/install/files/lib/data/event/listener/EventListenerList.class.php
new file mode 100644 (file)
index 0000000..39c2a37
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\event\listener;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of event listener.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.event\r
+ * @category   Community Framework\r
+ */\r
+class EventListenerList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\event\listener\EventListener';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/Language.class.php b/wcfsetup/install/files/lib/data/language/Language.class.php
new file mode 100644 (file)
index 0000000..eb562f7
--- /dev/null
@@ -0,0 +1,146 @@
+<?php\r
+namespace wcf\data\language;\r
+use wcf\data\DatabaseObject;\r
+use wcf\system\WCF;\r
+use wcf\system\language\LanguageFactory;\r
+\r
+/**\r
+ * Represents a language.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language\r
+ * @category   Community Framework\r
+ */\r
+class Language extends DatabaseObject {\r
+       /**\r
+        * @see DatabaseObject::$databaseTableName\r
+        */\r
+       protected static $databaseTableName = 'language';\r
+       \r
+       /**\r
+        * @see DatabaseObject::$databaseTableIndexName\r
+        */\r
+       protected static $databaseTableIndexName = 'languageID';\r
+       \r
+       /**\r
+        * list of language items\r
+        * \r
+        * @var array\r
+        */\r
+       protected $items = array();\r
+       \r
+       /**\r
+        * list of dynamic language items\r
+        * \r
+        * @param       array\r
+        */\r
+       protected $dynamicItems = array();\r
+       \r
+       /**\r
+        * instance of LanguageEditor\r
+        * \r
+        * @var LanguageEditor\r
+        */\r
+       private $editor = null;\r
+       \r
+       /**\r
+        * Active package id\r
+        * \r
+        * @var integer\r
+        */\r
+       public $packageID = PACKAGE_ID;\r
+       \r
+       /**\r
+        * Returns a single language variable.\r
+        * \r
+        * @param       string          $item\r
+        * @return      string\r
+        */\r
+       public function get($item) {\r
+               if (!isset($this->items[$item])) {\r
+                       // load category file\r
+                       $explodedItem = explode('.', $item);\r
+                       if (count($explodedItem) < 2) {\r
+                               return $item;\r
+                       }\r
+                       \r
+                       if (count($explodedItem) < 4 || !$this->loadCategory($explodedItem[0].'.'.$explodedItem[1].'.'.$explodedItem[2].'.'.$explodedItem[3])) {\r
+                               if (count($explodedItem) < 3 || !$this->loadCategory($explodedItem[0].'.'.$explodedItem[1].'.'.$explodedItem[2])) {\r
+                                       $this->loadCategory($explodedItem[0].'.'.$explodedItem[1]);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // return language variable\r
+               if (isset($this->items[$item])) {\r
+                       return $this->items[$item];\r
+               }\r
+               \r
+               // return plain variable\r
+               return $item;\r
+       }\r
+       \r
+       /**\r
+        * Executes template scripting in a language variable.\r
+        *\r
+        * @param       string          $item\r
+        * @param       array           $variables \r
+        * @return      string          result\r
+        */\r
+       public function getDynamicVariable($item, array $variables = array()) {\r
+               $staticItem = $this->get($item);\r
+               \r
+               if (isset($this->dynamicItems[$this->languageID][$item])) {\r
+                       if (count($variables)) WCF::getTPL()->assign($variables);\r
+                       return WCF::getTPL()->fetchString($this->dynamicItems[$this->languageID][$item]);\r
+               }\r
+               \r
+               return $staticItem;\r
+       }\r
+       \r
+       /**\r
+        * Loads category files.\r
+        *\r
+        * @param       string          $category\r
+        * @return      boolean\r
+        */\r
+       protected function loadCategory($category) {\r
+               if (!LanguageFactory::isValidCategory($category)) {\r
+                       return false;\r
+               }\r
+               \r
+               // search language file\r
+               $filename = WCF_DIR.'language/'.$this->packageID.'_'.$this->languageID.'_'.$category.'.php';\r
+               if (!@file_exists($filename)) { \r
+                       if ($this->editor === null) {\r
+                               $this->editor = new LanguageEditor($this);\r
+                       }\r
+                       \r
+                       // rebuild language file\r
+                       $languageCategory = LanguageFactory::getCategory($category);\r
+                       $this->editor->updateCategory(array($languageCategory['languageCategoryID']), array($this->packageID));\r
+               }\r
+               \r
+               // include language file\r
+               @include_once($filename);\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Returns true if given items includes template scripting.\r
+        * \r
+        * @param       string          $item\r
+        * @return      boolean\r
+        */\r
+       public function isDynamicItem($item) {\r
+               if (isset($this->dynamicItems[$item])) {\r
+                       return true;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/LanguageAction.class.php b/wcfsetup/install/files/lib/data/language/LanguageAction.class.php
new file mode 100644 (file)
index 0000000..9206945
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+namespace wcf\data\language;
+use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\exception\ValidateActionException;
+use wcf\system\WCF;
+
+/**
+ * Executes language-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language
+ * @category   Community Framework
+ */
+class LanguageAction extends AbstractDatabaseObjectAction {
+       /**
+        * @see AbstractDatabaseObjectAction::$className
+        */
+       protected $className = 'wcf\data\language\LanguageEditor';
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsCreate
+        */
+       protected $permissionsCreate = array('admin.language.canAddLanguage');
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsDelete
+        */
+       protected $permissionsDelete = array('admin.language.canDeleteLanguage');
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate
+        */
+       protected $permissionsUpdate = array('admin.language.canEditLanguage');
+       
+       /**
+        * Validates permission to set a language as default.
+        */
+       public function validateSetAsDefault() {
+               try {
+                       WCF::getSession()->checkPermission($this->permissionsUpdate);
+               }
+               catch (PermissionDeniedException $e) {
+                       throw new ValidateActionException('Insufficient permissions');
+               }
+               
+               // read data
+               $this->readObjects();
+               
+               if (!count($this->objects)) {
+                       throw new ValidateActionException('Invalid object id');
+               }
+       }
+       
+       /**
+        * Sets language as default
+        */     
+       public function setAsDefault() {
+               $language = array_shift($this->objects);
+               $language->setAsDefault();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/language/LanguageEditor.class.php b/wcfsetup/install/files/lib/data/language/LanguageEditor.class.php
new file mode 100644 (file)
index 0000000..c7aa018
--- /dev/null
@@ -0,0 +1,601 @@
+<?php
+namespace wcf\data\language;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\language\category\LanguageCategory;
+use wcf\data\language\category\LanguageCategoryEditor;
+use wcf\data\language\item\LanguageItemEditor;
+use wcf\data\language\item\LanguageItemList;
+use wcf\system\cache\CacheHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\io\File;
+use wcf\system\language\LanguageFactory;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+use wcf\util\XML;
+
+/**
+ * Provides functions to edit languages.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language
+ * @category   Community Framework
+ */
+class LanguageEditor extends DatabaseObjectEditor {
+       /**
+        * @see wcf\data\DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\language\Language';
+       
+       /**
+        * @see wcf\data\DatabaseObjectEditor::delete()
+        */     
+       public function delete() {
+               parent::delete();
+               
+               self::deleteLanguageFiles($this->languageID);
+       }
+       
+       /**
+        * Updates the language files for the given category.
+        *
+        * @param       array           $categoryIDs
+        * @param       array           $packageIDs
+        */
+       public function updateCategory(array $categoryIDs = array(), array $packageIDs = array()) {
+               if (!count($categoryIDs)) {
+                       // get all categories
+                       $sql = "SELECT  languageCategoryID
+                               FROM    wcf".WCF_N."_language_category";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute();
+                       while ($row = $statement->fetchArray()) {
+                               $categoryIDs[] = $row['languageCategoryID'];
+                       }
+               }
+               
+               $this->writeLanguageFiles($categoryIDs, $packageIDs);
+       }
+       
+       /**
+        * Write the languages files.
+        *
+        * @param       array           $categoryIDs
+        * @param       array           $packageIDs
+        */
+       protected function writeLanguageFiles(array $categoryIDs, array $packageIDs) {
+               // get categories
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("languageCategoryID IN (?)", array($categoryIDs));
+               
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_language_category
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($category = $statement->fetchArray()) {
+                       $categoryName = $category['languageCategory'];
+                       $categoryID = $category['languageCategoryID'];
+                       
+                       // loop packages
+                       foreach ($packageIDs as $packageID) {
+                               $conditions = new PreparedStatementConditionBuilder();
+                               $conditions->add("languageID = ?", array($this->languageID));
+                               $conditions->add("languageCategoryID = ?", array($categoryID));
+                               
+                               // get language items
+                               if ($packageID === 0) {
+                                       // update after wcf installation
+                                       $conditions->add("packageID = ?", array(0));
+                                       
+                                       $sql = "SELECT  languageItem, languageItemValue, languageCustomItemValue, languageUseCustomValue
+                                               FROM    wcf".WCF_N."_language_item
+                                               ".$conditions;
+                               }
+                               else {
+                                       // update after regular package installation or update or manual import
+                                       $conditions->add("package_dependency.packageID = ?", array($packageID));
+                                       
+                                       $sql = "SELECT          languageItem, languageItemValue, languageCustomItemValue, languageUseCustomValue
+                                               FROM            wcf".WCF_N."_language_item language_item
+                                               LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                                               ON              (package_dependency.dependency = language_item.packageID)
+                                               ".$conditions."
+                                               ORDER BY        package_dependency.priority ASC";
+                               }
+                               
+                               $statement2 = WCF::getDB()->prepareStatement($sql);
+                               $statement2->execute($conditions->getParameters());
+                               $items = array();
+                               while ($row = $statement2->fetchArray()) {
+                                       if ($row['languageUseCustomValue'] == 1) {
+                                               $items[$row['languageItem']] = $row['languageCustomItemValue'];
+                                       }
+                                       else {
+                                               $items[$row['languageItem']] = $row['languageItemValue'];
+                                       }
+                               }
+                               
+                               if (count($items) > 0) {
+                                       $file = new File(WCF_DIR.'language/'.$packageID.'_'.$this->languageID.'_'.$categoryName.'.php');
+                                       @$file->chmod(0777);
+                                       $file->write("<?php\n/**\n* WoltLab Community Framework\n* language: ".$this->languageCode."\n* encoding: UTF-8\n* category: ".$categoryName."\n* generated at ".gmdate("r")."\n* \n* DO NOT EDIT THIS FILE\n*/\n");
+                                       
+                                       foreach ($items as $languageItem => $languageItemValue) {
+                                               $file->write("\$this->items['".$languageItem."'] = '".str_replace("'", "\'", $languageItemValue)."';\n");
+                                               
+                                               // compile dynamic language variables
+                                               if ($categoryName != 'wcf.global' && strpos($languageItemValue, '{') !== false) {
+                                                       $file->write("\$this->dynamicItems['".$languageItem."'] = '".str_replace("'", "\'", LanguageFactory::getScriptingCompiler()->compileString($languageItem, $languageItemValue))."';\n");
+                                               }
+                                       }
+                                       
+                                       $file->write("?>");
+                                       $file->close();
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Imports language items from an XML file into this language.
+        * Updates the relevant language files automatically.
+        *
+        * @param       wcf\util\XML    $xml
+        * @param       integer         $packageID
+        * @param       boolean         $updateFiles
+        */
+       public function updateFromXML(XML $xml, $packageID, $updateFiles = true) {
+               $xpath = $xml->xpath();
+               $usedCategories = array();
+               
+               // fetch categories
+               $categories = $xpath->query('/ns:language/ns:category');
+               foreach ($categories as $category) {
+                       $usedCategories[$category->getAttribute('name')] = 0;
+               }
+               
+               if (!count($usedCategories)) return;
+               
+               // select existing categories
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("languageCategory IN (?)", array(array_keys($usedCategories)));
+               
+               $sql = "SELECT  languageCategoryID, languageCategory
+                       FROM    wcf".WCF_N."_language_category
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $usedCategories[$row['languageCategory']] = $row['languageCategoryID'];
+               }
+               
+               // create new categories
+               foreach ($usedCategories as $categoryName => $categoryID) {
+                       if ($categoryID) continue;
+                       
+                       $category = LanguageCategoryEditor::create(array(
+                               'languageCategory' => $categoryName
+                       ));
+                       $usedCategories[$categoryName] = $category->languageCategoryID;
+               }
+               
+               // loop through categories to import items
+               $items = array();
+               foreach ($categories as $category) {
+                       $categoryName = $category->getAttribute('name');
+                       $categoryID = $usedCategories[$categoryName];
+                       
+                       // loop through items
+                       $elements = $xpath->query('child::*', $category);
+                       foreach ($elements as $element) {
+                               $itemName = $element->getAttribute('name');
+                               $itemValue = $element->nodeValue;
+                               
+                               $items[$itemName] = array(
+                                       'name' => $itemName,
+                                       'value' => $itemValue,
+                                       'categoryID' => $categoryID
+                               );
+                       }
+               }
+               
+               if (count($items)) {
+                       $existingItems = $statementParameters = array();
+                       
+                       // find existing items
+                       $itemList = new LanguageItemList();
+                       $itemList->getConditionBuilder()->add("language_item.languageItem IN (?)", array(array_keys($items)));
+                       $itemList->getConditionBuilder()->add("language_item.packageID = ? AND language_item.languageID = ?", array($packageID, $this->languageID));
+                       $itemList->sqlLimit = 0;
+                       $itemList->readObjects();
+                       
+                       foreach ($itemList->getObjects() as $languageItem) {
+                               $existingItems[$languageItem->languageItem] = $languageItem;
+                       }
+                       
+                       foreach ($items as $item) {
+                               if (isset($existingItems[$item['name']])) {
+                                       // update existing item
+                                       $itemEditor = new LanguageItemEditor($existingItems[$item['name']]);
+                                       $itemEditor->update(array(
+                                               'languageItemValue' => $item['value'],
+                                               'languageCategoryID' => $item['categoryID'],
+                                               'languageUseCustomValue' => 0,
+                                               'languageItem' => $item['name']
+                                       ));
+                               }
+                               else {
+                                       // store item for later insert
+                                       $statementParameters[] = $item;
+                               }
+                       }
+                       
+                       if (count($statementParameters)) {
+                               if ($packageID) {
+                                       $sql = "INSERT INTO     wcf".WCF_N."_language_item
+                                                               (languageID, languageItem, languageItemValue, languageCategoryID, packageID)
+                                               VALUES          (?, ?, ?, ?, ?)";
+                                       $statement = WCF::getDB()->prepareStatement($sql);
+                                       
+                                       foreach ($statementParameters as $item) {
+                                               $statement->execute(array(
+                                                       $this->languageID,
+                                                       $item['name'],
+                                                       $item['value'],
+                                                       $item['categoryID'],
+                                                       $packageID
+                                               ));
+                                       }
+                               }
+                               else {
+                                       $sql = "INSERT INTO     wcf".WCF_N."_language_item
+                                                               (languageID, languageItem, languageItemValue, languageCategoryID)
+                                               VALUES          (?, ?, ?, ?)";
+                                       $statement = WCF::getDB()->prepareStatement($sql);
+                                       
+                                       foreach ($statementParameters as $item) {
+                                               $statement->execute(array(
+                                                       $this->languageID,
+                                                       $item['name'],
+                                                       $item['value'],
+                                                       $item['categoryID']
+                                               ));
+                                       }
+                               }
+                       }
+               }
+               
+               // update the relevant language files
+               if ($updateFiles) {
+                       self::deleteLanguageFiles($this->languageID);
+               }
+               
+               // delete relevant template compilations
+               $this->deleteCompiledTemplates();
+       }
+       
+       /**
+        * Deletes the language cache.
+        *
+        * @param       string          $languageID
+        * @param       string          $category
+        * @param       string          $packageID
+        */
+       public static function deleteLanguageFiles($languageID = '*', $category = '*', $packageID = '*') {
+               $files = @glob(WCF_DIR."language/".$packageID."_".$languageID."_".$category.".php");
+               if (is_array($files)) {
+                       foreach ($files as $filename) {
+                               @unlink($filename);
+                       }
+               }
+       }
+       
+       /**
+        * Deletes relevant template compilations.
+        */
+       public function deleteCompiledTemplates() {
+               // templates
+               $filenames = glob(WCF_DIR.'templates/compiled/*_'.$this->languageID.'_*.php');
+               if ($filenames) foreach ($filenames as $filename) @unlink($filename);
+               
+               // acp templates
+               $filenames = glob(WCF_DIR.'acp/templates/compiled/*_'.$this->languageID.'_*.php');
+               if ($filenames) foreach ($filenames as $filename) @unlink($filename);
+       }
+       
+       /**
+        * Updates all language files of the given package id.
+        */
+       public static function updateAll() {
+               self::deleteLanguageFiles();
+       }
+       
+       /**
+        * Takes an XML object and returns the specific language code.
+        *
+        * @param       wcf\util\XML    $xml
+        * @return      string          language code
+        */
+       public static function readLanguageCodeFromXML(XML $xml) {
+               $rootNode = $xml->xpath()->query('/ns:language')->item(0);
+               $attributes = $xml->xpath()->query('attribute::*', $rootNode);
+               foreach ($attributes as $attribute) {
+                       if ($attribute->name == 'languagecode') {
+                               return $attribute->value;
+                       }
+               }
+               
+               throw new SystemException("missing attribute 'languagecode' in language file", 13023);
+       }
+       
+       /**
+        * Imports language items from an XML file into a new or a current language.
+        * Updates the relevant language files automatically.
+        *
+        * @param       wcf\util\XML    $xml
+        * @param       integer         $packageID
+        * @return      wcf\data\language\LanguageEditor
+        */
+       public static function importFromXML(XML $xml, $packageID) {
+               $languageCode = self::readLanguageCodeFromXML($xml);
+               
+               // try to find an existing language with the given language code
+               $language = LanguageFactory::getLanguageByCode($languageCode);
+               
+               // create new language
+               if ($language === null) {
+                       $language = self::create(array(
+                               'languageCode' => $languageCode
+                       ));
+               }
+               
+               // import xml
+               $languageEditor = new LanguageEditor($language);
+               $languageEditor->updateFromXML($xml, $packageID);
+               
+               // return language object
+               return $languageEditor;
+       }
+       
+       /**
+        * Copies all language variables from current language to language specified as $destination.
+        * Caution: This method expects that target language does not have any items!
+        * 
+        * @param       wcf\data\language\Language      $destination
+        */     
+       public function copy(Language $destination) {
+               $sql = "INSERT INTO     wcf".WCF_N."_language_item
+                                       (languageID, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID)
+                       SELECT          ?, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID
+                       FROM            wcf".WCF_N."_language_item
+                       WHERE           languageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $destination->languageID,
+                       $this->languageID
+               ));
+       }
+       
+       /**
+        * Updates the language items of a language category.
+        * 
+        * @param       array           $items
+        * @param       wcf\data\language\category\LanguageCategory     $category
+        * @param       integer         $packageID
+        * @param       array           $useCustom
+        */
+       public function updateItems(array $items, LanguageCategory $category, $packageID = PACKAGE_ID, array $useCustom = array()) {
+               if (!count($items)) return;
+               
+               // find existing language items
+               $languageItemList = new LanguageItemList();
+               $languageItemList->sqlJoins = "LEFT JOIN wcf".WCF_N."_package_dependency package_dependency ON (package_dependency.dependency = language_item.packageID)";
+               $languageItemList->getConditionBuilder()->add("package_dependency.packageID = ?", array($packageID));
+               $languageItemList->getConditionBuilder()->add("language_item.languageItem IN (?)", array(array_keys($items)));
+               $languageItemList->getConditionBuilder()->add("languageID = ?", array($this->languageID));
+               $languageItemList->sqlOrderBy = "package_dependency.priority ASC";
+               $languageItemList->sqlLimit = 0;
+               $languageItemList->readObjects();
+               
+               foreach($languageItemList->getObjects() as $languageItem) {
+                       $languageItemEditor = new LanguageItemEditor($languageItem);
+                       $languageItemEditor->update(array(
+                               'languageCustomItemValue' => $items[$languageItem->languageItem],
+                               'languageUseCustomValue' => (isset($useCustom[$languageItem->languageItem])) ? 1 : 0
+                       ));
+                       
+                       // remove updated items, leaving items to be created within
+                       unset($items[$languageItem->languageItem]);
+               }
+               
+               // create remaining items
+               if (count($items)) {
+                       // bypass LanguageItemEditor::create() for performance reasons
+                       $sql = "INSERT INTO     wcf".WCF_N."_language_item
+                               (languageID, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID)
+                               VALUES          (?, ?, ?, ?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($items as $itemName => $itemValue) {
+                               $statement->execute(array(
+                                       $this->languageID,
+                                       $itemName,
+                                       $itemValue,
+                                       0,
+                                       $category->languageCategoryID,
+                                       $packageID
+                               ));
+                       }
+               }
+               
+               // update the relevant language files
+               self::deleteLanguageFiles($this->languageID, $category->languageCategory, $packageID);
+               
+               // delete relevant template compilations
+               $this->deleteCompiledTemplates();
+       }
+       
+       /**
+        * Sets current language as default language.
+        */
+       public function setAsDefault() {
+               // remove default flag from all languages
+               $sql = "UPDATE  wcf".WCF_N."_language
+                       SET     isDefault = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       0
+               ));
+               
+               // set current language as default language
+               $this->update(array(
+                       'isDefault' => 1
+               ));
+               
+               $this->clearCache();
+       }
+       
+       /**
+        * Clears language cache.
+        */     
+       public function clearCache() {
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache/', 'cache.languages.php');
+       }
+       
+       /**
+        * Searches in language items.
+        * 
+        * @param       string          $search         search query
+        * @param       string          $replace
+        * @param       integer         $languageID
+        * @param       boolean         $useRegex
+        * @param       boolean         $caseSensitive
+        * @param       boolean         $searchVariableName
+        * @return      array           results 
+        */
+       public static function search($search, $replace = null, $languageID = null, $useRegex = 0, $searchVariableName = 0) {
+               $results = array();
+               
+               // build condition
+               $conditionBuilder = new PreparedStatementConditionBuilder();
+               
+               
+               // search field
+               $statementParameters = array();
+               if ($searchVariableName) $searchCondition = 'languageItem ';
+               else $searchCondition = 'languageItemValue ';
+               
+               // regex
+               if ($useRegex) {
+                       $searchCondition .= "REGEXP ?";
+                       $statementParameters[] = $search;
+               }
+               else {
+                       $searchCondition .= "LIKE ?";
+                       $statementParameters[] = '%'.$search.'%';
+               }
+               
+               if (!$searchVariableName) {
+                       $searchCondition .= ' OR languageCustomItemValue ';
+                       // regex
+                       if ($useRegex) {
+                               $searchCondition .= "REGEXP ?";
+                               $statementParameters[] = $search;
+                       }
+                       else {
+                               $searchCondition .= "LIKE ?";
+                               $statementParameters[] = '%'.$search.'%';
+                       }
+               }
+               
+               $conditionBuilder->add($searchCondition, $statementParameters);
+               $conditionBuilder->add("packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+               if ($languageID !== null) $conditionBuilder->add("languageID = ?", array($languageID));
+               
+               // search
+               $updatedItems = array();
+               $sql = "SELECT          *
+                       FROM            wcf".WCF_N."_language_item
+                       ".$conditionBuilder;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditionBuilder->getParameters());
+               
+               while ($row = $statement->fetchArray()) {
+                       if ($replace !== null) {
+                               // search and replace
+                               $matches = 0;
+                               if ($useRegex) {
+                                       $newValue = preg_replace('~'.$search.'~s'.(!$caseSensitive ? 'i' : ''), $replace, ($row['languageCustomItemValue'] ? $row['languageCustomItemValue'] : $row['languageItemValue']), -1, $matches);
+                               }
+                               else {
+                                       if ($caseSensitive) $newValue = StringUtil::replace($search, $replace, ($row['languageCustomItemValue'] ? $row['languageCustomItemValue'] : $row['languageItemValue']), $matches);
+                                       else $newValue = StringUtil::replaceIgnoreCase($search, $replace, ($row['languageCustomItemValue'] ? $row['languageCustomItemValue'] : $row['languageItemValue']), $matches);
+                               }
+                               
+                               if ($matches > 0) {
+                                       // update value
+                                       if (!isset($updatedItems[$row['languageID']])) $updatedItems[$row['languageID']] = array();
+                                       if (!isset($updatedItems[$row['languageID']][$row['languageCategoryID']])) $updatedItems[$row['languageID']][$row['languageCategoryID']] = array();
+                                       $updatedItems[$row['languageID']][$row['languageCategoryID']][$row['languageItem']] = $newValue;
+                                       
+                                       // save matches
+                                       $row['matches'] = $matches;
+                               }
+                       }
+                       
+                       $results[] = $row;
+               }
+               
+               // save updates
+               if (count($updatedItems) > 0) {
+                       foreach ($updatedItems as $languageID => $categories) {
+                               $language = new LanguageEditor($languageID);
+                               
+                               foreach ($categories as $categoryID => $items) {
+                                       $useCustom = array();
+                                       foreach (array_keys($items) as $item) {
+                                               $useCustom[$item] = 1;
+                                       }
+                                       
+                                       $category = new LanguageCategory($categoryID);
+                                       $language->updateItems($items, $category, PACKAGE_ID, $useCustom);
+                               }
+                       }
+               }
+               
+               return $results;
+       }
+       
+       /**
+        * Enables the multilingualism feature for given languages.
+        * 
+        * @param       array           $languageIDs
+        */
+       public static function enableMultilingualism(array $languageIDs = array()) {
+               $sql = "UPDATE  wcf".WCF_N."_language
+                       SET     hasContent = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(0));
+               
+               if (count($languageIDs)) {
+                       $sql = '';
+                       $statementParameters = array();
+                       foreach ($languageIDs as $languageID) {
+                               if (!empty($sql)) $sql .= ',';
+                               $sql .= '?';
+                               $statementParameters[] = $languageID;
+                       }
+                       
+                       $sql = "UPDATE  wcf".WCF_N."_language
+                               SET     hasContent = ?
+                               WHERE   languageID IN (".$sql.")";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       array_unshift($statementParameters, 1);
+                       $statement->execute($statementParameters);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/language/LanguageList.class.php b/wcfsetup/install/files/lib/data/language/LanguageList.class.php
new file mode 100644 (file)
index 0000000..0195661
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\language;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of languages.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language\r
+ * @category   Community Framework\r
+ */\r
+class LanguageList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\language\Language';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/SetupLanguage.class.php b/wcfsetup/install/files/lib/data/language/SetupLanguage.class.php
new file mode 100644 (file)
index 0000000..061e4d6
--- /dev/null
@@ -0,0 +1,107 @@
+<?php\r
+namespace wcf\data\language;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\io\File;\r
+use wcf\system\language\LanguageFactory;\r
+use wcf\util\XML;\r
+\r
+/**\r
+ * SetupLanguage is a modification of Language only for the setup process.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language\r
+ * @category   Community Framework\r
+ */\r
+class SetupLanguage extends Language {\r
+       /**\r
+        * @see DatabaseObject::__construct()\r
+        */\r
+       public function __construct($languageID, array $row, Language $language = null) {\r
+               if ($row === null) {\r
+                       throw new SystemException('SetupLanguage accepts only an existing dataset.');\r
+               }\r
+               \r
+               parent::__construct(null, $row, null);\r
+               \r
+               $this->defineConstants();\r
+       }\r
+       \r
+       /**\r
+        * @see Language::loadCategory()\r
+        */\r
+       protected function loadCategory($category) {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Loads the compiled language file.\r
+        * Compiles the language file before if necessary.\r
+        */\r
+       public function loadLanguage() {\r
+               $filename = TMP_DIR.'setup/lang/cache/'.$this->languageCode.'_wcf.setup.php';\r
+               \r
+               if (!file_exists($filename)) {\r
+                       $xml = new XML();\r
+                       $xml->load(TMP_DIR.'setup/lang/setup_'.$this->languageCode.'.xml');\r
+                       \r
+                       // get language items\r
+                       $categoriesToCache = array();\r
+                       $items = $xml->xpath()->query('/ns:language/ns:category/ns:item');\r
+                       foreach ($items as $item) {\r
+                               $categoriesToCache[] = array(\r
+                                       'name' => $item->getAttribute('name'),\r
+                                       'cdata' => $item->nodeValue\r
+                               );\r
+                       }\r
+                       \r
+                       // update language files here\r
+                       if (count($categoriesToCache) > 0) {\r
+                               $file = new File($filename);\r
+                               $file->write("<?php\n/**\n* WoltLab Community Framework\n* language: ".$this->languageCode."\n* encoding: UTF-8\n* category: WCF Setup\n* generated at ".gmdate("r")."\n* \n* DO NOT EDIT THIS FILE\n*/\n");\r
+                               foreach ($categoriesToCache as $value => $name) {\r
+                                       $file->write("\$this->items['".$name['name']."'] = '".str_replace("'", "\'", $name['cdata'])."';\n");\r
+                                       \r
+                                       // compile dynamic language variables\r
+                                       if (strpos($name['cdata'], '{') !== false) {\r
+                                               $file->write("\$this->dynamicItems['".$name['name']."'] = '".str_replace("'", "\'", LanguageFactory::getScriptingCompiler()->compileString($name['name'], $name['cdata']))."';\n");\r
+                                       }\r
+                               }\r
+               \r
+                               $file->write("?>");\r
+                               $file->close();\r
+                       }\r
+               }\r
+\r
+               include_once($filename);\r
+               $this->setLocale();\r
+       }\r
+       \r
+       /**\r
+        * Defines all global constants.\r
+        */\r
+       private function defineConstants() {\r
+               if (!defined('LANGUAGE_CODE')) {\r
+                       define('LANGUAGE_CODE', LanguageFactory::fixLanguageCode($this->languageCode));\r
+                       mb_internal_encoding('UTF-8');\r
+                       if (function_exists('mb_regex_encoding')) mb_regex_encoding('UTF-8');\r
+                       mb_language('uni');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Sets the local language.\r
+        */\r
+       private function setLocale() {\r
+               // set locale for\r
+               // string comparison\r
+               // character classification and conversion\r
+               // date and time formatting\r
+               if (!defined('PAGE_DIRECTION')) define('PAGE_DIRECTION', $this->get('wcf.global.pageDirection'));\r
+               setlocale(LC_COLLATE, $this->get('wcf.global.locale.unix').'.UTF-8', $this->get('wcf.global.locale.unix'), $this->get('wcf.global.locale.win'));\r
+               setlocale(LC_CTYPE, $this->get('wcf.global.locale.unix').'.UTF-8', $this->get('wcf.global.locale.unix'), $this->get('wcf.global.locale.win'));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/data/language/category/LanguageCategory.class.php b/wcfsetup/install/files/lib/data/language/category/LanguageCategory.class.php
new file mode 100644 (file)
index 0000000..c5127d0
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\language\category;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a language category.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.category
+ * @category   Community Framework
+ */
+class LanguageCategory extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'language_category';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'languageCategoryID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/category/LanguageCategoryAction.class.php b/wcfsetup/install/files/lib/data/language/category/LanguageCategoryAction.class.php
new file mode 100644 (file)
index 0000000..a42b921
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\data\language\category;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes language category-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language.category\r
+ * @category   Community Framework\r
+ */\r
+class LanguageCategoryAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\language\category\LanguageCategoryEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.language.canAddLanguage');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.language.canDeleteLanguage');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.language.canEditLanguage');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/category/LanguageCategoryEditor.class.php b/wcfsetup/install/files/lib/data/language/category/LanguageCategoryEditor.class.php
new file mode 100644 (file)
index 0000000..71c823b
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\language\category;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit language categories.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.category
+ * @category   Community Framework
+ */
+class LanguageCategoryEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\language\category\LanguageCategory';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/category/LanguageCategoryList.class.php b/wcfsetup/install/files/lib/data/language/category/LanguageCategoryList.class.php
new file mode 100644 (file)
index 0000000..d727bf4
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\language\category;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of language categories.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language.category\r
+ * @category   Community Framework\r
+ */\r
+class LanguageCategoryList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\language\category\LanguageCategory';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/item/LanguageItem.class.php b/wcfsetup/install/files/lib/data/language/item/LanguageItem.class.php
new file mode 100644 (file)
index 0000000..d634840
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\language\item;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a language item.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.item
+ * @category   Community Framework
+ */
+class LanguageItem extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'language_item';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'languageItemID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/item/LanguageItemAction.class.php b/wcfsetup/install/files/lib/data/language/item/LanguageItemAction.class.php
new file mode 100644 (file)
index 0000000..b2cad98
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\data\language\item;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes language item-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language.item\r
+ * @category   Community Framework\r
+ */\r
+class LanguageItemAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\language\item\LanguageItemEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.language.canAddLanguage');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.language.canDeleteLanguage');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.language.canEditLanguage');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/item/LanguageItemEditor.class.php b/wcfsetup/install/files/lib/data/language/item/LanguageItemEditor.class.php
new file mode 100644 (file)
index 0000000..af9ce49
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\language\item;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit language items.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.item
+ * @category   Community Framework
+ */
+class LanguageItemEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\language\item\LanguageItem';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/item/LanguageItemList.class.php b/wcfsetup/install/files/lib/data/language/item/LanguageItemList.class.php
new file mode 100644 (file)
index 0000000..b3edd74
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\language\item;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of language items.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.language.item\r
+ * @category   Community Framework\r
+ */\r
+class LanguageItemList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\language\item\LanguageItem';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/language/server/LanguageServer.class.php b/wcfsetup/install/files/lib/data/language/server/LanguageServer.class.php
new file mode 100644 (file)
index 0000000..528ca9b
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\language\server;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a language server.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.server
+ * @category   Community Framework
+ */
+class LanguageServer extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'language_server';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'languageServerID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/language/server/LanguageServerAction.class.php b/wcfsetup/install/files/lib/data/language/server/LanguageServerAction.class.php
new file mode 100644 (file)
index 0000000..3b91603
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+namespace wcf\data\language\server;
+use wcf\data\AbstractDatabaseObjectAction;
+
+/**
+ * Executes language server-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.server
+ * @category   Community Framework
+ */
+class LanguageServerAction extends AbstractDatabaseObjectAction {
+       /**
+        * @see AbstractDatabaseObjectAction::$className
+        */
+       protected $className = 'wcf\data\language\server\LanguageServerEditor';
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsCreate
+        */
+       protected $permissionsCreate = array('admin.language.canAddServer');
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsDelete
+        */
+       protected $permissionsDelete = array('admin.language.canDeleteServer');
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate
+        */
+       protected $permissionsUpdate = array('admin.language.canEditServer');
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/language/server/LanguageServerEditor.class.php b/wcfsetup/install/files/lib/data/language/server/LanguageServerEditor.class.php
new file mode 100644 (file)
index 0000000..abbc7a5
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\language\server;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit language servers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.server
+ * @category   Community Framework
+ */
+class LanguageServerEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\language\server\LanguageServer';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/language/server/LanguageServerList.class.php b/wcfsetup/install/files/lib/data/language/server/LanguageServerList.class.php
new file mode 100644 (file)
index 0000000..2616395
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\language\server;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of language servers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.language.server
+ * @category   Community Framework
+ */
+class LanguageServerList extends DatabaseObjectList {
+       /**
+        * @see DatabaseObjectList::$className
+        */
+       public $className = 'wcf\data\language\server\LanguageServer';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/option/Option.class.php b/wcfsetup/install/files/lib/data/option/Option.class.php
new file mode 100644 (file)
index 0000000..f57f2d3
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+namespace wcf\data\option;
+use wcf\data\DatabaseObject;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Represents an option.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.option
+ * @category   Community Framework
+ */
+class Option extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'option';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'optionID';
+       
+       /**
+        * @see DatabaseObject::handleData()
+        */
+       protected function handleData($data) {
+               parent::handleData($data);
+               
+               // unserialize additional data
+               $this->data['additionalData'] = (empty($data['additionalData']) ? array() : @unserialize($data['additionalData']));
+       }
+       
+       /**
+        * Returns a list of options.
+        * TODO: move to optionlist
+        *
+        * @param       integer         $packageID
+        * @return      array
+        */
+       public static function getOptions($packageID = PACKAGE_ID) {
+               $sql = "SELECT          optionName, optionID
+                       FROM            wcf".WCF_N."_option option_table
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                       ON              (package_dependency.dependency = option_table.packageID)
+                       WHERE           package_dependency.packageID = ?
+                       ORDER BY        package_dependency.priority ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               
+               $optionIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       $optionIDs[$row['optionName']] = $row['optionID'];
+               }
+               
+               $options = array();
+               if (count($optionIDs)) {
+                       // get needed options
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("optionID IN (?)", array($optionIDs));
+                       
+                       $sql = "SELECT          optionName, optionValue, optionType
+                               FROM            wcf".WCF_N."_option
+                               ".$conditions."
+                               ORDER BY        optionName";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               $options[StringUtil::toUpperCase($row['optionName'])] = $row;
+                       }
+               }
+               
+               return $options;
+       }
+       
+       /**
+        * Parses enableOptions.
+        *
+        * @param       string          $optionData
+        * @return      array
+        */
+       public static function parseEnableOptions($optionData) {
+               $disableOptions = $enableOptions = '';
+               
+               if (!empty($optionData)) {
+                       $options = explode(',', $optionData);
+                       
+                       foreach ($options as $item) {
+                               if ($item{0} == '!') {
+                                       if (!empty($disableOptions)) $disableOptions .= ',';
+                                       $disableOptions .= "'".StringUtil::substring($item, 1)."' ";
+                               }
+                               else {
+                                       if (!empty($enableOptions)) $enableOptions .= ',';
+                                       $enableOptions .= "'".$item."' ";
+                               }
+                       }
+               }
+               
+               return array(
+                       'disableOptions' => $disableOptions,
+                       'enableOptions' => $enableOptions
+               );
+       }
+       
+       /**
+        * Returns a list of the available options.
+        *
+        * @return      array
+        */
+       public function parseSelectOptions() {
+               $result = array();
+               $options = explode("\n", StringUtil::trim(StringUtil::unifyNewlines($this->selectOptions)));
+               foreach ($options as $option) {
+                       $key = $value = $option;
+                       if (StringUtil::indexOf($option, ':') !== false) {
+                               $optionData = explode(':', $option);
+                               $key = array_shift($optionData);
+                               $value = implode(':', $optionData);
+                       }
+               
+                       $result[$key] = $value;
+               }
+               
+               return $result;
+       }
+       
+       /**
+        * Returns a list of the enable options.
+        *
+        * @return      array
+        */
+       public function parseMultipleEnableOptions() {
+               $result = array();
+               if (!empty($this->enableOptions)) {
+                       $options = explode("\n", StringUtil::trim(StringUtil::unifyNewlines($this->enableOptions)));
+                       $key = -1;
+                       foreach ($options as $option) {
+                               if (StringUtil::indexOf($option, ':') !== false) {
+                                       $optionData = explode(':', $option);
+                                       $key = array_shift($optionData);
+                                       $value = implode(':', $optionData);
+                               }
+                               else {
+                                       $key++;
+                                       $value = $option;
+                               }
+                       
+                               $result[$key] = $value;
+                       }
+               }
+               
+               return $result;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/option/OptionAction.class.php b/wcfsetup/install/files/lib/data/option/OptionAction.class.php
new file mode 100644 (file)
index 0000000..16b97e2
--- /dev/null
@@ -0,0 +1,68 @@
+<?php\r
+namespace wcf\data\option;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes option-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.\r
+ * @category   Community Framework\r
+ */\r
+class OptionAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\option\OptionEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.system.canEditOption');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.system.canEditOption');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.system.canEditOption');\r
+       \r
+       /**\r
+        * Validates permissions and parameters.\r
+        */\r
+       public function validateImport() {\r
+               parent::validateCreate(); \r
+       }\r
+       \r
+       /**\r
+        * Validates permissions and parameters.\r
+        */\r
+       public function validateUpdateAll() {\r
+               parent::validateCreate(); \r
+       }\r
+       \r
+       /**\r
+        * Imports options.\r
+        */\r
+       public function import() {\r
+               // create data\r
+               call_user_func(array($this->className, 'import'), $this->parameters['data']);\r
+       }\r
+       \r
+       /**\r
+        * Updates the value of all given options.\r
+        */\r
+       public function updateAll() {\r
+               // create data\r
+               call_user_func(array($this->className, 'updateAll'), $this->parameters['data']);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/option/OptionEditor.class.php b/wcfsetup/install/files/lib/data/option/OptionEditor.class.php
new file mode 100644 (file)
index 0000000..1526bf5
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+namespace wcf\data\option;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\EditableCachedObject;
+use wcf\system\cache\CacheHandler;
+use wcf\system\io\File;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Provides functions to edit options.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.option
+ * @category   Community Framework
+ */
+class OptionEditor extends DatabaseObjectEditor implements EditableCachedObject {
+       /**
+        * options cache file name
+        * @var string
+        */
+       const FILENAME = 'options.inc.php';
+       
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\option\Option';
+       
+       /**
+        * Imports the given options.
+        * 
+        * @param       array           $options        name to value
+        */
+       public static function import(array $options) {
+               // get option ids
+               $sql = "SELECT          optionName, optionID
+                       FROM            wcf".WCF_N."_option option_table
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                       ON              (package_dependency.dependency = option_table.packageID)
+                       WHERE           package_dependency.packageID = ?
+                       ORDER BY        package_dependency.priority ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(PACKAGE_ID));
+               $optionIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       $optionIDs[$row['optionName']] = $row['optionID'];
+               }
+               
+               $newOptions = array();
+               foreach ($options as $name => $value) {
+                       if (isset($optionIDs[$name])) {
+                               $newOptions[$optionIDs[$name]] = $value;
+                       }
+               }
+               
+               self::updateAll($newOptions);
+       }
+       
+       /**
+        * Updates the values of the given options.
+        * 
+        * @param       array           $options        id to value
+        */
+       public static function updateAll(array $options) {
+               $sql = "UPDATE  wcf".WCF_N."_option
+                       SET     optionValue = ?
+                       WHERE   optionID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               
+               foreach ($options as $id => $value) {
+                       $statement->execute(array(
+                               $value,
+                               $id
+                       ));
+               }
+       }
+       
+       /**
+        * @see EditableCachedObject::resetCache()
+        */
+       public static function resetCache() {
+               // reset cache
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.option-*.php', true);
+               
+               // reset options.inc.php files
+               $sql = "SELECT  package, packageID, packageDir
+                       FROM    wcf".WCF_N."_package
+                       WHERE   standalone = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(1));
+               while ($row = $statement->fetchArray()) {
+                       if ($row['package'] == 'com.woltlab.wcf') $packageDir = WCF_DIR;
+                       else $packageDir = FileUtil::getRealPath(WCF_DIR.$row['packageDir']);
+                       $filename = FileUtil::addTrailingSlash($packageDir).self::FILENAME;
+                       if (file_exists($filename)) {
+                               if (!@touch($filename, 1)) {
+                                       if (!@unlink($filename)) {
+                                               self::rebuildFile($filename, $row['packageID']);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Rebuilds cached options
+        *
+        * @param       string          filename
+        * @param       integer         $packageID
+        */
+       public static function rebuildFile($filename, $packageID = PACKAGE_ID) {
+               $buffer = '';
+               
+               // file header
+               $buffer .= "<?php\n/**\n* generated at ".gmdate('r')."\n*/\n";
+               
+               // get all options
+               $options = Option::getOptions($packageID);
+               foreach ($options as $optionName => $option) {
+                       $buffer .= "define('".$optionName."', ".(($option['optionType'] == 'boolean' || $option['optionType'] == 'integer') ? intval($option['optionValue']) : "'".addcslashes($option['optionValue'], "'\\")."'").");\n";
+               }
+               unset($options);
+               
+               // file footer
+               $buffer .= "?>";
+               
+               // open file
+               $file = new File($filename);
+               
+               // write buffer
+               $file->write($buffer);
+               unset($buffer);
+               
+               // close file
+               $file->close();
+               @$file->chmod(0777);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/option/OptionList.class.php b/wcfsetup/install/files/lib/data/option/OptionList.class.php
new file mode 100644 (file)
index 0000000..d03e637
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\option;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of options.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\option\Option';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/option/category/OptionCategory.class.php b/wcfsetup/install/files/lib/data/option/category/OptionCategory.class.php
new file mode 100644 (file)
index 0000000..67a5f8f
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\option\category;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents an option category.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.option.category
+ * @category   Community Framework
+ */
+class OptionCategory extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'option_category';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'categoryID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/option/category/OptionCategoryAction.class.php b/wcfsetup/install/files/lib/data/option/category/OptionCategoryAction.class.php
new file mode 100644 (file)
index 0000000..0364647
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\data\option\category;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes option categories-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.option.category\r
+ * @category   Community Framework\r
+ */\r
+class OptionCategoryAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\option\category\OptionCategoryEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.system.canEditOption');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.system.canEditOption');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.system.canEditOption');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/option/category/OptionCategoryEditor.class.php b/wcfsetup/install/files/lib/data/option/category/OptionCategoryEditor.class.php
new file mode 100644 (file)
index 0000000..fe3e1f3
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\option\category;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit option categories.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.option.category
+ * @category   Community Framework
+ */
+class OptionCategoryEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\option\category\OptionCategory';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/option/category/OptionCategoryList.class.php b/wcfsetup/install/files/lib/data/option/category/OptionCategoryList.class.php
new file mode 100644 (file)
index 0000000..e71eee0
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\option\category;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of option categories.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.option.category\r
+ * @category   Community Framework\r
+ */\r
+class OptionCategoryList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\option\category\OptionCategory';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/Package.class.php b/wcfsetup/install/files/lib/data/package/Package.class.php
new file mode 100644 (file)
index 0000000..8289425
--- /dev/null
@@ -0,0 +1,537 @@
+<?php
+namespace wcf\data\package;
+use wcf\data\DatabaseObject;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\io\File;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Represents a package.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package
+ * @category   Community Framework
+ */
+class Package extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'package';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'packageID';
+       
+       /**
+        * installation directory
+        *
+        * @var string
+        */
+       protected $dir = '';
+       
+       /**
+        * Returns true, if this package is required by other packages.
+        *
+        * @return      boolean
+        */
+       public function isRequired() {
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_package_requirement
+                       WHERE   requirement = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->packageID));
+               $row = $statement->fetchArray();
+               
+               return $row['count'];
+       }
+       
+       /**
+        * Returns true if package is a plugin.
+        *
+        * @return      boolean
+        */
+       public function isPlugin() {
+               if ($this->parentPackageID > 0) return true;
+               
+               return false;
+       }
+       
+       /**
+        * Returns the name of this package.
+        *
+        * @return      string
+        */
+       public function getName() {
+               return ($this->instanceName ? $this->instanceName : $this->packageName);
+       }
+       
+       /**
+        * Returns the installation dir of this package.
+        *
+        * @return      string
+        */
+       public function getDir() {
+               return $this->dir;
+       }
+       
+       /**
+        * Sets the installation dir of this package.
+        *
+        * @param       string          $dir
+        */
+       public function setDir($dir) {
+               $this->dir = $dir;
+       }
+       
+       /**
+        * Returns the abbreviation of the package name.
+        *
+        * @param       string          $package
+        * @return      string
+        */
+       public static function getAbbreviation($package) {
+               $array = explode('.', $package);
+               return array_pop($array);
+       }
+       
+       /**
+        * Returns package object for parent package.
+        * 
+        * @return      Package
+        */     
+       public function getParentPackage() {
+               if (!$this->parentPackageID) {
+                       throw new SystemException("Package ".$this->package." does not have a parent package.");
+               }
+               
+               return new Package($this->parentPackageID);
+       }
+       
+       /**
+        * Returns a list of all by this package required packages.
+        * Contains required packages and the requirements of the required packages.
+        *
+        * @return      array
+        */
+       public function getDependencies() {
+               $sql = "SELECT          package.*, CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                       FROM            wcf".WCF_N."_package_dependency package_dependency
+                       LEFT JOIN       wcf".WCF_N."_package package ON (package.packageID = package_dependency.dependency)
+                       WHERE           package_dependency.packageID = ?
+                       ORDER BY        packageName ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->packageID));
+               $packages = array();
+               while ($row = $statement->fetchArray()) {
+                       $packages[] = $row;
+               }
+               
+               return $packages;
+       }
+       
+       /**
+        * Returns a list of all packages that require this package.
+        * Returns packages that require this package and packages that require these packages.
+        *
+        * @return      array
+        */
+       public function getDependentPackages() {
+               $sql = "SELECT          package.*, CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                       FROM            wcf".WCF_N."_package_requirement package_requirement
+                       LEFT JOIN       wcf".WCF_N."_package package ON (package.packageID = package_requirement.packageID)
+                       WHERE           package_requirement.requirement = ?
+                       ORDER BY        packageName ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->packageID));
+               $packages = array();
+               while ($row = $statement->fetchArray()) {
+                       $packages[] = $row;
+               }
+               
+               return $packages;
+       }
+       
+       /**
+        * Returns a list of the requirements of this package.
+        * Contains the content of the <requiredPackages> tag in the package.xml of this package.
+        *
+        * @return      array
+        */
+       public function getRequiredPackages() {
+               $sql = "SELECT          package.*, CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                       FROM            wcf".WCF_N."_package_requirement package_requirement
+                       LEFT JOIN       wcf".WCF_N."_package package ON (package.packageID = package_requirement.requirement)
+                       WHERE           package_requirement.packageID = ?
+                       ORDER BY        packageName ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->packageID));
+               $packages = array();
+               while ($row = $statement->fetchArray()) {
+                       $packages[] = $row;
+               }
+               
+               return $packages;
+       }
+       
+       /**
+        * Checks if a package name is valid.
+        * A valid package name begins with at least one alphanumeric character or the underscore,
+        * followed by a dot, followed by at least one alphanumeric character or the underscore,
+        * and the same again, possibly repeatedly. Example: 'com.woltlab.wcf' (this will be the
+        * official WCF packet naming scheme in the future).
+        * Reminder: The '$packageName' variable being examined here contains the 'name' attribute
+        * of the 'package' tag noted in the 'packages.xml' file delivered inside the respective package.
+        *
+        * @param       string          $packageName
+        * @return      boolean         isValid
+        */
+       public static function isValidPackageName($packageName) {
+               return preg_match('%^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$%', $packageName);
+       }
+       
+       /**
+        * Compares two version number strings.
+        *
+        * @see version_compare()
+        */
+       public static function compareVersion($version1, $version2, $operator = null) {
+               $version1 = self::formatVersionForCompare($version1);
+               $version2 = self::formatVersionForCompare($version2);
+               if ($operator === null) return version_compare($version1, $version2);
+               else return version_compare($version1, $version2, $operator);
+       }
+       
+       /**
+        * Formats a package version string for comparing.
+        *
+        * @param       string          $version
+        * @return      string          formatted version
+        * @see         http://www.php.net/manual/en/function.version-compare.php
+        */
+       private static function formatVersionForCompare($version) {
+               // remove spaces
+               $version = str_replace(' ', '', $version);
+               
+               // correct special version strings
+               $version = str_ireplace('dev', 'dev', $version);
+               $version = str_ireplace('alpha', 'alpha', $version);
+               $version = str_ireplace('beta', 'beta', $version);
+               $version = str_ireplace('RC', 'RC', $version);
+               $version = str_ireplace('pl', 'pl', $version);
+               
+               return $version;
+       }
+       
+       /**
+        * Rebuilds the requirement map for the given package id.
+        *
+        * @param       integer         $packageID
+        */
+       public static function rebuildPackageRequirementMap($packageID) {
+               // delete old entries
+               $sql = "DELETE FROM     wcf".WCF_N."_package_requirement_map
+                       WHERE           packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               
+               // fetch requirements of requirements
+               $requirements = array();
+               $sql = "SELECT          requirement, level
+                       FROM            wcf".WCF_N."_package_requirement_map
+                       WHERE           packageID IN (
+                                               SELECT  requirement
+                                               FROM    wcf".WCF_N."_package_requirement
+                                               WHERE   packageID = ?
+                                       )
+                       ORDER BY        level ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               while ($row = $statement->fetchArray()) {
+                       // use reverse order, highest level epic wins
+                       $requirements[$row['requirement']] = $row['level'];
+               }
+               
+               // insert requirements of requirements
+               if (count($requirements) > 0) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_requirement_map
+                                               (packageID, requirement, level)
+                               VALUES          (?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($requirements as $requirement => $level) {
+                               $statement->execute(array($packageID, $requirement, $level));
+                       }
+               }
+               
+               // fetch requirements
+               $directRequirements = array();
+               $conditions = new PreparedStatementConditionBuilder($sql);
+               $conditions->add("packageID = ?", array($packageID));
+               if (count($requirements)) $conditions->add("requirement NOT IN (?)", array(array_keys($requirements)));
+               
+               $sql = "SELECT  requirement, 
+                               (
+                                       SELECT  MAX(level) AS requirementLevel
+                                       FROM    wcf".WCF_N."_package_requirement_map
+                                       WHERE   packageID = package_requirement.requirement
+                               ) AS requirementLevel
+                       FROM    wcf".WCF_N."_package_requirement package_requirement
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $row['requirementLevel'] = intval($row['requirementLevel']) + 1;
+                       $directRequirements[$row['requirement']] = $row['requirementLevel'];
+               }
+               
+               // insert requirements
+               if (count($directRequirements) > 0) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_requirement_map
+                                               (packageID, requirement, level)
+                               VALUES          (?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($directRequirements as $requirement => $level) {
+                               $statement->execute(array($packageID, $requirement, $level));
+                       }
+               }
+       }
+       
+       /**
+        * Rebuilds the dependencies list for the given package id.
+        *
+        * @param       integer         $packageID
+        */
+       public static function rebuildPackageDependencies($packageID) {
+               // delete old dependencies
+               $sql = "DELETE FROM     wcf".WCF_N."_package_dependency
+                       WHERE           packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               
+               // get all requirements of this package
+               $allRequirements = array($packageID);
+               $sql = "SELECT  requirement
+                       FROM    wcf".WCF_N."_package_requirement_map
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               while ($row = $statement->fetchArray()) {
+                       $allRequirements[] = $row['requirement'];
+               }
+               
+               // find their plugins
+               $requirements = $allRequirements;
+               do {
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("packageID IN (SELECT packageID FROM wcf".WCF_N."_package WHERE parentPackageID IN (?))", array($requirements));
+                       $conditions->add("requirement NOT IN (?)", array($allRequirements));
+                       
+                       $sql = "SELECT  DISTINCT requirement
+                               FROM    wcf".WCF_N."_package_requirement_map
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       $requirements = array();
+                       while ($row = $statement->fetchArray()) {
+                               $requirements[] = $row['requirement'];
+                               $allRequirements[] = $row['requirement'];
+                       }
+               }
+               while (!empty($requirements));
+               
+               // rebuild
+               // select requirements
+               $conditions = new PreparedStatementConditionBuilder(false);
+               $conditions->add("requirement IN (?)", array($allRequirements));
+               
+               $statementParameters = $conditions->getParameters();
+               $statementParameters[] = $packageID;
+               $statementParameters[] = $packageID;
+               
+               $requirements = array();
+               $sql = "SELECT          requirement, level
+                       FROM            wcf".WCF_N."_package_requirement_map
+                       WHERE           ".$conditions."
+                                       AND requirement NOT IN (                -- exclude dependencies to other installations of same package
+                                               SELECT  packageID
+                                               FROM    wcf".WCF_N."_package
+                                               WHERE   package = (
+                                                               SELECT  package
+                                                               FROM    wcf".WCF_N."_package
+                                                               WHERE   packageID = ?
+                                                       )
+                                                       AND packageID <> ?
+                                       )
+                       ORDER BY        level ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($statementParameters);
+               while ($row = $statement->fetchArray()) {
+                       $requirements[$row['requirement']] = $row['level'];
+               }
+               
+               // insert requirements
+               $sql = "INSERT INTO     wcf".WCF_N."_package_dependency
+                                       (packageID, dependency, priority)
+                       VALUES          (?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($requirements as $dependency => $priority) {
+                       $statement->execute(array($packageID, $dependency, $priority));
+               }
+               
+               // select plugins
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("parentPackageID IN (?)", array($allRequirements));
+               
+               $plugins = array();
+               $sql = "SELECT          packageID,
+                                       (
+                                               SELECT  MAX(level) AS level
+                                               FROM    wcf".WCF_N."_package_requirement_map
+                                               WHERE   packageID = package.packageID
+                                       ) AS requirementLevel
+                       FROM            wcf".WCF_N."_package package
+                       ".$conditions."
+                       ORDER BY        requirementLevel ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $row['requirementLevel'] = intval($row['requirementLevel']) + 1;
+                       $plugins[$row['packageID']] = $row['requirementLevel'];
+               }
+               
+               // insert plugins
+               $sql = "INSERT INTO     wcf".WCF_N."_package_dependency
+                                       (packageID, dependency, priority)
+                       VALUES          (?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($plugins as $dependency => $priority) {
+                       $statement->execute(array($packageID, $dependency, $priority));
+               }
+               
+               // in some cases (e.g. if rebuilding dependencies for WCF) it is very likely, that
+               // there is always a dependency on the package itself. This was avoided in the past
+               // by using INSERT IGNORE, thus we have to validate if a self-depdendency already
+               // exist before inserting.
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_package_dependency
+                       WHERE   packageID = ?
+                               AND dependency = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $packageID,
+                       $packageID
+               ));
+               $row = $statement->fetchArray();
+               
+               // no dependencies on the package itself exists yet
+               if (!$row['count']) {
+                       // self insert
+                       $sql = "SELECT  (MAX(priority) + 1) AS priority
+                               FROM    wcf".WCF_N."_package_dependency";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute();
+                       
+                       $row = $statement->fetchArray();
+                       if (!$row || !$row['priority']) {
+                               $row['priority'] = 0;
+                       }
+                       
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_dependency
+                                               (packageID, dependency, priority)
+                               VALUES          (?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($packageID, $packageID, $row['priority']));
+               }
+       }
+       
+       /**
+        * Writes the config.inc.php for a standalone application.
+        *
+        * @param       integer         $packageID
+        */
+       public static function writeConfigFile($packageID) {
+               $package = new Package($packageID);
+               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$package->packageDir));
+               $file = new File($packageDir.\wcf\system\package\PackageInstallationDispatcher::CONFIG_FILE);
+               $file->write("<?php\n");
+               $currentPrefix = strtoupper(Package::getAbbreviation($package->package));
+               
+               // get dependencies (only standalones)
+               $sql = "SELECT          package.*, IF(package.packageID = ?, 1, 0) AS sortOrder
+                       FROM            wcf".WCF_N."_package_dependency package_dependency
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = package_dependency.dependency)
+                       WHERE           package_dependency.packageID = ?
+                                       AND package.standalone = 1
+                                       AND package.packageDir <> ''
+                       ORDER BY        sortOrder DESC,
+                                       package_dependency.priority DESC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $packageID,
+                       $packageID
+               ));
+               while ($row = $statement->fetchArray()) {
+                       $dependency = new Package(null, $row);
+                       $dependencyDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$dependency->packageDir));
+                       $prefix = strtoupper(Package::getAbbreviation($dependency->package));
+                       
+                       $file->write("// ".$dependency->packageID." vars\n");
+                       $file->write("// ".strtolower($prefix)."\n");
+                       $file->write("if (!defined('".$prefix."_DIR')) define('".$prefix."_DIR', ".($dependency->packageID == $package->packageID ? "dirname(__FILE__).'/'" : "'".$dependencyDir."'").");\n");
+                       $file->write("if (!defined('RELATIVE_".$prefix."_DIR')) define('RELATIVE_".$prefix."_DIR', ".($dependency->packageID == $package->packageID ? "''" : "RELATIVE_".$currentPrefix."_DIR.'".FileUtil::getRelativePath($packageDir, $dependencyDir)."'").");\n");
+                       $file->write("if (!defined('".$prefix."_N')) define('".$prefix."_N', '".WCF_N."_".$dependency->instanceNo."');\n");
+                       $file->write("\$packageDirs[] = ".$prefix."_DIR;\n");
+                       $file->write("\n");
+               }
+               
+               // write general information
+               $file->write("// general info\n");
+               $file->write("if (!defined('RELATIVE_WCF_DIR')) define('RELATIVE_WCF_DIR', RELATIVE_".$currentPrefix."_DIR.'".FileUtil::getRelativePath($packageDir, WCF_DIR)."');\n");
+               $file->write("if (!defined('PACKAGE_ID')) define('PACKAGE_ID', ".$package->packageID.");\n");
+               $file->write("if (!defined('PACKAGE_NAME')) define('PACKAGE_NAME', '".str_replace("'", "\'", $package->getName())."');\n");
+               $file->write("if (!defined('PACKAGE_VERSION')) define('PACKAGE_VERSION', '".$package->packageVersion."');\n");
+               
+               // write end
+               $file->write("?>");
+               $file->close();
+       }
+       
+       /**
+        * Searches all dependent packages for the given package id
+        * and rebuild their package dependencies list.
+        *
+        * @param       integer         $packageID
+        */
+       public static function rebuildParentPackageDependencies($packageID) {
+               $sql = "SELECT          packageID, MAX(priority) AS maxPriority
+                       FROM            wcf".WCF_N."_package_dependency
+                       WHERE           packageID IN (
+                                               SELECT  packageID
+                                               FROM    wcf".WCF_N."_package_dependency
+                                               WHERE   dependency = ?
+                                                       AND packageID <> ?
+                                               UNION
+                                               SELECT  parentPackageID
+                                               FROM    wcf".WCF_N."_package
+                                               WHERE   packageID = ?
+                                       )
+                       GROUP BY        packageID
+                       ORDER BY        maxPriority ASC, packageID DESC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $packageID,
+                       $packageID,
+                       $packageID
+               ));
+               while ($row = $statement->fetchArray()) {
+                       self::rebuildPackageDependencies($row['packageID']);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/package/PackageAction.class.php b/wcfsetup/install/files/lib/data/package/PackageAction.class.php
new file mode 100644 (file)
index 0000000..fdccac1
--- /dev/null
@@ -0,0 +1,36 @@
+<?php\r
+namespace wcf\data\package;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes package-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package\r
+ * @category   Community Framework\r
+ */\r
+class PackageAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\package\PackageEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.system.package.canInstallPackage');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.system.package.canUninstallPackage');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.system.package.canUpdatePackage');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/PackageEditor.class.php b/wcfsetup/install/files/lib/data/package/PackageEditor.class.php
new file mode 100644 (file)
index 0000000..b65bcf0
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\package;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit packages.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package
+ * @category   Community Framework
+ */
+class PackageEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\package\Package';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/PackageList.class.php b/wcfsetup/install/files/lib/data/package/PackageList.class.php
new file mode 100644 (file)
index 0000000..0353960
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of packages.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package\r
+ * @category   Community Framework\r
+ */\r
+class PackageList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\package\Package';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..b63a089
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+namespace wcf\data\package\installation\plugin;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+
+/**
+ * Represents a package installation plugin.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.installation.plugin
+ * @category   Community Framework
+ */
+class PackageInstallationPlugin extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'package_installation_plugin';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'pluginName';
+       
+       /**
+        * @see wcf\data\DatabaseObject::$databaseTableIndexIsIdentity
+        */     
+       protected static $databaseTableIndexIsIdentity = false;
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginAction.class.php b/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginAction.class.php
new file mode 100644 (file)
index 0000000..98408cb
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\installation\plugin;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes package installation plugin-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.installation.plugin\r
+ * @category   Community Framework\r
+ */\r
+class PackageInstallationPluginAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\package\installation\plugin\PackageInstallationPluginEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginEditor.class.php b/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginEditor.class.php
new file mode 100644 (file)
index 0000000..d0020fd
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+namespace wcf\data\package\installation\plugin;
+use wcf\data\DatabaseObjectEditor;
+use wcf\system\WCF;
+
+/**
+ * Provides functions to edit package installation plugins.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.installation.plugin
+ * @category   Community Framework
+ */
+class PackageInstallationPluginEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\package\installation\plugin\PackageInstallationPlugin';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginList.class.php b/wcfsetup/install/files/lib/data/package/installation/plugin/PackageInstallationPluginList.class.php
new file mode 100644 (file)
index 0000000..2e62722
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\installation\plugin;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of package installation plugins.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.installation.plugin\r
+ * @category   Community Framework\r
+ */\r
+class PackageInstallationPluginList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\package\installation\plugin\PackageInstallationPluginObj';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueue.class.php b/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueue.class.php
new file mode 100644 (file)
index 0000000..1901806
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+namespace wcf\data\package\installation\queue;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+
+/**
+ * Represents a package installation queue.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.installation.queue
+ * @category   Community Framework
+ */
+class PackageInstallationQueue extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'package_installation_queue';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'queueID';
+       
+       /**
+        * Returns a new process number for package installation queue.
+        * 
+        * @return      integer
+        */
+       public static function getNewProcessNo() {
+               $sql = "SELECT  MAX(processNo) AS processNo
+                       FROM    wcf".WCF_N."_package_installation_queue";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               $row = $statement->fetchArray();
+               return intval($row['processNo']) + 1;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueAction.class.php b/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueAction.class.php
new file mode 100644 (file)
index 0000000..b830842
--- /dev/null
@@ -0,0 +1,57 @@
+<?php\r
+namespace wcf\data\package\installation\queue;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\data\package\Package;\r
+use wcf\system\exception\ValidateActionException;\r
+\r
+/**\r
+ * Executes package installation queue-related actions.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.installation.queue\r
+ * @category   Community Framework\r
+ */\r
+class PackageInstallationQueueAction extends AbstractDatabaseObjectAction {\r
+       protected $package = null;\r
+       protected $packageID = 0;\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\package\installation\queue\PackageInstallationQueueEditor';\r
+       \r
+       public function validatePrepareQueue() {\r
+               if (isset($this->parameters['packageID'])) $this->packageID = intval($this->parameters['packageID']);\r
+               \r
+               $this->package = new Package($packageID);\r
+               if (!$this->package->packageID) {\r
+                       throw new ValidateActionException('Invalid package id');\r
+               }\r
+               \r
+               if (!isset($this->parameters['action']) || !in_array($this->parameters['action'], array('install', 'update', 'uninstall', 'rollback'))) {\r
+                       throw new ValidateActionException('Invalid or missing action');\r
+               }\r
+       }\r
+       \r
+       public function prepareQueue() {\r
+               $processNo = PackageInstallationQueue::getNewProcessNo();\r
+               \r
+               $queue = PackageInstallationQueueEditor::create(array(\r
+                       'processNo' => $processNo,\r
+                       'userID' => WCF::getUser()->userID,\r
+                       'package' => $this->package->package,\r
+                       'packageName' => $this->package->packageName,\r
+                       'packageID' => $this->package->packageID,\r
+                       'action' => $this->parameters['action'],\r
+                       'installationType' => 'other'\r
+               ));\r
+               \r
+               return array(\r
+                       'queueID' => $queue->queueID\r
+               );\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueEditor.class.php b/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueEditor.class.php
new file mode 100644 (file)
index 0000000..4411d56
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\package\installation\queue;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit package installation queues.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.installation.queue
+ * @category   Community Framework
+ */
+class PackageInstallationQueueEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\package\installation\queue\PackageInstallationQueue';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueList.class.php b/wcfsetup/install/files/lib/data/package/installation/queue/PackageInstallationQueueList.class.php
new file mode 100644 (file)
index 0000000..04ce5f7
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\installation\queue;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of package installation queues.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.installation.queue\r
+ * @category   Community Framework\r
+ */\r
+class PackageInstallationQueueList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\package\installation\queue\PackageInstallationQueue';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/PackageUpdate.class.php b/wcfsetup/install/files/lib/data/package/update/PackageUpdate.class.php
new file mode 100644 (file)
index 0000000..f9bb02c
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\package\update;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a package update.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.update
+ * @category   Community Framework
+ */
+class PackageUpdate extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'package_update';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'packageUpdateID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/PackageUpdateAction.class.php b/wcfsetup/install/files/lib/data/package/update/PackageUpdateAction.class.php
new file mode 100644 (file)
index 0000000..f7cb22c
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\update;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes package update-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.update\r
+ * @category   Community Framework\r
+ */\r
+class PackageUpdateAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\package\update\PackageUpdateEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/PackageUpdateEditor.class.php b/wcfsetup/install/files/lib/data/package/update/PackageUpdateEditor.class.php
new file mode 100644 (file)
index 0000000..8984ab8
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\package\update;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit package updates.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.update
+ * @category   Community Framework
+ */
+class PackageUpdateEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\package\update\PackageUpdate';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/PackageUpdateList.class.php b/wcfsetup/install/files/lib/data/package/update/PackageUpdateList.class.php
new file mode 100644 (file)
index 0000000..cb71b72
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\update;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of package updates.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.update\r
+ * @category   Community Framework\r
+ */\r
+class PackageUpdateList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\package\update\PackageUpdate';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php
new file mode 100644 (file)
index 0000000..465e1f4
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+namespace wcf\data\package\update\server;
+use wcf\data\DatabaseObject;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * Contains business logic related to handling of package update servers.
+ *
+ * @author     Siegfried Schweizer
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.update.server
+ * @category   Community Framework
+ */
+class PackageUpdateServer extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'package_update_server';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'packageUpdateServerID';
+       
+       /**
+        * Returns all active update package servers sorted by hostname.
+        * 
+        * @param       array           $packageUpdateServerIDs
+        * @return      array           $servers
+        */
+       public static function getActiveUpdateServers(array $packageUpdateServerIDs = array()) {
+               $servers = array();
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("disabled = ?", array(0));
+               if (count($packageUpdateServerIDs)) $conditions->add("packageUpdateServerID IN (?)", array($packageUpdateServerIDs));
+               
+               $sql = "SELECT          * 
+                       FROM            wcf".WCF_N."_package_update_server
+                       ".$conditions."
+                       ORDER BY        serverURL ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $servers[$row['packageUpdateServerID']] = new PackageUpdateServer(null, $row);
+               }
+               
+               return $servers;
+       }
+       
+       /**
+        * Validates a server url.
+        *
+        * @param       string          $serverURL
+        * @return      boolean         validates
+        */
+       public static function isValidServerURL($serverURL) {
+               if (trim($serverURL)) {
+                       if (!$parsedURL = @parse_url($serverURL))
+                               return false;
+                       if (!isset($parsedURL['scheme']) || $parsedURL['scheme'] != 'http')
+                               return false;
+                       if (!isset($parsedURL['host']))
+                               return false;
+                       return true;
+               }
+               else {
+                       return false;
+               }
+       }
+       
+       /**
+        * Gets stored auth data of this update server.
+        *
+        * @return      array           $authData
+        */
+       public function getAuthData() {
+               $authData = array();
+               // database data
+               if ($this->loginUsername != '' && $this->loginPassword != '') {
+                       $authData = array(
+                               'authType' => 'Basic',
+                               'loginUsername' => $this->loginUsername,
+                               'loginPassword' => $this->loginPassword
+                       );
+               }
+               
+               // session data
+               $packageUpdateAuthData = WCF::getSession()->getVar('packageUpdateAuthData');
+               if ($packageUpdateAuthData !== null && isset($packageUpdateAuthData[$this->packageUpdateServerID])) {
+                       $authData = $packageUpdateAuthData[$this->packageUpdateServerID];
+               }
+               
+               return $authData;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerAction.class.php b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerAction.class.php
new file mode 100644 (file)
index 0000000..b374abc
--- /dev/null
@@ -0,0 +1,54 @@
+<?php\r
+namespace wcf\data\package\update\server;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes package update server-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.update.server\r
+ * @category   Community Framework\r
+ */\r
+class PackageUpdateServerAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\package\update\server\PackageUpdateServerEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.system.package.canEditServer');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.system.package.canEditServer');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.system.package.canEditServer');\r
+       \r
+       /**\r
+        * Validates permissions and parameters\r
+        */\r
+       public function validateToggle() {\r
+               parent::validateUpdate();\r
+       }\r
+       \r
+       /**\r
+        * Toggles status.\r
+        */\r
+       public function toggle() {\r
+               foreach ($this->objects as $server) {\r
+                       $server->update(array('disabled' => ($server->disabled) ? 0 : 1));\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerEditor.class.php b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerEditor.class.php
new file mode 100644 (file)
index 0000000..6530cb0
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+namespace wcf\data\package\update\server;
+use wcf\data\DatabaseObjectEditor;
+use wcf\system\WCF;
+
+/**
+ * Contains business logic related to handling of package update servers.
+ *
+ * @author     Siegfried Schweizer
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.update.server
+ * @category   Community Framework
+ */
+class PackageUpdateServerEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\package\update\server\PackageUpdateServer';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerList.class.php b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServerList.class.php
new file mode 100644 (file)
index 0000000..320f171
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\data\package\update\server;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of package update servers.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.update.server\r
+ * @category   Community Framework\r
+ */\r
+class PackageUpdateServerList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\package\update\server\PackageUpdateServer';\r
+       \r
+       /**\r
+        * @see DatabaseObjectList::readObjects()\r
+        */\r
+       public function readObjects() {\r
+               if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';\r
+               $this->sqlSelects .= "(SELECT COUNT(*) FROM wcf".WCF_N."_package_update WHERE packageUpdateServerID = ".$this->getDatabaseTableAlias().".packageUpdateServerID) AS packages";\r
+               \r
+               parent::readObjects();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersion.class.php b/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersion.class.php
new file mode 100644 (file)
index 0000000..b76f278
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\package\update\version;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a package update version.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.update.version
+ * @category   Community Framework
+ */
+class PackageUpdateVersion extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'package_update_version';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'packageUpdateVersionID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionAction.class.php b/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionAction.class.php
new file mode 100644 (file)
index 0000000..0e05ee2
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\update\version;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes package update version-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.update.version\r
+ * @category   Community Framework\r
+ */\r
+class PackageUpdateVersionAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\package\update\version\PackageUpdateVersionEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionEditor.class.php b/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionEditor.class.php
new file mode 100644 (file)
index 0000000..261ddf5
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\package\update\version;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit package update versions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.package.update.version
+ * @category   Community Framework
+ */
+class PackageUpdateVersionEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\package\update\version\PackageUpdateVersion';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionList.class.php b/wcfsetup/install/files/lib/data/package/update/version/PackageUpdateVersionList.class.php
new file mode 100644 (file)
index 0000000..113f31c
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\package\update\version;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of package update versions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.package.update.version\r
+ * @category   Community Framework\r
+ */\r
+class PackageUpdateVersionList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\package\update\version\PackageUpdateVersion';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/location/Location.class.php b/wcfsetup/install/files/lib/data/page/location/Location.class.php
new file mode 100644 (file)
index 0000000..b2671f0
--- /dev/null
@@ -0,0 +1,34 @@
+<?php\r
+/**\r
+ * Any page location class should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.page.location\r
+ * @category   Community Framework\r
+ */\r
+interface Location {\r
+       /**\r
+        * Caches the information of a page location.\r
+        * \r
+        * @param       array           $location\r
+        * @param       string          $requestURI\r
+        * @param       string          $requestMethod\r
+        * @param       array           $match\r
+        */\r
+       public function cache($location, $requestURI, $requestMethod, $match);\r
+       \r
+       /**\r
+        * Returns the information of a page location.\r
+        * \r
+        * @param       array           $location\r
+        * @param       string          $requestURI\r
+        * @param       string          $requestMethod\r
+        * @param       array           $match\r
+        * @return      string\r
+        */\r
+       public function get($location, $requestURI, $requestMethod, $match);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/location/PageLocation.class.php b/wcfsetup/install/files/lib/data/page/location/PageLocation.class.php
new file mode 100644 (file)
index 0000000..7774675
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\page\location;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a page location.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.page.location
+ * @category   Community Framework
+ */
+class PageLocation extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'page_location';
+       
+       /**
+        * @see DatabaseObject::$databaseIndexName
+        */
+       protected static $databaseIndexName = 'locationID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/location/PageLocationAction.class.php b/wcfsetup/install/files/lib/data/page/location/PageLocationAction.class.php
new file mode 100644 (file)
index 0000000..6e7edf2
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\page\location;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes page location-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.page.location\r
+ * @category   Community Framework\r
+ */\r
+class PageLocationAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\page\location\PageLocationEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/location/PageLocationEditor.class.php b/wcfsetup/install/files/lib/data/page/location/PageLocationEditor.class.php
new file mode 100644 (file)
index 0000000..a03bf71
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\page\location;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit page locations.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.page.location
+ * @category   Community Framework
+ */
+class PageLocationEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\page\location\PageLocation';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/location/PageLocationList.class.php b/wcfsetup/install/files/lib/data/page/location/PageLocationList.class.php
new file mode 100644 (file)
index 0000000..8117533
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\page\location;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of page locations.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.page.location\r
+ * @category   Community Framework\r
+ */\r
+class PageLocationList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\page\location\PageLocation';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItem.class.php b/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItem.class.php
new file mode 100644 (file)
index 0000000..83a79ef
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+namespace wcf\data\page\menu\item;
+use wcf\data\DatabaseObject;
+use wcf\system\exception\SystemException;
+use wcf\system\menu\page\DefaultPageMenuItemProvider;
+use wcf\system\menu\TreeMenuItem;
+use wcf\system\request\LinkHandler;
+use wcf\util\ClassUtil;
+
+/**
+ * Represents an page menu item.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.page.menu.item
+ * @category   Community Framework
+ */
+class PageMenuItem extends DatabaseObject implements TreeMenuItem {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'page_menu_item';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'menuItemID';
+       
+       /**
+        * item provider for this page menu item
+        * @var wcf\system\menu\page\PageMenuItemProvider
+        */
+       protected $provider = null;
+       
+       /**
+        * Returns the item provider for this page menu item.
+        * 
+        * @return wcf\system\menu\page\PageMenuItemProvider
+        */
+       public function getProvider() {
+               if ($this->provider === null) {
+                       if ($this->className) {
+                               if (!class_exists($this->className)) {
+                                       throw new SystemException("Unable to find class '".$this->className."'");
+                               }
+                               if (!ClassUtil::isInstanceOf($this->className, 'wcf\system\menu\page\PageMenuItemProvider')) {
+                                       throw new SystemException($this->className." should implement wcf\system\menu\page\PageMenuItemProvider");
+                               }
+                               
+                               $this->provider = new $this->className();
+                       }
+                       else {
+                               $this->provider = new DefaultPageMenuItemProvider();
+                       }
+               }
+               
+               return $this->provider;
+       }
+       
+       /**
+        * @see TreeMenuItem::getLink()
+        */
+       public function getLink() {
+               return LinkHandler::getInstance()->getLink($this->menuItemLink);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemAction.class.php b/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemAction.class.php
new file mode 100644 (file)
index 0000000..0c12233
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\page\menu\item;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes page menu item-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.page.menu.item\r
+ * @category   Community Framework\r
+ */\r
+class PageMenuItemAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\page\menu\item\PageMenuItemEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemEditor.class.php b/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemEditor.class.php
new file mode 100644 (file)
index 0000000..0b139b2
--- /dev/null
@@ -0,0 +1,189 @@
+<?php
+namespace wcf\data\page\menu\item;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\EditableCachedObject;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * Provides functions to edit page menu items.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.page.menu.item
+ * @category   Community Framework
+ */
+class PageMenuItemEditor extends DatabaseObjectEditor implements EditableCachedObject {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\page\menu\item\PageMenuItem';
+       
+       /**
+        * @see EditableObject::create()
+        * 
+        * @todo        Handle language id and create related language item
+        */
+       public static function create(array $parameters = array()) {
+               // calculate show order
+               $parameters['showOrder'] = self::getShowOrder($parameters['showOrder'], $parameters['menuPosition']);
+               
+               return parent::create($parameters);
+       }
+       
+       /**
+        * @see EditableObject::update()
+        * 
+        * @todo        Handle language id and update related language item
+        */
+       public function update(array $parameters = array()) {
+               if (isset($parameters['menuPosition']) && isset($parameters['showOrder'])) {
+                       $this->updateShowOrder($parameters['showOrder'], $parameters['menuPosition']);
+               }
+               
+               parent::update($parameters);
+       }
+       
+       /**
+        * @see EditableObject::delete()
+        */
+       public function delete() {
+               // update show order
+               $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                       SET     showOrder = showOrder - 1
+                       WHERE   showOrder >= ?
+                               AND menuPosition = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->showOrder,
+                       $this->menuPosition
+               ));
+               
+               parent::delete();
+       }
+       
+       /**
+        * Updates the positions of a page menu item directly.
+        *
+        * @param       integer         $menuItemID
+        * @param       string          $menuPosition
+        * @param       integer         $showOrder
+        */
+       public static function setShowOrder($menuItemID, $menuPosition = 'header', $showOrder = 1) {
+               // Update
+               $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                       SET     showOrder = ?,
+                               menuPosition = ?
+                       WHERE   menuItemID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $showOrder,
+                       $menuPosition,
+                       $menuItemID
+               ));
+       }
+       
+       /**
+        * Updates show order for current menu item.
+        * 
+        * @param       integer         $showOrder
+        * @param       string          $menuPosition
+        */
+       protected function updateShowOrder($showOrder, $menuPosition) {
+               if ($menuPosition == $this->menuPosition) {
+                       if ($this->showOrder != $showOrder) {
+                               if ($showOrder < $this->showOrder) {
+                                       $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                                               SET     showOrder = showOrder + 1
+                                               WHERE   showOrder >= ?
+                                                       AND showOrder < ?
+                                                       AND menuPosition = ?";
+                                       $statement = WCF::getDB()->prepareStatement($sql);
+                                       $statement->execute(array(
+                                               $showOrder,
+                                               $this->showOrder,
+                                               $menuPosition
+                                       ));
+                               }
+                               else if ($showOrder > $this->showOrder) {
+                                       $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                                               SET     showOrder = showOrder - 1
+                                               WHERE   showOrder <= ?
+                                                       AND showOrder > ?
+                                                       AND menuPosition = ?";
+                                       $statement = WCF::getDB()->prepareStatement($sql);
+                                       $statement->execute(array(
+                                               $showOrder,
+                                               $this->showOrder,
+                                               $menuPosition
+                                       ));
+                               }
+                       }
+               }
+               else {
+                       $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                               SET     showOrder = showOrder - 1
+                               WHERE   showOrder >= ?
+                                       AND menuPosition = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(
+                               $this->showOrder,
+                               $this->menuPosition
+                       ));
+                               
+                       $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                               SET     showOrder = showOrder + 1
+                               WHERE   showOrder >= ?
+                                       AND menuPosition = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(
+                               $showOrder,
+                               $menuPosition
+                       ));
+               }
+       }
+       
+       /**
+        * Returns show order for a new menu item.
+        * 
+        * @param       integer         $showOrder
+        * @param       string          $menuPosition
+        * @return      integer
+        */
+       protected static function getShowOrder($showOrder, $menuPosition) {
+               if ($showOrder == 0) {
+                       // get next number in row
+                       $sql = "SELECT  MAX(showOrder) AS showOrder
+                               FROM    wcf".WCF_N."_page_menu_item
+                               WHERE   menuPosition = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($menuPosition));
+                       $row = $statement->fetchArray();
+                       if (!empty($row)) $showOrder = intval($row['showOrder']) + 1;
+                       else $showOrder = 1;
+               }
+               else {
+                       $sql = "UPDATE  wcf".WCF_N."_page_menu_item
+                               SET     showOrder = showOrder + 1
+                               WHERE   showOrder >= ?
+                                       AND menuPosition = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(
+                               $showOrder,
+                               $menuPosition
+                       ));
+               }
+               
+               return $showOrder;
+       }
+       
+       /**
+        * Clears the page menu cache.
+        */
+       public static function resetCache() {
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.pageMenu-*.php');
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemList.class.php b/wcfsetup/install/files/lib/data/page/menu/item/PageMenuItemList.class.php
new file mode 100644 (file)
index 0000000..4bbdc38
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\page\menu\item;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of page menu items.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.page.menu.item\r
+ * @category   Community Framework\r
+ */\r
+class PageMenuItemList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\page\menu\item\PageMenuItem';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/search/Search.class.php b/wcfsetup/install/files/lib/data/search/Search.class.php
new file mode 100644 (file)
index 0000000..4c3a7b3
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\search;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a search.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.search
+ * @category   Community Framework
+ */
+class Search extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'search';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'searchID';  
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/search/SearchAction.class.php b/wcfsetup/install/files/lib/data/search/SearchAction.class.php
new file mode 100644 (file)
index 0000000..c792b3e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\search;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes search-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.search\r
+ * @category   Community Framework\r
+ */\r
+class SearchAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\search\SearchEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/search/SearchEditor.class.php b/wcfsetup/install/files/lib/data/search/SearchEditor.class.php
new file mode 100644 (file)
index 0000000..8b067b6
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\search;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit searches.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.search
+ * @category   Community Framework
+ */
+class SearchEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\search\Search';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/search/SearchList.class.php b/wcfsetup/install/files/lib/data/search/SearchList.class.php
new file mode 100644 (file)
index 0000000..4cd94bc
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\search;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of searches.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.search\r
+ * @category   Community Framework\r
+ */\r
+class SearchList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\search\Search';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/session/Session.class.php b/wcfsetup/install/files/lib/data/session/Session.class.php
new file mode 100644 (file)
index 0000000..a10b2ec
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\session;
+use wcf\data\acp\session\ACPSession;
+
+/**
+ * Represents a session.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.session
+ * @category   Community Framework
+ */
+class Session extends ACPSession {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'session';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'sessionID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/session/SessionAction.class.php b/wcfsetup/install/files/lib/data/session/SessionAction.class.php
new file mode 100644 (file)
index 0000000..3eadd43
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\session;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes session-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.session\r
+ * @category   Community Framework\r
+ */\r
+class SessionAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\session\SessionEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/session/SessionEditor.class.php b/wcfsetup/install/files/lib/data/session/SessionEditor.class.php
new file mode 100644 (file)
index 0000000..4444cfe
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\session;
+use wcf\data\acp\session\ACPSessionEditor;
+
+/**
+ * Provides functions to edit sessions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.session
+ * @category   Community Framework
+ */
+class SessionEditor extends ACPSessionEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\session\Session';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/session/SessionList.class.php b/wcfsetup/install/files/lib/data/session/SessionList.class.php
new file mode 100644 (file)
index 0000000..5ecee40
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\session;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of sessions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.session\r
+ * @category   Community Framework\r
+ */\r
+class SessionList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\session\Session';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/session/data/SessionData.class.php b/wcfsetup/install/files/lib/data/session/data/SessionData.class.php
new file mode 100644 (file)
index 0000000..6dc7c8a
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\session\data;
+use wcf\data\acp\session\data\ACPSessionData;
+
+/**
+ * Represents session data.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.session.data
+ * @category   Community Framework
+ */
+class SessionData extends ACPSessionData {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'session_data';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'sessionID';
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/session/data/SessionDataAction.class.php b/wcfsetup/install/files/lib/data/session/data/SessionDataAction.class.php
new file mode 100644 (file)
index 0000000..7c258c4
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\session\data;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes session data-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.session.data\r
+ * @category   Community Framework\r
+ */\r
+class SessionDataAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\session\data\SessionDataEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/session/data/SessionDataEditor.class.php b/wcfsetup/install/files/lib/data/session/data/SessionDataEditor.class.php
new file mode 100644 (file)
index 0000000..4b27e59
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\session\data;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit session data.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.session.data
+ * @category   Community Framework
+ */
+class SessionDataEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\session\data\SessionData';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/session/data/SessionDataList.class.php b/wcfsetup/install/files/lib/data/session/data/SessionDataList.class.php
new file mode 100644 (file)
index 0000000..6189dbe
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\session\data;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of session data.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.session.data\r
+ * @category   Community Framework\r
+ */\r
+class SessionDataList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\session\data\SessionData';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/spider/Spider.class.php b/wcfsetup/install/files/lib/data/spider/Spider.class.php
new file mode 100644 (file)
index 0000000..9d4a1dc
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\spider;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a spider.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.spider
+ * @category   Community Framework
+ */
+class Spider extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'spider';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'spiderID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/spider/SpiderAction.class.php b/wcfsetup/install/files/lib/data/spider/SpiderAction.class.php
new file mode 100644 (file)
index 0000000..e7d5dca
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\spider;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes spider-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.spider\r
+ * @category   Community Framework\r
+ */\r
+class SpiderAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\spider\SpiderEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/spider/SpiderEditor.class.php b/wcfsetup/install/files/lib/data/spider/SpiderEditor.class.php
new file mode 100644 (file)
index 0000000..e32ce3a
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\spider;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit spiders.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.spider
+ * @category   Community Framework
+ */
+class SpiderEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\spider\Spider';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/spider/SpiderList.class.php b/wcfsetup/install/files/lib/data/spider/SpiderList.class.php
new file mode 100644 (file)
index 0000000..a11e381
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\spider;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of spiders.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.spider\r
+ * @category   Community Framework\r
+ */\r
+class SpiderList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\spider\Spider';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/style/ActiveStyle.class.php b/wcfsetup/install/files/lib/data/style/ActiveStyle.class.php
new file mode 100644 (file)
index 0000000..8bb4a42
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+namespace wcf\data\style;
+use wcf\data\DatabaseObjectDecorator;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\StyleUtil;
+
+/**
+ * Represents the active user style.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.style
+ * @category   Community Framework
+ */
+class ActiveStyle extends DatabaseObjectDecorator {
+       /**
+        * @see DatabaseObjectDecorator::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\style\Style';
+       
+       /**
+        * icon cache
+        * @var array
+        */
+       protected $iconCache = array();
+       
+       /**
+        * Creates a new ActiveStyle object.
+        * 
+        * @param       Style           $object
+        */
+       public function __construct(Style $object) {
+               parent::__construct($object);
+               
+               // calculate page logo path
+               if (!empty($this->object->data['variables']['page.logo.image']) && !FileUtil::isURL($this->object->data['variables']['page.logo.image']) && StringUtil::substring($this->object->data['variables']['page.logo.image'], 0, 1) !== '/') {
+                       $this->object->data['variables']['page.logo.image'] = RELATIVE_WCF_DIR . $this->object->data['variables']['page.logo.image'];
+               }
+               
+               // load icon cache
+               WCF::getCache()->addResource('icon-'.PACKAGE_ID.'-'.$this->styleID, WCF_DIR.'cache/cache.icon-'.PACKAGE_ID.'-'.$this->styleID.'.php', 'wcf\system\cache\CacheBuilderIcon');
+               $this->iconCache = WCF::getCache()->get('icon-'.PACKAGE_ID.'-'.$this->styleID);
+       }
+       
+       /**
+        * Returns the value of a style variable.
+        * 
+        * @param       string          $name
+        * @return      string          value
+        */
+       public function getVariable($name) {
+               if (isset($this->object->data['variables'][$name])) return $this->object->data['variables'][$name];
+               return '';
+       }
+       
+       /**
+        * Returns the path of an icon.
+        * 
+        * @param       string          $iconName
+        * @return      string
+        */
+       public function getIconPath($iconName) {
+               if (isset($this->iconCache[$iconName])) return $this->iconCache[$iconName];
+               return RELATIVE_WCF_DIR.'icon/'.$iconName;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/style/Style.class.php b/wcfsetup/install/files/lib/data/style/Style.class.php
new file mode 100644 (file)
index 0000000..c1c6f36
--- /dev/null
@@ -0,0 +1,56 @@
+<?php\r
+namespace wcf\data\style;\r
+use wcf\data\DatabaseObject;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Represents a style.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.style\r
+ * @category   Community Framework\r
+ */\r
+class Style extends DatabaseObject {\r
+       /**\r
+        * @see DatabaseObject::$databaseTableName\r
+        */\r
+       protected static $databaseTableName = 'style';\r
+       \r
+       /**\r
+        * @see DatabaseObject::$databaseTableIndexName\r
+        */\r
+       protected static $databaseTableIndexName = 'styleID';\r
+       \r
+       /**\r
+        * Returns the name of this style.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function __toString() {\r
+               return $this->styleName;\r
+       }\r
+       \r
+       /**\r
+        * Returns the styles variables of this style.\r
+        * \r
+        * @return      array\r
+        */\r
+       public function getVariables() {\r
+               $variables = array();\r
+               $sql = "SELECT          variableName, variableValue\r
+                       FROM            wcf".WCF_N."_style_variable\r
+                       WHERE           styleID = ?\r
+                       ORDER BY        variableName ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($this->styleID));\r
+               while ($row = $statement->fetchArray()) {\r
+                       $variables[$row['variableName']] = $row['variableValue'];\r
+               }\r
+               \r
+               return $variables;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/data/style/StyleAction.class.php b/wcfsetup/install/files/lib/data/style/StyleAction.class.php
new file mode 100644 (file)
index 0000000..b261f96
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\style;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes style-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.style\r
+ * @category   Community Framework\r
+ */\r
+class StyleAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\style\StyleEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/style/StyleEditor.class.php b/wcfsetup/install/files/lib/data/style/StyleEditor.class.php
new file mode 100644 (file)
index 0000000..58f760f
--- /dev/null
@@ -0,0 +1,906 @@
+<?php\r
+namespace wcf\data\style;\r
+use wcf\data\template\group\TemplateGroupEditor;\r
+use wcf\data\template\TemplateEditor;\r
+use wcf\data\DatabaseObjectEditor;\r
+use wcf\data\EditableCachedObject;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\image\Thumbnail;\r
+use wcf\system\io\File;\r
+use wcf\system\io\Tar;\r
+use wcf\system\io\TarWriter;\r
+use wcf\system\WCF;\r
+use wcf\util\FileUtil;\r
+use wcf\util\StringUtil;\r
+use wcf\util\XML;\r
+\r
+/**\r
+ * Provides functions to edit, import, export and delete a style.\r
+ * \r
+ * @todo       Fix usage of XML-class (API-changes)!\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.style\r
+ * @category   Community Framework\r
+ */\r
+class StyleEditor extends DatabaseObjectEditor implements EditableCachedObject {\r
+       const INFO_FILE = 'style.xml';\r
+       const STYLE_PREVIEW_IMAGE_MAX_WIDTH = 185;\r
+       const STYLE_PREVIEW_IMAGE_MAX_HEIGHT = 140;\r
+       \r
+       /**\r
+        * @see DatabaseObjectEditor::$baseClass\r
+        */\r
+       protected static $baseClass = 'wcf\data\style\Style';\r
+       \r
+       /**\r
+        * @see EditableObject::update()\r
+        */\r
+       public function update(array $parameters = array()) {\r
+               $variables = null;\r
+               if (isset($parameters['variables'])) {\r
+                       $variables = $parameters['variables'];\r
+                       unset($parameters['variables']);\r
+               }\r
+\r
+               // update style data\r
+               parent::update($parameters);\r
+               \r
+               // update variables\r
+               if ($variables !== null) {\r
+                       $this->setVariables($variables);\r
+               }\r
+               \r
+               // scale preview image\r
+               if (!empty($parameters['image']) && $parameters['image'] != $this->image) {\r
+                       self::scalePreviewImage(WCF_DIR.$parameters['image']);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see EditableObject::delete()\r
+        */\r
+       public function delete() {\r
+               parent::delete();\r
+               \r
+               // delete variables\r
+               $sql = "DELETE FROM     wcf".WCF_N."_style_variable\r
+                       WHERE           styleID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($this->styleID));\r
+               \r
+               // delete style to package\r
+               $sql = "DELETE FROM     wcf".WCF_N."_style_to_package\r
+                       WHERE           styleID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($this->styleID));\r
+               \r
+               // delete style files\r
+               @unlink(WCF_DIR.'style/style-'.$this->styleID.'.css');\r
+               @unlink(WCF_DIR.'style/style-'.$this->styleID.'-rtl.css');\r
+               \r
+               // delete preview image\r
+               if ($this->image) {\r
+                       @unlink(WCF_DIR.$this->image);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Sets this style as default style.\r
+        */\r
+       public function setAsDefault() {\r
+               // remove old default\r
+               $sql = "UPDATE  wcf".WCF_N."_style\r
+                       SET     isDefault = ?\r
+                       WHERE   isDefault = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array(0, 1));\r
+               \r
+               // set new default\r
+               $this->update(array(\r
+                       'isDefault' => 1,\r
+                       'disabled' => 0\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * Reads the data of a style exchange format file.\r
+        * \r
+        * @param       Tar             $tar\r
+        * @return      array           data\r
+        */\r
+       public static function readStyleData(Tar $tar) {\r
+               // search style.xml\r
+               $i = $tar->getIndexByFilename(self::INFO_FILE);\r
+               if ($i === false) {\r
+                       throw new SystemException("unable to find required file '".self::INFO_FILE."' in style archive", 100001);\r
+               }\r
+               \r
+               // open style.xml\r
+               $styleXML = new XML();\r
+               $styleXML->loadString($tar->extractToString($i));\r
+               $xmlContent = $styleXML->getElementTree('style');\r
+               $data = array(\r
+                       'name' => '', 'description' => '', 'version' => '', 'image' => '', 'copyright' => '',\r
+                       'license' => '', 'authorName' => '', 'authorURL' => '', 'templates' => '', 'images' => '',\r
+                       'variables' => '', 'date' => '0000-00-00', 'icons' => ''\r
+               );\r
+               \r
+               foreach ($xmlContent['children'] as $child) {\r
+                       switch ($child['name']) {\r
+                               case 'general': \r
+                                       foreach ($child['children'] as $general) {\r
+                                               switch ($general['name']) {\r
+                                                       case 'stylename': $data['name'] = $general['cdata']; break;\r
+                                                       case 'description': case 'version': case 'date': \r
+                                                       case 'image': case 'copyright': case 'license': $data[$general['name']] = $general['cdata']; break;\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                               \r
+                               case 'author':\r
+                                       foreach ($child['children'] as $author) {\r
+                                               switch ($author['name']) {\r
+                                                       case 'authorname': $data['authorName'] = $author['cdata']; break;\r
+                                                       case 'authorurl': $data['authorURL'] = $author['cdata']; break;\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                               \r
+                               case 'files':\r
+                                       foreach ($child['children'] as $files) {\r
+                                               switch ($files['name']) {\r
+                                                       case 'templates': case 'images': case 'variables': case 'icons': $data[$files['name']] = $files['cdata']; break;\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                       }\r
+               }\r
+               \r
+               if (empty($data['name'])) {\r
+                       throw new SystemException("required tag 'stylename' is missing in '".self::INFO_FILE."'", 100002);\r
+               }\r
+               if (empty($data['variables'])) {\r
+                       throw new SystemException("required tag 'variables' is missing in '".self::INFO_FILE."'", 100002);\r
+               }\r
+               \r
+               // search variables.xml\r
+               $i = $tar->getIndexByFilename($data['variables']);\r
+               if ($i === false) {\r
+                       throw new SystemException("unable to find required file '".$data['variables']."' in style archive", 100001);\r
+               }\r
+               \r
+               // open variables.xml\r
+               $data['variables'] = self::readVariablesData($tar->extractToString($i));\r
+               \r
+               return $data;\r
+       }\r
+       \r
+       /**\r
+        * Reads the data of a variables.xml file.\r
+        * \r
+        * @param       string          $string         contents of a variable.xml file\r
+        * @return      array           data\r
+        */\r
+       public static function readVariablesData($string) {\r
+               // open variables.xml\r
+               $variablesXML = new XML();\r
+               $variablesXML->loadString($string);\r
+               $variablesXMLContent = $variablesXML->getElementTree('variables');\r
+               \r
+               // get variables\r
+               $variables = array();\r
+               foreach ($variablesXMLContent['children'] as $variable) {\r
+                       if (isset($variable['attrs']['name'])) {\r
+                               $variables[$variable['attrs']['name']] = $variable['cdata'];\r
+                       }\r
+               }\r
+               \r
+               return $variables;\r
+       }\r
+       \r
+       /**\r
+        * Gets the data of a style exchange format file.\r
+        * \r
+        * @param       string          $filename\r
+        * @return      array           data\r
+        */\r
+       public static function getStyleData($filename) {\r
+               // open file\r
+               $tar = new Tar($filename);\r
+               \r
+               // get style data\r
+               $data = self::readStyleData($tar);\r
+               \r
+               // export preview image to temporary location\r
+               if (!empty($data['image'])) {\r
+                       $i = $tar->getIndexByFilename($data['image']);\r
+                       if ($i !== false) {\r
+                               $path = FileUtil::getTemporaryFilename('stylePreview_', $data['image'], WCF_DIR.'tmp/');\r
+                               $data['image'] = basename($path);\r
+                               $tar->extract($i, $path);\r
+                       }\r
+               }\r
+               \r
+               $tar->close();\r
+               \r
+               return $data;\r
+       }\r
+       \r
+       /**\r
+        * Imports a style.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       integer         $packageID\r
+        * @param       StyleEditor     $style\r
+        * @return      StyleEditor\r
+        */\r
+       public static function import($filename, $packageID = PACKAGE_ID, StyleEditor $style = null) {\r
+               // open file\r
+               $tar = new Tar($filename);\r
+               \r
+               // get style data\r
+               $data = self::readStyleData($tar);\r
+               \r
+               // get image locations\r
+               $iconsLocation = FileUtil::addTrailingSlash($data['variables']['global.icons.location']);\r
+               $imagesLocation = $data['variables']['global.images.location'];\r
+               \r
+               // create template group\r
+               $templateGroupID = 0;\r
+               if (!empty($data['templates'])) {\r
+                       $originalTemplateGroupName = $templateGroupName = $data['name'];\r
+                       $templateGroupFolderName = preg_replace('/[^a-z0-9_-]/i', '', $templateGroupName);\r
+                       if (empty($templateGroupFolderName)) $templateGroupFolderName = 'generic'.StringUtil::substring(StringUtil::getRandomID(), 0, 8);\r
+                       $originalTemplatePackFolderName = $templateGroupFolderName;\r
+                       \r
+                       // get unique template pack name\r
+                       $i = 1;\r
+                       do {\r
+                               $sql = "SELECT  COUNT(*) AS count\r
+                                       FROM    wcf".WCF_N."_template_group\r
+                                       WHERE   templateGroupName = ?";\r
+                               $statement = WCF::getDB()->prepareStatement($sql);\r
+                               $statement->execute(array($templateGroupName));\r
+                               $row = $statement->fetchArray();\r
+                               if (!$row['count']) break;\r
+                               $templateGroupName = $originalTemplatePackName . '_' . $i;\r
+                               $i++;\r
+                       }\r
+                       while (true);\r
+                       // get unique folder name\r
+                       $i = 1;\r
+                       do {\r
+                               $sql = "SELECT  COUNT(*) AS count\r
+                                       FROM    wcf".WCF_N."_template_group\r
+                                       WHERE   templateGroupFolderName = ?\r
+                                               AND parentTemplatePackID = ?";\r
+                               $statement = WCF::getDB()->prepareStatement($sql);\r
+                               $statement->execute(array(\r
+                                       FileUtil::addTrailingSlash($templateGroupFolderName),\r
+                                       0\r
+                               ));\r
+                               $row = $statement->fetchArray();\r
+                               if (!$row['count']) break;\r
+                               $templateGroupFolderName = $originalTemplatePackFolderName . '_' . $i;\r
+                               $i++;\r
+                       }\r
+                       while (true);\r
+                       \r
+                       $templateGroup = TemplateGroupEditor::create(array(\r
+                               'templateGroupName' => $templateGroupName,\r
+                               'templateGroupFolderName' => FileUtil::addTrailingSlash($templateGroupFolderName)\r
+                       ));\r
+                       $templateGroupID = $templateGroup->templateGroupID;\r
+               }\r
+               \r
+               // save style\r
+               $styleData = array(\r
+                       'styleName' => $data['name'],\r
+                       'variables' => $data['variables'],\r
+                       'templateGroupID' => $templateGroupID,\r
+                       'styleDescription' => $data['description'],\r
+                       'styleVersion' => $data['version'],\r
+                       'styleDate' => $data['date'],\r
+                       'image' => ($data['image'] ? 'images/' : '').$data['image'],\r
+                       'copyright' => $data['copyright'],\r
+                       'license' => $data['license'],\r
+                       'authorName' => $data['authorName'],\r
+                       'authorURL' => $data['authorURL']\r
+               );\r
+               if ($style !== null) {\r
+                       $style->update($styleData);\r
+               }\r
+               else {\r
+                       $styleData['packageID'] = $packageID;\r
+                       $style = self::create($styleData);\r
+               }\r
+               \r
+               // import preview image\r
+               if (!empty($data['image'])) {\r
+                       $i = $tar->getIndexByFilename($data['image']);\r
+                       if ($i !== false) {\r
+                               $tar->extract($i, WCF_DIR.'images/'.$data['image']);\r
+                               @chmod(WCF_DIR.'images/'.$data['image'], 0777);\r
+                       }\r
+               }\r
+               \r
+               // import images\r
+               if (!empty($data['images'])) {\r
+                       // create images folder if necessary\r
+                       if (!file_exists(WCF_DIR.$imagesLocation)) {\r
+                               @mkdir(WCF_DIR.$data['variables']['global.images.location'], 0777);\r
+                               @chmod(WCF_DIR.$data['variables']['global.images.location'], 0777);\r
+                       }\r
+                       \r
+                       $i = $tar->getIndexByFilename($data['images']);\r
+                       if ($i !== false) {\r
+                               // extract images tar\r
+                               $destination = FileUtil::getTemporaryFilename('images_');\r
+                               $tar->extract($i, $destination);\r
+                               \r
+                               // open images tar\r
+                               $imagesTar = new Tar($destination);\r
+                               $contentList = $imagesTar->getContentList();\r
+                               foreach ($contentList as $key => $val) {\r
+                                       if ($val['type'] == 'file') {\r
+                                               $imagesTar->extract($key, WCF_DIR.$imagesLocation.basename($val['filename']));\r
+                                               @chmod(WCF_DIR.$imagesLocation.basename($val['filename']), 0666);\r
+                                       }\r
+                               }\r
+\r
+                               // delete tmp file\r
+                               $imagesTar->close();\r
+                               @unlink($destination);\r
+                       }\r
+               }\r
+               \r
+               // import icons\r
+               if (!empty($data['icons']) && $iconsLocation != 'icon/') {\r
+                       $i = $tar->getIndexByFilename($data['icons']);\r
+                       if ($i !== false) {\r
+                               // extract icons tar\r
+                               $destination = FileUtil::getTemporaryFilename('icons_');\r
+                               $tar->extract($i, $destination);\r
+                               \r
+                               // open icons tar and group icons by package\r
+                               $iconsTar = new Tar($destination);\r
+                               $contentList = $iconsTar->getContentList();\r
+                               $packageToIcons = array();\r
+                               foreach ($contentList as $key => $val) {\r
+                                       if ($val['type'] == 'file') {\r
+                                               $folders = explode('/', $val['filename']);\r
+                                               $packageName = array_shift($folders);\r
+                                               if (!isset($packageToIcons[$packageName])) {\r
+                                                       $packageToIcons[$packageName] = array();\r
+                                               }\r
+                                               $packageToIcons[$packageName][] = array('index' => $val['index'], 'filename' => implode('/', $folders));\r
+                                       }\r
+                               }\r
+                               \r
+                               // copy icons\r
+                               foreach ($packageToIcons as $package => $icons) {\r
+                                       // try to find package\r
+                                       $sql = "SELECT  *\r
+                                               FROM    wcf".WCF_N."_package\r
+                                               WHERE   package = ?\r
+                                                       AND standalone = ?";\r
+                                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                                       $statement->execute(array(\r
+                                               $package,\r
+                                               1\r
+                                       ));\r
+                                       while ($row = $statement->fetchArray()) {\r
+                                               // get icon path\r
+                                               $iconDir = FileUtil::getRealPath(WCF_DIR.$row['packageDir']).$iconsLocation;\r
+                                               \r
+                                               // create icon path\r
+                                               if (!file_exists($iconDir)) {\r
+                                                       @mkdir($iconDir, 0777);\r
+                                                       @chmod($iconDir, 0777);\r
+                                               }\r
+                                               \r
+                                               // copy icons\r
+                                               foreach ($icons as $icon) {\r
+                                                       $iconsTar->extract($icon['index'], $iconDir.$icon['filename']);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               // delete tmp file\r
+                               $iconsTar->close();\r
+                               @unlink($destination);\r
+                       }\r
+               }\r
+               \r
+               // import templates\r
+               if (!empty($data['templates'])) {\r
+                       $i = $tar->getIndexByFilename($data['templates']);\r
+                       if ($i !== false) {\r
+                               // extract templates tar\r
+                               $destination = FileUtil::getTemporaryFilename('templates_');\r
+                               $tar->extract($i, $destination);\r
+                               \r
+                               // open templates tar and group templates by package\r
+                               $templatesTar = new Tar($destination);\r
+                               $contentList = $templatesTar->getContentList();\r
+                               $packageToTemplates = array();\r
+                               foreach ($contentList as $key => $val) {\r
+                                       if ($val['type'] == 'file') {\r
+                                               $folders = explode('/', $val['filename']);\r
+                                               $packageName = array_shift($folders);\r
+                                               if (!isset($packageToTemplates[$packageName])) {\r
+                                                       $packageToTemplates[$packageName] = array();\r
+                                               }\r
+                                               $packageToTemplates[$packageName][] = array('index' => $val['index'], 'filename' => implode('/', $folders));\r
+                                       }\r
+                               }\r
+                               \r
+                               // copy templates\r
+                               foreach ($packageToTemplates as $package => $templates) {\r
+                                       // try to find package\r
+                                       $sql = "SELECT  *\r
+                                               FROM    wcf".WCF_N."_package\r
+                                               WHERE   package = ?\r
+                                                       AND standalone = ?";\r
+                                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                                       $statement->execute(array(\r
+                                               $package,\r
+                                               1\r
+                                               ));\r
+                                       while ($row = $statement->fetchArray()) {\r
+                                               // get icon path\r
+                                               $templatesDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$row['packageDir']).'templates/'.$templateGroupFolderName);\r
+                                               \r
+                                               // create template path\r
+                                               if (!file_exists($templatesDir)) {\r
+                                                       @mkdir($templatesDir, 0777);\r
+                                                       @chmod($templatesDir, 0777);\r
+                                               }\r
+                                               \r
+                                               // copy templates\r
+                                               foreach ($templates as $template) {\r
+                                                       $templatesTar->extract($template['index'], $templatesDir.$template['filename']);\r
+                                                       \r
+                                                       TemplateEditor::create(array(\r
+                                                               'packageID' => $row['packageID'],\r
+                                                               'templateName' => StringUtil::replace('.tpl', '', $template['filename']),\r
+                                                               'templateGroupID' => $templateGroupID\r
+                                                       ));\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               // delete tmp file\r
+                               $templatesTar->close();\r
+                               @unlink($destination);\r
+                       }\r
+               }\r
+\r
+               $tar->close();\r
+               \r
+               return $style;\r
+       }\r
+       \r
+       /**\r
+        * Exports this style.\r
+        * \r
+        * @param       boolean         $templates\r
+        * @param       boolean         $images\r
+        * @param       boolean         $icons\r
+        */\r
+       public function export($templates = false, $images = false, $icons = false) {\r
+               // create style tar\r
+               $styleTarName = FileUtil::getTemporaryFilename('style_', '.tgz');\r
+               $styleTar = new TarWriter($styleTarName, true);\r
+               \r
+               // append style preview image\r
+               if ($this->image && @file_exists(WCF_DIR.$this->image)) {\r
+                       $styleTar->add(WCF_DIR.$this->image, '', FileUtil::addTrailingSlash(dirname(WCF_DIR.$this->image)));\r
+               }\r
+               \r
+               // create style info file\r
+               $string = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE style SYSTEM \"http://www.woltlab.com/DTDs/SXF/style.dtd\">\n<style>\n";\r
+               \r
+               // general block\r
+               $string .= "\t<general>\n";\r
+               $string .= "\t\t<stylename><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->styleName) : $this->styleName))."]]></stylename>\n"; // style name\r
+               if ($this->styleDescription) $string .= "\t\t<description><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->styleDescription) : $this->styleDescription))."]]></description>\n"; // style description\r
+               if ($this->styleVersion) $string .= "\t\t<version><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->styleVersion) : $this->styleVersion))."]]></version>\n"; // style version\r
+               if ($this->styleDate) $string .= "\t\t<date><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->styleDate) : $this->styleDate))."]]></date>\n"; // style date\r
+               if ($this->image) $string .= "\t\t<image><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', basename($this->image)) : basename($this->image)))."]]></image>\n"; // style preview image\r
+               if ($this->copyright) $string .= "\t\t<copyright><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->copyright) : $this->copyright))."]]></copyright>\n"; // copyright\r
+               if ($this->license) $string .= "\t\t<license><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->license) : $this->license))."]]></license>\n"; // license\r
+               $string .= "\t</general>\n";\r
+               \r
+               // author block\r
+               $string .= "\t<author>\n";\r
+               if ($this->authorName) $string .= "\t\t<authorname><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->authorName) : $this->authorName))."]]></authorname>\n"; // author name\r
+               if ($this->authorURL) $string .= "\t\t<authorurl><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $this->authorURL) : $this->authorURL))."]]></authorurl>\n"; // author URL\r
+               $string .= "\t</author>\n";\r
+               \r
+               // files block\r
+               $string .= "\t<files>\n";\r
+               $string .= "\t\t<variables>variables.xml</variables>\n"; // variables\r
+               if ($templates && $this->templateGroupID) $string .= "\t\t<templates>templates.tar</templates>\n"; // templates\r
+               if ($images) $string .= "\t\t<images>images.tar</images>\n"; // images\r
+               if ($icons) $string .= "\t\t<icons>icons.tar</icons>\n"; // icons\r
+               $string .= "\t</files>\n";\r
+               \r
+               $string .= "</style>";\r
+               // append style info file to style tar\r
+               $styleTar->addString(self::INFO_FILE, $string);\r
+               unset($string);\r
+               \r
+               // create variable list\r
+               $string = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE variables SYSTEM \"http://www.woltlab.com/DTDs/SXF/variables.dtd\">\n<variables>\n";\r
+               // get variables\r
+               $variables = $this->getVariables();\r
+               $exportImages = array();\r
+               foreach ($variables as $name => $value) {\r
+                       // search images\r
+                       if ($images && $value) {\r
+                               if (preg_match_all('~([^/\s\$]+\.(?:gif|jpg|jpeg|png))~i', $value, $matches)) {\r
+                                       $exportImages = array_merge($exportImages, $matches[1]);\r
+                               }\r
+                       }\r
+                       $string .= "\t<variable name=\"".StringUtil::encodeHTML($name)."\"><![CDATA[".StringUtil::escapeCDATA((CHARSET != 'UTF-8' ? StringUtil::convertEncoding(CHARSET, 'UTF-8', $value) : $value))."]]></variable>\n";\r
+               }\r
+               \r
+               $string .= "</variables>";\r
+               // append variable list to style tar\r
+               $styleTar->addString('variables.xml', $string);\r
+               unset($string);\r
+\r
+               if ($templates && $this->templateGroupID) {\r
+                       $templateGroup = new TemplateGroup($this->templateGroupID);\r
+                       \r
+                       // create templates tar\r
+                       $templatesTarName = FileUtil::getTemporaryFilename('templates', '.tar');\r
+                       $templatesTar = new TarWriter($templatesTarName);\r
+                       @chmod($templatesTarName, 0777);\r
+                       \r
+                       // append templates to tar\r
+                       // get templates\r
+                       $sql = "SELECT          template.*, package.package, package.packageDir,\r
+                                               parent_package.package AS parentPackage, parent_package.packageDir AS parentPackageDir\r
+                               FROM            wcf".WCF_N."_template template\r
+                               LEFT JOIN       wcf".WCF_N."_package package\r
+                               ON              (package.packageID = template.packageID)\r
+                               LEFT JOIN       wcf".WCF_N."_package parent_package\r
+                               ON              (parent_package.packageID = package.parentPackageID)\r
+                               WHERE           template.templateGroupID = ?";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute(array($this->templateGroupID));\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $packageDir = 'com.woltlab.wcf';\r
+                               if (!empty($row['parentPackageDir'])) $packageDir = $row['parentPackage'];\r
+                               else if (!empty($row['packageDir'])) $packageDir = $row['package'];\r
+                               \r
+                               $filename = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $row['packageDir'] . 'templates/' . $templateGroup->templateGroupFolderName)) . $row['templateName'] . '.tpl';\r
+                               $templatesTar->add($filename, $packageDir, dirname($filename));\r
+                       }\r
+                       \r
+                       // append templates tar to style tar\r
+                       $templatesTar->create();\r
+                       $styleTar->add($templatesTarName, 'templates.tar', $templatesTarName);\r
+                       @unlink($templatesTarName);\r
+               }\r
+\r
+               if ($images) {\r
+                       // create images tar\r
+                       $imagesTarName = FileUtil::getTemporaryFilename('images_', '.tar');\r
+                       $imagesTar = new TarWriter($imagesTarName);\r
+                       @chmod($imagesTarName, 0777);\r
+                       \r
+                       // cache rtl versions\r
+                       foreach ($exportImages as $exportImage) {\r
+                               if (strpos($exportImage, '-ltr')) $exportImages[] = str_replace('-ltr', '-rtl', $exportImage);\r
+                       }\r
+                       \r
+                       // append images to tar\r
+                       $path = WCF_DIR.$variables['global.images.location'];\r
+                       if (file_exists($path) && is_dir($path)) {\r
+                               $handle = opendir($path);\r
+                               \r
+                               while (($file = readdir($handle)) !== false) {\r
+                                       if (is_file($path.$file) && in_array($file, $exportImages)) {\r
+                                               $imagesTar->add($path.$file, '', $path);\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       // append images tar to style tar\r
+                       $imagesTar->create();\r
+                       $styleTar->add($imagesTarName, 'images.tar', $imagesTarName);\r
+                       @unlink($imagesTarName);\r
+               }\r
+               \r
+               // export icons\r
+               $iconsLocation = FileUtil::addTrailingSlash($variables['global.icons.location']);\r
+               if ($icons && $iconsLocation != 'icon/') {\r
+                       // create icons tar\r
+                       $iconsTarName = FileUtil::getTemporaryFilename('icons_', '.tar');\r
+                       $iconsTar = new TarWriter($iconsTarName);\r
+                       @chmod($iconsTar, 0777);\r
+                       \r
+                       // get package dirs\r
+                       $sql = "SELECT  package, packageDir\r
+                               FROM    wcf".WCF_N."_package\r
+                               WHERE   standalone = 1\r
+                                       AND (packageDir <> '' OR package = 'com.woltlab.wcf')";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute();\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $iconsDir = FileUtil::getRealPath(WCF_DIR.$row['packageDir']).$iconsLocation;\r
+                               $packageIcons = array();\r
+                               if (file_exists($iconsDir)) {\r
+                                       $icons = glob($iconsDir.'*.png');\r
+                                       if (is_array($icons)) {\r
+                                               foreach ($icons as $icon) {\r
+                                                       $packageIcons[] = $icon;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               if (count($packageIcons)) {\r
+                                       $iconsTar->add($packageIcons, $row['package'].'/', $iconsDir);\r
+                               }\r
+                       }\r
+                       \r
+                       $iconsTar->create();\r
+                       $styleTar->add($iconsTarName, 'icons.tar', $iconsTarName);\r
+                       @unlink($iconsTarName);\r
+               }\r
+               \r
+               // output file content\r
+               $styleTar->create();\r
+               readfile($styleTarName);\r
+               @unlink($styleTarName);\r
+       }\r
+       \r
+       /**\r
+        * Sets the variables of a style.\r
+        */\r
+       public function setVariables($variables) {\r
+               // delete old variables\r
+               $sql = "DELETE FROM     wcf".WCF_N."_style_variable\r
+                       WHERE           styleID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($this->styleID));\r
+               \r
+               // insert new variables\r
+               $statementParameters = array();\r
+               foreach ($variables as $name => $value) {\r
+                       $statementParameters[] = array(\r
+                               'name' => $name,\r
+                               'value' => $value\r
+                       );\r
+               }\r
+               \r
+               if (count($statementParameters)) {\r
+                       $sql = "INSERT INTO     wcf".WCF_N."_style_variable\r
+                                               (styleID, variableName, variableValue)\r
+                               VALUES          (?, ?, ?)";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       \r
+                       foreach ($statementParameters as $parameter) {\r
+                               $statement->execute(array(\r
+                                       $this->styleID,\r
+                                       $parameter['name'],\r
+                                       $parameter['value']\r
+                               ));\r
+                       }\r
+               }\r
+               \r
+               $this->writeStyleFile();\r
+       }\r
+       \r
+       /**\r
+        * Writes the style-*.css file.\r
+        */\r
+       public function writeStyleFile() {\r
+               // get variables\r
+               $variables = $this->getVariables();\r
+               \r
+               // parse additional styles\r
+               self::parseAdditionalStyles($variables);\r
+               \r
+               // get file handle\r
+               $file = new File(WCF_DIR . 'style/style-'.$this->styleID.'.css', 'wb');\r
+               \r
+               // include static styles\r
+               $staticStyles = glob(WCF_DIR.'style/*.css');\r
+               if ($staticStyles) {\r
+                       foreach ($staticStyles as $staticStyle) {\r
+                               if (!preg_match('/style-\d+(?:-rtl)?\.css/', $staticStyle)) {\r
+                                       $contents = file_get_contents($staticStyle);\r
+                                       $contents = StyleUtil::compressCSS($contents);\r
+                                       $file->write("/* static: ".basename($staticStyle)." */\n");\r
+                                       $file->write(StringUtil::trim($contents)."\n");\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // get attributes\r
+               $file->write("/* dynamic style attributes */\n");\r
+               $sortedAttributes = array();\r
+               $sql = "SELECT          *\r
+                       FROM            wcf".WCF_N."_style_variable_to_attribute\r
+                       ORDER BY        variableName, attributeName, cssSelector";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               while ($row = $statement->fetchArray()) {\r
+                       if (!empty($variables[$row['variableName']])) {\r
+                               if (!isset($sortedAttributes[$row['variableName']])) $sortedAttributes[$row['variableName']] = array();\r
+                               if (!isset($sortedAttributes[$row['variableName']][$row['attributeName']])) $sortedAttributes[$row['variableName']][$row['attributeName']] = array();\r
+                               $sortedAttributes[$row['variableName']][$row['attributeName']][] = $row['cssSelector'];\r
+                       }\r
+               }\r
+               \r
+               foreach ($sortedAttributes as $variableName => $attributes) {\r
+                       foreach ($attributes as $attributeName => $cssSelectors) {\r
+                               $count = 0;\r
+                               \r
+                               // write selectors\r
+                               $css1Selectors = $css2Selectors = array();\r
+                               foreach ($cssSelectors as $cssSelector) {\r
+                                       if (empty($cssSelector)) {\r
+                                               $file->write("/* ".$variableName." */\n");\r
+                                               $file->write(StyleUtil::compressCSS($variables[$variableName]));\r
+                                               $file->write("\n");\r
+                                       }\r
+                                       else {\r
+                                               if (preg_match('/^[a-z0-9.#:_\s-*]+$/i', $cssSelector)) {\r
+                                                       $css1Selectors[] = $cssSelector;\r
+                                               }\r
+                                               else {\r
+                                                       $css2Selectors[] = $cssSelector;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               if (count($css1Selectors)) {\r
+                                       $file->write(implode(',', $css1Selectors));\r
+                                       \r
+                                       $file->write("{");\r
+                                       \r
+                                       // write attribute\r
+                                       if (!empty($attributeName)) $file->write($attributeName .":");\r
+                               \r
+                                       // write value\r
+                                       $file->write($variables[$variableName]);\r
+                                       \r
+                                       $file->write("}\n");\r
+                               }\r
+                               \r
+                               if (count($css2Selectors)) {\r
+                                       $file->write(implode(',', $css2Selectors));\r
+                                       \r
+                                       $file->write("{");\r
+                                       \r
+                                       // write attribute\r
+                                       if (!empty($attributeName)) $file->write($attributeName .":");\r
+                               \r
+                                       // write value\r
+                                       $file->write($variables[$variableName]);\r
+                                       \r
+                                       $file->write("}\n");\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // close file\r
+               $file->close();\r
+               @chmod(WCF_DIR . 'style/style-'.$this->styleID.'.css', 0777);\r
+               $this->writeStyleFileRTL();\r
+       }\r
+       \r
+       /**\r
+        * Converts the file of this style to a RTL ("right-to-left") version. \r
+        */\r
+       public function writeStyleFileRTL() {\r
+               // get contents of LTR version\r
+               $contents = file_get_contents(WCF_DIR . 'style/style-'.$this->styleID.'.css');\r
+               \r
+               // convert ltr to rtl\r
+               $contents = StyleUtil::convertCSSToRTL($contents);\r
+               \r
+               // write file\r
+               $file = new File(WCF_DIR . 'style/style-'.$this->styleID.'-rtl.css');\r
+               $file->write($contents);\r
+               $file->close();\r
+               @chmod(WCF_DIR . 'style/style-'.$this->styleID.'-rtl.css', 0777);\r
+       }\r
+       \r
+       /**\r
+        * @see EditableObject::create()\r
+        */\r
+       public static function create(array $parameters = array()) {\r
+               $variables = null;\r
+               if (isset($parameters['variables'])) {\r
+                       $variables = $parameters['variables'];\r
+                       unset($parameters['variables']);\r
+               }\r
+               \r
+               // default values\r
+               if (!isset($parameters['packageID'])) $parameters['packageID'] = PACKAGE_ID;\r
+               if (!isset($parameters['styleDate'])) $parameters['styleDate'] = gmdate('Y-m-d', TIME_NOW);\r
+               \r
+               // save style\r
+               $style = parent::create($parameters);           \r
+               $styleEditor = new StyleEditor($style);\r
+               \r
+               // save variables\r
+               if ($variables !== null) {\r
+                       $styleEditor->setVariables($variables);\r
+               }\r
+               \r
+               // scale preview image\r
+               if (!empty($parameters['image'])) {\r
+                       self::scalePreviewImage(WCF_DIR.$parameters['image']);\r
+               }\r
+               \r
+               return $style;\r
+       }\r
+       \r
+       /**\r
+        * @see EditableCachedObject::resetCache()\r
+        */\r
+       public static function resetCache() {\r
+               WCF::getCache()->clear(WCF_DIR.'cache', 'cache.icon-*-'.$this->styleID.'.php');\r
+       }\r
+       \r
+       /**\r
+        * Scales the style preview image.\r
+        * \r
+        * @param       string          $filename\r
+        * @return      boolean\r
+        */\r
+       public static function scalePreviewImage($filename) {\r
+               $thumbnail = new Thumbnail($filename, self::STYLE_PREVIEW_IMAGE_MAX_WIDTH, self::STYLE_PREVIEW_IMAGE_MAX_HEIGHT);\r
+               if (($source = $thumbnail->makeThumbnail())) {\r
+                       $file = new File($filename);\r
+                       $file->write($source);\r
+                       $file->close();\r
+                       \r
+                       return true;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       private static $variables = array();\r
+       private static function parseAdditionalStyles(&$variables) {\r
+               self::$variables = $variables;\r
+               // fix images location\r
+               if (!empty(self::$variables['global.images.location']) && !FileUtil::isURL(self::$variables['global.images.location']) && substr(self::$variables['global.images.location'], 0, 1) != '/') {\r
+                       self::$variables['global.images.location'] = '../'.self::$variables['global.images.location'];\r
+               }\r
+               // fix images location\r
+               if (!empty(self::$variables['global.icons.location']) && !FileUtil::isURL(self::$variables['global.icons.location']) && substr(self::$variables['global.icons.location'], 0, 1) != '/') {\r
+                       self::$variables['global.icons.location'] = '../'.self::$variables['global.icons.location'];\r
+               }\r
+               \r
+               // parse additional styles\r
+               if (!empty($variables['user.additional.style.input1.use'])) {\r
+                       $variables['user.additional.style.input1.use'] = preg_replace_callback('/\$([a-z0-9_\-\.]+)\$/', array('self', 'parseAdditionalStylesCallback'), $variables['user.additional.style.input1.use']);\r
+               }\r
+               if (!empty($variables['user.additional.style.input2.use'])) {\r
+                       $variables['user.additional.style.input2.use'] = preg_replace_callback('/\$([a-z0-9_\-\.]+)\$/', array('self', 'parseAdditionalStylesCallback'), $variables['user.additional.style.input2.use']);\r
+               }\r
+       }\r
+       \r
+       private static function parseAdditionalStylesCallback($match) {\r
+               if (isset(self::$variables[$match[1]])) {\r
+                       return self::$variables[$match[1]];\r
+               }\r
+               else {\r
+                       return $match[0];\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/data/style/StyleList.class.php b/wcfsetup/install/files/lib/data/style/StyleList.class.php
new file mode 100644 (file)
index 0000000..a4583ef
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\style;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of styles.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.style\r
+ * @category   Community Framework\r
+ */\r
+class StyleList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\style\Style';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/Template.class.php b/wcfsetup/install/files/lib/data/template/Template.class.php
new file mode 100644 (file)
index 0000000..7bf1679
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+namespace wcf\data\template;
+use wcf\data\DatabaseObject;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Represents a template.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.template
+ * @category   Community Framework
+ */
+class Template extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'template';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'templateID';
+       
+       /**
+        * @see DatabaseObject::__construct()
+        */
+       public function __construct($id, $row = null, DatabaseObject $object = null) {
+               if ($id !== null) {
+                       $sql = "SELECT          template.*, group.templateGroupFolderName, package.packageDir
+                               FROM            wcf".WCF_N."_template template
+                               LEFT JOIN       wcf".WCF_N."_template_group group
+                               ON              (group.templateGroupID = template.templateGroupID)
+                               LEFT JOIN       wcf".WCF_N."_package package
+                               ON              (package.packageID = template.packageID)
+                               WHERE           template.templateID = ?".$id;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($id));
+                       $row = $statement->fetchArray();
+                       
+                       // enforce data type 'array'
+                       if ($row === false) $row = array();
+               }
+               else if ($object !== null) {
+                       $row = $object->data;
+               }
+               
+               $this->handleData($row);
+       }
+       
+       /**
+        * Returns the path to this template.
+        * 
+        * @return      string
+        */
+       public function getPath() {
+               $path = FileUtil::getRealPath(WCF_DIR . $this->packageDir) . 'templates/' . $this->templateGroupFolderName . $this->templateName . '.tpl';
+               return $path;
+       }
+       
+       /**
+        * Returns the source of this template.
+        * 
+        * @return      string
+        */
+       public function getSource() {
+               return @file_get_contents($this->getPath());
+       }
+       
+       /**
+        * Searches in templates.
+        * TODO: move to template editor?
+        * 
+        * @param       string          $search         search query
+        * @param       string          $replace
+        * @param       array           $templateIDs
+        * @param       boolean         $invertTemplates
+        * @param       boolean         $useRegex
+        * @param       boolean         $caseSensitive
+        * @param       boolean         $invertSearch
+        * @return      array           results 
+        */
+       public static function search($search, $replace = null, $templateIDs = null, $invertTemplates = 0, $useRegex = 0, $caseSensitive = 0, $invertSearch = 0) {
+               // get available template ids
+               $results = array();
+               $availableTemplateIDs = array();
+               $sql = "SELECT          template.templateName, template.templateID, template.templateGroupID, template.packageID
+                       FROM            wcf".WCF_N."_template template
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                       ON              (package_dependency.dependency = template.packageID)
+                       WHERE           package_dependency.packageID = ?
+                                       ".($replace !== null ? "AND template.templateGroupID <> 0" : "")."
+                       ORDER BY        package_dependency.priority ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(PACKAGE_ID));
+               while ($row = $statement->fetchArray()) {
+                       if (!isset($availableTemplateIDs[$row['templateName'].'-'.$row['templateGroupID']]) || PACKAGE_ID == $row['packageID']) {
+                               $availableTemplateIDs[$row['templateName'].'-'.$row['templateGroupID']] = $row['templateID'];
+                       }
+               }
+               
+               // get templates
+               if (!count($availableTemplateIDs)) return $results;
+               
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("template.templateID IN (?)", array($availableTemplateIDs));
+               if ($templateIDs !== null) $conditions->add("template.templateID ".($invertTemplates ? "NOT " : "")." IN (?)", array($templateIDs));
+               
+               $sql = "SELECT          template.*, group.templateGroupFolderName, package.packageDir
+                       FROM            wcf".WCF_N."_template template
+                       LEFT JOIN       wcf".WCF_N."_template_group group
+                       ON              (group.templateGroupID = template.templateGroupID)
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = template.packageID)
+                       ".$conditions."
+                       ORDER BY        templateName ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               unset($availableTemplateIDs);
+               while ($row = $statement->fetchArray()) {
+                       $template = new TemplateEditor(null, $row);
+                       if ($replace === null) {
+                               // search
+                               if ($useRegex) $matches = (intval(preg_match('/'.$search.'/s'.(!$caseSensitive ? 'i' : ''), $template->getSource())) !== 0);
+                               else {
+                                       if ($caseSensitive) $matches = (StringUtil::indexOf($template->getSource(), $search) !== false);
+                                       else $matches = (StringUtil::indexOfIgnoreCase($template->getSource(), $search) !== false);
+                               }
+                               
+                               if (($matches && !$invertSearch) || (!$matches && $invertSearch)) {
+                                       $results[] = $row;
+                               }
+                       }
+                       else {
+                               // search and replace
+                               $matches = 0;
+                               if ($useRegex) {
+                                       $newSource = preg_replace('/'.$search.'/s'.(!$caseSensitive ? 'i' : ''), $replace, $template->getSource(), -1, $matches);
+                               }
+                               else {
+                                       if ($caseSensitive) $newSource = StringUtil::replace($search, $replace, $template->getSource(), $matches);
+                                       else $newSource = StringUtil::replaceIgnoreCase($search, $replace, $template->getSource(), $matches);
+                               }
+                               
+                               if ($matches > 0) {
+                                       $template->setSource($newSource);
+                                       $row['matches'] = $matches;
+                                       $results[] = $row;
+                               }
+                       }
+               }
+               
+               return $results;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/template/TemplateAction.class.php b/wcfsetup/install/files/lib/data/template/TemplateAction.class.php
new file mode 100644 (file)
index 0000000..ae51597
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\data\template;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes template-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.template\r
+ * @category   Community Framework\r
+ */\r
+class TemplateAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\template\TemplateEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.template.canAddTemplate');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.template.canDeleteTemplate');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.template.canEditTemplate');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/TemplateEditor.class.php b/wcfsetup/install/files/lib/data/template/TemplateEditor.class.php
new file mode 100644 (file)
index 0000000..bf05504
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+namespace wcf\data\template;
+use wcf\data\DatabaseObjectEditor;
+use wcf\system\io\File;
+use wcf\system\WCF;
+
+/**
+ * TemplateEditor provides functions to create, edit or delete templates. 
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.template
+ * @category   Community Framework
+ */
+class TemplateEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\template\Template';
+       
+       /**
+        * @see EditableObject::create()
+        */
+       public static function create(array $parameters = array()) {
+               // obtain default values
+               if (!isset($parameters['packageID'])) $parameters['packageID'] = PACKAGE_ID;
+               
+               parent::create($parameters);
+       }
+       
+       /**
+        * Saves the source of this template.
+        * 
+        * @param       string          $source 
+        */
+       public function setSource($source) {
+               $path = $this->getPath();
+               // create dir
+               $folder = dirname($path);
+               if (!file_exists($folder)) {
+                       mkdir($folder, 0777);
+               }
+               
+               // set source           
+               $file = new File($path);
+               $file->write($source);
+               $file->close();
+               @$file->chmod(0777);
+       }
+       
+       /**
+        * Renames the file of this template.
+        * 
+        * @param       string          $name
+        * @param       integer         $templateGroupID
+        */
+       protected function rename($name, $templateGroupID = 0) {
+               // get current path
+               $currentPath = $this->getPath();
+
+               // get new path         
+               $this->data['templateGroupFolderName'] = '';
+               if ($templateGroupID != 0) {
+                       // get folder name
+                       $sql = "SELECT  templateGroupFolderName
+                               FROM    wcf".WCF_N."_template_group
+                               WHERE   templateGroupID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($templateGroupID));
+                       $row = $statement->fetchArray();
+                       $this->data['templateGroupFolderName'] = $row['templateGroupFolderName'];
+               }
+               
+               // delete compiled templates
+               $this->deleteCompiledFiles();
+               
+               // rename
+               $this->data['templateName'] = $name;
+               $newPath = $this->getPath();
+               
+               // move file
+               @rename($currentPath, $newPath);
+       }
+       
+       /**
+        * Deletes this template.
+        */
+       public function delete() {
+               $this->deleteFile();
+               
+               $sql = "DELETE FROM     wcf".WCF_N."_template
+                       WHERE           templateID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->templateID));
+       }
+       
+       /**
+        * Deletes the file of this template.
+        */
+       public function deleteFile() {
+               // delete source
+               @unlink($this->getPath());
+               
+               // delete compiled templates
+               $this->deleteCompiledFiles();
+       }
+       
+       /**
+        * Deletes the compiled files of this template.
+        */
+       public function deleteCompiledFiles() {
+               $matches = glob(WCF_DIR . 'templates/compiled/' . $this->packageID . '_*_' . $this->templateName . '.php');
+               if (is_array($matches)) {
+                       foreach ($matches as $match) @unlink($match);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/template/TemplateList.class.php b/wcfsetup/install/files/lib/data/template/TemplateList.class.php
new file mode 100644 (file)
index 0000000..f23d70f
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\template;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of templates.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.template\r
+ * @category   Community Framework\r
+ */\r
+class TemplateList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\template\Template';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/group/TemplateGroup.class.php b/wcfsetup/install/files/lib/data/template/group/TemplateGroup.class.php
new file mode 100644 (file)
index 0000000..c43ab4d
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+namespace wcf\data\template\group;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * TemplateGroup represents a template group. 
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.template.group
+ * @category   Community Framework
+ */
+class TemplateGroup extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'template_group';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'templateGroupID';
+       
+       protected static $templateGroupStructure = null;
+       protected static $selectList = null;
+       
+       /**
+        * Creates a select list.
+        * 
+        * @param       array<intger>   $ignore
+        * @return      array
+        */
+       public static function getSelectList($ignore = array()) {
+               if (self::$templateGroupStructure === null) {
+                       self::$templateGroupStructure = array();
+                       
+                       $sql = "SELECT          templateGroupID, templateGroupName, parentTemplatePackID
+                               FROM            wcf".WCF_N."_template_group
+                               ORDER BY        templateGroupName ASC";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute();
+                       while ($row = $statement->fetchArray()) {
+                               self::$templateGroupStructure[$row['parentTemplatePackID']][] = new TemplateGroup(null, $row);
+                       }
+                       
+               }
+               
+               self::$selectList = array();
+               self::makeSelectList(0, 0, $ignore);
+               
+               return self::$selectList;
+       }
+       
+       /**
+        * Generates the select list.
+        * 
+        * @param       integer         $parentID               id of the parent template group
+        * @param       integer         $depth                  current list depth
+        * @param       array           $ignore                 list of template group ids to ignore in result
+        */
+       protected static function makeSelectList($parentID = 0, $depth = 0, $ignore = array()) {
+               if (!isset(self::$templateGroupStructure[$parentID])) return;
+               
+               foreach (self::$templateGroupStructure[$parentID] as $templateGroup) {
+                       if (!empty($ignore) && in_array($templateGroup->templateGroupID, $ignore)) continue;
+                       
+                       // we must encode html here because the htmloptions plugin doesn't do it
+                       $title = StringUtil::encodeHTML($templateGroup->templateGroupName);
+                       if ($depth > 0) $title = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $depth). ' ' . $title;
+                       
+                       self::$selectList[$templateGroup->templateGroupID] = $title;
+                       self::makeSelectList($templateGroup->templateGroupID, $depth + 1, $ignore);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/template/group/TemplateGroupAction.class.php b/wcfsetup/install/files/lib/data/template/group/TemplateGroupAction.class.php
new file mode 100644 (file)
index 0000000..d285480
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\data\template\group;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+use wcf\system\exception\ValidateActionException;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Executes template group-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.template.group\r
+ * @category   Community Framework\r
+ */\r
+class TemplateGroupAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\template\group\TemplateGroupEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.template.canAddTemplateGroup');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.template.canDeleteTemplateGroup');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.template.canEditTemplateGroup');\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/group/TemplateGroupEditor.class.php b/wcfsetup/install/files/lib/data/template/group/TemplateGroupEditor.class.php
new file mode 100644 (file)
index 0000000..1e6250d
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+namespace wcf\data\template\group;
+use wcf\data\DatabaseObjectEditor;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * TemplateGroupEditor provides functions to create, edit or delete template group. 
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.template.group
+ * @category   Community Framework
+ */
+class TemplateGroupEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\template\group\TemplateGroup';
+       
+       /**
+        * @see DatabaseObjectEditor::update()
+        */
+       public function update(array $parameters = array()) {
+               parent::update($parameters);
+               
+               if (isset($parameters['templateGroupFolderName']) && ($parameters['templateGroupFolderName'] != $this->templateGroupFolderName)) {
+                       $this->renameFolders($parameters['templateGroupFolderName']);
+               }
+       }
+       
+       /**
+        * Renames the folders of this template group.
+        * 
+        * @param       string          $newFolderName
+        */
+       public function renameFolders($newFolderName) {
+               // default template dir
+               $folders = array(WCF_DIR . 'templates/' . $this->templateGroupFolderName => WCF_DIR . 'templates/' . $newFolderName);
+               
+               // get package dirs
+               $sql = "SELECT  packageDir
+                       FROM    wcf".WCF_N."_package
+                       WHERE   packageDir <> ''";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $packageDir = FileUtil::getRealPath(WCF_DIR . $row['packageDir']);
+                       $folders[$packageDir . 'templates/' . $this->templateGroupFolderName] = $packageDir . 'templates/' . $newFolderName;
+               }
+               
+               // rename folders
+               foreach ($folders as $oldName => $newName) {
+                       if (file_exists($oldName)) {
+                               @rename($oldName, $newName);
+                       }
+               }
+       }
+       
+       /**
+        * Deletes this template group.
+        */
+       public function delete() {
+               // update children
+               $sql = "UPDATE  wcf".WCF_N."_template_group
+                       SET     parentTemplateGroupID = ?
+                       WHERE   parentTemplateGroupID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->parentTemplateGroupID, $this->templateGroupID));
+               
+               parent::delete();
+               
+               $this->deleteFolders();
+       }
+       
+       /**
+        * Deletes the folders of this template group.
+        */
+       public function deleteFolders() {
+               // default template dir
+               $folders = array(WCF_DIR . 'templates/' . $this->templateGroupFolderName);
+               
+               // get package dirs
+               $sql = "SELECT  packageDir
+                       FROM    wcf".WCF_N."_package
+                       WHERE   packageDir <> ''";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $packageDir = FileUtil::getRealPath(WCF_DIR . $row['packageDir']);
+                       $folders[] = $packageDir . 'templates/' . $this->templateGroupFolderName;
+               }
+               
+               // rename folders
+               foreach ($folders as $folder) {
+                       if (file_exists($folder)) {
+                               // empty folder
+                               $files = glob(FileUtil::addTrailingSlash($folder).'*');
+                               if (is_array($files)) {
+                                       foreach ($files as $file) @unlink($file);
+                               }
+                               
+                               // delete foler
+                               @rmdir($folder);
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/template/group/TemplateGroupList.class.php b/wcfsetup/install/files/lib/data/template/group/TemplateGroupList.class.php
new file mode 100644 (file)
index 0000000..6374117
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\template\group;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of template groups.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.template.group\r
+ * @category   Community Framework\r
+ */\r
+class TemplateGroupList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\template\group\TemplateGroup';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/listener/TemplateListener.class.php b/wcfsetup/install/files/lib/data/template/listener/TemplateListener.class.php
new file mode 100644 (file)
index 0000000..cca90a3
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\template\listener;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a template listener.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.template.listener
+ * @category   Community Framework
+ */
+class TemplateListener extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'template_listener';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'listenerID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/listener/TemplateListenerAction.class.php b/wcfsetup/install/files/lib/data/template/listener/TemplateListenerAction.class.php
new file mode 100644 (file)
index 0000000..acc5614
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\template\listener;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes template listener-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.template.listener\r
+ * @category   Community Framework\r
+ */\r
+class TemplateListenerAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\template\listener\TemplateListenerEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/listener/TemplateListenerEditor.class.php b/wcfsetup/install/files/lib/data/template/listener/TemplateListenerEditor.class.php
new file mode 100644 (file)
index 0000000..628f461
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\template\listener;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit template listener.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.template.listener
+ * @category   Community Framework
+ */
+class TemplateListenerEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\template\listener\TemplateListener';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/template/listener/TemplateListenerList.class.php b/wcfsetup/install/files/lib/data/template/listener/TemplateListenerList.class.php
new file mode 100644 (file)
index 0000000..ee6d662
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\template\listener;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of template listener.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.template.listener\r
+ * @category   Community Framework\r
+ */\r
+class TemplateListenerList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\template\listener\TemplateListener';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/User.class.php b/wcfsetup/install/files/lib/data/user/User.class.php
new file mode 100644 (file)
index 0000000..df3f493
--- /dev/null
@@ -0,0 +1,273 @@
+<?php
+namespace wcf\data\user;
+use wcf\data\DatabaseObject;
+use wcf\data\user\group\UserGroup;
+use wcf\data\user\UserList;
+use wcf\system\cache\CacheHandler;
+use wcf\system\storage\StorageHandler;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Represents a user.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user
+ * @category   Community Framework
+ */
+class User extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'user';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'userID';
+       
+       /**
+        * list of group ids
+        *
+        * @var array<integer>
+        */
+       protected $groupIDs = null;
+       
+       /**
+        * list of language ids
+        * 
+        * @var array<integer>
+        */
+       protected $languageIDs = null;
+       
+       /**
+        * date time zone object
+        * @var DateTimeZone
+        */
+       protected $timezoneObj = null;
+       
+       /**
+        * list of user options.
+        *
+        * @var array<string>
+        */
+       protected static $userOptions = null;
+       
+       /**
+        * Returns true, if the given password is the correct password for this user.
+        *
+        * @param       string          $password
+        * @return      boolean         password correct
+        */
+       public function checkPassword($password) {
+               return ($this->password == StringUtil::getDoubleSaltedHash($password, $this->salt));
+       }
+       
+       /**
+        * Returns true, if the given password hash from a cookie is the correct password for this user.
+        *
+        * @param       string          $passwordHash
+        * @return      boolean         password correct
+        */
+       public function checkCookiePassword($passwordHash) {
+               return ($this->password == StringUtil::encrypt($this->salt . $passwordHash));
+       }
+       
+       /**
+        * Returns an array with the all the groups in which the actual user is a member.
+        *
+        * @return      array           $groupIDs
+        */
+       public function getGroupIDs() {
+               if ($this->groupIDs === null) {
+                       if (!$this->userID) {
+                               // user is a guest, use default guest group
+                               $this->groupIDs = UserGroup::getGroupIDsByType(array(UserGroup::GUESTS));
+                       }
+                       else {
+                               // load storage data
+                               StorageHandler::getInstance()->loadStorage(array($this->userID), 1);
+                               
+                               // get group ids
+                               $data = StorageHandler::getInstance()->getStorage(array($this->userID), 'groupIDs', 1);
+                               
+                               // cache does not exist or is outdated
+                               if ($data[$this->userID] === null) {
+                                       $this->groupIDs = array();
+                                       $sql = "SELECT  groupID
+                                               FROM    wcf".WCF_N."_user_to_group
+                                               WHERE   userID = ?";
+                                       $statement = WCF::getDB()->prepareStatement($sql);
+                                       $statement->execute(array($this->userID));
+                                       while ($row = $statement->fetchArray()) {
+                                               $this->groupIDs[] = $row['groupID'];
+                                       }
+                                       
+                                       // update storage data
+                                       StorageHandler::getInstance()->update($this->userID, 'groupIDs', serialize($this->groupIDs), 1);
+                               }
+                               else {
+                                       $this->groupIDs = unserialize($data[$this->userID]);
+                               }
+                       }
+               }
+               
+               return $this->groupIDs;
+       }
+       
+       /**
+        * Returns a list of language ids for this user.
+        * 
+        * @return      array<integer>
+        */
+       public function getLanguageIDs() {
+               if ($this->languageIDs === null) {
+                       // load storage data
+                       StorageHandler::getInstance()->loadStorage(array($this->userID), 1);
+                       
+                       // get group ids
+                       $data = StorageHandler::getInstance()->getStorage(array($this->userID), 'languageIDs', 1);
+                       
+                       // cache does not exist or is outdated
+                       if ($data[$this->userID] === null) {
+                               $sql = "SELECT  languageID
+                                       FROM    wcf".WCF_N."_user_to_language
+                                       WHERE   userID = ?";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute(array($this->userID));
+                               while ($row = $statement->fetchArray()) {
+                                       $this->languageIDs[] = $row['languageID'];
+                               }
+                               
+                               // update storage data
+                               StorageHandler::getInstance()->update($this->userID, 'languageIDs', serialize($this->languageIDs), 1);
+                       }
+                       else {
+                               $this->languageIDs = unserialize($data[$this->userID]);
+                       }
+               }
+               
+               return $this->languageIDs;
+       }
+       
+       /**
+        * Returns the value of the user option with the given name.
+        *
+        * @param       string          $name           user option name
+        * @return      mixed                           user option value
+        */
+       public function getUserOption($name) {
+               $optionID = self::getUserOptionID($name);
+               if ($optionID === null) {
+                       return null;
+               }
+               
+               if (!isset($this->data['userOption'.$optionID])) return null;
+               return $this->data['userOption'.$optionID];
+       }
+       
+       /**
+        * Gets all user options from cache.
+        */
+       protected static function getUserOptionCache() {
+               $cacheName = 'user-option-'.PACKAGE_ID;
+               CacheHandler::getInstance()->addResource($cacheName, WCF_DIR.'cache/cache.'.$cacheName.'.php', 'wcf\system\cache\CacheBuilderOption');
+               self::$userOptions = CacheHandler::getInstance()->get($cacheName, 'options');
+       }
+       
+       /**
+        * Returns the id of a user option.
+        *
+        * @param       string          $name
+        * @return      integer         id
+        */
+       public static function getUserOptionID($name) {
+               // get user option cache if necessary
+               if (self::$userOptions === null) {
+                       self::getUserOptionCache();
+               }
+               
+               if (!isset(self::$userOptions[$name])) {
+                       return null;
+               }
+               
+               return self::$userOptions[$name]['optionID'];
+       }
+       
+       /**
+        * @see DatabaseObject::__get()
+        */
+       public function __get($name) {
+               $value = parent::__get($name);
+               if ($value === null) $value = $this->getUserOption($name);
+               return $value;
+       }
+       
+       /**
+        * Returns User-object by username.
+        *
+        * @param       string          $username
+        * @return      User
+        */
+       public static function getUserByUsername($username) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_user
+                       WHERE   username = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($username));
+               $row = $statement->fetchArray();
+               if (!$row) $row = array();
+               
+               return new User(null, $row);
+       }
+       
+       /**
+        * Returns true, if this user is marked.
+        *
+        * @return      boolean
+        */
+       public function isMarked() {
+               $markedUsers = WCF::getSession()->getVar('markedUsers');
+               if ($markedUsers !== null) {
+                       if (in_array($this->userID, $markedUsers)) return 1;
+               }
+               
+               return 0;
+       }
+       
+       /**
+        * Returns the time zone of this user.
+        *
+        * @return DateTimeZone
+        */
+       public function getTimeZone() {
+               if ($this->timezoneObj === null) {
+                       if ($this->timezone) {
+                               $this->timezoneObj = new \DateTimeZone($this->timezone);
+                       }
+                       else {
+                               $this->timezoneObj = new \DateTimeZone(TIMEZONE);
+                       }
+               }
+               
+               return $this->timezoneObj;
+       }
+       
+       /**
+        * Returns a list of users.
+        * 
+        * @param       array           $userIDs
+        * @return      array<User>
+        */     
+       public static function getUsers(array $userIDs) {
+               $userList = new UserList();
+               $userList->getConditionBuilder()->add("user_table.userID IN (?)", array($userIDs));
+               $userList->readObjects();
+               
+               return $userList->getObjects();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/user/UserAction.class.php b/wcfsetup/install/files/lib/data/user/UserAction.class.php
new file mode 100644 (file)
index 0000000..612d9bf
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+namespace wcf\data\user;
+use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\user\group\UserGroup;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\ValidateActionException;
+use wcf\system\WCF;
+
+/**
+ * Executes user-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user
+ * @category   Community Framework
+ */
+class UserAction extends AbstractDatabaseObjectAction {
+       /**
+        * @see AbstractDatabaseObjectAction::$className
+        */
+       public $className = 'wcf\data\user\UserEditor';
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsCreate
+        */
+       protected $permissionsCreate = array('admin.user.canAddUser');
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsDelete
+        */
+       protected $permissionsDelete = array('admin.user.canDeleteUser');
+       
+       /**
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate
+        */
+       protected $permissionsUpdate = array('admin.user.canEditUser');
+       
+       /**
+        * Validates permissions and parameters.
+        */
+       public function validateCreate() {
+               if (!isset($this->parameters['data']['password'])) {
+                       throw new ValidateActionException("Missing parameter 'password'");
+               }
+       }
+       
+       /**
+        * Validates permissions and parameters.
+        */
+       public function validateDelete() {
+               // read and validate user objects
+               parent::validateDelete();
+               
+               $userIDs = array();
+               foreach ($this->users as $user) $userIDs[] = $user->userID;
+               
+               // validate groups
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("userID IN (?)", array($userIDs));
+               
+               $sql = "SELECT  DISTINCT groupID
+                       FROM    wcf".WCF_N."_user_to_group
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               
+               $groupIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       $groupIDs[] = $row['groupID'];
+               }
+               
+               if (!UserGroup::isAccessibleGroup($groupIDs)) {
+                       throw new ValidateActionException('Insufficient permissions');
+               }
+       }
+       
+       /**
+        * Validates permissions and parameters.
+        * 
+        * @todo        Handle multiple users?
+        */
+       public function validateUpdate() {
+               // read and validate user objects
+               parent::validateUpdate();
+               
+               // editing own user
+               if (count($this->objectIDs) == 1 && WCF::getUser()->userID == $this->objects[0]->userID) return;
+               
+               throw new ValidateActionException('Insufficient permissions');
+       }
+       
+       /**
+        * Creates a new user.
+        * 
+        * @return      User
+        */
+       public function create() {
+               $user = parent::create();
+               $userEditor = new UserEditor($user);
+               
+               // updates user options
+               if (isset($this->parameters['options'])) {
+                       $userEditor->updateUserOptions($this->parameters['options']);
+               }
+               
+               // insert user groups
+               $groupIDs = (isset($this->parameters['groups'])) ? $this->parameters['groups'] : array();
+               $userEditor->addToGroups($groupIDs, false);
+               
+               // insert visible languages
+               $languageIDs = (isset($this->parameters['languages'])) ? $this->parameters['languages'] : array();
+               $userEditor->addToLanguages($languageIDs);
+               
+               return $user;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/user/UserEditor.class.php b/wcfsetup/install/files/lib/data/user/UserEditor.class.php
new file mode 100644 (file)
index 0000000..4651aff
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+namespace wcf\data\user;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\user\group\UserGroup;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Provides functions to edit users.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user
+ * @category   Community Framework
+ */
+class UserEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\user\User';
+       
+       /**
+        * @see EditableObject::create()
+        */
+       public static function create(array $parameters = array()) {
+               // create salt and password hash
+               $parameters['salt'] = StringUtil::getRandomID();
+               $parameters['password'] = StringUtil::getDoubleSaltedHash($parameters['password'], $parameters['salt']);
+               
+               $user = parent::create($parameters);
+               
+               // create default values for user options
+               self::createUserOptions($user->userID);
+               
+               return $user;
+       }
+       
+       /**
+        * @see DatabaseObjectEditor::update()
+        */
+       public function update(array $parameters = array()) {
+               // update salt and create new password hash
+               if (isset($parameters['password'])) {
+                       $parameters['salt'] = StringUtil::getRandomID();
+                       $parameters['password'] = StringUtil::getDoubleSaltedHash($parameters['password'], $parameters['salt']);
+               }
+               
+               parent::update($parameters);
+       }
+       
+       /**
+        * Inserts default options.
+        *
+        * @param       integer         $userID
+        */
+       protected static function createUserOptions($userID) {
+               $userOptions = array();
+               
+               // fetch default values
+               $sql = "SELECT  optionID, defaultValue
+                       FROM    wcf".WCF_N."_user_option";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       if (!empty($row['defaultValue'])) {
+                               $userOptions[$row['optionID']] = $row['defaultValue'];
+                       }
+               }
+               
+               // insert default values
+               $keys = $values = '';
+               $statementParameters = array($userID);
+               foreach ($userOptions as $optionID => $optionValue) {
+                       $keys .= ', userOption'.$optionID;
+                       $values .= ', ?';
+                       $statementParameters[] = $optionValue;
+               }
+               
+               $sql = "INSERT INTO     wcf".WCF_N."_user_option_value
+                                       (userID".$keys.")
+                       VALUES          (?".$values.")";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($statementParameters);
+       }
+       
+       /**
+        * Updates user options.
+        *
+        * @param       array           $userOptions
+        */
+       public function updateUserOptions(array $userOptions = array()) {
+               $updateSQL = '';
+               $statementParameters = array();
+               foreach ($userOptions as $optionID => $optionValue) {
+                       if (!empty($updateSQL)) $updateSQL .= ',';
+                       
+                       $updateSQL .= 'userOption'.$optionID.' = ?';
+                       $statementParameters[] = $optionValue;
+               }
+               $statementParameters[] = $this->userID;
+               
+               if (!empty($updateSQL)) {
+                       $sql = "UPDATE  wcf".WCF_N."_user_option_value
+                               SET     ".$updateSQL."
+                               WHERE   userID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($statementParameters);
+               }
+       }
+       
+       /**
+        * Adds a user to the groups he should be in.
+        *
+        * @param       array           $groups
+        * @param       boolean         $deleteOldGroups
+        * @param       boolean         $addDefaultGroups
+        */
+       public function addToGroups(array $groupIDs, $deleteOldGroups = true, $addDefaultGroups = true) {
+               // add default groups
+               if ($addDefaultGroups) {
+                       $groupIDs = array_merge($groupIDs, UserGroup::getGroupIDsByType(array(UserGroup::EVERYONE, UserGroup::USERS)));
+                       $groupIDs = array_unique($groupIDs);
+               }
+               
+               // remove old groups
+               if ($deleteOldGroups) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_user_to_group
+                               WHERE           userID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->userID));
+               }
+               
+               // insert new groups
+               if (count($groupIDs) > 0) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_user_to_group
+                                               (userID, groupID)
+                               VALUES          (?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($groupIDs as $groupID) {
+                               $statement->execute(array($this->userID, $groupID));
+                       }
+               }
+       }
+       
+       /**
+        * Adds a user to a user group.
+        *
+        * @param       integer         $groupID
+        */
+       public function addToGroup($groupID) {
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_user_to_group
+                       WHERE   userID = ?".$this->userID."
+                               AND groupID = ?".$groupID;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->userID,
+                       $groupID
+               ));
+               $row = $statement->fetchArray();
+               
+               if (!$row['count']) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_user_to_group
+                                               (userID, groupID)
+                               VALUES          (?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->userID, $groupID));
+               }
+       }
+       
+       /**
+        * Removes a user from a user group.
+        *
+        * @param       integer         $groupID
+        */
+       public function removeFromGroup($groupID) {
+               $sql = "DELETE FROM     wcf".WCF_N."_user_to_group
+                       WHERE           userID = ?
+                                       AND groupID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->userID, $groupID));
+       }
+       
+       /**
+        * Saves the visible languages of a user.
+        *
+        * @param       array           $languageIDs
+        */
+       public function addToLanguages(array $languageIDs) {
+               // remove previous languages
+               $sql = "DELETE FROM     wcf".WCF_N."_user_to_language
+                       WHERE           userID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->userID));
+               
+               // insert language ids
+               if (count($languageIDs) > 0) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_user_to_language
+                                               (userID, languageID)
+                               VALUES          (?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($languageIDs as $languageID) {
+                               $statement->execute(array($this->userID, $languageID));
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/user/UserList.class.php b/wcfsetup/install/files/lib/data/user/UserList.class.php
new file mode 100644 (file)
index 0000000..921ab4f
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of users.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user\r
+ * @category   Community Framework\r
+ */\r
+class UserList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\user\User';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/UserGroup.class.php b/wcfsetup/install/files/lib/data/user/group/UserGroup.class.php
new file mode 100644 (file)
index 0000000..febb780
--- /dev/null
@@ -0,0 +1,302 @@
+<?php
+namespace wcf\data\user\group;
+use wcf\data\DatabaseObject;
+use wcf\system\cache\CacheHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Represents a user group.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.group
+ * @category   Community Framework
+ */
+class UserGroup extends DatabaseObject {
+       /**
+        * group type everyone user group
+        * @var integer
+        */
+       const EVERYONE = 1;
+       
+       /**
+        * group type guests user group
+        * @var integer
+        */
+       const GUESTS = 2;
+       
+       /**
+        * group type registered users user group
+        * @var integer
+        */
+       const USERS = 3;
+       
+       /**
+        * group type of other user groups
+        * @var integer
+        */
+       const OTHER = 4;
+       
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'user_group';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'groupID';
+       
+       /**
+        * Caches groups.
+        * 
+        * @var array<UserGroup>
+        */
+       protected static $cache = null;
+       
+       /**
+        * list of accessible groups for active user.
+        * 
+        * @param       array<integer>
+        */
+       protected static $accessibleGroups = null;
+       
+       /**
+        * Cached group options of this group.
+        * 
+        * @var array<array>
+        */
+       protected $groupOptions = null;
+       
+       /**
+        * Returns group ids by given type.
+        * 
+        * @param       array<integer>          $types
+        * @return      array<integer>
+        */
+       public static function getGroupIDsByType(array $types) {
+               self::getCache();
+               
+               $groupIDs = array();
+               foreach ($types as $type) {
+                       if (isset(self::$cache['types'][$type])) {
+                               $groupIDs = array_merge($groupIDs, self::$cache['types'][$type]);
+                       }
+               }
+               $groupIDs = array_unique($groupIDs);
+               
+               return $groupIDs;
+       }
+       
+       /**
+        * Returns groups by given type. Returns all groups if no types given.
+        * 
+        * @param       array<integer>          $types
+        * @return      array<UserGroup>
+        */
+       public static function getGroupsByType(array $types = array()) {
+               self::getCache();
+               // get all groups
+               if (!count($types)) return self::$cache['groups'];
+               
+               // get groups by type
+               $groupIDs = self::getGroupIDsByType($types);
+               $groups = array();
+               
+               foreach ($groupIDs as $groupID) {
+                       $groups[$groupID] = self::$cache['groups'][$groupID];
+               }
+               
+               return $groups;
+       }
+       
+       /**
+        * Returns unique group by given type. Only works for the default user groups.
+        * 
+        * @param       integer         $type
+        * @return      UserGroup
+        */
+       public static function getGroupByType($type) {
+               if ($type != self::EVERYONE && $type != self::GUESTS && $type != self::USERS) {
+                       throw new SystemException('invalid value for type argument');
+               }
+               
+               $groups = self::getGroupsByType(array($type));
+               return array_shift($groups);
+       }
+       
+       /**
+        * Returns true, if the active user is member of the given group.
+        * 
+        * @param       integer         $groupID
+        * @return      boolean             
+        */
+       public static function isMember($groupID) {
+               if (in_array($groupID, WCF::getUser()->getGroupIDs())) return true;
+               return false;
+       }
+       
+       /**
+        * Returns true, if the given groups are accessible for the active user.
+        * 
+        * @param       array           $groupIDs
+        * @return      boolean
+        */
+       public static function isAccessibleGroup(array $groupIDs = array()) {
+               if (self::$accessibleGroups === null) {
+                       self::$accessibleGroups = explode(',', WCF::getSession()->getPermission('admin.user.accessibleGroups'));
+               }
+               
+               if (count($groupIDs) == 0) return false;
+               
+               foreach ($groupIDs as $groupID) {
+                       if (!in_array($groupID, self::$accessibleGroups)) {
+                               return false;
+                       } 
+               }
+               
+               return true;
+       }
+       
+       /**
+        * Returns a list of accessible groups.
+        * 
+        * @param       array<integer>          $groupTypes
+        * @param       array<integer>          $invalidGroupTypes
+        * @return      array<UserGroup>
+        */
+       public static function getAccessibleGroups(array $groupTypes = array(), array $invalidGroupTypes = array()) {
+               $groups = self::getGroupsByType($groupTypes);
+               
+               if (count($invalidGroupTypes) > 0) {
+                       $invalidGroups = self::getGroupsByType($invalidGroupTypes);
+                       foreach ($invalidGroups as $groupID => $group) {
+                               unset($groups[$groupID]);
+                       }
+               }
+               
+               foreach ($groups as $key => $value) {
+                       if (!self::isAccessibleGroup(array($key))) {
+                               unset($groups[$key]);
+                       }
+               }
+               
+               return $groups;
+       }
+       
+       /**
+        * Loads the group cache.
+        */
+       protected static function getCache() {
+               if (self::$cache === null) {
+                       CacheHandler::getInstance()->addResource('usergroups', WCF_DIR.'cache/cache.usergroups.php', 'wcf\system\cache\CacheBuilderUserGroup');
+                       self::$cache = CacheHandler::getInstance()->get('usergroups');
+               }
+       }
+       
+       /**
+        * Returns true, if this group is accessible for the active user.
+        * 
+        * @return      boolean
+        */
+       public function isAccessible() {
+               return self::isAccessibleGroup(array($this->groupID));
+       }
+       
+       /**
+        * Returns the name of this user group.
+        * 
+        * @return      string
+        */
+       public function __tostring() {
+               return $this->groupName;
+       }
+       
+       /**
+        * Returns true if current user may delete this group.
+        * 
+        * @return      boolean
+        */
+       public function isDeletable() {
+               // insufficient permissions
+               if (!WCF::getSession()->getPermission('admin.user.canDeleteGroup')) return false;
+               
+               // cannot delete own groups
+               if (UserGroup::isMember($this->groupID)) return false;
+               
+               // user cannot delete this group
+               if (!UserGroup::isAccessibleGroup(array($this->groupID))) return false;
+               
+               // cannot delete static groups
+               if ($this->groupType == UserGroup::EVERYONE || $this->groupType == UserGroup::GUESTS || $this->groupType == UserGroup::USERS) return false;
+               
+               return true;
+       }
+       
+       /**
+        * Returns true if current user may edit this group.
+        * 
+        * @return      boolean
+        */
+       public function isEditable() {
+               // insufficient permissions
+               if (!WCF::getSession()->getPermission('admin.user.canEditGroup')) return false;
+               
+               // user cannot edit this group
+               if (!UserGroup::isAccessibleGroup(array($this->groupID))) return false;
+               
+               return true;
+       }
+       
+       /**
+        * Returns the value of the group option with the given name.
+        * 
+        * @param       string          $name
+        * @return      mixed
+        */
+       public function getGroupOption($name) {
+               if ($this->groupOptions === null) {
+                       // get all options and filter options with low priority
+                       $groupOptionIDs = array();
+                       $sql = "SELECT          optionName, optionID 
+                               FROM            wcf".WCF_N."_user_group_option option_table
+                               LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                               ON              (package_dependency.dependency = option_table.packageID)
+                               WHERE           package_dependency.packageID = ?
+                               ORDER BY        package_dependency.priority ASC";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(PACKAGE_ID));
+                       while ($row = $statement->fetchArray()) {
+                               $groupOptionIDs[$row['optionName']] = $row['optionID'];
+                       }
+                       
+                       if (count($groupOptionIDs)) {
+                               $conditions = new PreparedStatementConditionBuilder();
+                               $conditions->add("option_value.groupID = ?", array($this->groupID));
+                               $conditions->add("option_value.optionID IN (?)", array($groupOptionIDs));
+                               
+                               $sql = "SELECT          group_option.optionName, option_value.optionValue
+                                       FROM            wcf".WCF_N."_user_group_option_value option_value
+                                       LEFT JOIN       wcf".WCF_N."_user_group_option group_option
+                                       ON              (group_option.optionID = option_value.optionID)
+                                       ".$conditions;
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute($conditions->getParameters());
+                               while ($row = $statement->fetchArray()) {
+                                       $this->groupOptions[$row['optionName']] = $row['optionValue'];
+                               }
+                       }
+               }
+               
+               if (isset($this->groupOptions[$name])) {
+                       return $this->groupOptions[$name];
+               }
+               
+               return null;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/user/group/UserGroupAction.class.php b/wcfsetup/install/files/lib/data/user/group/UserGroupAction.class.php
new file mode 100644 (file)
index 0000000..f4f44dd
--- /dev/null
@@ -0,0 +1,64 @@
+<?php\r
+namespace wcf\data\user\group;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes user group-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.group\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       public $className = 'wcf\data\user\group\UserGroupEditor';\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsCreate\r
+        */\r
+       protected $permissionsCreate = array('admin.user.canAddGroup');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsDelete\r
+        */\r
+       protected $permissionsDelete = array('admin.user.canDeleteGroup');\r
+       \r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$permissionsUpdate\r
+        */\r
+       protected $permissionsUpdate = array('admin.user.canEditGroup');\r
+       \r
+       /**\r
+        * Creates a new group.\r
+        * \r
+        * @return      UserGroup\r
+        */\r
+       public function create() {\r
+               $group = parent::create();\r
+               \r
+               $groupEditor = new UserGroupEditor($group);\r
+               $groupEditor->updateGroupOptions($this->parameters['options']);\r
+               \r
+               return $group;\r
+       }\r
+       \r
+       /**\r
+        * Updates groups.\r
+        */\r
+       public function update() {\r
+               if (!count($this->objects)) {\r
+                       $this->readObjects();\r
+               }\r
+               \r
+               foreach ($this->objects as $object) {\r
+                       $object->update($this->parameters['data']);\r
+                       $object->updateGroupOptions($this->parameters['options']);\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/UserGroupEditor.class.php b/wcfsetup/install/files/lib/data/user/group/UserGroupEditor.class.php
new file mode 100644 (file)
index 0000000..3f40e4e
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+namespace wcf\data\user\group;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\EditableCachedObject;
+use wcf\data\acp\session\ACPSession;
+use wcf\system\cache\CacheHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\session\SessionHandler;
+use wcf\system\WCF;
+
+/**
+ * Provides functions to edit user groups.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.group
+ * @category   Community Framework
+ */
+class UserGroupEditor extends DatabaseObjectEditor implements EditableCachedObject {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\user\group\UserGroup';
+       
+       /**
+        * @see EditableObject::create()
+        */
+       public static function create(array $parameters = array()) {
+               $group = parent::create($parameters);
+               
+               // update accessible groups
+               self::updateAccessibleGroups($group->groupID);
+               
+               return $group;
+       }
+       
+       /**
+        * @see DatabaseObjectEditor::__deleteAll()
+        */
+       public static function deleteAll(array $objectIDs = array()) {
+               parent::deleteAll($objectIDs);
+               
+               // remove user to group assignments
+               self::removeGroupAssignments($objectIDs);
+               
+               // remove group option values
+               self::removeOptionValues($objectIDs);
+               
+               foreach ($objectIDs as $objectID) {
+                       self::updateAccessibleGroups($objectID, true);
+               }
+               
+               return $returnValue;
+       }
+       
+       /**
+        * Removes user to group assignments.
+        * 
+        * @param       array           $groupIDs
+        */
+       protected static function removeGroupAssignments(array $groupIDs) {
+               if (!count($groupIDs)) return;
+               
+               $sql = "DELETE FROM     wcf".WCF_N."_user_to_group
+                       WHERE           groupID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($groupIDs as $groupID) {
+                       $statement->execute(array($groupID));
+               }
+       }
+       
+       /**
+        * Removes group option values.
+        * 
+        * @param       array           $groupIDs
+        */
+       protected static function removeOptionValues(array $groupIDs) {
+               if (!count($groupIDs)) return;
+               
+               $sql = "DELETE FROM     wcf".WCF_N."_user_group_option_value
+                       WHERE           groupID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($groupIDs as $groupID) {
+                       $statement->execute(array($groupID));
+               }
+       }
+       
+       /**
+        * Updates group options.
+        * 
+        * @param       array           $groupOptions
+        */
+       public function updateGroupOptions(array $groupOptions = array()) {
+               // delete old group options
+               $sql = "DELETE FROM     wcf".WCF_N."_user_group_option_value
+                       WHERE           groupID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->groupID));
+               
+               // insert new options
+               $sql = "INSERT INTO     wcf".WCF_N."_user_group_option_value
+                                       (groupID, optionID, optionValue)
+                       VALUES          (?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($groupOptions as $id => $value) {
+                       $statement->execute(array($this->groupID, $id, $value));
+               }
+       }
+       
+       /**
+        * Updates the value from the accessiblegroups option.
+        * 
+        * @param       integer         $groupID        this group is added or deleted in the value     
+        * @param       boolean         $delete         flag for group deletion
+        */
+       protected static function updateAccessibleGroups($groupID, $delete = false) {
+               if ($delete) {
+                       $sql = "UPDATE  wcf".WCF_N."_group_option_value
+                                       SET     optionValue = ?
+                                       WHERE   groupID = ?
+                                       AND     optionID = ?";
+                       $updateStatement = WCF::getDB()->prepareStatement($sql);
+                       
+                       $sql = "SELECT          groupID, optionValue, groupOption.optionID
+                               FROM            wcf".WCF_N."_group_option groupOption
+                               LEFT JOIN       wcf".WCF_N."_group_option_value optionValue
+                               ON              (groupOption.optionID = optionValue.optionID)
+                               WHERE           groupOption.optionname = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array('admin.user.accessibleGroups'));
+                       while ($row = $statement->fetchArray($result)) {
+                               $valueIDs = explode(',', $row['optionValue']);
+                               if (in_array($groupID, $valueIDs)) {
+                                       $key = array_keys($valueIDs, $groupID);
+                                       if (!empty($key)) unset($valueIDs[$key[0]]);
+                                       $updateIDs = implode(",", $valueIDs); 
+                                       
+                                       $updateStatement->execute(array(implode(',', $valueIDs), $row['groupID'], $row['optionID']));
+                               }
+                       }
+                       
+                       return;
+               }
+               
+               // get existing groups
+               $groupIDs = array();
+               $sql = "SELECT          groupID
+                       FROM            wcf".WCF_N."_user_group
+                       ORDER BY        groupID ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       if ($row['groupID'] == $groupID) continue;
+                       $groupIDs[] = $row['groupID'];
+               }
+               
+               $optionID = 0;
+               $targetGroupIDs = array();
+               
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("groupOption.optionName = ?", array('admin.user.accessibleGroups'));
+               $conditions->add("groupID IN (?)", array($groupIDs));
+               
+               $sql = "SELECT          groupID, optionValue, groupOption.optionID
+                       FROM            wcf".WCF_N."_user_group_option groupOption
+                       LEFT JOIN       wcf".WCF_N."_user_group_option_value optionValue
+                       ON              (groupOption.optionID = optionValue.optionID)
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               
+               $updateGroupIDs = array();
+               $optionID = 0;
+               // get groups which got "accessibleGroups"-option with all groupIDs
+               while ($row = $statement->fetchArray()) {
+                       
+                       // check for differences in options-groups and existing-groups  
+                       $optionGroupIDs = explode(',', $row['optionValue']);
+                       $differences = array_diff($optionGroupIDs, $groupIDs);
+                       
+                       // get groups which got the right to change all groups                  
+                       if (empty($differences) && (count($optionGroupIDs) == count($groupIDs))) {
+                               $updateGroupIDs[] = $row['groupID'];
+                               $optionID = $row['optionID'];
+                       }
+               }
+               
+               // update optionValue from groups which got all existing groups as value
+               if (count($updateGroupIDs)) {
+                       $groupIDs[] = $groupID;
+                       
+                       $sql = "UPDATE  wcf".WCF_N."_user_group_option_value
+                               SET     optionValue = ?
+                               WHERE   groupID IN (".implode(',', $updateGroupIDs).")
+                               AND     optionID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(implode(',', $groupIDs), $optionID));
+               }
+       }
+       
+       /**
+        * @see EditableCachedObject::resetCache()
+        */
+       public static function resetCache() {
+               // clear cache
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.groups*.php', true);
+               
+               // clear sessions
+               SessionHandler::resetSessions();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/data/user/group/UserGroupList.class.php b/wcfsetup/install/files/lib/data/user/group/UserGroupList.class.php
new file mode 100644 (file)
index 0000000..c197cff
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\group;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of user groups.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.group\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\user\group\UserGroup';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/UserGroupOption.class.php b/wcfsetup/install/files/lib/data/user/group/option/UserGroupOption.class.php
new file mode 100644 (file)
index 0000000..e3c2f4a
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\user\group\option;
+use wcf\data\option\Option;
+
+/**
+ * Represents a usergroup option.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.group.option
+ * @category   Community Framework
+ */
+class UserGroupOption extends Option {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'user_group_option';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'optionID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionAction.class.php b/wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionAction.class.php
new file mode 100644 (file)
index 0000000..8d07b43
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\group\option;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes user group option-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.group.option\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupOptionAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\user\group\option\UserGroupOptionEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionEditor.class.php b/wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionEditor.class.php
new file mode 100644 (file)
index 0000000..2008017
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\user\group\option;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit usergroup options.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.group.option
+ * @category   Community Framework
+ */
+class UserGroupOptionEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\user\group\option\UserGroupOption';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionList.class.php b/wcfsetup/install/files/lib/data/user/group/option/UserGroupOptionList.class.php
new file mode 100644 (file)
index 0000000..89b8f5e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\group\option;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of user group options.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.group.option\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupOptionList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\user\group\option\UserGroupOption';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategory.class.php b/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategory.class.php
new file mode 100644 (file)
index 0000000..1247e35
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+namespace wcf\data\user\group\option\category;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a usergroup options category.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.group.option.category
+ * @category   Community Framework
+ */
+class UserGroupOptionCategory extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'user_group_option_category';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'categoryID';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryAction.class.php b/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryAction.class.php
new file mode 100644 (file)
index 0000000..674344e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\group\option\category;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes user group option category-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.group.option.category\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupOptionCategoryAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\user\group\option\category\UserGroupOptionCategoryEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryEditor.class.php b/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryEditor.class.php
new file mode 100644 (file)
index 0000000..ae07ceb
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+namespace wcf\data\user\group\option\category;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit usergroup option categories.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.group.option.category
+ * @category   Community Framework
+ */
+class UserGroupOptionCategoryEditor extends DatabaseObjectEditor {
+       /**
+        * @see DatabaseObjectEditor::$baseClass
+        */
+       protected static $baseClass = 'wcf\user\group\option\category\UserGroupOptionCategory';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryList.class.php b/wcfsetup/install/files/lib/data/user/group/option/category/UserGroupOptionCategoryList.class.php
new file mode 100644 (file)
index 0000000..ba7178b
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\group\option\category;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of user group option categories.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.group.option.category\r
+ * @category   Community Framework\r
+ */\r
+class UserGroupOptionCategoryList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\user\group\option\category\UserGroupOptionCategory';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/UserOption.class.php b/wcfsetup/install/files/lib/data/user/option/UserOption.class.php
new file mode 100644 (file)
index 0000000..8582608
--- /dev/null
@@ -0,0 +1,26 @@
+<?php\r
+namespace wcf\data\user\option;\r
+use wcf\data\option\Option;\r
+\r
+/**\r
+ * Represents a user option.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option\r
+ * @category   Community Framework\r
+ */\r
+class UserOption extends Option {\r
+       /**\r
+        * @see DatabaseObject::$databaseTableName\r
+        */\r
+       protected static $databaseTableName = 'user_option';\r
+       \r
+       /**\r
+        * @see DatabaseObject::$databaseTableIndexName\r
+        */\r
+       protected static $databaseTableIndexName = 'optionID';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/UserOptionAction.class.php b/wcfsetup/install/files/lib/data/user/option/UserOptionAction.class.php
new file mode 100644 (file)
index 0000000..8e05fa3
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\option;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes user option-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option\r
+ * @category   Community Framework\r
+ */\r
+class UserOptionAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\user\option\UserOptionEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/UserOptionEditor.class.php b/wcfsetup/install/files/lib/data/user/option/UserOptionEditor.class.php
new file mode 100644 (file)
index 0000000..d05b37a
--- /dev/null
@@ -0,0 +1,141 @@
+<?php\r
+namespace wcf\data\user\option;\r
+use wcf\data\DatabaseObjectEditor;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Provides functions to edit user options.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option\r
+ * @category   Community Framework\r
+ */\r
+class UserOptionEditor extends DatabaseObjectEditor {\r
+       /**\r
+        * @see DatabaseObjectEditor::$baseClass\r
+        */\r
+       protected static $baseClass = 'wcf\data\user\option\UserOption';\r
+       \r
+       /**\r
+        * @see EditableObject::create()\r
+        */\r
+       public static function create(array $parameters = array()) {\r
+               $userOption = parent::create($parameters);\r
+               \r
+               // alter the table "wcf".WCF_N."_user_option_value" with this new option\r
+               WCF::getDB()->getEditor()->addColumn('wcf'.WCF_N.'_user_option_value', 'userOption'.$userOption->optionID, self::getColumnDefinition($parameters['optionType']));\r
+               \r
+               // add the default value to this column\r
+               if (isset($parameters['$defaultValue'])) {\r
+                       $sql = "UPDATE  wcf".WCF_N."_user_option_value\r
+                               SET     userOption".$userOption->optionID." = ?";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute(array($parameters['defaultValue']));\r
+               }\r
+               \r
+               return $userOption;\r
+       }\r
+       \r
+       /**\r
+        * @see EditableObject::update()\r
+        */\r
+       public function update(array $parameters = array()) {\r
+               parent::update($parameters);\r
+               \r
+               // alter the table "wcf".WCF_N."_user_option_value" with this new option\r
+               $sql = WCF::getDB()->getEditor()->updateColumn(\r
+                       'wcf'.WCF_N.'_user_option_value',\r
+                       'userOption'.$this->optionID,\r
+                       'userOption'.$this->optionID,\r
+                       self::getColumnDefinition($parameters['optionType'])\r
+               );\r
+       }\r
+       \r
+       /**\r
+        * @see EditableObject::delete()\r
+        */\r
+       public function delete() {\r
+               $sql = "DELETE FROM     wcf".WCF_N."_user_option\r
+                       WHERE           optionID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($this->optionID));\r
+               \r
+               $sql = WCF::getDB()->getEditor()->dropColumn('wcf'.WCF_N.'_user_option_value', 'userOption'.$this->optionID);\r
+       }\r
+       \r
+       /**\r
+        * Disables this option.\r
+        */\r
+       public function disable() {\r
+               $this->enable(false);\r
+       }\r
+       \r
+       /**\r
+        * Enables this option.\r
+        * \r
+        * @param       boolean         $enable\r
+        */\r
+       public function enable($enable = true) {\r
+               $value = intval(!$enable);\r
+               \r
+               $sql = "UPDATE  wcf".WCF_N."_user_option\r
+                       SET     disabled = ?\r
+                       WHERE   optionID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($value, $this->optionID));\r
+       }\r
+       \r
+       /**\r
+        * Determines the needed sql statement to modify column definitions.\r
+        * \r
+        * @param       string          $optionType\r
+        * @return      array           column definition\r
+        */\r
+       public static function getColumnDefinition($optionType) {\r
+               $column = array(\r
+                       'autoIncrement' => false,\r
+                       'key' => false,\r
+                       'notNull' => false,\r
+                       'type' => 'text'\r
+               );\r
+               \r
+               switch ($optionType) {\r
+                       case 'boolean':\r
+                               $column['notNull'] = true;\r
+                               $column['default'] = 0;\r
+                               $column['length'] = 1;\r
+                               $column['type'] = 'tinyint';\r
+                       break;\r
+                       \r
+                       case 'integer':\r
+                               $column['notNull'] = true;\r
+                               $column['default'] = 0;\r
+                               $column['length'] = 10;\r
+                               $column['type'] = 'int';\r
+                       break;\r
+                       \r
+                       case 'float':\r
+                               $column['notNull'] = true;\r
+                               $column['default'] = 0.0;\r
+                               $column['type'] = 'float';\r
+                       break;\r
+                       \r
+                       case 'textarea':\r
+                               $column['type'] = 'mediumtext';\r
+                       break;\r
+                       \r
+                       case 'birthday':\r
+                       case 'date':\r
+                               $column['notNull'] = true;\r
+                               $column['default'] = '0000-00-00';\r
+                               $column['length'] = 10;\r
+                               $column['type'] = 'char';\r
+                       break;\r
+               }\r
+               \r
+               return $column;\r
+       }\r
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/UserOptionList.class.php b/wcfsetup/install/files/lib/data/user/option/UserOptionList.class.php
new file mode 100644 (file)
index 0000000..7a73134
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\option;\r
+use wcf\data\DatabaseObjectList;\r
+\r
+/**\r
+ * Represents a list of user options.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option\r
+ * @category   Community Framework\r
+ */\r
+class UserOptionList extends DatabaseObjectList {\r
+       /**\r
+        * @see DatabaseObjectList::$className\r
+        */\r
+       public $className = 'wcf\data\user\option\UserOption';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/UserOptionOutput.class.php b/wcfsetup/install/files/lib/data/user/option/UserOptionOutput.class.php
new file mode 100644 (file)
index 0000000..3dd53ac
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+namespace wcf\data\user\option;\r
+use wcf\data\User;\r
+\r
+/**\r
+ * Any user option output class should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option\r
+ * @category   Community Framework\r
+ */\r
+interface UserOptionOutput {\r
+       /**\r
+        * Returns a short version of the html code for the output of the given user option.\r
+        * \r
+        * @param       User            $user\r
+        * @param       array           $optionData\r
+        * @param       string          $value\r
+        * @return      string\r
+        */\r
+       public function getShortOutput(User $user, $optionData, $value);\r
+       \r
+       /**\r
+        * Returns a medium version of the html code for the output of the given user option.\r
+        * \r
+        * @param       User            $user\r
+        * @param       array           $optionData\r
+        * @param       string          $value\r
+        * @return      string\r
+        */\r
+       public function getMediumOutput(User $user, $optionData, $value);\r
+       \r
+       /**\r
+        * Returns the html code for the output of the given user option.\r
+        * \r
+        * @param       User            $user\r
+        * @param       array           $optionData\r
+        * @param       string          $value\r
+        * @return      string\r
+        */\r
+       public function getOutput(User $user, $optionData, $value);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategory.class.php b/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategory.class.php
new file mode 100644 (file)
index 0000000..e8a02e6
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+namespace wcf\data\user\option\category;
+use wcf\data\DatabaseObject;
+use wcf\system\WCF;
+
+/**
+ * Represents a user option category.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.option.category
+ * @category   Community Framework
+ */
+class UserOptionCategory extends DatabaseObject {
+       /**
+        * @see DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'user_option_category';
+       
+       /**
+        * @see DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'categoryID';
+       
+       /**
+        * @todo        Methode so beibehalten und effektiv DatabaseObject::__construct() klonen
+        *              oder generell so etwas mit einem zusätzlichen Query abfragen?
+        */
+       public function __construct($categoryID, $row = null, UserOptionCategory $category = null) {
+               if ($categoryID !== null) {
+                       $sql = "SELECT  option_category.*,
+                                       (SELECT COUNT(DISTINCT optionName) FROM wcf".WCF_N."_user_option WHERE categoryName = option_category.categoryName) AS options
+                               FROM    wcf".WCF_N."_user_option_category option_category
+                               WHERE   option_category.categoryID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($categoryID));
+                       $row = $statement->fetchArray();
+               }
+               
+               parent::__construct(null, $row, $category);
+       }
+       
+       /**
+        * Returns the title of this category.
+        * 
+        * @return      string
+        */
+       public function __toString() {
+               return $this->categoryName;
+       }
+       
+       /**
+        * Returns an instance of UserOptionCategory by name and package id.
+        * 
+        * @param       string          $categoryName
+        * @param       integer         $packageID
+        * @return      UserOptionCategory
+        */
+       public static function getCategoryByName($categoryName, $packageID) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_user_option_category
+                       WHERE   categoryName = ?
+                               AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($categoryName, $packageID));
+               $row = $statement->fetchArray();
+               if (!$row) $row = array();
+               
+               return new UserOptionCategory(null, $row);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryAction.class.php b/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryAction.class.php
new file mode 100644 (file)
index 0000000..e59dd99
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\data\user\option\category;\r
+use wcf\data\AbstractDatabaseObjectAction;\r
+\r
+/**\r
+ * Executes user option category-related actions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option.category\r
+ * @category   Community Framework\r
+ */\r
+class UserOptionCategoryAction extends AbstractDatabaseObjectAction {\r
+       /**\r
+        * @see AbstractDatabaseObjectAction::$className\r
+        */\r
+       protected $className = 'wcf\data\user\option\category\UserOptionCategoryEditor';\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryEditor.class.php b/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryEditor.class.php
new file mode 100644 (file)
index 0000000..64c4e0e
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\data\user\option\category;\r
+use wcf\data\DatabaseObjectEditor;\r
+\r
+/**\r
+ * Provides functions to add, edit and delete user option categories.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.user.option.category\r
+ * @category   Community Framework\r
+ */\r
+class UserOptionCategoryEditor extends DatabaseObjectEditor {\r
+       /**\r
+        * @see UserOptionCategory::$baseClass\r
+        */\r
+       protected static $baseClass = 'wcf\data\user\option\category\UserOptionCategory';\r
+       \r
+       /**\r
+        * @see EditableObject::create()\r
+        */\r
+       public static function create(array $parameters = array()) {\r
+               // obtain default values\r
+               if (!isset($parameters['packageID'])) $parameters['packageID'] = PACKAGE_ID;\r
+               \r
+               return parent::create($parameters);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryList.class.php b/wcfsetup/install/files/lib/data/user/option/category/UserOptionCategoryList.class.php
new file mode 100644 (file)
index 0000000..a9d7b5c
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+namespace wcf\data\user\option\category;
+use wcf\data\DatabaseObjectList;
+use wcf\system\database\util\ConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * Represents an list of user option categories.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.user.option.category
+ * @category   Community Framework
+ */
+class UserOptionCategoryList extends DatabaseObjectList {
+       /**
+        * @see DatabaseObjectList::$className
+        */
+       public $className = 'wcf\data\user\option\category\UserOptionCategory';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/form/AbstractForm.class.php b/wcfsetup/install/files/lib/form/AbstractForm.class.php
new file mode 100644 (file)
index 0000000..6abbef4
--- /dev/null
@@ -0,0 +1,110 @@
+<?php\r
+namespace wcf\form;\r
+use wcf\page\AbstractPage;\r
+use wcf\system\WCF;\r
+use wcf\system\event\EventHandler;\r
+use wcf\system\exception\UserInputException;\r
+\r
+/**\r
+ * This class provides default implementations for the Form interface.\r
+ * This includes the default event listener for a form: readFormParameters, validate, save.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage form\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractForm extends AbstractPage implements Form {\r
+       /**\r
+        * Name of error field.\r
+        *\r
+        * @var string\r
+        */\r
+       public $errorField = '';\r
+       \r
+       /**\r
+        * Name of error type.\r
+        *\r
+        * @var string\r
+        */\r
+       public $errorType = '';\r
+       \r
+       /**\r
+        * @see Form::submit()\r
+        */\r
+       public function submit() {\r
+               // call submit event\r
+               EventHandler::getInstance()->fireAction($this, 'submit');\r
+               \r
+               $this->readFormParameters();\r
+               \r
+               try {\r
+                       $this->validate();\r
+                       // no errors\r
+                       $this->save();\r
+               }\r
+               catch (UserInputException $e) {\r
+                       $this->errorField = $e->getField();\r
+                       $this->errorType = $e->getType();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Form::readFormParameters()\r
+        */\r
+       public function readFormParameters() {\r
+               // call readFormParameters event\r
+               EventHandler::getInstance()->fireAction($this, 'readFormParameters');\r
+       }\r
+       \r
+       /**\r
+        * @see Form::validate()\r
+        */\r
+       public function validate() {\r
+               // call validate event\r
+               EventHandler::getInstance()->fireAction($this, 'validate');\r
+       }\r
+       \r
+       /**\r
+        * @see Form::save()\r
+        */\r
+       public function save() {\r
+               // call save event\r
+               EventHandler::getInstance()->fireAction($this, 'save');\r
+       }\r
+       \r
+       /**\r
+        * Calls the 'saved' event after the successful call of the save method.\r
+        * This functions won't called automatically. You must do this manually, if you inherit AbstractForm.\r
+        */\r
+       protected function saved() {\r
+               EventHandler::getInstance()->fireAction($this, 'saved');\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               if (count($_POST) || count($_FILES)) {\r
+                       $this->submit();\r
+               }\r
+               \r
+               parent::readData();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               // assign default variables\r
+               WCF::getTPL()->assign(array(\r
+                       'errorField' => $this->errorField,\r
+                       'errorType' => $this->errorType\r
+               ));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/form/AbstractSecureForm.class.php b/wcfsetup/install/files/lib/form/AbstractSecureForm.class.php
new file mode 100644 (file)
index 0000000..6463aa4
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\form;
+
+/**
+ * Extends AbstractForm by a function to validate a given security token.
+ * A missing or invalid token will be result in a throw of a IllegalLinkException.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage form
+ * @category   Community Framework
+ */
+abstract class AbstractSecureForm extends AbstractForm {
+       /**
+        * @see Form::readFormParameters()
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               // check security token
+               $this->checkSecurityToken();
+       }
+       
+       /**
+        * Validates the security token.
+        */
+       protected function checkSecurityToken() {
+               if (!isset($_POST['t']) || !WCF::getSession()->checkSecurityToken($_POST['t'])) {
+                       throw new IllegalLinkException();
+               }
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/form/Form.class.php b/wcfsetup/install/files/lib/form/Form.class.php
new file mode 100644 (file)
index 0000000..ff055d6
--- /dev/null
@@ -0,0 +1,36 @@
+<?php\r
+namespace wcf\form;\r
+use wcf\page\Page;\r
+\r
+/**\r
+ * All form classes should implement this interface. \r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage form\r
+ * @category   Community Framework\r
+ */\r
+interface Form extends Page {\r
+       /**\r
+        * Is called when the form was submitted.\r
+        */\r
+       public function submit();\r
+       \r
+       /**\r
+        * Validates form inputs.\r
+        */\r
+       public function validate();\r
+       \r
+       /**\r
+        * Saves the data of the form.\r
+        */\r
+       public function save();\r
+       \r
+       /**\r
+        * Reads the given form parameters.\r
+        */\r
+       public function readFormParameters();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/page/AbstractPage.class.php b/wcfsetup/install/files/lib/page/AbstractPage.class.php
new file mode 100644 (file)
index 0000000..3874e1e
--- /dev/null
@@ -0,0 +1,144 @@
+<?php\r
+namespace wcf\page;\r
+use wcf\system\WCF;\r
+use wcf\system\event\EventHandler;\r
+\r
+/**\r
+ * This class provides default implementations for the Page interface.\r
+ * This includes the call of the default event listeners for a page: readParameters, readData, assignVariables and show.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage page\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractPage implements Page {\r
+       /**\r
+        * Name of the template for the called page.\r
+        * \r
+        * @var string\r
+        */\r
+       public $templateName = '';\r
+       \r
+       /**\r
+        * Value of the given action parameter.\r
+        * \r
+        * @var string\r
+        */\r
+       public $action = '';\r
+       \r
+       /**\r
+        * Needed modules to view this page.\r
+        * \r
+        * @var array<string>\r
+        */\r
+       public $neededModules = array();\r
+       \r
+       /**\r
+        * Needed permissions to view this page.\r
+        * \r
+        * @var array<string>\r
+        */\r
+       public $neededPermissions = array();\r
+       \r
+       /**\r
+        * Creates a new AbstractPage object.\r
+        * Calls the readParameters() and show() methods automatically.\r
+        */\r
+       public function __construct() {\r
+               // call default methods\r
+               $this->readParameters();\r
+               $this->show();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               // call readParameters event\r
+               EventHandler::getInstance()->fireAction($this, 'readParameters');\r
+               \r
+               // read action parameter\r
+               if (isset($_REQUEST['action'])) $this->action = $_REQUEST['action'];\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               // call readData event\r
+               EventHandler::getInstance()->fireAction($this, 'readData');\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               // call assignVariables event\r
+               EventHandler::getInstance()->fireAction($this, 'assignVariables');\r
+               \r
+               // assign parameters\r
+               WCF::getTPL()->assign(array(\r
+                       'action' => $this->action,\r
+                       'templateName' => $this->templateName\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see Page::checkModules()\r
+        */\r
+       public function checkModules() {\r
+               // call checkModules event\r
+               EventHandler::getInstance()->fireAction($this, 'checkModules');\r
+               \r
+               // check modules\r
+               if (count($this->neededModules)) {\r
+                       foreach ($this->neededModules as $module) {\r
+                               if (!defined($module) || !constant($module)) {\r
+                                       throw new wcf\system\exception\IllegalLinkException();\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::checkPermissions()\r
+        */\r
+       public function checkPermissions() {\r
+               // call checkPermissions event\r
+               EventHandler::getInstance()->fireAction($this, 'checkPermissions');\r
+               \r
+               // check permission\r
+               if (count($this->neededPermissions)) {\r
+                       WCF::getSession()->checkPermission($this->neededPermissions);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::show()\r
+        */\r
+       public function show() {\r
+               // check modules\r
+               $this->checkModules();\r
+               \r
+               // check permission\r
+               $this->checkPermissions();\r
+               \r
+               // read data\r
+               $this->readData();\r
+\r
+               // assign variables\r
+               $this->assignVariables();               \r
+               \r
+               // call show event\r
+               EventHandler::getInstance()->fireAction($this, 'show');\r
+               \r
+               // show template\r
+               if (!empty($this->templateName)) {\r
+                       WCF::getTPL()->display($this->templateName);\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/page/AbstractSecurePage.class.php b/wcfsetup/install/files/lib/page/AbstractSecurePage.class.php
new file mode 100644 (file)
index 0000000..4cab961
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\page;
+
+/**
+ * Extends AbstractPage by a function to validate a given security token.
+ * A missing or invalid token will be result in a throw of a IllegalLinkException.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage page
+ * @category   Community Framework
+ */
+abstract class AbstractSecurePage extends AbstractPage {
+       /**
+        * @see Page::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               // check security token
+               $this->checkSecurityToken();
+       }
+       
+       /**
+        * Validates the security token.
+        */
+       protected function checkSecurityToken() {
+               if (!isset($_REQUEST['t']) || !WCF::getSession()->checkSecurityToken($_REQUEST['t'])) {
+                       throw new IllegalLinkException();
+               }
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/page/MultipleLinkPage.class.php b/wcfsetup/install/files/lib/page/MultipleLinkPage.class.php
new file mode 100644 (file)
index 0000000..a60b905
--- /dev/null
@@ -0,0 +1,209 @@
+<?php\r
+namespace wcf\page;\r
+use wcf\system\event\EventHandler;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\WCF;\r
+use wcf\util\ClassUtil;\r
+\r
+/**\r
+ * Provides default implementations for a multiple link page.\r
+ * Handles the page number parameter automatically.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage page\r
+ * @category   Community Framework\r
+ */\r
+abstract class MultipleLinkPage extends AbstractPage {\r
+       /**\r
+        * The current page number.\r
+        * \r
+        * @var integer\r
+        */\r
+       public $pageNo = 0;\r
+       \r
+       /**\r
+        * The number of all pages.\r
+        * \r
+        * @var integer\r
+        */\r
+       public $pages = 0;\r
+       \r
+       /**\r
+        * The number of items shown per page.\r
+        * \r
+        * @var integer\r
+        */\r
+       public $itemsPerPage = 20;\r
+       \r
+       /**\r
+        * The number of all items.\r
+        * \r
+        * @var integer\r
+        */\r
+       public $items = 0;\r
+       \r
+       /**\r
+        * Indicates the range of the listed items.\r
+        * \r
+        * @var integer\r
+        */\r
+       public $startIndex = 0;\r
+       \r
+       /**\r
+        * Indicates the range of the listed items.\r
+        * \r
+        * @var integer\r
+        */\r
+       public $endIndex = 0;\r
+       \r
+       /**\r
+        * DatabaseObjectList object\r
+        * \r
+        * @var wcf\data\DatabaseObjectList\r
+        */     \r
+       public $objectList = null;\r
+       \r
+       /**\r
+        * class name for DatabaseObjectList\r
+        * \r
+        * @var string\r
+        */     \r
+       public $objectListClassName = '';\r
+       \r
+       /**\r
+        * list of DatabaseObject objects\r
+        * \r
+        * @var array<wcf\data\DatabaseObject>\r
+        */     \r
+       public $objects = array();\r
+       \r
+       /**\r
+        * @see wcf\data\DatabaseObjectList::$sqlLimit\r
+        */     \r
+       public $sqlLimit = 0;\r
+       \r
+       /**\r
+        * @see wcf\data\DatabaseObjectList::$sqlOffset\r
+        */\r
+       public $sqlOffset = '';\r
+       \r
+       /**\r
+        * @see wcf\data\DatabaseObjectList::$sqlOrderBy\r
+        */     \r
+       public $sqlOrderBy = '';\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               // read page number parameter\r
+               if (isset($_REQUEST['pageNo'])) $this->pageNo = intval($_REQUEST['pageNo']);\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               parent::readData();\r
+               \r
+               // initialize database object list\r
+               $this->initObjectList();\r
+               \r
+               // calculates page number\r
+               $this->calculateNumberOfPages();\r
+               \r
+               // read objects\r
+               if ($this->items) {\r
+                       $this->sqlLimit = $this->itemsPerPage;\r
+                       $this->sqlOffset = ($this->pageNo - 1) * $this->itemsPerPage;\r
+                       $this->sqlOrderBy = $this->sortField." ".$this->sortOrder;\r
+                       $this->readObjects();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Initializes DatabaseObjectList instance.\r
+        */     \r
+       protected function initObjectList() {\r
+               if (empty($this->objectListClassName)) {\r
+                       throw new SystemException('DatabaseObjectList class name not specified.');\r
+               }\r
+               \r
+               if (!ClassUtil::isInstanceOf($this->objectListClassName, 'wcf\data\DatabaseObjectList')) {\r
+                       throw new SystemException("Class '".$this->objectListClassName."' does not extend 'wcf\data\DatabaseObjectList'");\r
+               }\r
+               \r
+               $this->objectList = new $this->objectListClassName();\r
+       }\r
+       \r
+       /**\r
+        * Reads object list.\r
+        */     \r
+       protected function readObjects() {\r
+               $this->objectList->sqlLimit = $this->sqlLimit;\r
+               $this->objectList->sqlOffset = $this->sqlOffset;\r
+               $this->objectList->sqlOrderBy = $this->sqlOrderBy;\r
+               $this->objectList->readObjects();\r
+               \r
+               $this->objects = $this->objectList->getObjects();\r
+       }\r
+       \r
+       /**\r
+        * Calculates the number of pages and\r
+        * handles the given page number parameter.\r
+        */\r
+       public function calculateNumberOfPages() {\r
+               // call calculateNumberOfPages event\r
+               EventHandler::getInstance()->fireAction($this, 'calculateNumberOfPages');\r
+               \r
+               // calculate number of pages\r
+               $this->items = $this->countItems();\r
+               $this->pages = intval(ceil($this->items / $this->itemsPerPage));\r
+               \r
+               // correct active page number\r
+               if ($this->pageNo > $this->pages) $this->pageNo = $this->pages;\r
+               if ($this->pageNo < 1) $this->pageNo = 1;\r
+               \r
+               // calculate start and end index\r
+               $this->startIndex = ($this->pageNo - 1) * $this->itemsPerPage;\r
+               $this->endIndex = $this->startIndex + $this->itemsPerPage;\r
+               $this->startIndex++;\r
+               if ($this->endIndex > $this->items) $this->endIndex = $this->items;\r
+       }\r
+       \r
+       /**\r
+        * Counts the displayed items.\r
+        * \r
+        * @return      integer\r
+        */\r
+       public function countItems() {\r
+               // call countItems event\r
+               EventHandler::getInstance()->fireAction($this, 'countItems');\r
+               \r
+               return $this->objectList->countObjects();\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               // assign page parameters\r
+               WCF::getTPL()->assign(array(\r
+                       'pageNo' => $this->pageNo,\r
+                       'pages' => $this->pages,\r
+                       'items' => $this->items,\r
+                       'itemsPerPage' => $this->itemsPerPage,\r
+                       'startIndex' => $this->startIndex,\r
+                       'endIndex' => $this->endIndex,\r
+                       'objects' => $this->objects\r
+               ));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/page/Page.class.php b/wcfsetup/install/files/lib/page/Page.class.php
new file mode 100644 (file)
index 0000000..4e71b67
--- /dev/null
@@ -0,0 +1,45 @@
+<?php\r
+namespace wcf\page;\r
+\r
+/**\r
+ * All page classes should implement this interface. \r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage page\r
+ * @category   Community Framework\r
+ */\r
+interface Page {\r
+       /**\r
+        * Reads the given parameters.\r
+        */\r
+       public function readParameters();\r
+       \r
+       /**\r
+        * Checks the modules of this page.\r
+        */\r
+       public function checkModules();\r
+       \r
+       /**\r
+        * Checks the permissions of this page.\r
+        */\r
+       public function checkPermissions();\r
+       \r
+       /**\r
+        * Reads/Gets the data to be displayed on this page.\r
+        */\r
+       public function readData();\r
+       \r
+       /**\r
+        * Assigns variables to the template engine.\r
+        */\r
+       public function assignVariables();\r
+       \r
+       /**\r
+        * Shows the requested page.\r
+        */\r
+       public function show();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/page/SortablePage.class.php b/wcfsetup/install/files/lib/page/SortablePage.class.php
new file mode 100644 (file)
index 0000000..4ddbafb
--- /dev/null
@@ -0,0 +1,102 @@
+<?php\r
+namespace wcf\page;\r
+use wcf\system\WCF;\r
+use wcf\system\event\EventHandler;\r
+\r
+/**\r
+ * Provides default implementations for a sortable page of listed items.\r
+ * Handles the sorting parameters automatically.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage page\r
+ * @category   Community Framework\r
+ */\r
+abstract class SortablePage extends MultipleLinkPage {\r
+       /**\r
+        * The selected sort field.\r
+        * \r
+        * @var string\r
+        */\r
+       public $sortField = '';\r
+       \r
+       /**\r
+        * The selected sort order.\r
+        * \r
+        * @var string\r
+        */\r
+       public $sortOrder = '';\r
+       \r
+       /**\r
+        * The default sort field.\r
+        * \r
+        * @var string\r
+        */\r
+       public $defaultSortField = '';\r
+       \r
+       /**\r
+        * The default sort order.\r
+        * \r
+        * @var string\r
+        */\r
+       public $defaultSortOrder = 'ASC';\r
+       \r
+       /**\r
+        * @see Page::readParameters()\r
+        */\r
+       public function readParameters() {\r
+               parent::readParameters();\r
+               \r
+               // read sorting parameter\r
+               if (isset($_REQUEST['sortField'])) $this->sortField = $_REQUEST['sortField'];\r
+               if (isset($_REQUEST['sortOrder'])) $this->sortOrder = $_REQUEST['sortOrder'];\r
+       }\r
+       \r
+       /**\r
+        * @see Page::readData()\r
+        */\r
+       public function readData() {\r
+               $this->validateSortOrder();\r
+               $this->validateSortField();\r
+                               \r
+               parent::readData();\r
+       }\r
+       \r
+       /**\r
+        * Validates the given sort field parameter. \r
+        */\r
+       public function validateSortField() {\r
+               // call validateSortField event\r
+               EventHandler::getInstance()->fireAction($this, 'validateSortField');\r
+       }\r
+       \r
+       /**\r
+        * Validates the given sort order parameter. \r
+        */\r
+       public function validateSortOrder() {\r
+               // call validateSortOrder event\r
+               EventHandler::getInstance()->fireAction($this, 'validateSortOrder');\r
+               \r
+               switch ($this->sortOrder) {\r
+                       case 'ASC':\r
+                       case 'DESC': break;\r
+                       default: $this->sortOrder = $this->defaultSortOrder;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public function assignVariables() {\r
+               parent::assignVariables();\r
+               \r
+               // assign sorting parameters\r
+               WCF::getTPL()->assign(array(\r
+                       'sortField' => $this->sortField,\r
+                       'sortOrder' => $this->sortOrder\r
+               ));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/page/util/InlineCalendar.class.php b/wcfsetup/install/files/lib/page/util/InlineCalendar.class.php
new file mode 100644 (file)
index 0000000..1ef99c2
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+namespace wcf\page\util;\r
+\r
+/**\r
+ * Assigns default variables for the usage of the inline (javascript) calendar.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage page.util\r
+ * @category   Community Framework\r
+ */\r
+class InlineCalendar {\r
+       /**\r
+        * @see Page::assignVariables()\r
+        */\r
+       public static function assignVariables() {\r
+               // create calendar data\r
+               $dayOptions = array(0 => '');\r
+               $hourOptions = $minuteOptions = array('' => '');\r
+               $monthList = $weekdayList = '';\r
+               $weekdays = $monthOptions = array();\r
+               \r
+               // days\r
+               for ($i = 1; $i <= 31; $i++) $dayOptions[$i] = $i;\r
+               // months\r
+               $monthFormat = (Language::$dateFormatLocalized ? '%B' : '%m');\r
+               for ($i = 1; $i <= 12; $i++) $monthOptions[$i] = DateUtil::formatDate($monthFormat, gmmktime(0, 0, 0, $i, 15, 2000), false, true);\r
+               $monthList = implode(',', $monthOptions);\r
+               $monthOptions[0] = '';\r
+               ksort($monthOptions);\r
+               \r
+               // weekdays\r
+               for ($i = 1; $i <= 7; $i++) {\r
+                       $weekdayNumber = intval(DateUtil::formatDate('%w', gmmktime(0, 0, 0, 1, $i, 2000), false, true));\r
+                       $weekdays[$weekdayNumber] = DateUtil::formatDate('%a', gmmktime(0, 0, 0, 1, $i, 2000), false, true);\r
+               }\r
+               ksort($weekdays);\r
+               $weekdayList = implode(',', $weekdays);\r
+               \r
+               // hours\r
+               for ($i = 0; $i < 24; $i++) $hourOptions[$i] = $i < 10 ? "0" . $i : $i;\r
+               \r
+               // minutes\r
+               for ($i = 0; $i < 60; $i += 5) $minuteOptions[$i] = $i < 10 ? "0" . $i : $i;\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'monthOptions' => $monthOptions,\r
+                       'monthList' => $monthList,\r
+                       'dayOptions' => $dayOptions,\r
+                       'weekdayList' => $weekdayList,\r
+                       'startOfWeek' => (WCF::getUser()->firstDayOfWeek == '' ? 1 : intval(WCF::getUser()->firstDayOfWeek)),\r
+                       'hourOptions' => $hourOptions,\r
+                       'minuteOptions' => $minuteOptions\r
+               ));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/SingletonFactory.class.php b/wcfsetup/install/files/lib/system/SingletonFactory.class.php
new file mode 100644 (file)
index 0000000..fdd4d06
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+namespace wcf\system;
+
+/**
+ * Basis class for singleton classes.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system
+ * @category   Community Framework
+ */
+abstract class SingletonFactory {
+       /**
+        * list of singletons
+        * @var array<SingletonFactory>
+        */
+       protected static $__singletonObjects = array();
+       
+       /**
+        * Singletons do not support a public constructor. Override init() if
+        * your class needs to initialize components on creation.
+        */
+       protected final function __construct() {
+               $this->init();
+       }
+       
+       /**
+        * Called within __construct(), override if neccessary.
+        */     
+       protected function init() { }
+       
+       /**
+        * Object cloning is disallowed.
+        */
+       protected final function __clone() { }
+       
+       /**
+        * Returns an unique instance of current child class.
+        * 
+        * @return      SingletonFactory
+        */
+       public static final function getInstance() {
+               $className = get_called_class();
+               if (!isset(self::$__singletonObjects[$className])) {
+                       self::$__singletonObjects[$className] = new $className();
+               }
+               
+               return self::$__singletonObjects[$className];
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/WCF.class.php b/wcfsetup/install/files/lib/system/WCF.class.php
new file mode 100644 (file)
index 0000000..db4d80e
--- /dev/null
@@ -0,0 +1,565 @@
+<?php\r
+namespace wcf\system;\r
+use wcf\data\application\Application;\r
+use wcf\data\package\Package;\r
+use wcf\system\application\ApplicationHandler;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\database\statement\PreparedStatement;\r
+use wcf\system\language\LanguageFactory;\r
+use wcf\system\package\PackageInstallationDispatcher;\r
+use wcf\system\session\SessionFactory;\r
+use wcf\system\session\SessionHandler;\r
+use wcf\system\storage\StorageHandler;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\exception;\r
+use wcf\util;\r
+\r
+// try to disable execution time limit\r
+@set_time_limit(0);\r
+\r
+// define current wcf version\r
+define('WCF_VERSION', '2.0.0 Alpha 1 (Maelstrom)');\r
+\r
+// define current unix timestamp\r
+define('TIME_NOW', time());\r
+\r
+// wcf imports\r
+if (!defined('NO_IMPORTS')) {\r
+       require_once(WCF_DIR.'lib/core.functions.php');\r
+}\r
+\r
+/**\r
+ * WCF is the central class for the community framework.\r
+ * It holds the database connection, access to template and language engine.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system\r
+ * @category   Community Framework\r
+ */\r
+class WCF {\r
+       /**\r
+        * list of autoload directories\r
+        *\r
+        * @var array\r
+        */\r
+       protected static $autoloadDirectories = array();\r
+       \r
+       /**\r
+        * list of unique instances of each core object\r
+        *\r
+        * @var array<wcf\system\SingletonFactory>\r
+        */\r
+       protected static $coreObject = array();\r
+       \r
+       /**\r
+        * list of cached core objects\r
+        *\r
+        * @var array<array>\r
+        */\r
+       protected static $coreObjectCache = array();\r
+       \r
+       /**\r
+        * list of package dependencies\r
+        *\r
+        * @var array\r
+        */     \r
+       protected static $packageDependencies = array();\r
+       \r
+       /**\r
+        * database object\r
+        *\r
+        * @var wcf\system\database\Database\r
+        */\r
+       protected static $dbObj = null;\r
+       \r
+       /**\r
+        * language object\r
+        *\r
+        * @var wcf\system\language\Language\r
+        */\r
+       protected static $languageObj = null;\r
+       \r
+       /**\r
+        * session object\r
+        *\r
+        * @var wcf\system\session\SessionHandler\r
+        */\r
+       protected static $sessionObj = null;\r
+       \r
+       /**\r
+        * template object\r
+        *\r
+        * @var wcf\system\template\TemplateEngine\r
+        */\r
+       protected static $tplObj = null;\r
+       \r
+       /**\r
+        * current user object\r
+        *\r
+        * @var wcf\data\user\User\r
+        */\r
+       protected static $userObj = null;\r
+       \r
+       /**\r
+        * Calls all init functions of the WCF class.\r
+        */\r
+       public function __construct() {\r
+               // add autoload directory\r
+               self::$autoloadDirectories['wcf'] = WCF_DIR . 'lib/';\r
+               \r
+               // define tmp directory\r
+               if (!defined('TMP_DIR')) define('TMP_DIR', util\BasicFileUtil::getTempFolder());\r
+               \r
+               // start initialization\r
+               $this->initMagicQuotes();\r
+               $this->initDB();\r
+               $this->initOptions();\r
+               $this->initCache();\r
+               $this->initSession();\r
+               $this->initLanguage();\r
+               $this->initTPL();\r
+               $this->initBlacklist();\r
+               $this->initApplications();\r
+               $this->initCoreObjects();\r
+       }\r
+       \r
+       /**\r
+        * Replacement of the "__destruct()" method.\r
+        * Seems that under specific conditions (windows) the destructor is not called automatically.\r
+        * So we use the php register_shutdown_function to register an own destructor method.\r
+        * Flushs the output, updates the session and executes the shutdown queries.\r
+        */\r
+       public static function destruct() {\r
+               // flush ouput\r
+               if (ob_get_level() && ini_get('output_handler')) {\r
+                       ob_flush();\r
+               }\r
+               else {\r
+                       flush();\r
+               }\r
+               \r
+               // update session\r
+               if (is_object(self::getSession())) {\r
+                       self::getSession()->update();\r
+               }\r
+               \r
+               // close cache source\r
+               if (is_object(CacheHandler::getInstance()) && is_object(CacheHandler::getInstance()->getCacheSource())) {\r
+                       CacheHandler::getInstance()->getCacheSource()->close();\r
+               }\r
+               \r
+               // execute shutdown actions\r
+               StorageHandler::getInstance()->shutdown();\r
+       }\r
+       \r
+       /**\r
+        * Removes slashes in superglobal gpc data arrays if 'magic quotes gpc' is enabled.\r
+        */\r
+       protected function initMagicQuotes() {\r
+               if (function_exists('get_magic_quotes_gpc')) {\r
+                       if (@get_magic_quotes_gpc()) {\r
+                               if (count($_REQUEST)) {\r
+                                       $_REQUEST = util\ArrayUtil::stripslashes($_REQUEST);\r
+                               }\r
+                               if (count($_POST)) {\r
+                                       $_POST = util\ArrayUtil::stripslashes($_POST);\r
+                               }\r
+                               if (count($_GET)) {\r
+                                       $_GET = util\ArrayUtil::stripslashes($_GET);\r
+                               }\r
+                               if (count($_COOKIE)) {\r
+                                       $_COOKIE = util\ArrayUtil::stripslashes($_COOKIE);\r
+                               }\r
+                               if (count($_FILES)) {\r
+                                       foreach ($_FILES as $name => $attributes) {\r
+                                               foreach ($attributes as $key => $value) {\r
+                                                       if ($key != 'tmp_name') {\r
+                                                               $_FILES[$name][$key] = util\ArrayUtil::stripslashes($value);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       \r
+               if (function_exists('set_magic_quotes_runtime')) {\r
+                       @set_magic_quotes_runtime(0);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the database object.\r
+        *\r
+        * @return      wcf\system\database\Database\r
+        */\r
+       public static final function getDB() {\r
+               return self::$dbObj;\r
+       }\r
+       \r
+       /**\r
+        * Returns the session object.\r
+        *\r
+        * @return      wcf\system\session\SessionHandler\r
+        */\r
+       public static final function getSession() {\r
+               return self::$sessionObj;\r
+       }\r
+       \r
+       /**\r
+        * Returns the user object.\r
+        *\r
+        * @return      wcf\data\user\User\r
+        */\r
+       public static final function getUser() {\r
+               return self::$userObj;\r
+       }\r
+       \r
+       /**\r
+        * Returns the language object.\r
+        *\r
+        * @return      wcf\data\language\Language\r
+        */\r
+       public static final function getLanguage() {\r
+               return self::$languageObj;\r
+       }\r
+       \r
+       /**\r
+        * Returns the template object.\r
+        *\r
+        * @return      wcf\system\template\TemplateEngine\r
+        */\r
+       public static final function getTPL() {\r
+               return self::$tplObj;\r
+       }\r
+       \r
+       /**\r
+        * Calls the show method on the given exception.\r
+        *\r
+        * @param       \Exception      $e\r
+        */\r
+       public static final function handleException(\Exception $e) {\r
+               if ($e instanceof exception\PrintableException) {\r
+                       $e->show();\r
+                       exit;\r
+               }\r
+               \r
+               print $e;\r
+               exit;\r
+       }\r
+       \r
+       /**\r
+        * Catches php errors and throws instead a system exception.\r
+        *\r
+        * @param       integer         $errorNo\r
+        * @param       string          $message\r
+        * @param       string          $filename\r
+        * @param       integer         $lineNo\r
+        */\r
+       public static final function handleError($errorNo, $message, $filename, $lineNo) {\r
+               if (error_reporting() != 0) {\r
+                       $type = 'error';\r
+                       switch ($errorNo) {\r
+                               case 2: $type = 'warning';\r
+                                       break;\r
+                               case 8: $type = 'notice';\r
+                                       break;\r
+                       }\r
+                       \r
+                       throw new exception\SystemException('PHP '.$type.' in file '.$filename.' ('.$lineNo.'): '.$message, 0);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Loads the database configuration and creates a new connection to the database.\r
+        */\r
+       protected function initDB() {\r
+               // get configuration\r
+               $dbHost = $dbUser = $dbPassword = $dbName = '';\r
+               $dbPort = 0;\r
+               $dbClass = 'wcf\system\database\MySQLDatabase';\r
+               require_once(WCF_DIR.'config.inc.php');\r
+               \r
+               // create database connection\r
+               self::$dbObj = new $dbClass($dbHost, $dbUser, $dbPassword, $dbName, $dbPort);\r
+       }\r
+       \r
+       /**\r
+        * Initialises the cache handler and loads the default cache resources.\r
+        */\r
+       protected function initCache() {\r
+               $this->loadDefaultCacheResources();\r
+       }\r
+       \r
+       /**\r
+        * Loads the default cache resources.\r
+        */\r
+       protected function loadDefaultCacheResources() {\r
+               CacheHandler::getInstance()->addResource('languages', WCF_DIR.'cache/cache.languages.php', 'wcf\system\cache\CacheBuilderLanguage');\r
+               CacheHandler::getInstance()->addResource('spiders', WCF_DIR.'cache/cache.spiders.php', 'wcf\system\cache\CacheBuilderSpider');\r
+               if (defined('PACKAGE_ID')) {\r
+                       CacheHandler::getInstance()->addResource('coreObjects-'.PACKAGE_ID, WCF_DIR.'cache/cache.coreObjects-'.PACKAGE_ID.'.php', 'wcf\system\cache\CacheBuilderCoreObject');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Includes the options file.\r
+        * If the option file doesn't exist, the rebuild of it is started.\r
+        */\r
+       protected function initOptions() {\r
+               // get options file name\r
+               $optionsFile = $this->getOptionsFilename();\r
+               \r
+               // create options file if doesn't exist\r
+               if (!file_exists($optionsFile) || filemtime($optionsFile) <= 1) {\r
+                       \wcf\data\option\OptionEditor::rebuildFile($optionsFile);\r
+               }\r
+               require_once($optionsFile);\r
+       }\r
+       \r
+       /**\r
+        * Returns the name of the options file.\r
+        *\r
+        * @return      string          name of the options file\r
+        */\r
+       protected function getOptionsFilename() {\r
+               return WCF_DIR.'options.inc.php';\r
+       }\r
+       \r
+       /**\r
+        * Starts the session system.\r
+        */\r
+       protected function initSession() {\r
+               $factory = new SessionFactory();\r
+               $factory->load();\r
+               \r
+               self::$sessionObj = SessionHandler::getInstance();\r
+               self::$userObj = self::getSession()->getUser();\r
+       }\r
+       \r
+       /**\r
+        * Initialises the language engine.\r
+        */\r
+       protected function initLanguage() {\r
+               if (isset($_GET['l']) && !self::getUser()->userID) {\r
+                       self::getSession()->setLanguageID(intval($_GET['l']));\r
+               }\r
+               \r
+               self::$languageObj = LanguageFactory::getLanguage(self::getSession()->getLanguageID());\r
+       }\r
+       \r
+       /**\r
+        * Initialises the template engine.\r
+        */\r
+       protected function initTPL() {\r
+               self::$tplObj = TemplateEngine::getInstance();\r
+               self::getTPL()->setLanguageID(self::getLanguage()->languageID);\r
+               $this->assignDefaultTemplateVariables();\r
+       }\r
+       \r
+       /**\r
+        * Executes the blacklist.\r
+        */\r
+       protected function initBlacklist() {\r
+               if (defined('BLACKLIST_IP_ADDRESSES') && BLACKLIST_IP_ADDRESSES != '') {\r
+                       if (!util\StringUtil::executeWordFilter(WCF::getSession()->ipAddress, BLACKLIST_IP_ADDRESSES)) {\r
+                               throw new exception\PermissionDeniedException();\r
+                       }\r
+               }\r
+               if (defined('BLACKLIST_USER_AGENTS') && BLACKLIST_USER_AGENTS != '') {\r
+                       if (!util\StringUtil::executeWordFilter(WCF::getSession()->userAgent, BLACKLIST_USER_AGENTS)) {\r
+                               throw new exception\PermissionDeniedException();\r
+                       }\r
+               }\r
+               if (defined('BLACKLIST_HOSTNAMES') && BLACKLIST_HOSTNAMES != '') {\r
+                       if (!util\StringUtil::executeWordFilter(@gethostbyaddr(WCF::getSession()->ipAddress), BLACKLIST_HOSTNAMES)) {\r
+                               throw new exception\PermissionDeniedException();\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Initialises applications.\r
+        *\r
+        * @todo        Determine all required applications as such connected\r
+        *              with each other. Ensure all applications implement the\r
+        *              'Application' interface.\r
+        */\r
+       protected function initApplications() {\r
+               if (PACKAGE_ID == 1) return;\r
+               \r
+               // prepare statement\r
+               $sql = "SELECT  package, packageDir\r
+                       FROM    wcf".WCF_N."_package\r
+                       WHERE   packageID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               \r
+               // start main application\r
+               $application = ApplicationHandler::getInstance()->getActiveApplication();\r
+               $this->loadApplication($statement, $application);\r
+               \r
+               // start dependent applications\r
+               $applications = ApplicationHandler::getInstance()->getDependentApplications();\r
+               foreach ($applications as $application) {\r
+                       $this->loadApplication($statement, $application, true);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Loads an application.\r
+        *\r
+        * @param       wcf\system\database\statement\PreparedStatement $statement\r
+        * @param       wcf\data\application\Application        $application\r
+        * @param       boolean $isDependentApplication\r
+        */     \r
+       protected function loadApplication(PreparedStatement $statement, Application $application, $isDepedentApplication = false) {\r
+               $statement->execute(array($application->packageID));\r
+               $row = $statement->fetchArray();\r
+               \r
+               $abbreviation = ApplicationHandler::getInstance()->getAbbreviation($application->packageID);\r
+               $packageDir = util\FileUtil::getRealPath(WCF_DIR.$row['packageDir']);\r
+               self::$autoloadDirectories[$abbreviation] = $packageDir . 'lib/';\r
+               \r
+               $className = $abbreviation.'\system\\'.strtoupper($abbreviation).'Core';\r
+               if (class_exists($className) && util\ClassUtil::isInstanceOf($className, 'wcf\system\application\Application')) {\r
+                       // include config file\r
+                       $configPath = $packageDir . PackageInstallationDispatcher::CONFIG_FILE;\r
+                       if (file_exists($configPath)) {\r
+                               require_once($configPath);\r
+                       }\r
+                       else {\r
+                               throw new exception\SystemException('Unable to load configuration for '.$row['package']);\r
+                       }\r
+                       \r
+                       // start application\r
+                       new $className();\r
+               }\r
+               else {\r
+                       unset(self::$autoloadDirectories[$abbreviation]);\r
+                       throw new exception\SystemException('Unable to run '.$row['package'].', '.$className.' missing.');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Initializes core object cache.\r
+        */\r
+       protected function initCoreObjects() {\r
+               // ignore core objects if installing WCF\r
+               if (PACKAGE_ID == 0) {\r
+                       return;\r
+               }\r
+               \r
+               self::$coreObjectCache = CacheHandler::getInstance()->get('coreObjects-'.PACKAGE_ID);\r
+               self::$packageDependencies = \wcf\system\package\PackageDependencyHandler::getDependencies();\r
+       }\r
+       \r
+       /**\r
+        * Assigns some default variables to the template engine.\r
+        */\r
+       protected function assignDefaultTemplateVariables() {\r
+               self::getTPL()->registerPrefilter(array('event', 'hascontent', 'lang'));\r
+               self::getTPL()->assign(array('__wcf' => $this));\r
+       }\r
+       \r
+       /**\r
+        * Wrapper for the getter methods of this class.\r
+        *\r
+        * @param       string          $name\r
+        * @return      mixed           value\r
+        */\r
+       public function __get($name) {\r
+               $method = 'get'.ucfirst($name);\r
+               if (method_exists($this, $method)) {\r
+                       return $this->$method();\r
+               }\r
+               \r
+               throw new exception\SystemException("method '".$method."' does not exist in class WCF");\r
+       }\r
+       \r
+       /**\r
+        * Changes the active language.\r
+        *\r
+        * @param       integer         $languageID\r
+        */\r
+       public static final function setLanguage($languageID) {\r
+               self::$languageObj = new Language($languageID);\r
+       }\r
+       \r
+       /**\r
+        * Includes the required util or exception classes automatically.\r
+        *\r
+        * @param       string          $className\r
+        * @see         spl_autoload_register()\r
+        */\r
+       public static final function autoload($className) {\r
+               $namespaces = explode('\\', $className);\r
+               if (count($namespaces) > 1) {\r
+                       $applicationPrefix = array_shift($namespaces);\r
+                       if (isset(self::$autoloadDirectories[$applicationPrefix])) {\r
+                               $classPath = self::$autoloadDirectories[$applicationPrefix] . implode('/', $namespaces) . '.class.php';\r
+                               if (file_exists($classPath)) {\r
+                                       require_once($classPath);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see WCF::__callStatic()\r
+        */\r
+       public final function __call($name, array $arguments) {\r
+               // bug fix to avoid php crash, see http://bugs.php.net/bug.php?id=55020\r
+               if (!method_exists($this, $name)) {\r
+                       return self::__callStatic($name, $arguments);\r
+               }\r
+               \r
+               return $this->$name($arguments);\r
+       }\r
+       \r
+       /**\r
+        * Returns dynamically loaded core objects.\r
+        *\r
+        * @param       string          $name\r
+        * @param       array           $arguments\r
+        */\r
+       public static final function __callStatic($name, array $arguments) {\r
+               $className = preg_replace('~^get~', '', $name);\r
+               \r
+               if (isset(self::$coreObject[$className])) {\r
+                       return self::$coreObject[$className];\r
+               }\r
+               \r
+               $objectName = self::getCoreObject($className);\r
+               if ($objectName === null) {\r
+                       throw new exception\SystemException("Core object '".$className."' is unknown.");\r
+               }\r
+               \r
+               if (class_exists($objectName)) {\r
+                       if (!(util\ClassUtil::isInstanceOf($objectName, 'wcf\system\SingletonFactory'))) {\r
+                               throw new exception\SystemException("class '".$objectName."' does not implement the interface 'SingletonFactory'", 11010);\r
+                       }\r
+                       \r
+                       self::$coreObject[$className] = call_user_func(array($objectName, 'getInstance'));\r
+                       return self::$coreObject[$className];\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Searches for cached core object definition.\r
+        *\r
+        * @param       string          $className\r
+        * @return      string\r
+        */\r
+       protected static final function getCoreObject($className) {\r
+               foreach (self::$packageDependencies as $packageID) {\r
+                       if (isset(self::$coreObjectCache[$packageID][$className])) {\r
+                               return self::$coreObjectCache[$packageID][$className];\r
+                       }\r
+               }\r
+               \r
+               return null;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/WCFACP.class.php b/wcfsetup/install/files/lib/system/WCFACP.class.php
new file mode 100644 (file)
index 0000000..0a7491e
--- /dev/null
@@ -0,0 +1,178 @@
+<?php\r
+namespace wcf\system;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\session\ACPSessionFactory;\r
+use wcf\system\session\SessionHandler;\r
+use wcf\system\template\ACPTemplateEngine;\r
+use wcf\util;\r
+\r
+/**\r
+ * Extends WCF class with functions for the admin control panel.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system\r
+ * @category   Community Framework\r
+ */\r
+class WCFACP extends WCF {\r
+       /**\r
+        * Calls all init functions of the WCF and the WCFACP class. \r
+        */\r
+       public function __construct() {\r
+               // add autoload directory\r
+               self::$autoloadDirectories['wcf'] = WCF_DIR . 'lib/';\r
+               \r
+               // define tmp directory\r
+               if (!defined('TMP_DIR')) define('TMP_DIR', util\BasicFileUtil::getTempFolder());\r
+               \r
+               // start initialization\r
+               $this->initMagicQuotes();\r
+               $this->initDB();\r
+               $this->initPackage();\r
+               $this->initOptions();\r
+               $this->initCache();\r
+               $this->initSession();\r
+               $this->initLanguage();\r
+               $this->initTPL();\r
+               $this->initBlacklist();\r
+               $this->initAuth();\r
+               $this->initCoreObjects();\r
+       }\r
+       \r
+       /**\r
+        * Does the user authentication.\r
+        */\r
+       protected function initAuth() {\r
+               if ((!isset($_REQUEST['page']) || ($_REQUEST['page'] != 'Logout' && $_REQUEST['page'] != 'ACPCaptcha')) && (isset($_REQUEST['page']) || !isset($_REQUEST['form']) || $_REQUEST['form'] != 'Login')) {\r
+                       if (WCF::getUser()->userID == 0) {\r
+                               util\HeaderUtil::redirect('index.php?form=Login'.SID_ARG_2ND_NOT_ENCODED);\r
+                               exit;\r
+                       }\r
+                       else {\r
+                               WCF::getSession()->checkPermission(array('admin.general.canUseAcp'));\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Starts the session system.\r
+        */\r
+       protected function initSession() {\r
+               $factory = new ACPSessionFactory();\r
+               $factory->load();\r
+               \r
+               self::$sessionObj = SessionHandler::getInstance();\r
+               self::$userObj = self::getSession()->getUser();\r
+       }\r
+       \r
+       /**\r
+        * Initialises the template engine.\r
+        */\r
+       protected function initTPL() {\r
+               self::$tplObj = ACPTemplateEngine::getInstance();\r
+               self::getTPL()->setLanguageID(self::getLanguage()->languageID);\r
+               $this->assignDefaultTemplateVariables();\r
+       }\r
+       \r
+       /**\r
+        * @see WCF::assignDefaultTemplateVariables()\r
+        */\r
+       protected function assignDefaultTemplateVariables() {\r
+               parent::assignDefaultTemplateVariables();\r
+               \r
+               self::getTPL()->assign(array(\r
+                       'quickAccessPackages' => $this->getQuickAccessPackages(),\r
+                       //'timezone' => util\DateUtil::getTimezone()\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * @see WCF::loadDefaultCacheResources()\r
+        */\r
+       protected function loadDefaultCacheResources() {\r
+               parent::loadDefaultCacheResources();\r
+               CacheHandler::getInstance()->addResource('packages', WCF_DIR.'cache/cache.packages.php', 'wcf\system\cache\CacheBuilderPackage');\r
+       }\r
+       \r
+       /**\r
+        * Initialises the active package.\r
+        */\r
+       protected function initPackage() {\r
+               // define active package id\r
+               if (!defined('PACKAGE_ID')) {\r
+                       $packageID = self::getWcfPackageID();\r
+                       define('PACKAGE_ID', $packageID);\r
+               }\r
+               \r
+               /*\r
+               $packageID = 0;\r
+               $packages = CacheHandler::getInstance()->get('packages');\r
+               if (isset($_REQUEST['packageID'])) $packageID = intval($_REQUEST['packageID']);\r
+               \r
+               if (!isset($packages[$packageID]) || !$packages[$packageID]['standalone']) {\r
+                       // package id is invalid\r
+                       $packageID = self::getWcfPackageID();\r
+               }\r
+               \r
+               // define active package id\r
+               if (!defined('PACKAGE_ID')) define('PACKAGE_ID', $packageID);*/ \r
+       }\r
+       \r
+       /**\r
+        * Returns the package id of the wcf package.\r
+        * \r
+        * @return      integer\r
+        */\r
+       public static final function getWcfPackageID() {\r
+               // try to find package wcf id\r
+               $sql = "SELECT  packageID\r
+                       FROM    wcf".WCF_N."_package\r
+                       WHERE   package = 'com.woltlab.wcf'";\r
+               $statement = WCFACP::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               $package = $statement->fetchArray();\r
+               \r
+               if (!$package) return 0;\r
+               else return $package['packageID'];\r
+       }\r
+       \r
+       /**\r
+        * Returns a list of all installed standalone packages.\r
+        * \r
+        * @return      array\r
+        */\r
+       protected function getQuickAccessPackages() {\r
+               $quickAccessPackages = array();\r
+               $packages = CacheHandler::getInstance()->get('packages');\r
+               foreach ($packages as $packageID => $package) {\r
+                       if (!$package->standalone) break;\r
+                       if ($package->package != 'com.woltlab.wcf') {\r
+                               $quickAccessPackages[] = $package;\r
+                       }\r
+               }\r
+               \r
+               return $quickAccessPackages;\r
+       }\r
+       \r
+       /**\r
+        * Checks whether the active user has entered the valid master password.\r
+        */\r
+       public static function checkMasterPassword() {\r
+               if (defined('MODULE_MASTER_PASSWORD') && MODULE_MASTER_PASSWORD == 1 && !WCF::getSession()->getVar('masterPassword')) {\r
+                       if (file_exists(WCF_DIR.'acp/masterPassword.inc.php')) {\r
+                               require_once(WCF_DIR.'acp/masterPassword.inc.php');\r
+                       }\r
+                       if (defined('MASTER_PASSWORD') && defined('MASTER_PASSWORD_SALT')) {\r
+                               new \wcf\acp\form\MasterPasswordForm();\r
+                               exit;\r
+                       }\r
+                       else {\r
+                               new \wcf\acp\form\MasterPasswordInitForm();\r
+                               exit;\r
+                       }\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/WCFSetup.class.php b/wcfsetup/install/files/lib/system/WCFSetup.class.php
new file mode 100644 (file)
index 0000000..9fe6856
--- /dev/null
@@ -0,0 +1,1099 @@
+<?php\r
+namespace wcf\system;\r
+use wcf\data\language\LanguageEditor;\r
+use wcf\data\language\SetupLanguage;\r
+use wcf\data\user\User;\r
+use wcf\data\user\UserAction;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\database\util\SQLParser;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\io\File;\r
+use wcf\system\io\Tar;\r
+use wcf\system\language\LanguageFactory;\r
+use wcf\system\package\PackageArchive;\r
+use wcf\system\session\ACPSessionFactory;\r
+use wcf\system\session\SessionHandler;\r
+use wcf\system\setup\Installer;\r
+use wcf\system\template\SetupTemplateEngine;\r
+use wcf\system\WCF;\r
+use wcf\util\FileUtil;\r
+use wcf\util\StringUtil;\r
+use wcf\util\UserUtil;\r
+use wcf\util\XML;\r
+\r
+// define\r
+define('PACKAGE_ID', '0');\r
+define('HTTP_ENABLE_NO_CACHE_HEADERS', 0);\r
+define('HTTP_ENABLE_GZIP', 0);\r
+define('HTTP_GZIP_LEVEL', 0);\r
+define('CACHE_SOURCE_TYPE', 'disk');\r
+define('ENABLE_SESSION_DATA_CACHE', 0);\r
+define('MODULE_MASTER_PASSWORD', 1);\r
+\r
+/**\r
+ * WCFSetup executes the installation of the basic wcf systems.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system\r
+ * @category   Community Framework\r
+ */\r
+class WCFSetup extends WCF {\r
+       protected static $availableLanguages = array();\r
+       protected static $selectedLanguageCode = 'en';\r
+       protected static $selectedLanguages = array();\r
+       protected static $wcfDir = '';\r
+       protected static $installedFiles = array();\r
+       protected static $setupPackageName = 'WoltLab Community Framework';\r
+       protected static $developerMode = 0;\r
+       protected static $dbClasses = array(\r
+               'MySQLDatabase' => array('class' => 'wcf\system\database\MySQLDatabase', 'minversion' => '5.1.17'),     // MySQL 5.0.0+\r
+               'PostgreSQLDatabase' => array('class' => 'wcf\system\database\PostgreSQLDatabase', 'minversion' => '8.2.0')     // PostgreSQL 8.2.0+\r
+       );\r
+       \r
+       /**\r
+        * Calls all init functions of the WCFSetup class and starts the setup process.\r
+        */\r
+       public function __construct() {\r
+               @set_time_limit(0);\r
+               $this->initMagicQuotes();\r
+               $this->getDeveloperMode();\r
+               $this->getLanguageSelection();\r
+               $this->getWCFDir();\r
+               $this->initLanguage();\r
+               $this->initTPL();\r
+               self::getLanguage()->loadLanguage();\r
+               $this->getPackageName();\r
+               \r
+               // start setup\r
+               $this->setup();\r
+       }\r
+       \r
+       /**\r
+        * Gets the status of the developer mode.\r
+        */\r
+       protected static function getDeveloperMode() {\r
+               if (isset($_GET['dev'])) self::$developerMode = intval($_GET['dev']);\r
+               else if (isset($_POST['dev'])) self::$developerMode = intval($_POST['dev']);\r
+       }\r
+       \r
+       /**\r
+        * Gets the selected language.\r
+        */\r
+       protected static function getLanguageSelection() {\r
+               self::$availableLanguages = self::getAllLanguages();\r
+               \r
+               if (isset($_REQUEST['languageCode']) && in_array($_REQUEST['languageCode'], self::$availableLanguages)) {\r
+                       self::$selectedLanguageCode = $_REQUEST['languageCode'];\r
+               }\r
+               else {\r
+                       self::$selectedLanguageCode = LanguageFactory::getPreferredLanguage(self::$availableLanguages, self::$selectedLanguageCode);\r
+               }\r
+               \r
+               if (isset($_POST['selectedLanguages']) && is_array($_POST['selectedLanguages'])) {\r
+                       self::$selectedLanguages = $_POST['selectedLanguages'];\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Gets the available database classes.\r
+        *\r
+        * @return      array\r
+        */\r
+       protected static function getAvailableDBClasses() {\r
+               $availableDBClasses = array();\r
+               foreach (self::$dbClasses as $class => $data) {\r
+                       if (call_user_func(array($data['class'], 'isSupported'))) {\r
+                               $availableDBClasses[$class] = $data;\r
+                       }\r
+               }\r
+               \r
+               return $availableDBClasses;\r
+       }\r
+\r
+       /**\r
+        * Gets the selected wcf dir from request.\r
+        */\r
+       protected static function getWCFDir() {\r
+               if (isset($_REQUEST['wcfDir']) && $_REQUEST['wcfDir'] != '') {\r
+                       self::$wcfDir = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator($_REQUEST['wcfDir']));\r
+                       if (@file_exists(self::$wcfDir)) {\r
+                               define('RELATIVE_WCF_DIR', FileUtil::getRelativePath(INSTALL_SCRIPT_DIR, self::$wcfDir));\r
+                       }\r
+               }\r
+               \r
+               define('WCF_DIR', self::$wcfDir);\r
+       }\r
+               \r
+       /**\r
+        * Initialises the language engine.\r
+        */\r
+       protected function initLanguage() {\r
+               self::$languageObj = new SetupLanguage(null, array(\r
+                       'languageCode' => self::$selectedLanguageCode\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * Initialises the template engine.\r
+        */\r
+       protected function initTPL() {\r
+               self::$tplObj = SetupTemplateEngine::getInstance();\r
+               self::getTPL()->setLanguageID(array_search(self::$selectedLanguageCode, self::$availableLanguages));\r
+               self::getTPL()->setCompileDir(TMP_DIR);\r
+               self::getTPL()->addTemplatePath(PACKAGE_ID, TMP_DIR);\r
+               self::getTPL()->registerPrefilter(array('lang'));\r
+               self::getTPL()->assign(array(\r
+                       'tmpFilePrefix' => TMP_FILE_PREFIX,\r
+                       'languageCode' => self::$selectedLanguageCode,\r
+                       'selectedLanguages' => self::$selectedLanguages,\r
+                       'wcfDir' => self::$wcfDir,\r
+                       'developerMode' => self::$developerMode\r
+               ));\r
+       }\r
+       \r
+       /**\r
+        * Returns all languages from WCFSetup.tar.gz.\r
+        *\r
+        * @return      array\r
+        */\r
+       protected static function getAllLanguages() {\r
+               $languages = $match = array();\r
+               $tar = new Tar(SETUP_FILE);\r
+               foreach ($tar->getContentList() as $file) {\r
+                       if (strpos($file['filename'], 'setup/lang/') === 0 && substr($file['filename'], -4) == '.xml' && preg_match('!^setup_([a-z]{2}(?:-[A-Za-z0-9]+)?(?:_[A-Za-z]{2})?)$!', basename($file['filename'], '.xml'), $match)) {\r
+                               $languages[] = $match[1];\r
+                       }\r
+               }\r
+               $tar->close();\r
+\r
+               // sort languages by language code\r
+               sort($languages);\r
+\r
+               return $languages;\r
+       }\r
+       \r
+       /**\r
+        * Calculates the current state of the progress bar.\r
+        *\r
+        * @param       integer         $currentStep\r
+        */\r
+       protected function calcProgress($currentStep) {\r
+               // count delivered packages\r
+               $packages = 1; // one for wcf setup\r
+               $tar = new Tar(SETUP_FILE);\r
+               foreach ($tar->getContentList() as $file) {\r
+                       if ($file['type'] != 'folder' && StringUtil::indexOf($file['filename'], 'install/packages/') === 0) {\r
+                               $packages++;\r
+                       }\r
+               }\r
+               $tar->close();\r
+               \r
+               // calculate part of total install\r
+               $part = 100 / $packages;\r
+               \r
+               // calculate progress\r
+               $progress = round($part / 11 * $currentStep, 0);\r
+               self::getTPL()->assign(array('progress' => $progress));\r
+       }\r
+       \r
+       /**\r
+        * Executes the setup steps.\r
+        */\r
+       protected function setup() {\r
+               // get current step\r
+               if (isset($_REQUEST['step'])) $step = $_REQUEST['step'];\r
+               else $step = 'selectSetupLanguage';\r
+\r
+               // execute current step\r
+               switch ($step) {\r
+                       case 'selectSetupLanguage':\r
+                               if (!self::$developerMode) {\r
+                                       $this->calcProgress(0);\r
+                                       $this->selectSetupLanguage();\r
+                                       break;\r
+                               }\r
+                               \r
+                       case 'showLicense':\r
+                               if (!self::$developerMode) {\r
+                                       $this->calcProgress(1);\r
+                                       $this->showLicense();\r
+                                       break;\r
+                               }\r
+                               \r
+                       case 'showSystemRequirements':\r
+                               if (!self::$developerMode) {\r
+                                       $this->calcProgress(2);\r
+                                       $this->showSystemRequirements();\r
+                                       break;\r
+                               }\r
+                               \r
+                       case 'searchWcfDir':\r
+                               $this->calcProgress(3);\r
+                               $this->searchWcfDir();\r
+                               break;\r
+                               \r
+                       case 'unzipFiles':\r
+                               $this->calcProgress(4);\r
+                               $this->unzipFiles();\r
+                               break;\r
+                               \r
+                       case 'selectLanguages':\r
+                               $this->calcProgress(5);\r
+                               $this->selectLanguages();\r
+                               break;\r
+                               \r
+                       case 'configureDB':\r
+                               $this->calcProgress(6);\r
+                               $this->configureDB();\r
+                               break;\r
+                               \r
+                       case 'createDB':\r
+                               $this->calcProgress(7);\r
+                               $this->createDB();\r
+                               break;\r
+                               \r
+                       case 'logFiles':\r
+                               $this->calcProgress(8);\r
+                               $this->logFiles();\r
+                               break;\r
+                               \r
+                       case 'installLanguage':\r
+                               $this->calcProgress(9);\r
+                               $this->installLanguage();\r
+                               break;\r
+                               \r
+                       case 'createUser':\r
+                               $this->calcProgress(10);\r
+                               $this->createUser();\r
+                               break;\r
+                               \r
+                       case 'installPackages':\r
+                               $this->calcProgress(11);\r
+                               $this->installPackages();\r
+                               break;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Shows the first setup page.\r
+        */\r
+       protected function selectSetupLanguage() {\r
+               // build language list\r
+               $languages = array();\r
+               foreach (self::$availableLanguages as $languageCode) {\r
+                       $languages[$languageCode] = self::getLanguage()->get('wcf.global.language.'.$languageCode).' ('.$languageCode.')';\r
+               }\r
+               \r
+               // sort languages\r
+               StringUtil::sort($languages);\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'availableLanguages' => $languages,\r
+                       'nextStep' => 'showLicense'\r
+               ));\r
+               WCF::getTPL()->display('stepSelectSetupLanguage');\r
+       }\r
+       \r
+       /**\r
+        * Shows the license agreement.\r
+        */\r
+       protected function showLicense() {\r
+               if (isset($_POST['send'])) {\r
+                       if (isset($_POST['accepted'])) {\r
+                               $this->gotoNextStep('showSystemRequirements');\r
+                               exit;\r
+                       }\r
+                       else {\r
+                               WCF::getTPL()->assign(array('missingAcception' => true));\r
+                       }\r
+               \r
+               }\r
+               \r
+               if (file_exists(TMP_DIR.'setup/license/license_'.self::$selectedLanguageCode.'.txt')) {\r
+                       $license = file_get_contents(TMP_DIR.'setup/license/license_'.self::$selectedLanguageCode.'.txt');\r
+               }\r
+               else {\r
+                       $license = file_get_contents(TMP_DIR.'setup/license/license_en.txt');\r
+               }\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'license' => $license,\r
+                       'nextStep' => 'showLicense'\r
+               ));\r
+               WCF::getTPL()->display('stepShowLicense');\r
+       }\r
+       \r
+       /**\r
+        * Shows the system requirements.\r
+        */\r
+       protected function showSystemRequirements() {\r
+               $system = array();\r
+               \r
+               // php version\r
+               $system['phpVersion']['value'] = phpversion();\r
+               $comparePhpVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $system['phpVersion']['value']);\r
+               $system['phpVersion']['result'] = (version_compare($comparePhpVersion, '5.3.0') >= 0);\r
+               \r
+               // sql\r
+               $system['sql']['value'] = array_keys(self::getAvailableDBClasses());\r
+               $system['sql']['result'] = count($system['sql']['value'] > 0);\r
+               \r
+               // upload_max_filesize\r
+               $system['uploadMaxFilesize']['value'] = ini_get('upload_max_filesize');\r
+               $system['uploadMaxFilesize']['result'] = (intval($system['uploadMaxFilesize']['value']) > 0);\r
+               \r
+               // gdlib version\r
+               $system['gdLib']['value'] = '0.0.0';\r
+               if (function_exists('gd_info')) {\r
+                       $temp = gd_info();\r
+                       $match = array();\r
+                       if (preg_match('!([0-9]+\.[0-9]+(?:\.[0-9]+)?)!', $temp['GD Version'], $match)) {\r
+                               if (preg_match('/^[0-9]+\.[0-9]+$/', $match[1])) $match[1] .= '.0';\r
+                               $system['gdLib']['value'] = $match[1];\r
+                       }\r
+               }\r
+               $system['gdLib']['result'] = (version_compare($system['gdLib']['value'], '2.0.0') >= 0);\r
+               \r
+               // mb string\r
+               $system['mbString']['result'] = extension_loaded('mbstring');\r
+               \r
+               // safe mode\r
+               $system['safeMode']['result'] = (FileUtil::getSafeMode() != 1);\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'system' => $system,\r
+                       'nextStep' => 'searchWcfDir'\r
+               ));\r
+               WCF::getTPL()->display('stepShowSystemRequirements');\r
+       }\r
+       \r
+       /**\r
+        * Searches the wcf dir.\r
+        */\r
+       protected function searchWcfDir() {\r
+               $foundDirectory = '';\r
+               if (self::$wcfDir) {\r
+                       $wcfDir = self::$wcfDir;\r
+               }\r
+               else {\r
+                       if ($foundDirectory = FileUtil::scanFolder(INSTALL_SCRIPT_DIR, "WCF.class.php", true)) {\r
+                               $foundDirectory = $wcfDir = FileUtil::unifyDirSeperator(dirname(dirname(dirname($foundDirectory))).'/');\r
+                       }\r
+                       else {\r
+                               $wcfDir = FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR).'wcf/';\r
+                       }\r
+               }\r
+               \r
+               // domain\r
+               $domainName = '';\r
+               if (!empty($_SERVER['SERVER_NAME'])) $domainName = 'http://' . $_SERVER['SERVER_NAME'];\r
+               // port\r
+               if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80) $domainName .= ':' . $_SERVER['SERVER_PORT'];\r
+               // script url\r
+               $installScriptUrl = '';\r
+               if (!empty($_SERVER['REQUEST_URI'])) $installScriptUrl = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash(FileUtil::unifyDirSeperator(dirname($_SERVER['REQUEST_URI']))));\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'nextStep' => 'unzipFiles',\r
+                       'foundDirectory' => $foundDirectory,\r
+                       'wcfDir' => $wcfDir,\r
+                       'domainName' => $domainName,\r
+                       'installScriptUrl' => $installScriptUrl,\r
+                       'installScriptDir' => FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR)\r
+               ));\r
+               \r
+               WCF::getTPL()->display('stepSearchWcfDir');\r
+       }\r
+       \r
+       /**\r
+        * Unzips the files of the wcfsetup tar archive.\r
+        */\r
+       protected function unzipFiles() {\r
+               // WCF seems to be installed, skip installation of\r
+               // files, database and admin account\r
+               // and go directly to the installation of packages\r
+               if (@is_file(self::$wcfDir.'lib/system/WCF.class.php')) {\r
+                       $this->gotoNextStep('installPackages');\r
+                       exit;\r
+               }\r
+               // WCF not yet installed, install files first\r
+               else {\r
+                       try {\r
+                               $this->installFiles();\r
+                       }\r
+                       catch (Exception $e) {\r
+                               WCF::getTPL()->assign(array('exception' => $e));\r
+                               $this->searchWcfDir();\r
+                               return;\r
+                       }\r
+                       \r
+                       $this->gotoNextStep('selectLanguages');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Shows the page for choosing the installed languages.\r
+        */\r
+       protected function selectLanguages() {\r
+               $errorField = $errorType = '';\r
+               $allLanguages = $this->getAllLanguages();\r
+               $illegalLanguages = array();\r
+               \r
+               // build visible language list\r
+               $languages = array();\r
+               foreach ($allLanguages as $languageCode) {\r
+                       $languages[$languageCode] = self::getLanguage()->get('wcf.global.language.'.$languageCode).' ('.$languageCode.')';\r
+               }\r
+               \r
+               // skip step in developer mode\r
+               // select all available languages automatically\r
+               if (self::$developerMode) {\r
+                       self::$selectedLanguages = array();\r
+                       foreach ($allLanguages as $languageCode) {\r
+                               self::$selectedLanguages[] = $languageCode;\r
+                       }\r
+                       \r
+                       self::getTPL()->assign(array('selectedLanguages' => self::$selectedLanguages));\r
+                       $this->gotoNextStep('configureDB');\r
+                       exit;\r
+               }\r
+               \r
+               // sort languages\r
+               StringUtil::sort($languages);\r
+               \r
+               // start error handling\r
+               if (isset($_POST['send'])) {\r
+                       try {\r
+                               // no languages selected\r
+                               if (count(self::$selectedLanguages) == 0) {\r
+                                       throw new UserInputException('selectedLanguages');\r
+                               }\r
+                               \r
+                               // illegal selection\r
+                               foreach (self::$selectedLanguages as $language) {\r
+                                       if (!isset($languages[$language])) {\r
+                                               throw new UserInputException('selectedLanguages');\r
+                                       }\r
+                               }\r
+                               \r
+                               // no errors\r
+                               // go to next step\r
+                               $this->gotoNextStep('configureDB');\r
+                               exit;\r
+                       }\r
+                       catch (UserInputException $e) {\r
+                               $errorField = $e->getField();\r
+                               $errorType = $e->getType();\r
+                       }\r
+               }\r
+               else {\r
+                       self::$selectedLanguages[] = self::$selectedLanguageCode;\r
+                       WCF::getTPL()->assign(array('selectedLanguages' => self::$selectedLanguages));\r
+               }\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'errorField' => $errorField,\r
+                       'errorType' => $errorType,\r
+                       'languages' => $languages,\r
+                       'nextStep' => 'selectLanguages'\r
+               ));\r
+               WCF::getTPL()->display('stepSelectLanguages');\r
+       }\r
+       \r
+       /**\r
+        * Shows the page for configurating the database connection.\r
+        */\r
+       protected function configureDB() {\r
+               $availableDBClasses = self::getAvailableDBClasses();\r
+               $dbHost = 'localhost';\r
+               $dbUser = 'root';\r
+               $dbPassword = '';\r
+               $dbName = 'wcf';\r
+               $dbNumber = '1';\r
+               $dbClass = 'MySQLDatabase';\r
+               if (!function_exists('mysql_connect')) $dbClass = 'MySQLiDatabase';\r
+               $overwriteTables = false;\r
+               \r
+               if (isset($_POST['send'])) {\r
+                       if (isset($_POST['dbHost'])) $dbHost = $_POST['dbHost'];\r
+                       if (isset($_POST['dbUser'])) $dbUser = $_POST['dbUser'];\r
+                       if (isset($_POST['dbPassword'])) $dbPassword = $_POST['dbPassword'];\r
+                       if (isset($_POST['dbName'])) $dbName = $_POST['dbName'];\r
+                       if (isset($_POST['overwriteTables'])) $overwriteTables = intval($_POST['overwriteTables']);\r
+                       // Should the user not be prompted if converted or default n match an\r
+                       // existing installation number? By now the existing installation\r
+                       // will be overwritten just so!\r
+                       if (isset($_POST['dbNumber'])) $dbNumber = intval($_POST['dbNumber']);\r
+                       if (isset($_POST['dbClass'])) $dbClass = $_POST['dbClass'];\r
+                       \r
+                       // get port\r
+                       $dbPort = 0;\r
+                       if (preg_match('/^(.+?):(\d+)$/', $dbHost, $match)) {\r
+                               $dbHost = $match[1];\r
+                               $dbPort = intval($match[2]);\r
+                       }\r
+                       \r
+                       // test connection\r
+                       try {\r
+                               // check db class\r
+                               $validDB = false;\r
+                               foreach ($availableDBClasses as $dbData) {\r
+                                       if ($dbData['class'] == $dbClass) {\r
+                                               $validDB = true;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               \r
+                               if (!$validDB) {\r
+                                       throw new SystemException("Database type '".$dbClass."'. is not available on this system.");\r
+                               }\r
+                               \r
+                               // check connection data\r
+                               $db = new $dbClass($dbHost, $dbUser, $dbPassword, $dbName, $dbPort);\r
+                               $db->connect();\r
+                               \r
+                               // check sql version\r
+                               if (!empty($availableDBClasses[$dbClass]['minversion'])) {\r
+                                       $sqlVersion = $db->getVersion();\r
+                                       if ($sqlVersion != 'unknown') {\r
+                                               $compareSQLVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $sqlVersion);\r
+                                               if (!(version_compare($compareSQLVersion, $availableDBClasses[$dbClass]['minversion']) >= 0)) {\r
+                                                       throw new SystemException("Insufficient SQL version '".$compareSQLVersion."'. Version '".$availableDBClasses[$dbClass]['minversion']."' or greater is needed.");\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               // check for table conflicts\r
+                               $conflictedTables = $this->getConflictedTables($db, $dbNumber);\r
+                               \r
+                               // write config.inc\r
+                               if (empty($conflictedTables) || $overwriteTables || self::$developerMode) {\r
+                                       // connection successfully established\r
+                                       // write configuration to config.inc.php\r
+                                       $file = new File(WCF_DIR.'config.inc.php');\r
+                                       $file->write("<?php\n");\r
+                                       $file->write("\$dbHost = '".StringUtil::replace("'", "\\'", $dbHost)."';\n");\r
+                                       $file->write("\$dbPort = ".$dbPort.";\n");\r
+                                       $file->write("\$dbUser = '".StringUtil::replace("'", "\\'", $dbUser)."';\n");\r
+                                       $file->write("\$dbPassword = '".StringUtil::replace("'", "\\'", $dbPassword)."';\n");\r
+                                       $file->write("\$dbName = '".StringUtil::replace("'", "\\'", $dbName)."';\n");\r
+                                       $file->write("\$dbClass = '".StringUtil::replace("'", "\\'", $dbClass)."';\n");\r
+                                       $file->write("if (!defined('WCF_N')) define('WCF_N', $dbNumber);\n?>");\r
+                                       $file->close();\r
+                               \r
+                                       // go to next step\r
+                                       $this->gotoNextStep('createDB');\r
+                                       exit;\r
+                               }\r
+                               // show configure temnplate again\r
+                               else {\r
+                                       WCF::getTPL()->assign(array('conflictedTables' => $conflictedTables));\r
+                               }\r
+                       }\r
+                       catch (SystemException $e) {\r
+                               WCF::getTPL()->assign(array('exception' => $e));\r
+                       }\r
+               }\r
+               WCF::getTPL()->assign(array(\r
+                       'dbHost' => $dbHost,\r
+                       'dbUser' => $dbUser,\r
+                       'dbPassword' => $dbPassword,\r
+                       'dbName' => $dbName,\r
+                       'dbNumber' => $dbNumber,\r
+                       'dbClass' => $dbClass,\r
+                       'availableDBClasses' => $availableDBClasses,\r
+                       'nextStep' => 'configureDB'\r
+               ));\r
+               WCF::getTPL()->display('stepConfigureDB');\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Checks if in the chosen database are tables in conflict with the wcf tables\r
+        * which will be created in the next step.\r
+        *\r
+        * @param       Database        $db\r
+        * @param       integer         $dbNumber\r
+        */\r
+       protected function getConflictedTables($db, $dbNumber) {\r
+               // get content of the sql structure file\r
+               $sql = file_get_contents(TMP_DIR.'setup/db/install.sql');\r
+               \r
+               // installation number value 'n' (WCF_N) must be reflected in the executed sql queries\r
+               $sql = StringUtil::replace('wcf1_', 'wcf'.$dbNumber.'_', $sql);\r
+               \r
+               // get all tablenames which should be created\r
+               preg_match_all("%CREATE\s+TABLE\s+(\w+)%", $sql, $matches);\r
+               \r
+               // get all installed tables from chosen database\r
+               $existingTables = $db->getEditor()->getTableNames();\r
+               \r
+               // check if existing tables are in conflict with wcf tables\r
+               $conflictedTables = array();\r
+               foreach ($existingTables as $existingTableName) {\r
+                       foreach ($matches[1] as $wcfTableName) {\r
+                               if ($existingTableName == $wcfTableName) {\r
+                                       $conflictedTables[] = $wcfTableName;\r
+                               }\r
+                       }\r
+               }\r
+               return $conflictedTables;\r
+       }\r
+       \r
+       /**\r
+        * Creates the database structure of the wcf.\r
+        */\r
+       protected function createDB() {\r
+               $this->initDB();\r
+               \r
+               // get content of the sql structure file\r
+               $sql = file_get_contents(TMP_DIR.'setup/db/install.sql');\r
+               \r
+               // installation number value 'n' (WCF_N) must be reflected in the executed sql queries\r
+               $sql = StringUtil::replace('wcf1_', 'wcf'.WCF_N.'_', $sql);\r
+               \r
+               // execute sql queries\r
+               $parser = new SQLParser($sql);\r
+               $parser->execute();\r
+               \r
+               // log sql queries\r
+               preg_match_all("~CREATE\s+TABLE\s+(\w+)~i", $sql, $matches);\r
+               \r
+               if (count($matches[1])) {\r
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_sql_log\r
+                                               (sqlTable)\r
+                               VALUES          (?)";\r
+                       $statement = self::getDB()->prepareStatement($sql);\r
+                       foreach ($matches[1] as $tableName) {\r
+                               $statement->execute(array($tableName));\r
+                       }\r
+               }\r
+               \r
+               /*\r
+                * Manually install PIPPackageInstallationPlugin since install.sql content is not escaped resulting\r
+                * in different behaviour in MySQL and MSSQL. You SHOULD NOT move this into install.sql!\r
+                */\r
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_plugin\r
+                                       (pluginName, priority, className)\r
+                       VALUES          (?, ?, ?)";\r
+               $statement = self::getDB()->prepareStatement($sql);\r
+               $statement->execute(array(\r
+                       'packageinstallationplugins',\r
+                       1,\r
+                       'wcf\system\package\plugin\PIPPackageInstallationPlugin'\r
+               ));\r
+               \r
+               $this->gotoNextStep('logFiles');\r
+       }\r
+       \r
+       /**\r
+        * Logs the unzipped files.\r
+        */\r
+       protected function logFiles() {\r
+               $this->initDB();\r
+               \r
+               $this->getInstalledFiles(WCF_DIR);\r
+               $acpTemplateInserts = $fileInserts = array();\r
+               foreach (self::$installedFiles as $file) {\r
+                       $match = array();\r
+                       if (preg_match('!/acp/templates/([^/]+)\.tpl$!', $file, $match)) {\r
+                               // acp template\r
+                               $acpTemplateInserts[] = $match[1];\r
+                       }\r
+                       else {\r
+                               // regular file\r
+                               $fileInserts[] = StringUtil::replace(WCF_DIR, '', $file);\r
+                       }\r
+               }\r
+               \r
+               // save acp template log\r
+               if (!empty($acpTemplateInserts)) {\r
+                       $sql = "INSERT INTO     wcf".WCF_N."_acp_template\r
+                                               (templateName)\r
+                               VALUES          (?)";\r
+                       $statement = self::getDB()->prepareStatement($sql);\r
+                       \r
+                       foreach ($acpTemplateInserts as $acpTemplate) {\r
+                               $statement->execute(array($acpTemplate));\r
+                       }\r
+               }\r
+               \r
+               // save file log\r
+               if (!empty($fileInserts)) {\r
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_file_log\r
+                                               (filename)\r
+                               VALUES          (?)";\r
+                       $statement = self::getDB()->prepareStatement($sql);\r
+                       \r
+                       foreach ($fileInserts as $file) {\r
+                               $statement->execute(array($file));\r
+                       }\r
+               }\r
+               \r
+               $this->gotoNextStep('installLanguage');\r
+       }\r
+       \r
+       /**\r
+        * Scans the given dir for installed files.\r
+        *\r
+        * @param       string          $dir\r
+        */\r
+       protected function getInstalledFiles($dir) {\r
+               if ($files = glob($dir.'*')) {\r
+                       foreach ($files as $file) {\r
+                               if (is_dir($file)) {\r
+                                       $this->getInstalledFiles(FileUtil::addTrailingSlash($file));\r
+                               }\r
+                               else {\r
+                                       self::$installedFiles[] = FileUtil::unifyDirSeperator($file);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Installs the selected languages.\r
+        */\r
+       protected function installLanguage() {\r
+               $this->initDB();\r
+               \r
+               foreach (self::$selectedLanguages as $language) {\r
+                       // get language.xml file name\r
+                       $filename = TMP_DIR.'install/lang/'.$language.'.xml';\r
+                       \r
+                       // check the file\r
+                       if (!file_exists($filename)) {\r
+                               throw new SystemException("unable to find language file '".$filename."'", 11002);\r
+                       }\r
+                       \r
+                       // open the file\r
+                       $xml = new XML();\r
+                       $xml->load($filename);\r
+                       \r
+                       // import xml\r
+                       LanguageEditor::importFromXML($xml, 0);\r
+               }\r
+               \r
+               // set default language\r
+               $language = LanguageFactory::getLanguageByCode(in_array(self::$selectedLanguageCode, self::$selectedLanguages) ? self::$selectedLanguageCode : self::$selectedLanguages[0]);\r
+               LanguageFactory::makeDefault($language->languageID);\r
+               \r
+               // assign all languages to package id 0\r
+               $sql = "SELECT  languageID\r
+                       FROM    wcf".WCF_N."_language";\r
+               $statement = self::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               $languages = array();\r
+               while ($row = $statement->fetchArray()) {\r
+                       $languages[] = $row['languageID'];\r
+               }\r
+               \r
+               if (count($languages) > 0) {\r
+                       $sql = "INSERT INTO     wcf".WCF_N."_language_to_package\r
+                                               (languageID)\r
+                               VALUES          (?)";\r
+                       $statement = self::getDB()->prepareStatement($sql);\r
+                       \r
+                       foreach ($languages as $languageID) {\r
+                               $statement->execute(array(\r
+                                       $languageID\r
+                               ));\r
+                       }\r
+               }\r
+               \r
+               // rebuild language cache\r
+               CacheHandler::getInstance()->clearResource('languages');\r
+               \r
+               // go to next step\r
+               $this->gotoNextStep('createUser');\r
+       }\r
+       \r
+       /**\r
+        * Shows the page for creating the admin account.\r
+        */\r
+       protected function createUser() {\r
+               $errorType = $errorField = $username = $email = $confirmEmail = $password = $confirmPassword = '';\r
+               \r
+               $username = '';\r
+               $email = $confirmEmail = '';\r
+               $password = $confirmPassword = '';\r
+               \r
+               if (isset($_POST['send']) || self::$developerMode) {\r
+                       if (isset($_POST['send'])) {\r
+                               if (isset($_POST['username']))          $username = StringUtil::trim($_POST['username']);\r
+                               if (isset($_POST['email']))             $email = StringUtil::trim($_POST['email']);\r
+                               if (isset($_POST['confirmEmail']))      $confirmEmail = StringUtil::trim($_POST['confirmEmail']);\r
+                               if (isset($_POST['password']))          $password = $_POST['password'];\r
+                               if (isset($_POST['confirmPassword']))   $confirmPassword = $_POST['confirmPassword'];\r
+                       }\r
+                       else {\r
+                               $username = $password = $confirmPassword = 'root';\r
+                               $email = $confirmEmail = 'woltlab@woltlab.com';\r
+                       }\r
+                       \r
+                       // error handling\r
+                       try {\r
+                               // username\r
+                               if (empty($username)) {\r
+                                       throw new UserInputException('username');\r
+                               }\r
+                               if (!UserUtil::isValidUsername($username)) {\r
+                                       throw new UserInputException('username', 'notValid');\r
+                               }\r
+                               \r
+                               // e-mail address\r
+                               if (empty($email)) {\r
+                                       throw new UserInputException('email');\r
+                               }\r
+                               if (!UserUtil::isValidEmail($email)) {\r
+                                       throw new UserInputException('email', 'notValid');\r
+                               }\r
+                               \r
+                               // confirm e-mail address\r
+                               if ($email != $confirmEmail) {\r
+                                       throw new UserInputException('confirmEmail', 'notEqual');\r
+                               }\r
+                               \r
+                               // password\r
+                               if (empty($password)) {\r
+                                       throw new UserInputException('password');\r
+                               }\r
+                               \r
+                               // confirm e-mail address\r
+                               if ($password != $confirmPassword) {\r
+                                       throw new UserInputException('confirmPassword', 'notEqual');\r
+                               }\r
+                               \r
+                               // no errors\r
+                               // init database connection\r
+                               $this->initDB();\r
+                               \r
+                               // get language id\r
+                               $languageID = 0;\r
+                               $sql = "SELECT  languageID\r
+                                       FROM    wcf".WCF_N."_language\r
+                                       WHERE   languageCode = ?";\r
+                               $statement = self::getDB()->prepareStatement($sql);\r
+                               $statement->execute(array(self::$selectedLanguageCode));\r
+                               $row = $statement->fetchArray();\r
+                               if (isset($row['languageID'])) $languageID = $row['languageID'];\r
+                               \r
+                               // create user\r
+                               $data = array(\r
+                                       'data' => array(\r
+                                               'email' => $email,\r
+                                               'languageID' => $languageID,\r
+                                               'password' => $password,\r
+                                               'username' => $username\r
+                                       ),\r
+                                       'groups' => array(\r
+                                               1,\r
+                                               3,\r
+                                               4\r
+                                       ),\r
+                                       'languages' => array(\r
+                                               $languageID\r
+                                       )\r
+                               );\r
+                               \r
+                               $userAction = new UserAction(array(), 'create', $data);\r
+                               $userAction->executeAction();\r
+                               \r
+                               // go to next step\r
+                               $this->gotoNextStep('installPackages');\r
+                               exit;\r
+                       }\r
+                       catch (UserInputException $e) {\r
+                               $errorField = $e->getField();\r
+                               $errorType = $e->getType();\r
+                       }\r
+               }\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'errorField' => $errorField,\r
+                       'errorType' => $errorType,\r
+                       'username' => $username,\r
+                       'email' => $email,\r
+                       'confirmEmail' => $confirmEmail,\r
+                       'password' => $password,\r
+                       'confirmPassword' => $confirmPassword,\r
+                       'nextStep' => 'createUser'\r
+               ));\r
+               WCF::getTPL()->display('stepCreateUser');\r
+       }\r
+       \r
+       /**\r
+        * Registers with wcf setup delivered packages in the package installation queue.\r
+        */\r
+       protected function installPackages() {\r
+               // init database connection\r
+               $this->initDB();\r
+               \r
+               // get admin account\r
+               $admin = new User(1);\r
+               \r
+               // get delivered packages\r
+               $wcfPackageFile = '';\r
+               $otherPackages = array();\r
+               $tar = new Tar(SETUP_FILE);\r
+               foreach ($tar->getContentList() as $file) {\r
+                       if ($file['type'] != 'folder' && StringUtil::indexOf($file['filename'], 'install/packages/') === 0) {\r
+                               $packageFile = basename($file['filename']);\r
+                               $packageName = preg_replace('!\.(tar\.gz|tgz|tar)$!', '', $packageFile);\r
+                               \r
+                               if ($packageName == 'com.woltlab.wcf') {\r
+                                       $wcfPackageFile = $packageFile;\r
+                               }\r
+                               else {\r
+                                       $isStrato = (!empty($_SERVER['DOCUMENT_ROOT']) && (strpos($_SERVER['DOCUMENT_ROOT'], 'strato') !== false));\r
+                                       if (!$isStrato && preg_match('!\.(tar\.gz|tgz)$!', $packageFile)) {\r
+                                               // try to unzip zipped package files\r
+                                               if (FileUtil::uncompressFile(TMP_DIR.'install/packages/'.$packageFile, TMP_DIR.'install/packages/'.$packageName.'.tar')) {\r
+                                                       @unlink(TMP_DIR.'install/packages/'.$packageFile);\r
+                                                       $packageFile = $packageName.'.tar';\r
+                                               }\r
+                                       }\r
+                                       \r
+                                       $otherPackages[$packageName] = $packageFile;\r
+                               }\r
+                       }\r
+               }\r
+               $tar->close();\r
+               \r
+               // register packages in queue\r
+               // get new process id\r
+               $sql = "SELECT  MAX(processNo) AS processNo\r
+                       FROM    wcf".WCF_N."_package_installation_queue";\r
+               $statement = self::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               $result = $statement->fetchArray();\r
+               $processNo = intval($result['processNo']) + 1;\r
+               $statementParameters = array();\r
+               \r
+               // search existing wcf package\r
+               $sql = "SELECT  COUNT(*) AS count\r
+                       FROM    wcf".WCF_N."_package\r
+                       WHERE   package = 'com.woltlab.wcf'";\r
+               $statement = self::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               $row = $statement->fetchArray();\r
+               if (!$row['count']) {\r
+                       if (empty($wcfPackageFile)) {\r
+                               throw new SystemException('the essential package com.woltlab.wcf is missing.', 11007);\r
+                       }\r
+                       \r
+                       // register essential wcf package\r
+                       $statementParameters[] = array(\r
+                               'packageName' => 'com.woltlab.wcf',\r
+                               'archive' => TMP_DIR.'install/packages/'.$wcfPackageFile\r
+                       );\r
+               }\r
+               \r
+               // register all other delivered packages\r
+               asort($otherPackages);\r
+               foreach ($otherPackages as $packageName => $packageFile) {\r
+                       $statementParameters[] = array(\r
+                               'packageName' => $packageName,\r
+                               'archive' => TMP_DIR.'install/packages/'.$packageFile\r
+                       );\r
+               }\r
+               \r
+               if (!empty($statementParameters)) {\r
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_queue\r
+                                               (processNo, userID, package, archive)\r
+                               VALUES          (?, ?, ?, ?)";\r
+                       $statement = self::getDB()->prepareStatement($sql);\r
+                       \r
+                       foreach ($statementParameters as $parameter) {\r
+                               $statement->execute(array(\r
+                                       $processNo,\r
+                                       $admin->userID,\r
+                                       $parameter['packageName'],\r
+                                       $parameter['archive']\r
+                               ));\r
+                       }\r
+               }\r
+               \r
+               // login as admin\r
+               $factory = new ACPSessionFactory();\r
+               $factory->load();\r
+               \r
+               SessionHandler::getInstance()->changeUser($admin);\r
+               SessionHandler::getInstance()->register('masterPassword', 1);\r
+               SessionHandler::getInstance()->update();\r
+               \r
+               // TODO: print message if delete fails\r
+               $installPhpDeleted = @unlink('./install.php');\r
+               $testPhpDeleted = @unlink('./test.php');\r
+               $wcfSetupTarDeleted = @unlink('./WCFSetup.tar.gz');\r
+               \r
+               // print page\r
+               WCF::getTPL()->assign(array(\r
+                       'installPhpDeleted' => $installPhpDeleted,\r
+                       'wcfSetupTarDeleted' => $wcfSetupTarDeleted\r
+               ));\r
+               WCF::getTPL()->display('stepInstallPackages');\r
+               \r
+               // delete tmp files\r
+               $directory = TMP_DIR.TMP_FILE_PREFIX.'/';\r
+               $it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory));\r
+               while ($it->valid()) {\r
+                       // delete all files except directories and packages (required for post-wcfsetup installation)\r
+                       if (!$it->isDot() && !$it->isDir() && !preg_match('~\.tar(\.gz)?$~', $it->getSubPathName())) {\r
+                               @unlink($it->key());\r
+                       }\r
+                       \r
+                       $it->next();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Goes to the next step.\r
+        *\r
+        * @param       string          $nextStep\r
+        */\r
+       protected function gotoNextStep($nextStep) {\r
+               WCF::getTPL()->assign(array('nextStep' => $nextStep));\r
+               WCF::getTPL()->display('stepNext');\r
+       }\r
+       \r
+       /**\r
+        * Installs the files of the tar archive.\r
+        */\r
+       protected static function installFiles() {\r
+               new Installer(self::$wcfDir, SETUP_FILE, null, 'install/files/');\r
+       }\r
+       \r
+       /**\r
+        * Gets the package name of the first standalone application in WCFSetup.tar.gz.\r
+        */\r
+       protected static function getPackageName() {\r
+               // get package name\r
+               $tar = new Tar(SETUP_FILE);\r
+               foreach ($tar->getContentList() as $file) {\r
+                       if ($file['type'] != 'folder' && StringUtil::indexOf($file['filename'], 'install/packages/') === 0) {\r
+                               $packageFile = basename($file['filename']);\r
+                               $packageName = preg_replace('!\.(tar\.gz|tgz|tar)$!', '', $packageFile);\r
+                               \r
+                               if ($packageName != 'com.woltlab.wcf') {\r
+                                       try {\r
+                                               $archive = new PackageArchive(TMP_DIR.'install/packages/'.$packageFile);\r
+                                               $archive->openArchive();\r
+                                               self::$setupPackageName = $archive->getPackageInfo('packageName');\r
+                                               $archive->getTar()->close();\r
+                                               break;\r
+                                       }\r
+                                       catch (SystemException $e) {}\r
+                               }\r
+                       }\r
+               }\r
+               $tar->close();\r
+               \r
+               // assign package name\r
+               WCF::getTPL()->assign(array('setupPackageName' => self::$setupPackageName));\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/application/AbstractApplication.class.php b/wcfsetup/install/files/lib/system/application/AbstractApplication.class.php
new file mode 100644 (file)
index 0000000..95ce717
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+namespace wcf\system\application;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * Default implementation for all applications for the community framework.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system
+ * @category   Community Framework
+ */
+abstract class AbstractApplication implements Application {
+       /**
+        * @see Application::__callStatic()
+        */
+       public static function __callStatic($method, array $arguments) {
+               return call_user_func_array(array('wcf\system\WCF', $method), $arguments);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/application/Application.class.php b/wcfsetup/install/files/lib/system/application/Application.class.php
new file mode 100644 (file)
index 0000000..c5901e8
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+namespace wcf\system\application;
+
+/**
+ * Default interface for all applications for the community framework.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system
+ * @category   Community Framework
+ */
+interface Application {
+       /**
+        * Forwards unknown method calls to WCF.
+        * 
+        * @param       string          $method
+        * @param       array           $arguments
+        * @return      mixed
+        */
+       public static function __callStatic($method, array $arguments);
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/application/ApplicationHandler.class.php b/wcfsetup/install/files/lib/system/application/ApplicationHandler.class.php
new file mode 100644 (file)
index 0000000..f4322f0
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+namespace wcf\system\application;
+use wcf\system\cache\CacheHandler;
+use wcf\system\SingletonFactory;
+
+/**
+ * Handles multi-application environments.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.application
+ * @category   Community Framework
+ */
+class ApplicationHandler extends SingletonFactory {
+       /**
+        * application cache
+        *
+        * @var array<array>
+        */     
+       protected $cache = null;
+       
+       /**
+        * Initializes cache.
+        */
+       protected function init() {
+               CacheHandler::getInstance()->addResource(
+                       'application-'.PACKAGE_ID,
+                       WCF_DIR.'cache/cache.application-'.PACKAGE_ID.'.php',
+                       'wcf\system\cache\CacheBuilderApplication'
+               );
+               $this->cache = CacheHandler::getInstance()->get('application-'.PACKAGE_ID);
+       }
+       
+       /**
+        * Returns the primary application for current group. Will return current
+        * application equal to PACKAGE_ID if not within any group.
+        * 
+        * @return      Application
+        */
+       public function getPrimaryApplication() {
+               return $this->cache['application'][$this->cache['primary']];
+       }
+       
+       /**
+        * Returns an application based upon it's abbreviation. Will return the
+        * primary application if $abbreviation equals to 'wcf'
+        * 
+        * @return      Application
+        */      
+       public function getApplication($abbreviation) {
+               if ($abbreviation == 'wcf') {
+                       return $this->getPrimaryApplication();
+               }
+               
+               if (isset($this->cache['abbreviation'][$abbreviation])) {
+                       $packageID = $this->cache['abbreviation'][$abbreviation];
+                       
+                       if (isset($this->cache['application'][$packageID])) {
+                               return $this->cache['application'][$packageID];
+                       }
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Returns active application group or 'null' if current application
+        * is not within a group.
+        * 
+        * @return      ApplicationGroup
+        */     
+       public function getActiveGroup() {
+               return $this->cache['group'];
+       }
+       
+       /**
+        * Returns pseudo-application representing WCF used for special cases,
+        * e.g. cross-domain files requestable through the webserver.
+        * 
+        * @return      Application
+        */
+       public function getWCF() {
+               return $this->cache['wcf'];
+       }
+       
+       /**
+        * Returns the currently active application.
+        * 
+        * @return      wcf\data\application\Application
+        */     
+       public function getActiveApplication() {
+               return $this->cache['application'][PACKAGE_ID];
+       }
+       
+       /**
+        * Returns a list of dependent applications.
+        * 
+        * @return      array<wcf\data\application\Application>
+        */     
+       public function getDependentApplications() {
+               $applications = array();
+               foreach ($this->cache['application'] as $packageID => $application) {
+                       if ($packageID == PACKAGE_ID) continue;
+                       
+                       $applications[] = $application;
+               }
+               
+               return $applications;
+       }
+       
+       /**
+        * Returns abbreviation for a given package id or null if application is unknown.
+        * 
+        * @return      string
+        */
+       public function getAbbreviation($packageID) {
+               foreach ($this->cache['abbreviation'] as $abbreviation => $applicationID) {
+                       if ($packageID == $applicationID) {
+                               return $abbreviation;
+                       }
+               }
+               
+               return null;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/auth/UserAuth.class.php b/wcfsetup/install/files/lib/system/auth/UserAuth.class.php
new file mode 100644 (file)
index 0000000..462afa6
--- /dev/null
@@ -0,0 +1,83 @@
+<?php\r
+namespace wcf\system\auth;\r
+use wcf\data\user\User;\r
+use wcf\system\event\EventHandler;\r
+\r
+/**\r
+ * All user authentication types should implement the abstract functions of this class.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.auth\r
+ * @category   Community Framework\r
+ */\r
+abstract class UserAuth {\r
+       /**\r
+        * active instance\r
+        *\r
+        * @var UserAuth\r
+        */\r
+       protected static $instance = null;\r
+       \r
+       /**\r
+        * Returns an instance of the enabled user auth class.\r
+        * \r
+        * @return      UserAuth\r
+        */\r
+       public static function getInstance() {\r
+               if (self::$instance === null) {\r
+                       // call loadInstance event\r
+                       EventHandler::getInstance()->fireAction(__CLASS__, 'loadInstance');\r
+               \r
+                       // use default implementation\r
+                       if (self::$instance === null) {\r
+                               self::$instance = new UserAuthDefault();\r
+                       }\r
+               }\r
+               \r
+               return self::$instance;\r
+       }\r
+       \r
+       /**\r
+        * Prevents creating an additional instance.\r
+        */\r
+       protected function __clone() {}\r
+       \r
+       /**\r
+        * Returns true, if this auth type supports persistent logins.\r
+        * \r
+        * @return      boolean\r
+        */\r
+       public abstract function supportsPersistentLogins();\r
+       \r
+       /**\r
+        * Stores the user access data for a persistent login.\r
+        * \r
+        * @param       User            $user\r
+        * @param       string          $username\r
+        * @param       string          $password\r
+        */\r
+       public abstract function storeAccessData(User $user, $username, $password);\r
+       \r
+       /**\r
+        * Does an manual user login.\r
+        * \r
+        * @param       string          $username\r
+        * @param       string          $password\r
+        * @param       string          $userClassname          class name of user class\r
+        * @return      User\r
+        */\r
+       public abstract function loginManually($username, $password, $userClassname = 'wcf\data\user\User');\r
+       \r
+       /**\r
+        * Does an automatic user login.\r
+        * \r
+        * @param       boolean         $persistent             true = persistent login\r
+        * @param       string          $userClassname          class name of user class\r
+        * @return      User\r
+        */\r
+       public abstract function loginAutomatically($persistent = false, $userClassname = 'wcf\data\user\User');\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/auth/UserAuthDefault.class.php b/wcfsetup/install/files/lib/system/auth/UserAuthDefault.class.php
new file mode 100644 (file)
index 0000000..52129e1
--- /dev/null
@@ -0,0 +1,100 @@
+<?php\r
+namespace wcf\system\auth;\r
+use wcf\data\user\User;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\util\HeaderUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Default implementation of the user authentication.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.auth\r
+ * @category   Community Framework\r
+ */\r
+class UserAuthDefault extends UserAuth {\r
+       /**\r
+        * @see UserAuth::supportsPersistentLogins()\r
+        */\r
+       public function supportsPersistentLogins() {\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * @see UserAuth::loginManually()\r
+        */\r
+       public function loginManually($username, $password, $userClassname = 'wcf\data\user\User') {\r
+               $user = User::getUserByUsername($username);\r
+               $userSession = new $userClassname(null, null, $user);\r
+               \r
+               if ($userSession->userID == 0) {\r
+                       throw new UserInputException('username', 'notFound');\r
+               }\r
+       \r
+               // check password\r
+               if (!$userSession->checkPassword($password)) {\r
+                       throw new UserInputException('password', 'false');\r
+               }\r
+               \r
+               return $userSession;\r
+       }\r
+       \r
+       /**\r
+        * @see UserAuth::storeAccessData()\r
+        */\r
+       public function storeAccessData(User $user, $username, $password) {\r
+               HeaderUtil::setCookie('userID', $user->userID, TIME_NOW + 365 * 24 * 3600);\r
+               HeaderUtil::setCookie('password', StringUtil::getSaltedHash($password, $user->salt), TIME_NOW + 365 * 24 * 3600);\r
+       }\r
+\r
+       /**\r
+        * @see UserAuth::loginAutomatically()\r
+        */\r
+       public function loginAutomatically($persistent = false, $userClassname = 'wcf\data\user\User') {\r
+               if (!$persistent) return null;\r
+               \r
+               $user = null;\r
+               if (isset($_COOKIE[COOKIE_PREFIX.'userID']) && isset($_COOKIE[COOKIE_PREFIX.'password'])) {\r
+                       if (!($user = $this->getUserAutomatically(intval($_COOKIE[COOKIE_PREFIX.'userID']), $_COOKIE[COOKIE_PREFIX.'password'], $userClassname))) {\r
+                               $user = null;\r
+                               // reset cookie\r
+                               HeaderUtil::setCookie('userID', '');\r
+                               HeaderUtil::setCookie('password', '');\r
+                       }\r
+               }\r
+               \r
+               return $user;\r
+       }\r
+       \r
+       /**\r
+        * Returns a user object or null on failure.\r
+        * \r
+        * @param       integer         $userID\r
+        * @param       string          $password\r
+        * @param       string          $userClassname\r
+        * @return      User    \r
+        */\r
+       protected function getUserAutomatically($userID, $password, $userClassname = 'wcf\data\user\User') {\r
+               $user = new $userClassname($userID);\r
+               if (!$user->userID || !$this->checkCookiePassword($user, $password)) {\r
+                       $user = null;\r
+               }\r
+               \r
+               return $user;\r
+       }\r
+       \r
+       /**\r
+        * Validates the cookie password.\r
+        * \r
+        * @param       User            $user\r
+        * @param       string          $password\r
+        * @return      boolean\r
+        */\r
+       protected function checkCookiePassword($user, $password) {\r
+               return $user->checkCookiePassword($password);\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/breadcrumb/Breadcrumb.class.php b/wcfsetup/install/files/lib/system/breadcrumb/Breadcrumb.class.php
new file mode 100644 (file)
index 0000000..96c8638
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+namespace wcf\system\breadcrumb;
+use wcf\util\StringUtil;
+
+/**
+ * Represents a breadcrumb.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.breadcrumb
+ * @category   Community Framework
+ */
+class Breadcrumb {
+       /**
+        * displayed label
+        * 
+        * @var string
+        */
+       protected $label = '';
+       
+       /**
+        * target url
+        * 
+        * @var string
+        */
+       protected $url = '';
+       
+       /**
+        * Sets the displayed label.
+        * 
+        * @param       string          $label
+        */     
+       public function setLabel($label) {
+               $this->label = $label;
+       }
+       
+       /**
+        * Sets the target url, by default appends appropriate session id.
+        * May be left empty to disable url functionality.
+        * 
+        * @param       string          $url
+        * @param       boolean         $appendSession
+        */     
+       public function setURL($url, $appendSession = true) {
+               // append session id
+               if ($appendSession) {
+                       if (StringUtil::indexOf($url, '?') === false) {
+                               $url .= SID_ARG_1ST;
+                       }
+                       else {
+                               $url .= SID_ARG_2ND_NOT_ENCODED;
+                       }
+               }
+               
+               $this->url = $url;
+       }
+       
+       /**
+        * Returns displayed label.
+        * 
+        * @return      string
+        */
+       public function getLabel() {
+               return $this->label;
+       }
+       
+       /**
+        * Returns target url.
+        * 
+        * @return      string
+        */
+       public function getURL() {
+               return $this->url;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/breadcrumb/Breadcrumbs.class.php b/wcfsetup/install/files/lib/system/breadcrumb/Breadcrumbs.class.php
new file mode 100644 (file)
index 0000000..9c0a7b0
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+namespace wcf\system\breadcrumb;
+use wcf\system\SingletonFactory;
+
+/**
+ * Manages breadcrumbs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.breadcrumb
+ * @category   Community Framework
+ */
+class Breadcrumbs extends SingletonFactory {
+       /**
+        * list of breadcrumbs
+        * 
+        * @var array<Breadcrumb>
+        */     
+       protected $items = array();
+       
+       /**
+        * Adds a breadcrumb (insert order is crucial!)
+        * 
+        * @param       Breadcrumb              $item
+        */     
+       public function add(Breadcrumb $item) {
+               $this->items[] = $item;
+       }
+       
+       /**
+        * Returns the list of breadcrumbs.
+        * 
+        * @return      array<Breadcrumb>
+        */      
+       public function get() {
+               return $this->items;
+       }
+       
+       /**
+        * Replaces a breadcrumb, returns true if replacement was successful.
+        * 
+        * @param       Breadcrumb              $item
+        * @param       integer                 $index
+        * @return      boolean
+        */
+       public function replace(Breadcrumbs $item, $index) {
+               if (isset($this->items[$index])) {
+                       $this->items[$index] = $item;
+                       
+                       return true;
+               }
+               
+               return false;
+       }
+       
+       /**
+        * Removes a breadcrumb, returns true if deletion was successful.
+        * 
+        * @param       integer                 $index
+        * @return      boolean
+        */
+       public function remove($index) {
+               if (isset($this->items[$index])) {
+                       unset($this->items[$index]);
+                       
+                       return true;
+               }
+               
+               return false;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilder.class.php
new file mode 100644 (file)
index 0000000..3038d1b
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+namespace wcf\system\cache;\r
+\r
+/**\r
+ * A CacheBuilder provides data to the CacheHandler that ought to be cached.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+interface CacheBuilder {\r
+       /**\r
+        * Returns the data that ought to be cached.\r
+        *\r
+        * @param       array           $cacheResource\r
+        * @return      array           $data\r
+        */\r
+       public function getData($cacheResource);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderACPMenu.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderACPMenu.class.php
new file mode 100644 (file)
index 0000000..c989ef9
--- /dev/null
@@ -0,0 +1,152 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\data\acp\menu\item\ACPMenuItem;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Caches the acp menu items tree.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderACPMenu implements CacheBuilder {\r
+       protected $optionCategoryStructure = array();\r
+\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               list($cache, $packageID) = explode('-', $cacheResource['cache']); \r
+               $data = array();\r
+\r
+               // get all menu items and filter menu items with low priority\r
+               $sql = "SELECT          menuItem, menuItemID\r
+                       FROM            wcf".WCF_N."_acp_menu_item menu_item\r
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                       ON              (menu_item.packageID = package_dependency.dependency)\r
+                       WHERE           package_dependency.packageID = ?\r
+                       ORDER BY        package_dependency.priority ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               $itemIDs = array();\r
+               while ($row = $statement->fetchArray()) {\r
+                       $itemIDs[$row['menuItem']] = $row['menuItemID'];\r
+               }\r
+               \r
+               if (count($itemIDs) > 0) {\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("menuItemID IN (?)", array($itemIDs));\r
+                       \r
+                       // get needed menu items and build item tree\r
+                       $sql = "SELECT          menu_item.packageID, menuItem, parentMenuItem,\r
+                                               menuItemLink, permissions, options, packageDir\r
+                               FROM            wcf".WCF_N."_acp_menu_item menu_item\r
+                               LEFT JOIN       wcf".WCF_N."_package package\r
+                               ON              (package.packageID = menu_item.packageID)\r
+                               ".$conditions."\r
+                               ORDER BY        showOrder ASC";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               if (!isset($data[$row['parentMenuItem']])) {\r
+                                       $data[$row['parentMenuItem']] = array();\r
+                               }\r
+                               \r
+                               $data[$row['parentMenuItem']][] = new ACPMenuItem(null, $row);\r
+                       }\r
+               }\r
+               \r
+               // get top option categories\r
+               $optionCategories = $this->getTopOptionCategories($packageID);\r
+               if (count($optionCategories) > 0) {\r
+                       if (!isset($data['wcf.acp.menu.link.option.category'])) {\r
+                               $data['wcf.acp.menu.link.option.category'] = array();\r
+                       }\r
+                       \r
+                       // get option category data\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("categoryID IN (?)", array($optionCategories));\r
+                       \r
+                       $sql = "SELECT          *\r
+                               FROM            wcf".WCF_N."_option_category\r
+                               ".$conditions."\r
+                               ORDER BY        showOrder ASC";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $data['wcf.acp.menu.link.option.category'][] = new ACPMenuItem(null, array(\r
+                                       'packageID' => $packageID,\r
+                                       'menuItem' => 'wcf.acp.option.category.'.$row['categoryName'],\r
+                                       'parentMenuItem' => 'wcf.acp.menu.link.option.category',\r
+                                       'menuItemLink' => 'index.php?form=Option&categoryID='.$row['categoryID'],\r
+                                       'packageDir' => '',\r
+                                       'permissions' => $row['permissions'],\r
+                                       'options' => $row['options']\r
+                               ));\r
+                       }\r
+               }\r
+               \r
+               return $data;\r
+       }\r
+       \r
+       protected function getTopOptionCategories($packageID) {\r
+               // get all option categories and filter categories with low priority\r
+               $sql = "SELECT          categoryName, categoryID \r
+                       FROM            wcf".WCF_N."_option_category option_category\r
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                       ON              (package_dependency.dependency = option_category.packageID)\r
+                       WHERE           package_dependency.packageID = ?\r
+                       ORDER BY        package_dependency.priority ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               $optionCategories = array();\r
+               while ($row = $statement->fetchArray()) {\r
+                       $optionCategories[$row['categoryName']] = $row['categoryID'];\r
+               }\r
+               \r
+               $conditions = new PreparedStatementConditionBuilder();\r
+               $conditions->add("categoryID IN (?)", array($optionCategories));\r
+               $statementParameters = $conditions->getParameters();\r
+               array_unshift($statementParameters, $packageID);\r
+               \r
+               $sql = "SELECT          categoryID, parentCategoryName, categoryName,\r
+                                       (\r
+                                               SELECT COUNT(*) FROM wcf".WCF_N."_option WHERE categoryName = category.categoryName AND packageID IN (\r
+                                                       SELECT dependency FROM wcf".WCF_N."_package_dependency WHERE packageID = ?\r
+                                               )\r
+                                       ) AS count\r
+                       FROM            wcf".WCF_N."_option_category category\r
+                       ".$conditions;\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute($statementParameters);\r
+               while ($row = $statement->fetchArray()) {\r
+                       if (!isset($this->optionCategoryStructure[$row['parentCategoryName']])) $this->optionCategoryStructure[$row['parentCategoryName']] = array();\r
+                       $this->optionCategoryStructure[$row['parentCategoryName']][] = $row;\r
+               }\r
+               \r
+               $topOptionCategories = array();\r
+               foreach ($this->optionCategoryStructure[''] as $optionCategory) {\r
+                       $count = $optionCategory['count'] + $this->countOptions($optionCategory['categoryName']);\r
+                       if ($count > 0) $topOptionCategories[] = $optionCategory['categoryID'];\r
+               }\r
+               \r
+               return $topOptionCategories;\r
+       }\r
+       \r
+       protected function countOptions($parentCategoryName) {\r
+               if (!isset($this->optionCategoryStructure[$parentCategoryName])) return 0;\r
+               \r
+               $count = 0;\r
+               foreach ($this->optionCategoryStructure[$parentCategoryName] as $optionCategory) {\r
+                       $count += $optionCategory['count'] + $this->countOptions($optionCategory['categoryName']);\r
+               }\r
+               \r
+               return $count;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderApplication.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderApplication.class.php
new file mode 100644 (file)
index 0000000..58a454b
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\application\group\ApplicationGroup;
+use wcf\data\application;
+use wcf\data\package\Package;
+use wcf\data\package\PackageList;
+use wcf\system\WCF;
+
+/**
+ * Caches applications.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderApplication implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID) = explode('-', $cacheResource['cache']);
+               $data = array(
+                       'abbreviation' => array(),
+                       'application' => array(),
+                       'group' => null,
+                       'primary' => 0,
+                       'wcf' => null
+               );
+               
+               // lookup group id for currently active application
+               $sql = "SELECT  groupID
+                       FROM    wcf".WCF_N."_application
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               $row = $statement->fetchArray();
+               
+               // current application is not part of an application group
+               if (!$row || ($row['groupID'] == 0) || $row['groupID'] === null) {
+                       $data['application'] = array($packageID => new application\Application($packageID));
+               }
+               else {
+                       // fetch applications
+                       $applicationList = new application\ApplicationList();
+                       $applicationList->getConditionBuilder()->add("application.groupID = ?", array($row['groupID']));
+                       $applicationList->sqlLimit = 0;
+                       $applicationList->readObjects();
+                       $applications = $applicationList->getObjects();
+                       
+                       foreach ($applications as $application) {
+                               $data['application'][$application->packageID] = $application;
+                               
+                               // save primary application's package id
+                               if ($application->isPrimary) {
+                                       $data['primary'] = $application->packageID;
+                               }
+                       }
+                       
+                       // fetch application group
+                       $data['group'] = new ApplicationGroup($row['groupID']);
+               }
+               
+               // fetch abbreviations
+               $packageList = new PackageList();
+               $packageList->getConditionBuilder()->add('packageID IN (?)', array(array_keys($data['application'])));
+               $packageList->readObjects();
+               foreach ($packageList->getObjects() as $package) {
+                       $data['abbreviation'][Package::getAbbreviation($package->package)] = $package->packageID;
+               }
+               
+               // fetch wcf pseudo-application
+               $data['wcf'] = new application\Application(1);
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderCleanupAdapter.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderCleanupAdapter.class.php
new file mode 100644 (file)
index 0000000..4f08810
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+namespace wcf\system\cache;
+use wcf\system\WCF;
+
+/**
+ * Caches cleanup adapters.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderCleanupAdapter implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID) = explode('-', $cacheResource['cache']);
+               $data = array(
+                       'adapters' => array(),
+                       'objectTypes' => array(),
+                       'packageIDs' => array()
+               );
+               
+               $sql = "SELECT          listener.*, package.packageDir
+                       FROM            wcf".WCF_N."_cleanup_listener listener
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                       ON              (package_dependency.dependency = listener.packageID)
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = listener.packageID)
+                       WHERE           package_dependency.packageID = ?
+                       ORDER BY        package_dependency.priority ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               while ($row = $statement->fetchArray()) {
+                       if (!is_array($data['adapters'][$row['objectType']])) $data['adapters'][$row['objectType']] = array();
+                       $data['adapters'][$row['objectType']][] = $row;
+                       
+                       if (!is_array($data['objectTypes'][$row['objectType']])) $data['objectTypes'][$row['objectType']] = array();
+                       $data['objectTypes'][$row['objectType']][] = $row['packageID'];
+               }
+               
+               $data['objectTypes'] = array_unique($data['objectTypes']);
+               $data['packageIDs'] = array_unique($data['packageIDs']);
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderCoreObject.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderCoreObject.class.php
new file mode 100644 (file)
index 0000000..930d24f
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\core\object\CoreObjectList;
+use wcf\system\package\PackageDependencyHandler;
+
+/**
+ * Caches the core objects.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderCoreObject implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID) = explode('-', $cacheResource['cache']);
+               $data = array();
+               
+               $coreObjectList = new CoreObjectList();
+               $coreObjectList->getConditionBuilder()->add("core_object.packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+               $coreObjectList->sqlLimit = 0;
+               $coreObjectList->readObjects();
+               $coreObjects = $coreObjectList->getObjects();
+               
+               foreach ($coreObjects as $coreObject) {
+                       if (!isset($data[$coreObject->packageID])) {
+                               $data[$coreObject->packageID] = array();
+                       }
+                       
+                       $tmp = explode('\\', $coreObject->objectName);
+                       $className = array_pop($tmp);
+                       $data[$coreObject->packageID][$className] = $coreObject->objectName;
+               }
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderCronjob.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderCronjob.class.php
new file mode 100644 (file)
index 0000000..33fab3b
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+namespace wcf\system\cache;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+
+/**
+ * Caches cronjob information.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderCronjob implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               // get next execution time
+               $conditionBuilder = new PreparedStatementConditionBuilder();
+               $conditionBuilder->add("packageID IN (?)", array(PackageDependencyHandler::getDependenciesString()));
+               
+               $sql = "SELECT          MIN(nextExec) AS nextExec,
+                                       MIN(afterNextExec) AS afterNextExec
+                       FROM            wcf".WCF_N."_cronjob
+                       ".$conditionBuilder->__toString();
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditionBuilder->getParameters());
+               $row = $statement->fetchArray();
+               
+               return array(
+                       'afterNextExec' => $row['afterNextExec'],
+                       'nextExec' => $row['nextExec']
+               );
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderEventListener.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderEventListener.class.php
new file mode 100644 (file)
index 0000000..c1ed56b
--- /dev/null
@@ -0,0 +1,77 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\system\event\listener\EventHandler;\r
+use wcf\system\WCF;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Caches the event listeners.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderEventListener implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               list($cache, $packageID) = explode('-', $cacheResource['cache']); \r
+               $data = array(\r
+                       'actions' => array('user' => array(), 'admin' => array()),\r
+                       'inheritedActions' => array('user' => array(), 'admin' => array())\r
+               );\r
+               \r
+               // get all listeners and filter options with low priority\r
+               $sql = "SELECT          event_listener.*\r
+                       FROM            wcf".WCF_N."_event_listener event_listener\r
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                       ON              (package_dependency.dependency = event_listener.packageID)\r
+                       WHERE           package_dependency.packageID = ?\r
+                       ORDER BY        package_dependency.priority ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               while ($row = $statement->fetchArray()) {\r
+                       // distinguish between inherited actions and non-inherited actions\r
+                       if (!$row['inherit']) {\r
+                               $data['actions'][EventHandler::generateKey($row['eventClassName'], $row['eventName'])][] = $row;\r
+                       }\r
+                       else {\r
+                               if (!isset($data['inheritedActions'][$row['eventClassName']])) $data['inheritedActions'][$row['eventClassName']] = array();\r
+                               $data['inheritedActions'][$row['eventClassName']][$row['eventName']][] = $row;  \r
+                       }\r
+               }\r
+               \r
+               // sort data by nice value and class name\r
+               foreach ($data['actions'] as $key => $listeners) {\r
+                       uasort($data['actions'][$key], array(__CLASS__, 'sortListeners'));\r
+               }\r
+               \r
+               foreach ($data['inheritedActions'] as $class => $listeners) {\r
+                       foreach ($listeners as $key => $val) {\r
+                               uasort($data['inheritedActions'][$class][$key], array(__CLASS__, 'sortListeners'));\r
+                       }\r
+               }\r
+               \r
+               return $data;\r
+       }\r
+       \r
+       /**\r
+        * Sorts the event listeners alphabetically.\r
+        */\r
+       public static function sortListeners($listenerA, $listenerB) {\r
+               if ($listenerA['niceValue'] < $listenerB['niceValue']) {\r
+                       return -1;\r
+               }\r
+               else if ($listenerA['niceValue'] > $listenerB['niceValue']) {\r
+                       return 1;\r
+               }\r
+               else {\r
+                       return strcmp($listenerA['listenerClassName'], $listenerB['listenerClassName']);\r
+               }       \r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderIcon.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderIcon.class.php
new file mode 100644 (file)
index 0000000..bf108ae
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\package\Package;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Caches the paths of icons.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderIcon implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID, $styleID) = explode('-', $cacheResource['cache']); 
+               $data = array();
+
+               // get active package
+               $activePackage = new Package($packageID);
+               $activePackageDir = FileUtil::getRealPath(WCF_DIR.$activePackage->getDir());
+               
+               // get package dirs
+               $packageDirs = array();
+               $conditionBuilder = new PreparedStatementConditionBuilder();
+               $conditionBuilder->add("packageID IN (?) AND packageDir <> ''", array(PackageDependencyHandler::getDependenciesString()));
+               $sql = "SELECT          DISTINCT packageDir
+                       FROM            wcf".WCF_N."_package package
+                       ".$conditionBuilder->__toString()."
+                       ORDER BY        priority DESC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditionBuilder->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $packageDirs[] = FileUtil::getRealPath(WCF_DIR.$row['packageDir']);
+               }
+               $packageDirs[] = WCF_DIR;
+               
+               // get style icon path
+               $iconDirs = array();
+               $sql = "SELECT  variableValue
+                       FROM    wcf".WCF_N."_style_variable
+                       WHERE   styleID = ?
+                               AND variableName = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($styleID, 'global.icons.location'));
+               $row = $statement->fetchArray();
+               if (!empty($row['variableValue'])) $iconDirs[] = FileUtil::addTrailingSlash($row['variableValue']);
+               if (!in_array('icon/', $iconDirs)) $iconDirs[] = 'icon/';
+               
+               // get icons
+               foreach ($packageDirs as $packageDir) {
+                       $relativePackageDir = ($activePackageDir != $packageDir ? FileUtil::getRelativePath($activePackageDir, $packageDir) : '');
+                       
+                       foreach ($iconDirs as $iconDir) {
+                               $path = FileUtil::addTrailingSlash($packageDir.$iconDir);
+                               $icons = self::getIconFiles($path);
+                               foreach ($icons as $icon) {
+                                       $icon = str_replace($path, '', $icon);
+                                       if (!isset($data[$icon])) {
+                                               $data[$icon] = $relativePackageDir.$iconDir.$icon;
+                                       }
+                               }
+                       }
+               }
+               
+               return $data;
+       }
+       
+       protected static function getIconFiles($path) {
+               $files = array();
+               if (is_dir($path)) {
+                       $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
+                       foreach ($iterator as $file) {
+                               if (preg_match('/\.png$/', $file->getFilename())) {
+                                       $files[] = $file->getPathname();
+                               }
+                       }
+               }
+               
+               return $files;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderLanguage.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderLanguage.class.php
new file mode 100644 (file)
index 0000000..3d7561d
--- /dev/null
@@ -0,0 +1,90 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Caches languages, language to packages relation, package to languages relation\r
+ * and the id of the default language. \r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderLanguage implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $languageToPackages = array();\r
+               $data = array(\r
+                       'codes' => array(),\r
+                       'languages' => array(), \r
+                       'packages' => array(),\r
+                       'default' => 0,\r
+                       'categories' => array()\r
+               );\r
+               \r
+               // get language to packages\r
+               $sql = "SELECT          package.languageID, package.packageID\r
+                       FROM            wcf".WCF_N."_language_to_package package\r
+                       LEFT JOIN       wcf".WCF_N."_language language\r
+                       ON              (language.languageID = package.languageID)\r
+                       ORDER BY        language.isDefault DESC,\r
+                                       language.languageCode ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               while ($row = $statement->fetchArray()) {\r
+                       // package to languages\r
+                       if (!isset($data['packages'][$row['packageID']])) {\r
+                               $data['packages'][$row['packageID']] = array();\r
+                       }\r
+                       $data['packages'][$row['packageID']][] = $row['languageID'];\r
+                       \r
+                       // language to packages\r
+                       if (!isset($languageToPackages[$row['languageID']])) {\r
+                               $languageToPackages[$row['languageID']] = array();\r
+                       }\r
+                       $languageToPackages[$row['languageID']][] = $row['packageID'];\r
+               }\r
+               \r
+               // get languages\r
+               $sql = "SELECT  *\r
+                       FROM    wcf".WCF_N."_language";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               while ($row = $statement->fetchArray()) {\r
+                       // language data\r
+                       $data['languages'][$row['languageID']] = $row;\r
+                       \r
+                       // language to packages\r
+                       if (!isset($languageToPackages[$row['languageID']])) {\r
+                               $languageToPackages[$row['languageID']] = array();\r
+                       }\r
+                       $data['languages'][$row['languageID']]['packages'] = $languageToPackages[$row['languageID']];\r
+                       \r
+                       // default language\r
+                       if ($row['isDefault']) {\r
+                               $data['default'] = $row['languageID'];\r
+                       }\r
+                       \r
+                       // language code to language id\r
+                       $data['codes'][$row['languageCode']] = $row['languageID'];\r
+               }\r
+               \r
+               // get language categories\r
+               $sql = "SELECT  *\r
+                       FROM    wcf".WCF_N."_language_category";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               while ($row = $statement->fetchArray()) {\r
+                       // package to languages\r
+                       $data['categories'][$row['languageCategory']] = $row;\r
+               }\r
+\r
+               return $data;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderOption.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderOption.class.php
new file mode 100644 (file)
index 0000000..c1310aa
--- /dev/null
@@ -0,0 +1,117 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\data\option\category\OptionCategory;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Caches the options and option categories\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderOption implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $information = explode('-', $cacheResource['cache']);\r
+               if (count($information) == 3) {\r
+                       $type = $information[0].'_';\r
+                       $packageID = $information[2];\r
+               }\r
+               else {\r
+                       $type = '';\r
+                       $packageID = $information[1];\r
+               }\r
+                \r
+               $data = array(\r
+                       'categories' => array(),\r
+                       'options' => array(),\r
+                       'categoryStructure' => array(),\r
+                       'optionToCategories' => array()\r
+               );\r
+\r
+               // option categories\r
+               // get all option categories and sort categories by priority\r
+               $sql = "SELECT          categoryName, categoryID \r
+                       FROM            wcf".WCF_N."_".$type."option_category option_category\r
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                       ON              (package_dependency.dependency = option_category.packageID)\r
+                       WHERE           package_dependency.packageID = ?\r
+                       ORDER BY        package_dependency.priority ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               $optionCategories = array();\r
+               while ($row = $statement->fetchArray()) {\r
+                       $optionCategories[$row['categoryName']] = $row['categoryID'];\r
+               }\r
+               \r
+               if (count($optionCategories) > 0) {\r
+                       // get needed option categories\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("categoryID IN (?)", array($optionCategories));\r
+                       \r
+                       $sql = "SELECT          option_category.*, package.packageDir\r
+                               FROM            wcf".WCF_N."_".$type."option_category option_category\r
+                               LEFT JOIN       wcf".WCF_N."_package package\r
+                               ON              (package.packageID = option_category.packageID)\r
+                               ".$conditions."\r
+                               ORDER BY        showOrder ASC";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $data['categories'][$row['categoryName']] = new OptionCategory(null, $row);\r
+                               if (!isset($data['categoryStructure'][$row['parentCategoryName']])) {\r
+                                       $data['categoryStructure'][$row['parentCategoryName']] = array();\r
+                               }\r
+                               \r
+                               $data['categoryStructure'][$row['parentCategoryName']][] = $row['categoryName'];\r
+                       }\r
+               }\r
+               \r
+               // options\r
+               // get all options and sort options by priority\r
+               $optionIDs = array();\r
+               $sql = "SELECT          optionName, optionID \r
+                       FROM            wcf".WCF_N."_".$type."option option_table\r
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                       ON              (package_dependency.dependency = option_table.packageID)\r
+                       WHERE           package_dependency.packageID = ?\r
+                       ORDER BY        package_dependency.priority ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               while ($row = $statement->fetchArray()) {\r
+                       $optionIDs[$row['optionName']] = $row['optionID'];\r
+               }\r
+               \r
+               if (count($optionIDs) > 0) {\r
+                       // get needed options\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("optionID IN (?)", array($optionIDs));\r
+                       \r
+                       $sql = "SELECT          *\r
+                               FROM            wcf".WCF_N."_".$type."option\r
+                               ".$conditions."\r
+                               ORDER BY        showOrder ASC";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               $data['options'][$row['optionName']] = new Option(null, $row);\r
+                               if (!isset($data['optionToCategories'][$row['categoryName']])) {\r
+                                       $data['optionToCategories'][$row['categoryName']] = array();\r
+                               }\r
+                               \r
+                               $data['optionToCategories'][$row['categoryName']][] = $row['optionName'];\r
+                       }\r
+               }\r
+               \r
+               return $data;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderPackage.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderPackage.class.php
new file mode 100644 (file)
index 0000000..98a65da
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\data\package\PackageList;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Caches all registered packages.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderPackage implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $packageList = new PackageList();\r
+               $packageList->sqlLimit = 0;\r
+               $packageList->readObjects();\r
+               \r
+               return $packageList->getObjects();\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderPackageDependency.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderPackageDependency.class.php
new file mode 100644 (file)
index 0000000..1c050db
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+namespace wcf\system\cache;
+use wcf\system\WCF;
+
+/**
+ * Caches the dependencies of a package.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderPackageDependency implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID) = explode('-', $cacheResource['cache']);
+               $data = array(
+                       'dependency' => array(),
+                       'resolve' => array()
+               );
+               
+               if ($packageID != 0) {
+                       // general dependencies for current package id
+                       $sql = "SELECT  dependency
+                               FROM    wcf".WCF_N."_package_dependency
+                               WHERE   packageID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($packageID));
+                       while ($row = $statement->fetchArray()) {
+                               $data['dependency'][] = $row['dependency'];
+                       }
+                       
+                       // resolve package id by package name
+                       $sql = "SELECT          package.packageID, package.package
+                               FROM            wcf".WCF_N."_package_dependency package_dependency
+                               LEFT JOIN       wcf".WCF_N."_package package
+                               ON              (package.packageID = package_dependency.dependency)
+                               WHERE           package_dependency.packageID = ?
+                               ORDER BY        package_dependency.priority ASC";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($packageID));
+                       while ($row = $statement->fetchArray()) {
+                               if (!isset($data['resolve'][$row['package']])) $data['resolve'][$row['package']] = array();
+                               $data['resolve'][$row['package']][] = $row['packageID'];
+                       }
+                       
+                       foreach ($data['resolve'] as $package => $packageIDArray) {
+                               if (count($packageIDArray) == 1) {
+                                       $data[$package] = array_shift($packageIDArray);
+                               }
+                       }
+               }
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderPageMenu.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderPageMenu.class.php
new file mode 100644 (file)
index 0000000..29c6b68
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\page\menu\item\PageMenuItem;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * Caches the page menu items.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderPageMenu implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID) = explode('-', $cacheResource['cache']); 
+               $data = array();
+
+               // get all menu items and filter menu items with low priority
+               $sql = "SELECT          menuItem, menuItemID 
+                       FROM            wcf".WCF_N."_page_menu_item menu_item
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                       ON              (package_dependency.dependency = menu_item.packageID)
+                       WHERE           package_dependency.packageID = ?
+                       ORDER BY        package_dependency.priority ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               $itemIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       $itemIDs[$row['menuItem']] = $row['menuItemID'];
+               }
+               
+               if (count($itemIDs) > 0) {
+                       // get needed menu items and build item tree
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("menu_item.menuItemID IN (?)", array($itemIDs));
+                       $conditions->add("menu_item.isDisabled = ?", array(0));
+                       
+                       $sql = "SELECT          menuItemID, menuItem, parentMenuItem, menuItemLink,
+                                               permissions, options, packageDir, menuPosition, className,
+                                               CASE WHEN parentPackageID <> 0 THEN parentPackageID ELSE menu_item.packageID END AS packageID
+                               FROM            wcf".WCF_N."_page_menu_item menu_item
+                               LEFT JOIN       wcf".WCF_N."_package package
+                               ON              (package.packageID = menu_item.packageID)
+                               ".$conditions."
+                               ORDER BY        showOrder ASC";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               $data[($row['parentMenuItem'] ? $row['parentMenuItem'] : $row['menuPosition'])][] = new PageMenuItem(null, $row);
+                       }
+               }
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderSpider.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderSpider.class.php
new file mode 100644 (file)
index 0000000..53dd7ec
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\data\spider\SpiderList;\r
+\r
+/**\r
+ * Caches the list of search engine spiders.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderSpider implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $spiderList = new SpiderList();\r
+               $spiderList->sqlOrderBy = "spider.spiderID ASC";\r
+               $spiderList->sqlLimit = 0;\r
+               $spiderList->readObjects();\r
+               \r
+               return $spiderList->getObjects();\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderStyle.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderStyle.class.php
new file mode 100644 (file)
index 0000000..be5b553
--- /dev/null
@@ -0,0 +1,68 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\data\style\Style;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Caches the styles and style variables.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderStyle implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $data = array('default' => 0, 'styles' => array(), 'packages' => array());\r
+               \r
+               // get all styles\r
+               $sql = "SELECT          *\r
+                       FROM            wcf".WCF_N."_style\r
+                       ORDER BY        styleName ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               while ($row = $statement->fetchArray()) {\r
+                       if ($row['isDefault']) $data['default'] = $row['styleID'];\r
+                       $row['variables'] = array();\r
+                       \r
+                       // get variable\r
+                       $sql = "SELECT  *\r
+                               FROM    wcf".WCF_N."_style_variable\r
+                               WHERE   styleID = ?";\r
+                       $statement2 = WCF::getDB()->prepareStatement($sql);\r
+                       $statement2->execute(array($row['styleID']));\r
+                       while ($row = $statement2->fetchArray()) {\r
+                               \r
+                               $row['variables'][$row2['variableName']] = $row2['variableValue'];\r
+                       }\r
+                       \r
+                       $data['styles'][$row['styleID']] = new Style(null, $row);\r
+               }\r
+               \r
+               // get style to packages\r
+               $sql = "SELECT          *\r
+                       FROM            wcf".WCF_N."_style_to_package\r
+                       ORDER BY        packageID ASC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute();\r
+               while ($row = $statement->fetchArray()) {\r
+                       \r
+                       if (!isset($data['packages'][$row['packageID']])) {\r
+                               $data['packages'][$row['packageID']] = array('default' => 0, 'disabled' => array());\r
+                       }\r
+                       \r
+                       if ($row['isDefault']) {\r
+                               $data['packages'][$row['packageID']]['default'] = $row['styleID'];\r
+                       }\r
+                       $data['packages'][$row['packageID']]['disabled'][$row['styleID']] = $row['disabled'];\r
+               }\r
+               \r
+               return $data;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplate.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplate.class.php
new file mode 100644 (file)
index 0000000..716b596
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Caches the structure of templates.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderTemplate implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $information = explode('-', $cacheResource['cache']);\r
+               if (count($information) == 3) {\r
+                       $prefix = $information[0].'_';\r
+                       $packageID = $information[2];\r
+               }\r
+               else {\r
+                       $prefix = '';\r
+                       $packageID = $information[1];\r
+               }\r
+               \r
+               $data = array();\r
+               \r
+               // get package directory for given package id\r
+               $sql = "SELECT  packageDir\r
+                       FROM    wcf".WCF_N."_package\r
+                       WHERE   packageID = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               $row = $statement->fetchArray();\r
+               \r
+               // get all templates and filter options with low priority\r
+               $sql = "SELECT          templateName, template.packageID \r
+                       FROM            wcf".WCF_N."_".$prefix."template template\r
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                       ON              (package_dependency.dependency = template.packageID)\r
+                       WHERE           package_dependency.packageID = ?\r
+                       ORDER BY        package_dependency.priority DESC";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($packageID));\r
+               while ($row = $statement->fetchArray()) {\r
+                       if (!isset($data[$row['templateName']]) || $packageID == $row['packageID']) {\r
+                               $data[$row['templateName']] = $row['packageID'];\r
+                       }\r
+               }\r
+               \r
+               return $data;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateGroup.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateGroup.class.php
new file mode 100644 (file)
index 0000000..44c47da
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\template\group\TemplateGroupList;
+
+/**
+ * Caches template groups.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderTemplateGroup implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               $templateGroupList = new TemplateGroupList();
+               $templateGroupList->sqlLimit = 0;
+               $templateGroupList->readObjects();
+               
+               return $templateGroupList->getObjects();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateListener.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateListener.class.php
new file mode 100644 (file)
index 0000000..daca6f7
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\template\listener\TemplateListenerList;
+use wcf\system\package\PackageDependencyHandler;
+
+/**
+ * Caches template listener information.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderTemplateListener implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($cache, $packageID, $environment) = explode('-', $cacheResource['cache']); 
+               
+               // get templates for current package id
+               $templateListenerList = new TemplateListenerList();
+               $templateListenerList->getConditionBuilder()->add("template_listener.environment = ?", array($environment));
+               // work-around during setup
+               if (PACKAGE_ID) $templateListenerList->getConditionBuilder()->add("template_listener.packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+               $templateListenerList->sqlLimit = 0;
+               $templateListenerList->readObjects();
+               
+               $data = array();
+               foreach ($templateListenerList->getObjects() as $templateListener) {
+                       $data[$templateListener->templateName] = array();
+               }
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateListenerCode.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderTemplateListenerCode.class.php
new file mode 100644 (file)
index 0000000..05cde26
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+namespace wcf\system\cache;
+use wcf\data\template\listener\TemplateListenerList;
+use wcf\system\package\PackageDependencyHandler;
+
+/**
+ * Caches template listener code.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache
+ * @category   Community Framework
+ */
+class CacheBuilderTemplateListenerCode implements CacheBuilder {
+       /**
+        * @see CacheBuilder::getData()
+        */
+       public function getData($cacheResource) {
+               list($packageID, $environment, $templateName) = explode('-', $cacheResource['cache']); 
+               
+               // get template codes for specified template
+               $templateListenerList = new TemplateListenerList();
+               $templateListenerList->getConditionBuilder()->add("template_listener.environment = ?", array($environment));
+               $templateListenerList->getConditionBuilder()->add("template_listener.templateName = ?", array($templateName));
+               $templateListenerList->getConditionBuilder()->add("template_listener.packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+               $templateListenerList->sqlLimit = 0;
+               $templateListenerList->readObjects();
+               
+               $data = array();
+               foreach ($templateListenerList->getObjects() as $templateListener) {
+                       $data[$templateListener->eventName][] = $templateListener->templateCode;
+               }
+               
+               return $data;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderUserGroup.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderUserGroup.class.php
new file mode 100644 (file)
index 0000000..4390f85
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\data\user\group\UserGroupList;\r
+\r
+/**\r
+ * Caches all user groups.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderUserGroup implements CacheBuilder {\r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               $data = array('types' => array(), 'groups' => array());\r
+\r
+               // get all user groups\r
+               $groupList = new UserGroupList();\r
+               $groupList->sqlOrderBy = "user_group.groupName";\r
+               $groupList->sqlLimit = 0;\r
+               $groupList->readObjects();\r
+               $groups = $groupList->getObjects();\r
+               \r
+               foreach ($groups as $group) {\r
+                       if (!isset($data['types'][$group->groupType])) {\r
+                               $data['types'][$group->groupType] = array();\r
+                       }\r
+                       \r
+                       $data['types'][$group->groupType][] = $group->groupID;\r
+                       $data['groups'][$group->groupID] = $group;\r
+               }\r
+               \r
+               return $data;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cache/CacheBuilderUserGroupPermission.class.php b/wcfsetup/install/files/lib/system/cache/CacheBuilderUserGroupPermission.class.php
new file mode 100644 (file)
index 0000000..9a559a3
--- /dev/null
@@ -0,0 +1,123 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\WCF;\r
+use wcf\util\ClassUtil;\r
+\r
+/**\r
+ * Caches the merged group options of a group combination.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheBuilderUserGroupPermission implements CacheBuilder {\r
+       protected $typeObjects = array();\r
+       \r
+       /**\r
+        * @see CacheBuilder::getData()\r
+        */\r
+       public function getData($cacheResource) {\r
+               list($cache, $packageID, $groupIDs) = explode('-', $cacheResource['cache']);\r
+               $data = array();\r
+               \r
+               // get all options and filter options with low priority\r
+               if ($packageID == 0) {\r
+                       // during the installation of the package wcf\r
+                       $sql = "SELECT          optionName, optionID \r
+                               FROM            wcf".WCF_N."_user_group_option\r
+                               WHERE           packageID IS NULL";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute();\r
+               }\r
+               else {\r
+                       $sql = "SELECT          optionName, optionID \r
+                               FROM            wcf".WCF_N."_user_group_option option_table\r
+                               LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency\r
+                               ON              (package_dependency.dependency = option_table.packageID)\r
+                               WHERE           package_dependency.packageID = ?\r
+                               ORDER BY        package_dependency.priority ASC";\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute(array($packageID));\r
+               }\r
+               \r
+               $options = array();\r
+               while ($row = $statement->fetchArray()) {\r
+                       $options[$row['optionName']] = $row['optionID'];\r
+               }\r
+               \r
+               if (count($options) > 0) {\r
+                       // get needed options\r
+                       $conditions = new PreparedStatementConditionBuilder();\r
+                       $conditions->add("option_value.groupID IN (?)", array(explode(',', $groupIDs)));\r
+                       $conditions->add("option_value.optionID IN (?)", array($options));\r
+                       \r
+                       $sql = "SELECT          option_table.optionName, option_table.optionType, option_value.optionValue\r
+                               FROM            wcf".WCF_N."_user_group_option_value option_value\r
+                               LEFT JOIN       wcf".WCF_N."_user_group_option option_table\r
+                               ON              (option_table.optionID = option_value.optionID)\r
+                               ".$conditions;\r
+                       $statement = WCF::getDB()->prepareStatement($sql);\r
+                       $statement->execute($conditions->getParameters());\r
+                       while ($row = $statement->fetchArray()) {\r
+                               if (!isset($data[$row['optionName']])) {\r
+                                       $data[$row['optionName']] = array('type' => $row['optionType'], 'values' => array());\r
+                               }\r
+                               \r
+                               $data[$row['optionName']]['values'][] = $row['optionValue'];\r
+                       }\r
+                       \r
+                       // merge values\r
+                       foreach ($data as $optionName => $option) {\r
+                               if (count($option['values']) == 1) {\r
+                                       $result = $option['values'][0];\r
+                               }\r
+                               else {\r
+                                       $typeObj = $this->getTypeObject($option['type']);\r
+                                       $result = $typeObj->merge($option['values']);\r
+                               }\r
+                               \r
+                               // unset false values\r
+                               if ($result === false) {\r
+                                       unset($data[$optionName]);\r
+                               }\r
+                               else {\r
+                                       $data[$optionName] = $result;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               $data['groupIDs'] = $groupIDs;\r
+               return $data;\r
+       }\r
+       \r
+       /**\r
+        * Returns an object of the requested group option type.\r
+        * \r
+        * @param       string                  $type\r
+        * @return      GroupOptionType\r
+        */\r
+       protected function getTypeObject($type) {\r
+               if (!isset($this->typeObjects[$type])) {\r
+                       $className = 'wcf\system\option\group\GroupOptionType'.ucfirst($type);\r
+                       \r
+                       // validate class\r
+                       if (!class_exists($className)) {\r
+                               throw new SystemException("unable to find class '".$className."'", 11001);\r
+                       }\r
+                       if (!ClassUtil::isInstanceOf($className, 'wcf\system\option\group\GroupOptionType')) {\r
+                               throw new SystemException("'".$className."' should implement GroupOptionType");\r
+                       }\r
+                       \r
+                       // create instance\r
+                       $this->typeObjects[$type] = new $className();\r
+               }\r
+               \r
+               return $this->typeObjects[$type];\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/CacheHandler.class.php b/wcfsetup/install/files/lib/system/cache/CacheHandler.class.php
new file mode 100644 (file)
index 0000000..390beaa
--- /dev/null
@@ -0,0 +1,170 @@
+<?php\r
+namespace wcf\system\cache;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\SingletonFactory;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * CacheHandler holds all registered cache resources.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class CacheHandler extends SingletonFactory {\r
+       /**\r
+        * Registered cache resources.\r
+        * \r
+        * @var array\r
+        */\r
+       protected $cacheResources = array();\r
+       \r
+       /**\r
+        * cache source object\r
+        * \r
+        * @var CacheSource\r
+        */\r
+       protected $cacheSource = null;\r
+       \r
+       /**\r
+        * Creates a new CacheHandler object.\r
+        */\r
+       protected function init() {\r
+               // init cache source object\r
+               try {\r
+                       $className = 'wcf\system\cache\source\\'.ucfirst(CACHE_SOURCE_TYPE).'CacheSource';\r
+                       $this->cacheSource = new $className();\r
+               }\r
+               catch (SystemException $e) {\r
+                       if (CACHE_SOURCE_TYPE != 'disk') {\r
+                               // fallback to disk cache\r
+                               $this->cacheSource = new wcf\system\cache\source\DiskCacheSource();\r
+                       }\r
+                       else {\r
+                               throw $e;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Registers a new cache resource.\r
+        * \r
+        * @param       string          $cache          name of this resource\r
+        * @param       string          $file           data file for this resource\r
+        * @param       string          $className\r
+        * @param       integer         $minLifetime\r
+        * @param       integer         $maxLifetime\r
+        */\r
+       public function addResource($cache, $file, $className, $minLifetime = 0, $maxLifetime = 0) {\r
+               $this->cacheResources[$cache] = array(\r
+                       'cache' => $cache,\r
+                       'file' => $file, \r
+                       'className' => $className, \r
+                       'minLifetime' => $minLifetime,\r
+                       'maxLifetime' => $maxLifetime\r
+               );\r
+       }\r
+       \r
+       /**\r
+        * Deletes a registered cache resource.\r
+        * \r
+        * @param       string          $cache\r
+        * @param       boolean         $ignoreLifetime\r
+        */\r
+       public function clearResource($cache, $ignoreLifetime = false) {\r
+               if (!isset($this->cacheResources[$cache])) {\r
+                       throw new SystemException("cache resource '".$cache."' does not exist", 11005);\r
+               }\r
+               \r
+               $this->getCacheSource()->delete($this->cacheResources[$cache], $ignoreLifetime);\r
+       }\r
+       \r
+       /**\r
+        * Marks cached files as obsolete.\r
+        *\r
+        * @param       string          $directory\r
+        * @param       string          $filepattern\r
+        * @param       boolean         $forceDelete\r
+        */\r
+       public function clear($directory, $filepattern, $forceDelete = false) {\r
+               $this->getCacheSource()->clear($directory, $filepattern, $forceDelete);\r
+       }\r
+       \r
+       /**\r
+        * Returns a cached variable.\r
+        *\r
+        * @param       string          $cache\r
+        * @param       string          $variable\r
+        * @return      mixed           $value\r
+        */\r
+       public function get($cache, $variable = '') {\r
+               if (!isset($this->cacheResources[$cache])) {\r
+                       throw new SystemException("unknown cache resource '".$cache."'", 11005);\r
+               }\r
+               \r
+               // try to get value\r
+               $value = $this->getCacheSource()->get($this->cacheResources[$cache]);\r
+               if ($value === null) {\r
+                       // rebuild cache\r
+                       $this->rebuild($this->cacheResources[$cache]);\r
+                       \r
+                       // try to get value again\r
+                       $value = $this->getCacheSource()->get($this->cacheResources[$cache]);\r
+                       if ($value === null) {\r
+                               throw new SystemException("cache resource '".$cache."' does not exist", 11005);\r
+                       }\r
+               }\r
+               \r
+               // return value\r
+               if (!empty($variable)) {\r
+                       if (!isset($value[$variable])) {\r
+                               throw new SystemException("variable '".$variable."' does not exist in cache resource '".$cache."'", 11008);\r
+                       }\r
+                       \r
+                       return $value[$variable];\r
+               }\r
+               else {\r
+                       return $value;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Rebuilds a cache resource.\r
+        * \r
+        * @param       array           $cacheResource\r
+        * @return      boolean         result\r
+        */\r
+       public function rebuild($cacheResource) {\r
+               // instance cache class\r
+               if (!class_exists($cacheResource['className'])) {\r
+                       throw new SystemException("Unable to find class '".$cacheResource['className']."'", 11001);\r
+               }\r
+               \r
+               // update file last modified time to avoid multiple users rebuilding cache at the same time\r
+               if (get_class($this->getCacheSource()) == 'wcf\system\cache\source\DiskCacheSource') {\r
+                       @touch($cacheResource['file']);\r
+               }\r
+               \r
+               // build cache\r
+               $cacheBuilder = new $cacheResource['className'];\r
+               $value = $cacheBuilder->getData($cacheResource);\r
+\r
+               // save cache\r
+               $this->getCacheSource()->set($cacheResource, $value);\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Returns the cache source object.\r
+        *\r
+        * @return      CacheSource\r
+        */\r
+       public function getCacheSource() {\r
+               return $this->cacheSource;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/cache/SetupCacheHandler.class.php b/wcfsetup/install/files/lib/system/cache/SetupCacheHandler.class.php
new file mode 100644 (file)
index 0000000..dfbee8d
--- /dev/null
@@ -0,0 +1,57 @@
+<?php\r
+namespace wcf\system\cache;\r
+\r
+/**\r
+ * Disables cache functions during the wcf setup.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cache\r
+ * @category   Community Framework\r
+ */\r
+class SetupCacheHandler extends CacheHandler {\r
+       /**\r
+        * @see CacheHandler::addResource()\r
+        */\r
+       public function addResource($cache, $file, $classFile, $minLifetime = 0, $maxLifetime = 0) {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * @see CacheHandler::clearResource()\r
+        */\r
+       public function clearResource($cache, $ignoreLifetime = false) {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * @see CacheHandler::clear()\r
+        */\r
+       public function clear($directory, $filepattern, $forceDelete = false) {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * @see CacheHandler::get()\r
+        */\r
+       public function get($cache, $variable = '') {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * @see CacheHandler::load()\r
+        */\r
+       public function load($cacheResource, $reload = false) {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * @see CacheHandler::rebuild()\r
+        */\r
+       public function rebuild($cacheResource, $forceRebuilt = false) {\r
+               return false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cache/source/CacheSource.class.php b/wcfsetup/install/files/lib/system/cache/source/CacheSource.class.php
new file mode 100644 (file)
index 0000000..1b7d89c
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+namespace wcf\system\cache\source;
+
+/**
+ * Any cache sources should implement this interface.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache.source
+ * @category   Community Framework
+ */
+interface CacheSource {
+       /**
+        * Returns a cached variable.
+        *
+        * @param       array           $cacheResource
+        * @return      mixed
+        */
+       public function get($cacheResource);
+       
+       /**
+        * Stores a variable in the cache.
+        *
+        * @param       array           $cacheResource
+        * @param       mixed           $value
+        */
+       public function set($cacheResource, $value);
+       
+       /**
+        * Deletes a variable in the cache.
+        *
+        * @param       array           $cacheResource
+        * @param       boolean         $ignoreLifetime
+        */
+       public function delete($cacheResource, $ignoreLifetime = false);
+       
+       /**
+        * Marks cached files as obsolete.
+        *
+        * @param       string          $directory
+        * @param       string          $filepattern
+        * @param       boolean         $forceDelete
+        */
+       public function clear($directory, $filepattern, $forceDelete = false);
+       
+       /**
+        * Closes this cache source.
+        */
+       public function close();
+       
+       /**
+        * Clears the cache completely.
+        */
+       public function flush();
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cache/source/DiskCacheSource.class.php b/wcfsetup/install/files/lib/system/cache/source/DiskCacheSource.class.php
new file mode 100644 (file)
index 0000000..04e0896
--- /dev/null
@@ -0,0 +1,222 @@
+<?php
+namespace wcf\system\cache\source;
+use wcf\system\exception\SystemException;
+use wcf\system\io\File;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * DiskCacheSource is an implementation of CacheSource that stores the cache as simple files in the file system.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache.source
+ * @category   Community Framework
+ */
+class DiskCacheSource implements CacheSource {
+       /**
+        * Loaded cache
+        * 
+        * @var array
+        */
+       protected $cache = null;
+       
+       /**
+        * List of loaded resources
+        * 
+        * @var array
+        */
+       protected $loaded = array();
+       
+       /**
+        * @see CacheSource::get()
+        */
+       public function get($cacheResource) {
+               if (!isset($this->cache[$cacheResource['cache']])) {
+                       // check for rebuilt
+                       if ($this->needRebuild($cacheResource)) {
+                               return null;
+                       }
+                       
+                       // load resource
+                       $this->load($cacheResource);
+                       
+                       if (!isset($this->cache[$cacheResource['cache']])) {
+                               return null;
+                       }
+               }
+               
+               return $this->cache[$cacheResource['cache']];
+       }
+       
+       /**
+        * @see CacheSource::set()
+        */
+       public function set($cacheResource, $value) {
+               // write cache
+               $targetFile = new File($cacheResource['file']);
+               $targetFile->write("<?php exit; /* cache: ".$cacheResource['cache']." (generated at ".gmdate('r').") DO NOT EDIT THIS FILE */ ?>\n");
+               $targetFile->write(serialize($value));
+               $targetFile->close();
+               
+               // add value
+               $this->cache[$cacheResource['cache']] = $value;
+               $this->loaded[$cacheResource['file']] = true;
+       }
+       
+       /**
+        * @see CacheSource::delete()
+        */
+       public function delete($cacheResource, $ignoreLifetime = false) {
+               if (file_exists($cacheResource['file'])) {
+                       if ($ignoreLifetime || ($cacheResource['minLifetime'] == 0 || (TIME_NOW - filemtime($cacheResource['file'])) >= $cacheResource['minLifetime'])) {
+                               // delete cache file
+                               @unlink($cacheResource['file']);
+                               
+                               // reset open cache
+                               if (isset($this->cache[$cacheResource['cache']])) unset($this->cache[$cacheResource['cache']]);
+                               if (isset($this->loaded[$cacheResource['file']])) unset($this->loaded[$cacheResource['file']]);
+                       }
+               }
+       }
+       
+       /**
+        * @see CacheSource::clear()
+        */
+       public function clear($directory, $filepattern, $forceDelete = false) {
+               $filepattern = str_replace('*', '.*', str_replace('.', '\.', $filepattern));
+               if (substr($directory, -1) != '/') {
+                       $directory .= '/';      
+               }
+               
+               if (@file_exists($directory)) {
+                       $dirh = opendir($directory);
+                       while ($filename = readdir($dirh)) {
+                               if ($filename != '.' && $filename != '..' && preg_match('%^'.$filepattern.'$%i', $filename)) {
+                                       if ($forceDelete || !@touch($directory.$filename, 1)) {
+                                               @unlink($directory.$filename);
+                                       }
+                               }
+                       }
+                       closedir($dirh);
+               }
+       }
+       
+       /**
+        * Determines wheater the cache needs to be rebuild or not.
+        *
+        * @param       array           $cacheResource
+        * @return      boolean         $needRebuilt
+        */
+       protected function needRebuild($cacheResource) {
+               // cache does not exist
+               if (!file_exists($cacheResource['file'])) {
+                       return true;    
+               }
+               
+               // cache is empty
+               if (!@filesize($cacheResource['file'])) {
+                       return true;    
+               }
+               
+               // cache resource was marked as obsolete
+               if (($mtime = filemtime($cacheResource['file'])) <= 1) {
+                       return true;    
+               }
+               
+               // cache resource has a delay marking
+               if ($cacheResource['minLifetime'] > 0 && (TIME_NOW - $mtime) < $cacheResource['minLifetime']) {
+                       return false;
+               }
+               
+               // maxlifetime expired
+               if ($cacheResource['maxLifetime'] > 0 && (TIME_NOW - $mtime) > $cacheResource['maxLifetime']) {
+                       return true;    
+               }
+               
+               // do not rebuild cache
+               return false;
+       }
+       
+       /**
+        * Loads a cached resource.
+        * 
+        * @param       array           $cacheResource
+        */
+       public function load($cacheResource) {
+               if (!isset($this->loaded[$cacheResource['file']])) {
+                       try {
+                               // load cache file
+                               $this->loadCacheFile($cacheResource);
+                       }
+                       catch (Exception $e) {
+                               return false;
+                       }
+                       
+                       $this->loaded[$cacheResource['file']] = true;
+               }
+               
+               return true;
+       }
+       
+       /**
+        * Loads the file of a cached resource.
+        * 
+        * @param       array           $cacheResource
+        */
+       protected function loadCacheFile($cacheResource) {
+               // get file contents
+               $contents = file_get_contents($cacheResource['file']);
+               
+               // find first newline
+               $position = strpos($contents, "\n");
+               if ($position === false) throw new SystemException("Unable to load cache resource '".$cacheResource['cache']."'");
+               
+               // cut contents
+               $contents = substr($contents, $position + 1);
+               
+               // unserialize
+               $this->cache[$cacheResource['cache']] = @unserialize($contents);
+               if ($this->cache[$cacheResource['cache']] === false) throw new SystemException("Unable to load cache resource '".$cacheResource['cache']."'");
+       }
+       
+       /**
+        * @see CacheSource::close()
+        */
+       public function close() {
+               // does nothing
+       }
+       
+       /**
+        * @see CacheSource::flush()
+        */
+       public function flush() {
+               $sql = "SELECT          package.packageDir
+                       FROM            wcf".WCF_N."_package_dependency package_dependency
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = package_dependency.dependency)
+                       WHERE           package_dependency.packageID = ?
+                                       AND standalone = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       PACKAGE_ID,
+                       1
+               ));
+               while ($row = $statement->fetchArray()) {
+                       $packageDir = FileUtil::getRealPath(WCF_DIR.$row['packageDir']);
+                       $cacheDir = $packageDir.'cache';
+                       if (file_exists($cacheDir)) {
+                               // get files in cache directory
+                               $files = glob($cacheDir.'/*.php');
+                               if (is_array($files)) {
+                                       foreach ($files as $file) {
+                                               @unlink($file);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cache/source/MemcacheAdapter.class.php b/wcfsetup/install/files/lib/system/cache/source/MemcacheAdapter.class.php
new file mode 100644 (file)
index 0000000..437fae5
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+namespace wcf\system\cache\source;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+use wcf\util\StringUtil;
+
+/**
+ * Provides a global adapter for accessing the memcache server.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache.source
+ * @category   Community Framework
+ */
+class MemcacheAdapter extends SingletonFactory {
+       /**
+        * memcache object
+        *
+        * @var Memcache
+        */
+       private $memcache = null;
+       
+       /**
+        * Creates a new MemcacheAdapter object.
+        */
+       protected function __construct() {
+               if (!class_exists('Memcache')) {
+                       throw new SystemException('memcache support is not enabled.');
+               }
+
+               // init memcache
+               $this->memcache = new \Memcache();
+               
+               // add servers
+               $servers = explode("\n", StringUtil::unifyNewlines(CACHE_SOURCE_MEMCACHE_HOST));
+               foreach ($servers as $server) {
+                       $server = StringUtil::trim($server);
+                       if (!empty($server)) {
+                               $host = $server;
+                               $port = 11211; // default memcache port
+                               // get port
+                               if (strpos($host, ':')) {
+                                       $parsedHost = explode(':', $host);
+                                       $host = $parsedHost[0];
+                                       $port = $parsedHost[1];
+                               }
+                               
+                               $this->memcache->addServer($host, $port, CACHE_SOURCE_MEMCACHE_USE_PCONNECT);
+                       }
+               }
+               
+               // test connection
+               $this->memcache->get('testing');
+       }
+       
+       /**
+        * Returns the memcache object.
+        *
+        * @return Memcache
+        */
+       public function getMemcache() {
+               return $this->memcache;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cache/source/MemcacheCacheSource.class.php b/wcfsetup/install/files/lib/system/cache/source/MemcacheCacheSource.class.php
new file mode 100644 (file)
index 0000000..3457594
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+namespace wcf\system\cache\source;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * MemcacheCacheSource is an implementation of CacheSource that uses a Memcache server to store cached variables.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache.source
+ * @category   Community Framework
+ */
+class MemcacheCacheSource implements CacheSource {
+       /**
+        * MemcacheAdapter object
+        *
+        * @var MemcacheAdapter
+        */
+       protected $adapter = null;
+       
+       /**
+        * list of cache resources
+        *
+        * @var array<string>
+        */
+       protected $cacheResources = null;
+       
+       /**
+        * list of new cache resources
+        * 
+        * @var array<string>
+        */
+       protected $newLogEntries = array();
+       
+       /**
+        * list of obsolete resources
+        * 
+        * @var array<string>
+        */
+       protected $obsoleteLogEntries = array();
+       
+       /**
+        * Creates a new MemcacheCacheSource object.
+        */
+       public function __construct() {
+               $this->adapter = MemcacheAdapter::getInstance();
+       }
+       
+       /**
+        * Returns the memcache adapter.
+        *
+        * @return      MemcacheAdapter
+        */
+       public function getAdapter() {
+               return $this->adapter;
+       }
+       
+       // internal log functions
+       /**
+        * Loads the cache log.
+        */
+       protected function loadLog() {
+               if ($this->cacheResources === null) {
+                       $this->cacheResources = array();
+                       $sql = "SELECT  *
+                               FROM    wcf".WCF_N."_cache_resource";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute();
+                       while ($row = $statement->fetchArray()) {
+                               $this->cacheResources[] = $row['cacheResource'];
+                       }
+               }
+       }
+       
+       /**
+        * Saves modifications of the cache log.
+        */
+       protected function updateLog() {
+               if (count($this->newLogEntries)) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_cache_resource
+                               WHERE           cacheResource = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($this->newLogEntries as $entry) {
+                               $statement->execute(array($entry));
+                       }
+                       
+                       $sql = "INSERT INTO     wcf".WCF_N."_cache_resource
+                                               (cacheResource)
+                               VALUES          (?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($this->newLogEntries as $entry) {
+                               $statement->execute(array($entry));
+                       }
+                       
+               }
+               if (count($this->obsoleteLogEntries)) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_cache_resource
+                               WHERE           cacheResource = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($this->obsoleteLogEntries as $entry) {
+                               $statement->execute(array($entry));
+                       }
+               }
+       }
+       
+       /**
+        * Adds a cache resource to cache log.
+        *
+        * @param       string          $cacheResource
+        */
+       protected function addToLog($cacheResource) {
+               $this->newLogEntries[] = $cacheResource;
+       }
+       
+       /**
+        * Removes an obsolete cache resource from cache log.
+        *
+        * @param       string          $cacheResource
+        */
+       protected function removeFromLog($cacheResource) {
+               $this->obsoleteLogEntries[] = $cacheResource;
+       }
+       
+       // CacheSource implementations
+       /**
+        * @see CacheSource::get()
+        */
+       public function get($cacheResource) {
+               $value = $this->getAdapter()->getMemcache()->get($cacheResource['file']);
+               if ($value === false) return null;
+               return $value;
+       }
+       
+       /**
+        * @see CacheSource::set()
+        */
+       public function set($cacheResource, $value) {
+               $this->getAdapter()->getMemcache()->set($cacheResource['file'], $value, MEMCACHE_COMPRESSED, $cacheResource['maxLifetime']);
+               $this->addToLog($cacheResource['file']);
+       }
+       
+       /**
+        * @see CacheSource::delete()
+        */
+       public function delete($cacheResource, $ignoreLifetime = false) {
+               $this->getAdapter()->getMemcache()->delete($cacheResource['file']);
+               $this->removeFromLog($cacheResource['file']);
+       }
+       
+       /**
+        * @see CacheSource::clear()
+        */
+       public function clear($directory, $filepattern, $forceDelete = false) {
+               $this->loadLog();
+               $pattern = preg_quote(FileUtil::addTrailingSlash($directory), '%').str_replace('*', '.*', str_replace('.', '\.', $filepattern));
+               foreach ($this->cacheResources as $cacheResource) {
+                       if (preg_match('%^'.$pattern.'$%i', $cacheResource)) {
+                               $this->getAdapter()->getMemcache()->delete($cacheResource);
+                               $this->removeFromLog($cacheResource);
+                       }
+               }
+       }
+       
+       /**
+        * @see CacheSource::flush()
+        */
+       public function flush() {
+               // clear cache
+               $this->getAdapter()->getMemcache()->flush();
+               
+               // clear log
+               $this->newLogEntries = $this->obsoleteLogEntries = array();
+               
+               $sql = "DELETE FROM     wcf".WCF_N."_cache_resource";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see CacheSource::close()
+        */
+       public function close() {
+               // update log
+               $this->updateLog();
+               // close connection
+               // if ($this->getAdapter() !== null && $this->getAdapter()->getMemcache() !== null) $this->getAdapter()->getMemcache()->close();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cleanup/CleanupAdapter.class.php b/wcfsetup/install/files/lib/system/cleanup/CleanupAdapter.class.php
new file mode 100644 (file)
index 0000000..86a1de4
--- /dev/null
@@ -0,0 +1,22 @@
+<?php\r
+namespace wcf\system\cleanup;\r
+\r
+/**\r
+ * Default interface for cleanup adapters.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cleanup\r
+ * @category   Community Framework\r
+ */\r
+interface CleanupAdapter {\r
+       /**\r
+        * Executes this adapter.\r
+        * \r
+        * @param       array           $objectIDs\r
+        */\r
+       public function execute(array $objectIDs);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cleanup/CleanupHandler.class.php b/wcfsetup/install/files/lib/system/cleanup/CleanupHandler.class.php
new file mode 100644 (file)
index 0000000..c6deb7d
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+namespace wcf\system\cleanup;
+use wcf\system\cache\CacheHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\event\EventHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
+use wcf\util\ClassUtil;
+
+/**
+ * Handles cleanup related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cleanup
+ * @category   Community Framework
+ */
+class CleanupHandler {
+       /**
+        * unique instance of CleanupHandler
+        * 
+        * @var CleanupHandler
+        */
+       protected static $instance = null;
+       
+       /**
+        * cleanup adapter cache
+        * 
+        * @var array<array>
+        */
+       protected $cache = null;
+       
+       /**
+        * Initializes cleanup handler.
+        */
+       protected function __construct() {
+               $this->loadCache();
+       }
+       
+       /**
+        * Prevents creating an additional instance.
+        */
+       protected function __clone() {}
+       
+       /**
+        * Loads cleanup adapter cache.
+        */
+       protected function loadCache() {
+               CacheHandler::getInstance()->addResource(
+                       'cleanupAdapter-'.PACKAGE_ID,
+                       WCF_DIR.'cache/cache.cleanupAdapter.php',
+                       'wcf\system\cache\CacheBuilderCleanupAdapter'
+               );
+               
+               $this->cache = CacheHandler::getInstance()->get('cleanupAdapter');
+       }
+       
+       /**
+        * Prepares adapter execution
+        */
+       public function execute() {
+               // remove all logged items older than 24 hours
+               $sql = "DELETE FROM     wcf".WCF_N."_cleanup_log
+                       WHERE           deleteTime < ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       (TIME_NOW - 86400)
+               ));
+               
+               // loop through all available adapters
+               foreach ($this->cache['adapters'] as $objectType => $adapters) {
+                       // determine if there are any items for current object type
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("objectType = ?", array($objectType));
+                       $conditions->add("packageID IN (?)", array($this->cache['objectTypes'][$objectType]));
+                       
+                       $sql = "SELECT  objectID
+                               FROM    wcf".WCF_N."_cleanup_log
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       
+                       $objectIDs = array();
+                       while ($row = $statement->fetchArray()) {
+                               $objectIDs[] = $row['objectID'];
+                       }
+                       
+                       if (count($objectIDs)) {
+                               $this->executeAdapters($adapters, $objectIDs);
+                       }
+               }
+       }
+       
+       /**
+        * Executes specific cleanup adapters.
+        * 
+        * @param       array           $adapters
+        * @param       array           $objectIDs
+        */
+       protected function executeAdapters(array $adapters, array $objectIDs) {
+               $sql = "UPDATE  wcf".WCF_N."_cleanup_listener
+                       SET     lastUpdateTime = ?
+                       WHERE   listenerID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               
+               foreach ($adapters as $adapterData) {
+                       // validate class
+                       if (!class_exists($adapterData['className'])) {
+                               throw new SystemException("unable to find class '".$adapterData['className']."'", 11001);
+                       }
+                       
+                       // validate interface
+                       if (!(ClassUtil::isInstanceOf($adapterData['className'], 'wcf\system\cleanup\CleanupAdapter'))) {
+                               throw new SystemException("class '".$adapterData['className']."' does not implement the interface 'CleanupAdapter'", 11010);
+                       }
+                       
+                       $adapter = new $adapterData['className']();
+                       $adapter->execute($objectIDs);
+                       
+                       // update last time of execution
+                       $statement->execute(array(TIME_NOW, $adapterData['listenerID']));
+               }
+       }
+       
+       /**
+        * Returns an unique instance of CleanupHandler.
+        * 
+        * @return      CleanupHandler
+        */
+       public static function getInstance() {
+               if (self::$instance === null) {
+                       // call loadInstance event
+                       EventHandler::getInstance()->fireAction(__CLASS__, 'loadInstance');
+                       
+                       if (self::$instance === null) {
+                               self::$instance = new CleanupHandler();
+                       }
+               }
+               
+               return self::$instance;
+       }
+       
+       /**
+        * Registers deleted objects.
+        * 
+        * @param       string          $objectType
+        * @param       array           $objectIDs
+        * @param       integer         $packageID
+        */
+       public static function registerObjects($objectType, array $objectIDs, $packageID) {
+               $objectIDs = ArrayUtil::toIntegerArray($objectIDs);
+               $packageID = intval($packageID);
+               
+               // insert items
+               $sql = "INSERT INTO     wcf".WCF_N."_cleanup_log
+                                       (packageID, objectType, objectID, deleteTime)
+                       VALUES          (?, ?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               
+               foreach ($objectIDs as $objectID) {
+                       $statement->execute(array(
+                               $packageID,
+                               $objectType,
+                               $objectID,
+                               TIME_NOW
+                       ));
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cronjob/CleanUpCronjobLogCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/CleanUpCronjobLogCronjob.class.php
new file mode 100644 (file)
index 0000000..21f699e
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+namespace wcf\system\cronjob;
+use wcf\system\WCF;
+
+/**
+ * Deletes old entries from cronjob log.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cronjob
+ * @category   Community Framework
+ */
+class CleanUpCronjobLogCronjob implements Cronjob {
+       /**
+        * @see Cronjob::execute()
+        */
+       public function execute(array $data) {
+               $sql = "DELETE FROM     wcf".WCF_N."_cronjobs_log
+                       WHERE           execTime < ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       (TIME_NOW - (86400 * 7))
+               ));
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cronjob/CleanUpSessionLogCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/CleanUpSessionLogCronjob.class.php
new file mode 100644 (file)
index 0000000..daa6f0d
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+namespace wcf\system\cronjob;
+use wcf\system\WCF;
+
+/**
+ * Deletes old entries from session log.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cronjob
+ * @category   Community Framework
+ */
+class CleanUpSessionLogCronjob implements Cronjob {
+       /**
+        * @see Cronjob::execute()
+        */
+       public function execute(array $data) {
+               // delete access log
+               $sql = "DELETE FROM     wcf".WCF_N."_acp_session_access_log
+                       WHERE           sessionLogID IN (
+                                               SELECT  sessionLogID
+                                               FROM    wcf".WCF_N."_acp_session_log
+                                               WHERE   lastActivityTime < ?
+                                       )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       (TIME_NOW - (86400 * 30))
+               ));
+               
+               // delete session log
+               $sql = "DELETE FROM     wcf".WCF_N."_acp_session_log
+                       WHERE           lastActivityTime < ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       (TIME_NOW - (86400 * 30))
+               ));
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cronjob/CleanupListenerCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/CleanupListenerCronjob.class.php
new file mode 100644 (file)
index 0000000..e51edbd
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+namespace wcf\system\cronjob;\r
+use wcf\system\cleanup\CleanupHandler;\r
+\r
+/**\r
+ * Executes cleanup adapters.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cronjob\r
+ * @category   Community Framework\r
+ */\r
+class CleanupListenerCronjob implements Cronjob {\r
+       /**\r
+        * @see Cronjob::execute()\r
+        */\r
+       public function execute(array $data) {\r
+               CleanupHandler::getInstance()->execute();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cronjob/Cronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/Cronjob.class.php
new file mode 100644 (file)
index 0000000..edea24a
--- /dev/null
@@ -0,0 +1,26 @@
+<?php\r
+namespace wcf\system\cronjob;\r
+\r
+/**\r
+ * Any Cronjob should implement this interface.\r
+ * \r
+ * @author     Siegfried Schweizer\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf.data.cronjobs\r
+ * @subpackage system.cronjob\r
+ * @category   Community Framework\r
+ */\r
+interface Cronjob {\r
+       /**\r
+        * To be called when executing the cronjob; the $data array e.g. might be used for passing\r
+        * meaningful values to the cronjob in order to reasonably avail multipleExecs.\r
+        * \r
+        * @param       array           $data           This array should basically contain the dataset \r
+        *                                              associated to the executed cronjob, particularly \r
+        *                                              the date of the planned execution (the nextExec \r
+        *                                              field).\r
+        */\r
+       public function execute(array $data);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php b/wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php
new file mode 100644 (file)
index 0000000..b4a10cb
--- /dev/null
@@ -0,0 +1,204 @@
+<?php
+namespace wcf\system\cronjob;
+use wcf\data\cronjob\log\CronjobLogEditor;
+use wcf\data\cronjob\Cronjob AS CronjobObj;
+use wcf\data\cronjob\CronjobEditor;
+use wcf\system\cache\CacheHandler;
+use wcf\system\database\condition\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\WCF;
+use wcf\util\ClassUtil;
+
+/**
+ * Provides functions to execute cronjobs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cronjob
+ * @category   Community Framework
+ */
+abstract class CronjobScheduler {
+       /**
+        * list of outstanding cronjobs
+        * 
+        * @var array<CronjobEditor>
+        */
+       protected static $cronjobs = array();
+       
+       /**
+        * Executes outstanding cronjobs.
+        */
+       public static function execute() {
+               $cache = self::getCache();
+               
+               // break if there are no outstanding cronjobs
+               if ($cache['nextExec'] > TIME_NOW && $cache['afterNextExec'] > TIME_NOW) return;
+               
+               // get outstanding cronjobs
+               self::loadCronjobs();
+               
+               // clear cache
+               self::clearCache();
+               
+               foreach (self::$cronjobs as $cronjob) {
+                       // mark cronjob as being executed
+                       $cronjobEditor->update(array(
+                               'state' => CronjobObj::EXECUTING
+                       ));
+                       
+                       // create log entry
+                       $log = CronjobLogEditor::create(array(
+                               'cronjobID' => $cronjobEditor->cronjobID,
+                               'execTime' => TIME_NOW
+                       ));
+                       $logEditor = new CronjobLogEditor($log);
+                       
+                       try {
+                               self::executeCronjob($cronjob, $logEditor);
+                       }
+                       catch (SystemException $e) {
+                               self::logResult($logEditor, $e);
+                       }
+                       
+                       // get time of next execution
+                       $nextExec = $cronjobEditor->getNextExec();
+                       $afterNextExec = $cronjobEditor->getNextExec($nextExec);
+                       
+                       // mark cronjob as done
+                       $cronjobEditor->update(array(
+                               'afterNextExec' => $afterNextExec,
+                               'failCount' => 0,
+                               'nextExec' => $nextExec,
+                               'state' => CronjobObj::READY
+                       ));
+               }
+       }
+       
+       /**
+        * Loads and executes outstanding cronjobs.
+        */
+       protected static function loadCronjobs() {
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("cronjob.packageID IN (?)", array(PackageDependencyHandler::getDependencies()));
+               $conditions->add("(cronjob.nextExec <= ? OR cronjob.afterNextExec <= ?)", array(TIME_NOW, TIME_NOW));
+               $conditions->add("cronjob.active = ?", array(1));
+               $conditions->add("cronjob.failCount < ?", array(3));
+               $conditions->add("cronjob.state = ?", array(CronjobObj::READY));
+               
+               $sql = "SELECT          cronjob.*, package.packageDir
+                       FROM            wcf".WCF_N."_cronjob cronjob
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = cronjob.packageID)
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       $cronjob = new CronjobObj(null, $row);
+                       $cronjobEditor = new CronjobEditor($cronjob);
+                       $executeCronjob = true;
+                       
+                       $data = array(
+                               'state' => CronjobObj::PENDING
+                       );
+                       
+                       // reset cronjob if it got stuck before and afterNextExec is in the past
+                       if ($cronjobEditor->afterNextExec <= TIME_NOW && $cronjobEditor->state == CronjobObj::EXECUTING) {
+                               $failCount = $cronjobEditor->failCount + 1;
+                               $data['failCount'] = $failCount;
+                               
+                               // disable cronjob
+                               if ($failCount == 3) {
+                                       $data['active'] = 0;
+                                       $executeCronjob = false;
+                               }
+                       }
+                       // ignore cronjobs which seem to be running
+                       else if ($cronjobEditor->nextExec <= TIME_NOW && $cronjobEditor->state != CronjobObj::READY) {
+                               $executeCronjob = false;
+                       }
+                       
+                       // mark cronjob as pending, preventing parallel execution
+                       $cronjobEditor->update($data);
+                       
+                       if ($executeCronjob) {
+                               self::$cronjobs[] = $cronjobEditor;
+                       }
+               }
+       }
+       
+       /**
+        * Executes a cronjob.
+        * 
+        * @param       CronjobEditor           $cronjobEditor
+        * @param       CronjobLogEditor        $logEditor
+        */
+       protected static function executeCronjob(CronjobEditor $cronjobEditor, CronjobLogEditor $logEditor) {
+               $className = $cronjobEditor->className;
+               if (!class_exists($className)) {
+                       throw new SystemException("unable to find class '".$className."'", 11001);
+               }
+               
+               // verify class signature
+               if (!(ClassUtil::isInstanceOf($className, 'wcf\system\cronjob\Cronjob'))) {
+                       throw new SystemException("class '".$className."' does not implement the interface 'Cronjob'", 11010);
+               }
+               
+               // execute cronjob
+               $cronjob = new $className();
+               $cronjob->execute();
+               
+               self::logResult($logEditor);
+       }
+       
+       /**
+        * Logs cronjob exec success or failure.
+        * 
+        * @param       CronjobLogEditor        $log
+        * @param       SystemException         $e
+        */
+       protected static function logResult(CronjobLogEditor $log, SystemException $e = null) {
+               if ($exception !== null) {
+                       $errString = implode("\n", array(
+                               $e->getMessage(),
+                               $e->getCode(),
+                               $e->getFile(),
+                               $e->getLine(),
+                               $e->getTraceAsString()
+                       ));
+                       
+                       $logEditor->update(array(
+                               'success' => 0,
+                               'error' => $errString
+                       ));
+               } 
+               else {
+                       $logEditor->update(array(
+                               'success' => 1
+                       ));
+               }
+       }
+       
+       /**
+        * Returns cached cronjob data.
+        * 
+        * @return      array
+        */
+       protected static function getCache() {
+               $cacheName = 'cronjobs-'.PACKAGE_ID;
+               CacheHandler::getInstance()->addResource($cacheName, WCF_DIR.'cache/cache.'.$cacheName.'.php', 'wcf\system\cache\CacheBuilderCronjob');
+               
+               return CacheHandler::getInstance()->get($cacheName);
+       }
+       
+       /**
+        * Clears cronjob cache.
+        */
+       public static function clearCache() {
+               // clear cache
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache/', 'cache.cronjobs-'.PACKAGE_ID.'php');
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/cronjob/GetUpdateInfoCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/GetUpdateInfoCronjob.class.php
new file mode 100644 (file)
index 0000000..795fa2e
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\cronjob;\r
+use wcf\acp\package\update\PackageUpdate;\r
+\r
+/**\r
+ * Gets update package information.\r
+ * \r
+ * @author     Siegfried Schweizer\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.cronjob\r
+ * @category   Community Framework\r
+ */\r
+class GetUpdateInfoCronjob implements Cronjob {\r
+       /**\r
+        * @see Cronjob::execute()\r
+        * @TODO Change path and move method to lib/system/package\r
+        */\r
+       public function execute(array $data) {\r
+               PackageUpdate::refreshPackageDatabaseAutomatically();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cronjob/RefreshSearchRobotsCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/RefreshSearchRobotsCronjob.class.php
new file mode 100644 (file)
index 0000000..ea770f6
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+namespace wcf\system\cronjob;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\StringUtil;
+use wcf\util\XML;
+
+/**
+ * Refreshes list of search robots.
+ * 
+ * @todo       Use new XML-API
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cronjob
+ * @category   Community Framework
+ */
+class RefreshSearchRobotsCronjob implements Cronjob {
+       /**
+        * @see Cronjob::execute()
+        */
+       public function execute(array $data) {
+               $filename = FileUtil::downloadFileFromHttp('http://www.woltlab.com/spiderlist/spiderlist.xml', 'spiders');
+               $xml = new XML($filename);
+               $spiders = $xml->getElementTree('spiderlist');
+               
+               if (count($spiders['children'])) {
+                       // delete old entries
+                       $sql = "DELETE FROM wcf".WCF_N."_spider";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute();
+                       
+                       $statementParameters = array();
+                       foreach ($spiders['children'] as $spider) {
+                               $identifier = $spider['attrs']['ident'];
+                               
+                               // get attributes
+                               foreach ($spider['children'] as $values) {
+                                       $spider[$values['name']] = $values['cdata'];
+                               }
+                               
+                               $name = $spider['name'];
+                               $info = '';
+                               if (isset($spider['info'])) $info = $spider['info'];
+                               
+                               $statementParameters[] = array(
+                                       'spiderIdentifier' => StringUtil::toLowerCase($identifier),
+                                       'spiderName' => $name,
+                                       'spiderURL' => $info
+                               );
+                       }
+                       
+                       if (!empty($statementParameters)) {
+                               $sql = "INSERT INTO     wcf".WCF_N."_spider
+                                                       (spiderIdentifier, spiderName, spiderURL)
+                                       VALUES          (?, ?, ?)";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               
+                               foreach ($statementParameters as $parameters) {
+                                       $statement->execute(array(
+                                               $parameters['spiderIdentifier'],
+                                               $parameters['spiderName'],
+                                               $parameters['spiderURL']
+                                       ));
+                               }
+                       }
+                       
+                       // clear spider cache
+                       CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.spiders.php');
+               }
+               
+               // delete tmp file
+               @unlink($filename);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/database/Database.class.php b/wcfsetup/install/files/lib/system/database/Database.class.php
new file mode 100644 (file)
index 0000000..737b5ea
--- /dev/null
@@ -0,0 +1,339 @@
+<?php\r
+namespace wcf\system\database;\r
+use wcf\system\database\statement\PreparedStatement;\r
+use wcf\data\DatabaseObject;\r
+use wcf\system\SystemException;\r
+\r
+/**\r
+ * This is an abstract implementation of a database access class using PDO.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.database\r
+ * @category   Community Framework\r
+ */\r
+abstract class Database {\r
+       /**\r
+        * Name of the class used for prepared statements.\r
+        * @var string\r
+        */\r
+       protected $preparedStatementClassName = 'wcf\system\database\statement\PreparedStatement';\r
+\r
+       /**\r
+        * Name of the database editor class\r
+        * @var string\r
+        */\r
+       protected $editorClassName = 'wcf\system\database\editor\DatabaseEditor';\r
+       \r
+       /**\r
+        * sql server hostname\r
+        * @var string\r
+        */\r
+       protected $host = '';\r
+       \r
+       /**\r
+        * sql server post\r
+        * @var integer\r
+        */\r
+       protected $port = 0;\r
+       \r
+       /**\r
+        * sql server login name\r
+        * @var string\r
+        */\r
+       protected $user = '';\r
+       \r
+       /**\r
+        * sql server login password\r
+        * @var string\r
+        */\r
+       protected $password = '';\r
+       \r
+       /**\r
+        * database name\r
+        * @var string\r
+        */\r
+       protected $database = '';\r
+       \r
+       /**\r
+        * number of executed queries\r
+        * @var integer\r
+        */\r
+       protected $queryCount = 0;\r
+       \r
+       /**\r
+        * database editor object\r
+        * @var wcf\system\database\editor\DatabaseEditor\r
+        */\r
+       protected $editor = null;\r
+       \r
+       /**\r
+        * pdo object\r
+        * @var \PDO\r
+        */\r
+       protected $pdo = null;\r
+       \r
+       /**\r
+        * Indicates if there is an open transaction.\r
+        * @var boolean\r
+        */\r
+       protected $hasActiveTransaction = false;\r
+       \r
+       /**\r
+        * Creates a Dabatase Object.\r
+        * \r
+        * @param       string          $host                   SQL database server host address\r
+        * @param       string          $user                   SQL database server username\r
+        * @param       string          $password               SQL database server password\r
+        * @param       string          $database               SQL database server database name\r
+        * @param       integer         $port                   SQL database server port\r
+        */\r
+       public function __construct($host, $user, $password, $database, $port) {\r
+               $this->host = $host;\r
+               $this->port = $port;\r
+               $this->user = $user;\r
+               $this->password = $password;\r
+               $this->database = $database;\r
+               \r
+               // connect database\r
+               $this->connect();\r
+       }\r
+       \r
+       /**\r
+        * Connects to database server.\r
+        */\r
+       public abstract function connect();\r
+       \r
+       /**\r
+        * Returns ID from last insert.\r
+        *\r
+        * @param       string          $table\r
+        * @param       string          $field\r
+        * @return      integer                         last insert ID\r
+        */\r
+       public function getInsertID($table, $field) {\r
+               try {\r
+                       return $this->pdo->lastInsertId();\r
+               }\r
+               catch (\PDOException $e) {\r
+                       throw new DatabaseException("Can not fetch last insert id", $this);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Initiates a transaction.\r
+        *\r
+        * @return      boolean         true on success\r
+        */\r
+       public function beginTransaction() {\r
+               try {\r
+                       if ($this->hasActiveTransaction) {\r
+                               return false;\r
+                       }\r
+                       else {\r
+                               $this->hasActiveTransaction = $this->pdo->beginTransaction();\r
+                               return $this->hasActiveTransaction;\r
+                       }\r
+               }\r
+               catch (\PDOException $e) {\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Commits a transaction.\r
+        *\r
+        * @return      boolean         true on success\r
+        */\r
+       public function commitTransaction() {\r
+               try {\r
+                       $this->hasActiveTransaction = false;\r
+                       return $this->pdo->commit();\r
+               }\r
+               catch (\PDOException $e) {\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Rolls back a transaction.\r
+        *\r
+        * @return      boolean         true on success\r
+        */\r
+       public function rollBackTransaction() {\r
+               try {\r
+                       $this->hasActiveTransaction = false;\r
+                       return $this->pdo->rollBack();\r
+               }\r
+               catch (\PDOException $e) {\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Prepares a statement for execution and returns a statement object.\r
+        *\r
+        * @param       string                  $statement\r
+        * @param       integer                 $limit\r
+        * @param       integer                 $offset\r
+        * @return      wcf\system\database\statement\PreparedStatement\r
+        */\r
+       public function prepareStatement($statement, $limit = 0, $offset = 0) {\r
+               $statement = $this->handleLimitParameter($statement, $limit, $offset);\r
+               \r
+               try {\r
+                       $pdoStatement = $this->pdo->prepare($statement);\r
+                       if ($pdoStatement instanceof \PDOStatement) {\r
+                               return new $this->preparedStatementClassName($this, $pdoStatement);\r
+                       }\r
+                       throw new DatabaseException("Can not prepare statement: ".$statement, $this);\r
+               }\r
+               catch (\PDOException $e) {\r
+                       throw new DatabaseException("Can not prepare statement: ".$statement, $this);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Handles the limit and offset parameter in SELECT queries.\r
+        * This is a default implementation compatible to MySQL and PostgreSQL.\r
+        * Other database implementations should override this function. \r
+        * \r
+        * @param       string          $query\r
+        * @param       integer         $limit\r
+        * @param       integer         $offset\r
+        * @return      string          $query\r
+        */\r
+       public function handleLimitParameter($query, $limit = 0, $offset = 0) {\r
+               if ($limit != 0) {\r
+                       $query .= " LIMIT " . $limit . " OFFSET " . $offset;\r
+               }\r
+\r
+               return $query;\r
+       }\r
+       \r
+       /**\r
+        * Returns the number of the last error.\r
+        * \r
+        * @return integer\r
+        */\r
+       public function getErrorNumber() {\r
+               if ($this->pdo !== null) return $this->pdo->errorCode();\r
+               return 0;\r
+       }\r
+\r
+       /**\r
+        * Returns the description of the last error.\r
+        * \r
+        * @return string\r
+        */\r
+       public function getErrorDesc() {\r
+               if ($this->pdo !== null) {\r
+                       $errorInfoArray = $this->pdo->errorInfo();\r
+                       if (isset($errorInfoArray[2])) return $errorInfoArray[2];\r
+               }\r
+               return '';\r
+       }\r
+\r
+       /**\r
+        * Gets the current database type.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getDBType() {\r
+               return get_class($this);\r
+       }\r
+\r
+       /**\r
+        * Escapes a string for use in sql query.\r
+        * \r
+        * @param       string          $string\r
+        * @return      string\r
+        */\r
+       public function escapeString($string) {\r
+               return addslashes($string);\r
+       }\r
+       \r
+       /**\r
+        * Gets the sql version.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getVersion() {\r
+               try {\r
+                       if ($this->pdo !== null) {\r
+                               return $this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);\r
+                       }\r
+               }\r
+               catch (\PDOException $e) {}\r
+                \r
+               return 'unknown';\r
+       }\r
+       \r
+       /**\r
+        * Gets the database name.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getDatabaseName() {\r
+               return $this->database;\r
+       }\r
+       \r
+       /**\r
+        * Returns the name of the database user.\r
+        *\r
+        * @param       string          user name\r
+        */\r
+       public function getUser() {\r
+               return $this->user;\r
+       }\r
+       \r
+       /**\r
+        * Returns the amount of executed sql queries.\r
+        *\r
+        * @return      integer\r
+        */\r
+       public function getQueryCount() {\r
+               return $this->queryCount;\r
+       }\r
+       \r
+       /**\r
+        * Increments the query counter by one.\r
+        */\r
+       public function incrementQueryCount() {\r
+               $this->queryCount++;\r
+       }\r
+       \r
+       /**\r
+        * Returns a database editor object.\r
+        *\r
+        * @return      wcf\system\database\editor\DatabaseEditor\r
+        */\r
+       public function getEditor() {\r
+               if ($this->editor === null) {\r
+                       $this->editor = new $this->editorClassName($this);\r
+               }\r
+               \r
+               return $this->editor;\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if this database type is supported.\r
+        *\r
+        * @return      boolean\r
+        */\r
+       public static function isSupported() {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Sets default connection attributes.\r
+        */\r
+       protected function setAttributes() {\r
+               $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);\r
+               $this->pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_NATURAL);\r
+               $this->pdo->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, false);\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/database/DatabaseException.class.php b/wcfsetup/install/files/lib/system/database/DatabaseException.class.php
new file mode 100644 (file)
index 0000000..8d57816
--- /dev/null
@@ -0,0 +1,141 @@
+<?php\r
+namespace wcf\system\database;\r
+use wcf\system\database\statement\PreparedStatement;\r
+use wcf\system\exception\SystemException;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * DatabaseException is a specific SystemException for database errors.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.database\r
+ * @category   Community Framework\r
+ */\r
+class DatabaseException extends SystemException {\r
+       /**\r
+        * error number\r
+        * @var integer\r
+        */\r
+       protected $errorNumber = null;\r
+       \r
+       /**\r
+        * error description\r
+        * @var string\r
+        */\r
+       protected $errorDesc = null;\r
+       \r
+       /**\r
+        * sql version number\r
+        * @var string\r
+        */\r
+       protected $sqlVersion = null;\r
+       \r
+       /**\r
+        * sql type\r
+        * @var string\r
+        */\r
+       protected $DBType = null;\r
+       \r
+       /**\r
+        * Database object\r
+        * @var Database\r
+        */\r
+       protected $db = null;\r
+       \r
+       /**\r
+        * PreparedStatement object\r
+        * @var PreparedStatement\r
+        */\r
+       protected $preparedStatement = null;\r
+       \r
+       /**\r
+        * Creates a new DatabaseException.\r
+        * \r
+        * @param       string                  $message                error message\r
+        * @param       Database                $db                     affected db object\r
+        * @param       PreparedStatement       $preparedStatement      affected prepared statement\r
+        */\r
+       public function __construct($message, Database $db, PreparedStatement $preparedStatement = null) {\r
+               $this->db = $db;\r
+               $this->DBType = $db->getDBType();\r
+               $this->preparedStatement = $preparedStatement;\r
+               \r
+               // prefer errors from prepared statement\r
+               if (($this->preparedStatement instanceof PreparedStatement) && $this->preparedStatement->getErrorNumber()) {\r
+                       $this->errorNumber = $this->preparedStatement->getErrorNumber();\r
+                       $this->errorDesc = $this->preparedStatement->getErrorDesc();\r
+               }\r
+               else {\r
+                       $this->errorNumber = $this->db->getErrorNumber();\r
+                       $this->errorDesc = $this->db->getErrorDesc();\r
+               }\r
+               \r
+               parent::__construct($message, intval($this->errorNumber));\r
+       }\r
+       \r
+       /**\r
+        * Returns the error number of this exception.\r
+        * \r
+        * @return      integer\r
+        */\r
+       public function getErrorNumber() {\r
+               return $this->errorNumber;\r
+       }\r
+       \r
+       /**\r
+        * Returns the error description of this exception.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getErrorDesc() {\r
+               return $this->errorDesc;\r
+       }\r
+       \r
+       /**\r
+        * Returns the current sql version of the database.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getSQLVersion() {\r
+               if ($this->sqlVersion === null) {\r
+                       try {\r
+                               $this->sqlVersion = $this->db->getVersion();\r
+                       }\r
+                       catch (DatabaseException $e) {\r
+                               $this->sqlVersion = 'unknown';\r
+                       }\r
+               }\r
+               \r
+               return $this->sqlVersion;\r
+       }\r
+       \r
+       /**\r
+        * Returns the sql type of the active database.\r
+        * \r
+        * @return      string \r
+        */\r
+       public function getDBType() {\r
+               return $this->DBType;\r
+       }\r
+       \r
+       /**\r
+        * Prints the error page.\r
+        */\r
+       public function show() {\r
+               $this->information .= '<b>sql type:</b> ' . StringUtil::encodeHTML($this->getDBType()) . '<br />';\r
+               $this->information .= '<b>sql error:</b> ' . StringUtil::encodeHTML($this->getErrorDesc()) . '<br />';\r
+               $this->information .= '<b>sql error number:</b> ' . StringUtil::encodeHTML($this->getErrorNumber()) . '<br />';\r
+               $this->information .= '<b>sql version:</b> ' . StringUtil::encodeHTML($this->getSQLVersion()) . '<br />';\r
+               \r
+               $this->information .= "\n<!-- db error: #".$this->db->getErrorNumber().': '.$this->db->getErrorDesc()." -->\n";\r
+               if ($this->preparedStatement !== null) {\r
+                       $this->information .= "\n<!-- statement error: #".$this->preparedStatement->getErrorNumber().': '.$this->preparedStatement->getErrorDesc()." -->\n";\r
+               }\r
+               \r
+               parent::show();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/MySQLDatabase.class.php b/wcfsetup/install/files/lib/system/database/MySQLDatabase.class.php
new file mode 100644 (file)
index 0000000..89f9cd8
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+namespace wcf\system\database;
+use wcf\system\database\editor\MySQLDatabaseEditor;
+
+/**
+ * This is the database implementation for MySQL4.1 or higher using PDO.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database
+ * @category   Community Framework
+ */
+class MySQLDatabase extends Database {
+       /**
+        * @see Database::$editorClassName
+        */
+       protected $editorClassName = 'wcf\system\database\editor\MySQLDatabaseEditor';
+       
+       /**
+        * @see Database::connect()
+        */
+       public function connect() {
+               if (!$this->port) $this->port = 3306; // mysql default port
+               
+               try {
+                       $this->pdo = new \PDO('mysql:host='.$this->host.';port='.$this->port.';dbname='.$this->database, $this->user, $this->password);
+                       $this->setAttributes();
+               }
+               catch (\PDOException $e) {
+                       throw new DatabaseException("Connecting to MySQL server '".$this->host."' failed:\n".$e->getMessage(), $this);
+               }
+               
+               // set sql mode
+               $this->setSQLMode();
+               
+               // set connection character set
+               $this->setCharset();
+       }
+
+       /**
+        * Sets the MySQL sql_mode variable.
+        */
+       protected function setSQLMode() {
+               try {
+                       $statement = $this->prepareStatement("SET SESSION sql_mode = 'ANSI,ONLY_FULL_GROUP_BY,STRICT_ALL_TABLES'");
+                       $statement->execute();
+               }
+               catch (DatabaseException $e) {
+                       // ignore
+               }
+       }
+       
+       /**
+        * Sets the charset of the database connection.
+        */
+       protected function setCharset() {
+               try {
+                       $statement = $this->prepareStatement("SET NAMES 'utf8'");
+                       $statement->execute();
+               }
+               catch (DatabaseException $e) {
+                       // ignore
+               }
+       }
+       
+       /**
+        * @see Database::isSupported()
+        */
+       public static function isSupported() {
+               return (extension_loaded('PDO') && extension_loaded('pdo_mysql'));
+       }
+       
+       /**
+        * @see Database::handleLimitParameter()
+        */
+       public function handleLimitParameter($query, $limit = 0, $offset = 0) {
+               if ($limit != 0) {
+                       if ($offset > 0) $query .= " LIMIT " . $offset . ", " . $limit;
+                       else $query .= " LIMIT " . $limit;
+               }
+
+               return $query;
+       }
+       
+       /**
+        * @see PDODatabase::setAttributes()
+        */
+       protected function setAttributes() {
+               parent::setAttributes();
+               $this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/database/PostgreSQLDatabase.class.php b/wcfsetup/install/files/lib/system/database/PostgreSQLDatabase.class.php
new file mode 100644 (file)
index 0000000..f3cd782
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+namespace wcf\system\database;
+use wcf\system\database\editor\PostgreSQLDatabaseEditor;
+use wcf\util\StringStack;
+
+/**
+ * This is the database implementation for PostgreSQL.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database
+ * @category   Community Framework
+ */
+class PostgreSQLDatabase extends Database {
+       /**
+        * @see Database::$editorClassName
+        */
+       protected $editorClassName = 'wcf\system\database\editor\PostgreSQLDatabaseEditor';
+       
+       /**
+        * @see Database::connect()
+        */
+       public function connect() {
+               if (!$this->port) $this->port = 5432; // postgresql default port
+               
+               try {
+                       $this->pdo = new \PDO('pgsql:host='.$this->host.';port='.$this->port.';dbname='.$this->database, $this->user, $this->password);
+                       $this->setAttributes();
+               }
+               catch (\PDOException $e) {
+                       throw new DatabaseException("Connecting to PostgreSQL server '".$this->host."' failed:\n".$e->getMessage(), $this);
+               }
+               
+               // set connection character set
+               $this->setCharset();
+       }
+
+       /**
+        * Sets the charset of the database connection.
+        */
+       protected function setCharset() {
+               try {
+                       $statement = $this->prepareStatement("SET NAMES 'UTF8'");
+                       $statement->execute();
+               }
+               catch (DatabaseException $e) {
+                       // ignore
+               }
+       }
+       
+       /**
+        * @see Database::isSupported()
+        */
+       public static function isSupported() {
+               return (extension_loaded('PDO') && extension_loaded('pdo_pgsql'));
+       }
+       
+       /**
+        * @see Database::prepareStatement()
+        */
+       public function prepareStatement($statement, $limit = 0, $offset = 0) {
+               $statement = self::fixQuery($statement);
+               return parent::prepareStatement($statement, $limit, $offset);
+       }
+
+       /**
+        * @see Database::getInsertID()
+        */
+       public function getInsertID($table, $field) {
+               try {
+                       return $this->pdo->lastInsertId('"' . $table . '_' . $field . '_seq"');
+               }
+               catch (\PDOException $e) {
+                       throw new DatabaseException("Can not fetch last insert id", $this);
+               }
+       }
+       
+       /**
+        * By default identifiers are case insensitive in PostgreSQL.
+        * We need to double quote identifiers here automatically.\r
+        * \r
+        * @param       string          $query\r
+        * @return      string          $query
+        */
+       public static function fixQuery($query) {
+               // replace quotes
+               $query = preg_replace_callback('~\'([^\'\\\\]+|\\\\.)*\'~', array('self', 'replaceQuotesCallback'), $query);
+               $query = preg_replace_callback('~"([^"\\\\]+|\\\\.)*"~', array('self', 'replaceQuotesCallback'), $query);
+               
+               // double quote identifiers (column & table names ...)
+               $query = preg_replace('~(?<=^|\s|\.|\(|,)([A-Za-z0-9_-]*[a-z]{1}[A-Za-z0-9_-]*)(?=$|\s|\.|\)|,|=)~', '"\\1"', $query);
+
+               // rename LIKE to ILIKE for case-insensitive comparisons
+               $query = preg_replace('/(?<=\s)LIKE(?=\s)/si', 'ILIKE', $query);
+               
+               // reinsert quotes
+               $query = StringStack::reinsertStrings($query, 'postgresQuotes');
+
+               return $query;
+       }
+       
+       /**
+        * @see Database::escapeString()
+        */
+       public function escapeString($string) {
+               $string = str_replace("\x00", "\\x00", $string); // escape nul bytes
+               return parent::escapeString($string);
+       }
+       
+       /**
+        * Callback function used in fixQuery()
+        */
+       private static function replaceQuotesCallback($matches) {
+               return StringStack::pushToStringStack($matches[0], 'postgresQuotes');
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php
new file mode 100644 (file)
index 0000000..6c479fd
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+namespace wcf\system\database\editor;
+use wcf\system\database\Database;
+
+/**
+ * This is an abstract implementation of a database editor class.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database.editor
+ * @category   Community Framework
+ */
+abstract class DatabaseEditor {
+       /**
+        * database object
+        *
+        * @var Database
+        */
+       protected $dbObj = null;
+
+       /**
+        * Creates a new DatabaseEditor object.
+        *
+        * @param       Database        $dbObj
+        */
+       public function __construct(Database $dbObj) {
+               $this->dbObj = $dbObj;
+       }
+       
+       /**
+        * Returns all existing tablenames.  
+        * 
+        * @return      array           $existingTables
+        */
+       public abstract function getTableNames();
+       
+       /**
+        * Returns the columns of a table.
+        * 
+        * @param       string          $tableName
+        * @return      array           $columns
+        */
+       public abstract function getColumns($tableName);
+       
+       /**
+        * Returns the indices of a table.
+        * 
+        * @param       string          $tableName
+        * @return      array           $indices
+        */
+       public abstract function getIndices($tableName);
+       
+       /**
+        * Creates a new database table.
+        * 
+        * @param       string          $tableName
+        * @param       array           $columns
+        * @param       array           $indices
+        */
+       public abstract function createTable($tableName, $columns, $indices = array());
+       
+       /**
+        * Drops a database table.
+        * 
+        * @param       string          $tableName
+        */
+       public abstract function dropTable($tableName);
+       
+       /**
+        * Adds a new column to an existing database table.
+        * 
+        * @param       string          $tableName
+        * @param       string          $columnName
+        * @param       array           $columnData
+        */
+       public abstract function addColumn($tableName, $columnName, $columnData);
+       
+       /**
+        * Alters an existing column.
+        *
+        * @param       string          $tableName
+        * @param       string          $oldColumnName
+        * @param       string          $newColumnName
+        * @param       array           $newColumnData
+        */
+       public abstract function alterColumn($tableName, $oldColumnName, $newColumnName, $newColumnData);
+       
+       /**
+        * Drops an existing column.
+        * 
+        * @param       string          $tableName
+        * @param       string          $columnName
+        */
+       public abstract function dropColumn($tableName, $columnName);
+       
+       /**
+        * Adds a new index to an existing database table.
+        * 
+        * @param       string          $tableName
+        * @param       string          $indexName
+        * @param       array           $indexData
+        */
+       public abstract function addIndex($tableName, $indexName, $indexData);
+       
+       /**
+        * Adds a new foreign key to an existing database table.
+        * 
+        * @param       string          $tableName
+        * @param       string          $indexName
+        * @param       array           $indexData
+        */
+       public abstract function addForeignKey($tableName, $indexName, $indexData);
+       
+       /**
+        * Drops an existing index.
+        * 
+        * @param       string          $tableName
+        * @param       string          $indexName
+        */
+       public abstract function dropIndex($tableName, $indexName);
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php
new file mode 100644 (file)
index 0000000..d839a35
--- /dev/null
@@ -0,0 +1,223 @@
+<?php
+namespace wcf\system\database\editor;
+use wcf\system\database\Database;
+
+/**
+ * This is the database editor implementation for MySQL4.1 or higher.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database.editor
+ * @category   Community Framework
+ */
+class MySQLDatabaseEditor extends DatabaseEditor {
+       /**
+        * @see DatabaseEditor::getTableNames()
+        */
+       public function getTableNames() {
+               $existingTables = array();
+               $sql = "SHOW TABLES FROM `".$this->dbObj->getDatabaseName()."`";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray(\PDO::FETCH_NUM)) {
+                       $existingTables[] = $row[0];
+               }
+               return $existingTables;
+       }
+       
+       /**
+        * @see DatabaseEditor::getColumns()
+        */
+       public function getColumns($tableName) {
+               $columns = array();
+               $sql = "SHOW COLUMNS FROM ".$tableName;
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $columns[] = $row['Field'];
+               }
+               return $columns;
+       }
+       
+       /**
+        * @see DatabaseEditor::getIndices()
+        */
+       public function getIndices($tableName) {
+               $indices = array();
+               $sql = "SHOW INDEX FROM ".$tableName;
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $indices[] = $index['Key_name'];
+               }
+               
+               return $indices;
+       }
+       
+       /**
+        * @see DatabaseEditor::createTable()
+        */
+       public function createTable($tableName, $columns, $indices = array()) {
+               $columnDefinition = $indexDefinition = '';
+               
+               // build column definition
+               foreach ($columns as $column) {
+                       if (!empty($columnDefinition)) $columnDefinition .= ',';
+                       $columnDefinition .= $this->buildColumnDefinition($column['name'], $column['data']);
+               }
+               
+               // build index definition
+               $hasFulltextIndex = false;
+               foreach ($indices as $index) {
+                       if (!empty($indexDefinition)) $indexDefinition .= ',';
+                       $indexDefinition .= $this->buildIndexDefinition($index['name'], $index['data']);
+                       if ($index['data']['type'] == 'FULLTEXT') $hasFulltextIndex = true;
+               }
+               
+               // create table
+               $sql = "CREATE TABLE ".$tableName." (
+                               ".$columnDefinition."
+                               ".(!empty($indexDefinition) ? ',' : '')."
+                               ".$indexDefinition."
+                       ) ENGINE=".($hasFulltextIndex ? 'MyISAM' : 'InnoDB')." DEFAULT CHARSET=utf8";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::dropTable()
+        */
+       public function dropTable($tableName) {
+               $sql = "DROP TABLE IF EXISTS ".$tableName;
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::addColumn()
+        */
+       public function addColumn($tableName, $columnName, $columnData) {
+               $sql = "ALTER TABLE ".$tableName." ADD COLUMN ".$this->buildColumnDefinition($columnName, $columnData);
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::alterColumn()
+        */
+       public function alterColumn($tableName, $oldColumnName, $newColumnName, $newColumnData) {
+               $sql = "ALTER TABLE ".$tableName." CHANGE COLUMN ".$oldColumnName." ".$this->buildColumnDefinition($newColumnName, $newColumnData);
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::dropColumn()
+        */
+       public function dropColumn($tableName, $columnName) {
+               $sql = "ALTER TABLE ".$tableName." DROP COLUMN ".$columnName;
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::addIndex()
+        */
+       public function addIndex($tableName, $indexName, $indexData) {
+               $sql = "ALTER TABLE ".$tableName." ADD ".$this->buildIndexDefinition($indexName, $indexData);
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::addIndex()
+        */
+       public function addForeignKey($tableName, $indexName, $indexData) {
+               $sql = "ALTER TABLE ".$tableName." ADD";
+               
+               // add index name
+               if (!empty($indexName)) $sql .= " CONSTRAINT ".$indexName;
+               
+               // add columns
+               $sql .= " FOREIGN KEY (".str_replace(',', ',', preg_replace('/\s+/', '', $indexData['columns'])).")";
+               
+               // add referenced table name
+               $sql .= " REFERENCES ".$indexData['referencedTable'];
+               
+               // add referenced columns
+               $sql .= " (".str_replace(',', ',', preg_replace('/\s+/', '', $indexData['referencedColumns'])).")";
+               
+               // add operation and action
+               if (!empty($indexData['operation'])) $sql .= " ON ".$indexData['operation']." ".$indexData['action'];
+               
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::dropIndex()
+        */
+       public function dropIndex($tableName, $indexName) {
+               $sql = "ALTER TABLE ".$tableName." DROP INDEX ".$indexName;
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * Builds a column definition for execution in a create table or alter table statement.
+        * 
+        * @param       string          $columnName
+        * @param       array           $columnData
+        * @param       string
+        */
+       protected function buildColumnDefinition($columnName, $columnData) {
+               // column name
+               $definition = $columnName;
+               // column type
+               $definition .= " ".$columnData['type'];
+               // column length and decimals
+               if (!empty($columnData['length'])) {
+                       $definition .= "(".$columnData['length'].(!empty($columnData['decimals']) ? ",".$columnData['decimals'] : "").")";
+               }
+               // enum / set
+               if ($columnData['type'] == 'enum' && !empty($columnData['values'])) {
+                       $definition .= "(".$columnData['values'].")";
+               }
+               // not null / null
+               if (!empty($columnData['notNull'])) $definition .= " NOT NULL";
+               // default
+               if (isset($columnData['default']) && $columnData['default'] !== '') $definition .= " DEFAULT ".$columnData['default'];
+               // auto_increment
+               if (!empty($columnData['autoIncrement'])) $definition .= " AUTO_INCREMENT";
+               // key
+               if (!empty($columnData['key'])) $definition .= " ".$columnData['key']." KEY";
+               
+               return $definition;
+       }
+       
+       /**
+        * Builds a index definition for execution in a create table or alter table statement.
+        * 
+        * @param       string          $indexName
+        * @param       array           $indexData
+        * @param       string
+        */
+       protected function buildIndexDefinition($indexName, $indexData) {
+               $definition = "";
+               // index type
+               if ($indexData['type'] == 'PRIMARY') $definition = "PRIMARY KEY";
+               else if ($indexData['type'] == 'UNIQUE') $definition = "UNIQUE KEY";
+               else if ($indexData['type'] == 'FULLTEXT') $definition = "FULLTEXT KEY";
+               else $definition = "KEY";
+               
+               // index name
+               if (!empty($indexName)) $definition .= " ".$indexName."";
+               // columns
+               $definition .= " (".str_replace(',', ',', preg_replace('/\s+/', '', $indexData['columns'])).")";
+               
+               return $definition;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php
new file mode 100644 (file)
index 0000000..9f5f612
--- /dev/null
@@ -0,0 +1,376 @@
+<?php
+namespace wcf\system\database\editor;
+use wcf\system\database\DatabaseException;
+use wcf\util\ArrayUtil;
+
+/**
+ * This is the database editor implementation for PostgreSQL 8.0 or higher.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2010 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database.editor
+ * @category   Community Framework
+ */
+class PostgreSQLDatabaseEditor extends DatabaseEditor {
+       /**
+        * @see DatabaseEditor::getTableNames()
+        */
+       public function getTableNames() {
+               $existingTables = array();
+               $sql = "SELECT          tablename
+                       FROM            pg_catalog.pg_tables
+                       WHERE           schemaname = 'public'
+                       ORDER BY        tablename";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $existingTables[] = $row['tablename'];
+               }
+               return $existingTables;
+       }
+       
+       /**
+        * @see DatabaseEditor::getColumns()
+        */
+       public function getColumns($tableName) {
+               $columns = array();
+               $sql = "SELECT  pg_attribute.attname
+                       FROM    pg_attribute,
+                               pg_class
+                       WHERE   pg_class.oid = pg_attribute.attrelid
+                               AND pg_attribute.attnum > 0
+                               AND pg_class.relname = ?";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute(array($tableName));
+               while ($row = $statement->fetchArray()) {
+                       $columns[] = $row['attname'];
+               }
+               
+               return $columns;
+       }
+       
+       /**
+        * @see DatabaseEditor::getIndices()
+        */
+       public function getIndices($tableName) {
+               $indices = array();
+               $sql = "SELECT  indexname
+                       FROM    pg_indexes
+                       WHERE   tablename = ?";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute(array($tableName));
+               while ($row = $statement->fetchArray()) {
+                       $indices[] = $index['indexname'];
+               }
+               
+               return $indices;
+       }
+       
+       /**
+        * Returns the data of an existing database table column.
+        * 
+        * @param       string          $tableName
+        * @param       string          $columnName
+        * @return      array
+        */
+       protected function getColumnData($tableName, $columnName) {
+               $sql = "SELECT  pg_catalog.FORMAT_TYPE(atttypid, atttypmod) AS type, attnotnull AS notNull, atthasdef AS default
+                       FROM    pg_catalog.pg_attribute
+                       WHERE   attrelid = (
+                                       SELECT  oid
+                                       FROM    pg_catalog.pg_class
+                                       WHERE   relname = '".$this->dbObj->escapeString($tableName)."'
+                                               AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = 'public')
+                               )
+                               AND attname = '".$this->dbObj->escapeString($columnName)."'";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+               $row = $statement->fetchArray();
+               if (empty($row['type'])) {
+                       throw new DatabaseException("Can not retrieve data for column '".$columnName."' on table '".$tableName."'", $this->dbObj);
+               }
+               
+               // parse type
+               if (preg_match('~(\w)\((\d+)(?:,(\d+))?\)~i', $row['type'], $match)) {
+                       $row['type'] = $match[1];
+                       $row['length'] = $match[2];
+                       $row['decimal'] = $match[3];
+               }
+               
+               return $row;
+       }
+       
+       /**
+        * @see DatabaseEditor::createTable()
+        */
+       public function createTable($tableName, $columns, $indices = array()) {
+               $columnDefinition = $indexDefinition = '';
+               
+               // build column definition
+               foreach ($columns as $column) {
+                       if (!empty($columnDefinition)) $columnDefinition .= ',';
+                       $columnDefinition .= $this->buildColumnDefinition($column['name'], $column['data']);
+               }
+               
+               // build index definition
+               foreach ($indices as $index) {
+                       if ($index['data']['type'] == 'PRIMARY') {
+                               if (!empty($indexDefinition)) $indexDefinition .= ',';
+                               $indexDefinition .= 'PRIMARY KEY ('.$index['data']['columns'].')';
+                       }
+               }
+               
+               // create table
+               $sql = "CREATE TABLE ".$tableName." (
+                               ".$columnDefinition."
+                               ".(!empty($indexDefinition) ? ',' : '')."
+                               ".$indexDefinition."
+                       )";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+               
+               // create other indices
+               foreach ($indices as $index) {
+                       if ($index['data']['type'] != 'PRIMARY') {
+                               $this->addIndex($tableName, $index['name'], $index['data']);
+                       }
+               }
+       }
+       
+       /**
+        * @see DatabaseEditor::dropTable()
+        */
+       public function dropTable($tableName) {
+               $sql = "DROP TABLE IF EXISTS ".$tableName." CASCADE";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::addColumn()
+        */
+       public function addColumn($tableName, $columnName, $columnData) {
+               $sql = "ALTER TABLE ".$tableName." ADD COLUMN ".$this->buildColumnDefinition($columnName, $columnData);
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::alterColumn()
+        */
+       public function alterColumn($tableName, $oldColumnName, $newColumnName, $newColumnData) {
+               // change column name if necessary
+               if ($oldColumnName != $newColumnName) {
+                       $sql = "ALTER TABLE ".$tableName." RENAME COLUMN ".$oldColumnName." TO ".$newColumnName;
+                       $statement = $this->dbObj->prepareStatement($sql);
+                       $statement->execute();
+               }
+
+               // get column information
+               $columnData = $this->getColumnData($tableName, $newColumnName);
+               
+               // change column type
+               $alterStatements = '';
+               $newColumnData['type'] = $this->getColumnType($newColumnData['type']);
+               if ($columnData['type'] != $newColumnData['type'] || (isset($columnData['length']) && isset($newColumnData['length']) && $columnData['length'] != $newColumnData['length']) || (isset($columnData['decimals']) && isset($newColumnData['decimals']) && $columnData['decimals'] != $newColumnData['decimals'])) {
+                       if (!empty($alterStatements)) $alterStatements .= ',';
+                       $alterStatements .= "ALTER COLUMN ".$newColumnName." TYPE ".$this->buildColumnType($newColumnData);
+               }
+
+               // change not null status
+               if (empty($columnData['notNull']) && !empty($newColumnData['notNull'])) {
+                       if (!empty($alterStatements)) $alterStatements .= ',';
+                       $alterStatements .= "ALTER COLUMN ".$newColumnName." SET NOT NULL";
+               }
+               else if (!empty($columnData['notNull']) && empty($newColumnData['notNull'])) {
+                       if (!empty($alterStatements)) $alterStatements .= ',';
+                       $alterStatements .= "ALTER COLUMN ".$newColumnName." DROP NOT NULL";
+               }
+
+               // change default value
+               if ((isset($columnData['default']) && $columnData['default'] !== '') && (!isset($newColumnData['default']) || $newColumnData['default'] === '')) {
+                       if (!empty($alterStatements)) $alterStatements .= ',';
+                       $alterStatements .= "ALTER COLUMN ".$newColumnName." DROP DEFAULT";
+               }
+               else if (isset($newColumnData['default']) && $newColumnData['default'] !== '') {
+                       if (!empty($alterStatements)) $alterStatements .= ',';
+                       $alterStatements .= "ALTER COLUMN ".$newColumnName." SET DEFAULT ".$newColumnData['default'];
+               }
+               
+               // send alter statement
+               if (!empty($alterStatements)) {
+                       $sql = "ALTER TABLE ".$tableName." ".$alterStatements;
+                       $statement = $this->dbObj->prepareStatement($sql);
+                       $statement->execute();
+               }
+       }
+       
+       /**
+        * @see DatabaseEditor::dropColumn()
+        */
+       public function dropColumn($tableName, $columnName) {
+               $sql = "ALTER TABLE ".$tableName." DROP COLUMN ".$columnName." CASCADE";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::addIndex()
+        */
+       public function addIndex($tableName, $indexName, $indexData) {
+               if ($indexData['type'] == 'FULLTEXT') {
+                       // TODO: implement fulltext search in postgresql
+               }
+               else {
+                       if (empty($indexName)) {
+                               // create index name
+                               // TODO: solve naming conflicts
+                               $columns = ArrayUtil::trim(explode(',', $indexData['columns']));
+                               $indexName = $tableName.'_'.(!empty($columns[0]) ? $columns[0] : 'generic').'_key';
+                       }
+                       else {
+                               $indexName = $tableName.'_'.$indexName.'_key';
+                       }
+                       
+                       $sql = "CREATE ".($indexData['type'] == 'UNIQUE' ? "UNIQUE " : "")."INDEX ".$indexName." ON ".$tableName." (".$indexData['columns'].")";
+                       $statement = $this->dbObj->prepareStatement($sql);
+                       $statement->execute();
+               }
+       }
+       
+       /**
+        * @see DatabaseEditor::addIndex()
+        */
+       public function addForeignKey($tableName, $indexName, $indexData) {
+               $sql = "ALTER TABLE ".$tableName." ADD";
+               
+               // add index name
+               if (!empty($indexName)) $sql .= " CONSTRAINT ".$indexName;
+               
+               // add columns
+               $sql .= " FOREIGN KEY (".str_replace(',', ',', preg_replace('/\s+/', '', $indexData['columns'])).")";
+               
+               // add referenced table name
+               $sql .= " REFERENCES ".$indexData['referencedTable'];
+               
+               // add referenced columns
+               $sql .= " (".str_replace(',', ',', preg_replace('/\s+/', '', $indexData['referencedColumns'])).")";
+               
+               // add operation and action
+               if (!empty($indexData['operation'])) $sql .= " ON ".$indexData['operation']." ".$indexData['action'];
+               
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * @see DatabaseEditor::dropIndex()
+        */
+       public function dropIndex($tableName, $indexName) {
+               $sql = "DROP INDEX IF EXISTS ".$tableName."_".$indexName."_key CASCADE";
+               $statement = $this->dbObj->prepareStatement($sql);
+               $statement->execute();
+       }
+       
+       /**
+        * Builds a column definition for execution in a create table or alter table statement.
+        * 
+        * @param       string          $columnName
+        * @param       array           $columnData
+        * @param       string
+        */
+       protected function buildColumnDefinition($columnName, $columnData) {
+               // column name
+               $definition = $columnName;
+               // auto_increment
+               if (!empty($columnData['autoIncrement'])) {
+                       if ($columnData['type'] == 'bigint') $definition .= " BIGSERIAL";
+                       else $definition .= " SERIAL";
+                       // key
+                       if (!empty($columnData['key'])) $definition .= ' '.$columnData['key'].($columnData['key'] == 'PRIMARY' ? ' KEY' : '');
+                       
+                       return $definition;
+               }
+               
+               // column type
+               if ($columnData['type'] == 'enum') $columnData['length'] = 255;
+               $columnData['type'] = $this->getColumnType($columnData['type']);
+               $definition .= " ".$this->buildColumnType($columnData);
+               
+               // not null / null
+               if (!empty($columnData['notNull'])) $definition .= " NOT NULL";
+               // default
+               if (isset($columnData['default']) && $columnData['default'] !== '') $definition .= " DEFAULT ".$columnData['default'];
+               // key
+               if (!empty($columnData['key'])) $definition .= ' '.$columnData['key'].($columnData['key'] == 'PRIMARY' ? ' KEY' : '');
+               
+               return $definition;
+       }
+       
+       /**
+        * Builds a column type for execution in a create table or alter table statement.
+        * 
+        * @param       array           $columnData
+        * @param       string
+        */
+       protected function buildColumnType($columnData) {
+               $definition = strtoupper($columnData['type']);
+               
+               // column length and decimals
+               if (!empty($columnData['length'])) {
+                       if (!empty($columnData['decimals']) && $columnData['type'] == 'numeric') {
+                               $definition .= "(".$columnData['length'].",".$columnData['decimals'].")";
+                       }
+                       else if ($columnData['type'] == 'character' || $columnData['type'] == 'character varying') {
+                               $definition .= "(".$columnData['length'].")";
+                       }
+               }
+               
+               return $definition;
+       }
+       
+       /**
+        * Converts a MySQL column type to PostgreSQL.
+        *
+        * @param       string          $mySQLType
+        * @param       string
+        */
+       protected function getColumnType($mySQLType) {
+               switch ($mySQLType) {
+                       // numeric types
+                       case 'tinyint':
+                       case 'smallint':        return 'smallint';
+                       case 'mediumint':
+                       case 'int':             return 'integer';
+                       case 'bigint':          return 'bigint';
+                       case 'float':           return 'real';
+                       case 'double':          return 'double precision';
+                       case 'decimal':         
+                       case 'numeric':         return 'numeric';
+                       
+                       // string types
+                       case 'char':            return 'character';
+                       case 'varchar':         return 'character varying';
+                       case 'tinytext':        
+                       case 'text':
+                       case 'mediumtext':
+                       case 'longtext':        return 'text';
+                       
+                       // blobs
+                       case 'binary':          
+                       case 'varbinary':
+                       case 'tinyblob':
+                       case 'blob':
+                       case 'mediumblob':
+                       case 'longblob':        return 'bytea';
+                       
+                       // enum
+                       case 'enum':            return 'character varying';
+               }
+               
+               throw new DatabaseException("Unknown / unsupported data type '".$mySQLType."'", $this->dbObj);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php b/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php
new file mode 100644 (file)
index 0000000..a3fc0c0
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+namespace wcf\system\database\statement;
+use wcf\data\DatabaseObject;
+use wcf\system\database\Database;
+use wcf\system\database\DatabaseException;
+
+/**
+ * This is an implementation of prepared statements based upon pdo statements.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database.statement
+ * @category   Community Framework
+ */
+class PreparedStatement {
+       /**
+        * database object
+        *
+        * @var wcf\system\database\Database
+        */
+       protected $database = null;
+       
+       /**
+        * pdo statement object
+        *
+        * @var \PDOStatement
+        */
+       protected $pdoStatement = null;
+       
+       /**
+        * Creates a new PreparedStatement object.
+        *
+        * @param       wcf\system\database\Database    $database
+        * @param       \PDOStatement                   $pdoStatement
+        */
+       public function __construct(Database $database, \PDOStatement $pdoStatement) {
+               $this->database = $database;
+               $this->pdoStatement = $pdoStatement;
+       }
+       
+       /**
+        * Delegates inaccessible methods calls to the decorated object.
+        *  
+        * @param       string          $name
+        * @param       array           $arguments
+        * @return      mixed
+        */
+       public function __call($name, $arguments) {
+               if (!method_exists($this->pdoStatement, $name)) {
+                       throw new SystemException("unknown method '".$name."'");
+               }
+               
+               try {
+                       return call_user_func_array(array($this->pdoStatement, $name), $arguments);
+               }
+               catch (\PDOException $e) {
+                       throw new DatabaseException('Could not handle prepared statement: '.$e->getMessage(), $this->database, $this);
+               }
+       }
+       
+       /**
+        * Executes a prepared statement.
+        *
+        * @param       array           $parameters
+        * @return      boolean         true on success
+        */
+       public function execute(array $parameters = array()) {
+               $this->database->incrementQueryCount();
+               
+               try {
+                       if (!count($parameters)) return $this->pdoStatement->execute();
+                       return $this->pdoStatement->execute($parameters);
+               }
+               catch (\PDOException $e) {
+                       throw new DatabaseException('Could not execute prepared statement: '.$e->getMessage(), $this->database, $this);
+               }
+       }
+       
+       /**
+        * Fetches the next row from a result set in an array.
+        *
+        * @param       integer         $type           fetch type
+        * @return      mixed
+        */
+       public function fetchArray($type = null) {
+               // get fetch style
+               if ($type === null) $type = \PDO::FETCH_ASSOC;
+               
+               return $this->fetch($type);
+       }
+       
+       /**
+        * Fetches the next row from a result set in a database object.
+        *
+        * @param       string                  $className
+        * @return      wcf\data\DatabaseObject
+        */
+       public function fetchObject($className) {
+               $row = $this->fetchArray();
+               if ($row !== false) {
+                       return new $className(null, $row);
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Fetches the all rows from a result set into database objects.
+        *
+        * @param       string                  $className
+        * @return      array<wcf\data\DatabaseObject>
+        */
+       public function fetchObjects($className) {
+               $objects = array();
+               while ($object = $this->fetchObject($className)) {
+                       $objects[] = $object;
+               }
+               
+               return $objects;
+       }
+       
+       /**
+        * Counts number of affected rows by the last sql statement (INSERT, UPDATE or DELETE).
+        *
+        * @return      integer         number of affected rows
+        */
+       public function getAffectedRows() {
+               try {
+                       return $this->pdoStatement->rowCount();
+               }
+               catch (\PDOException $e) {
+                       throw new DatabaseException("Can not fetch affected rows: ".$e->getMessage(), $this);
+               }
+       }
+       
+       /**
+        * Returns the number of the last error.
+        * 
+        * @return integer
+        */
+       public function getErrorNumber() {
+               if ($this->pdoStatement !== null) return $this->pdoStatement->errorCode();
+               return 0;
+       }
+
+       /**
+        * Returns the description of the last error.
+        * 
+        * @return string
+        */
+       public function getErrorDesc() {
+               if ($this->pdoStatement !== null) {
+                       $errorInfoArray = $this->pdoStatement->errorInfo();
+                       if (isset($errorInfoArray[2])) return $errorInfoArray[2];
+               }
+               return '';
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/util/ConditionBuilder.class.php b/wcfsetup/install/files/lib/system/database/util/ConditionBuilder.class.php
new file mode 100644 (file)
index 0000000..0932edd
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+namespace wcf\system\database\util;\r
+\r
+/**\r
+ * Builds a sql query 'where' condition.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.database.util\r
+ * @category   Community Framework\r
+ */\r
+class ConditionBuilder {\r
+       /**\r
+        * conditions string\r
+        * @var string\r
+        */\r
+       protected $conditions = '';\r
+       \r
+       /**\r
+        * must be true to add the 'WHERE' keyword automatically\r
+        * @var boolean\r
+        */\r
+       protected $addWhereKeyword = true;\r
+       \r
+       /**\r
+        * Creates a new ConditionBuilder object.\r
+        *\r
+        * @param       string          $addWhereKeyword\r
+        */\r
+       public function __construct($addWhereKeyword = true) {\r
+               $this->addWhereKeyword = $addWhereKeyword;\r
+       }\r
+       \r
+       /**\r
+        * Adds a new condition.\r
+        * \r
+        * @param       mixed           $conditions\r
+        */\r
+       public function add($conditions) {\r
+               if (!is_array($conditions)) $conditions = array($conditions);\r
+               \r
+               foreach ($conditions as $condition) {\r
+                       if (!empty($this->conditions)) $this->conditions .= " AND ";\r
+                       else $this->conditions = ($this->addWhereKeyword ? " WHERE " : '');\r
+                       \r
+                       $this->conditions .= $condition;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the build condition.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function __toString() {\r
+               return $this->conditions;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/util/PreparedStatementConditionBuilder.class.php b/wcfsetup/install/files/lib/system/database/util/PreparedStatementConditionBuilder.class.php
new file mode 100644 (file)
index 0000000..8bbba4c
--- /dev/null
@@ -0,0 +1,77 @@
+<?php\r
+namespace wcf\system\database\util;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * Builds a sql query 'where' condition for prepared statements.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.database.util\r
+ * @category   Community Framework\r
+ */\r
+class PreparedStatementConditionBuilder extends ConditionBuilder {\r
+       /**\r
+        * input parameters\r
+        * @var array\r
+        */\r
+       protected $parameters = array();\r
+       \r
+       /**\r
+        * Adds a new condition.\r
+        * \r
+        * @param       string          $condition\r
+        * @param       array           $parameters\r
+        */\r
+       public function add($condition, array $parameters = array()) {\r
+               if (count($parameters)) {\r
+                       $count = 0;\r
+                       $callback = function ($matches) use (&$count, $parameters) {\r
+                               if (!isset($parameters[$count])) {\r
+                                       throw new SystemException();\r
+                               }\r
+\r
+                               $result = '?';\r
+                               if (is_array($parameters[$count]) && count($parameters[$count])) {\r
+                                       $result .= str_repeat(',?', count($parameters[$count]) - 1);\r
+                               }\r
+                               \r
+                               $count++;\r
+                               return $result;\r
+                       };\r
+                       \r
+                       $condition = preg_replace_callback('/\?/', $callback, $condition);\r
+               }\r
+               \r
+               // add condtion\r
+               if (!empty($this->conditions)) $this->conditions .= " AND ";\r
+               else $this->conditions = ($this->addWhereKeyword ? " WHERE " : '');\r
+               $this->conditions .= $condition;\r
+               \r
+               // parameter handling\r
+               if (count($parameters)) {\r
+                       foreach ($parameters as $parameter) {\r
+                               if (is_array($parameter)) {\r
+                                       foreach ($parameter as $value) {\r
+                                               $this->parameters[] = $value;\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       $this->parameters[] = $parameter;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the input parameters.\r
+        * \r
+        * @return      array\r
+        */\r
+       public function getParameters() {\r
+               return $this->parameters;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/database/util/SQLParser.class.php b/wcfsetup/install/files/lib/system/database/util/SQLParser.class.php
new file mode 100644 (file)
index 0000000..9b244fd
--- /dev/null
@@ -0,0 +1,302 @@
+<?php
+namespace wcf\system\database\util;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
+use wcf\util\StringUtil;
+
+/**
+ * SQLParser takes many sql queries in a simple mysql syntax.
+ * Given queries will be parsed, converted and executed in the active database.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2008 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.database.util
+ * @category   Community Framework
+ */
+class SQLParser {
+       /**
+        * list of sql queries
+        * 
+        * @var array
+        */
+       protected $queryArray = array();
+       
+       /**
+        * Creates a new SQLParser object.
+        * 
+        * @param       string          $queries
+        */
+       public function __construct($queries) {
+               // delete comments
+               $queries = preg_replace("~('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(?:(?:--|#)[^\n]*|/\*.*?\*/)~s", '$1', $queries);
+               
+               // split queries by semicolon
+               if (preg_match_all("~(?:[^;']+(?:'[^'\\\\]*(?:\\\\.[^'\\\\]*)*')*)*(?=;|\$)~s", $queries, $matches)) {
+                       $this->queryArray = ArrayUtil::trim($matches[0]);
+               }
+       }
+       
+       /**
+        * Executes the sql queries.
+        */
+       public function execute() {
+               foreach ($this->queryArray as $query) {
+                       if (preg_match('~^(ALTER\s+TABLE|CREATE\s+INDEX|CREATE\s+TABLE|DROP\s+INDEX|DROP\s+TABLE|INSERT|UPDATE|DELETE)~i', $query, $match)) {
+                               $statement = strtoupper(preg_replace('~\s+~', ' ', $match[0]));
+                               
+                               $this->executeStatement($statement, $query);
+                       }
+               }
+       }
+       
+       /**
+        * Executes a sql statement.
+        * 
+        * @param       string          $statement
+        * @param       string          $query
+        */
+       protected function executeStatement($statement, $query) {
+               switch ($statement) {
+                       case 'CREATE TABLE':
+                               // get table name
+                               if (preg_match('~^CREATE\s+TABLE\s+(\w+)\s*\(~i', $query, $match)) {
+                                       $tableName = $match[1];
+                                       $columns = $indices = array();
+                                       
+                                       // find columns
+                                       if (preg_match_all("~(?:\(|,)\s*(\w+)\s+(\w+)(?:\s*\((\s*(?:\d+(?:\s*,\s*\d+)?|'[^']*'(?:\s*,\s*'[^']*')*))\))?(?:\s+UNSIGNED)?(?:\s+(NOT NULL|NULL))?(?:\s+DEFAULT\s+(\d+.\d+|\d+|NULL|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'))?(?:\s+(AUTO_INCREMENT))?(?:\s+(UNIQUE|PRIMARY)(?: KEY)?)?~i", $query, $matches)) {
+                                               for ($i = 0, $j = count($matches[0]); $i < $j; $i++) {
+                                                       $columName = strtoupper($matches[1][$i]);
+                                                       if ($columName == 'UNIQUE' || $columName == 'KEY' || $columName == 'PRIMARY' || $columName == 'FULLTEXT') continue;
+                                                       
+                                                       $column = array('name' => $matches[1][$i]);
+                                                       $columnType = strtolower($matches[2][$i]);
+                                                       $column['data'] = array(
+                                                               'type' => $columnType,
+                                                               'notNull' => ((!empty($matches[4][$i]) && strtoupper($matches[4][$i]) == 'NOT NULL') ? true : false),
+                                                               'default' => $matches[5][$i],
+                                                               'autoIncrement' => (!empty($matches[6][$i]) ? true : false),
+                                                               'key' => strtoupper($matches[7][$i])
+                                                       );
+                                                       if (!empty($matches[3][$i])) {
+                                                               if ($columnType == 'enum') $column['data']['values'] = $matches[3][$i];
+                                                               else {
+                                                                       if (preg_match('~^(\d+)(?:\s*,\s*(\d+))?$~', StringUtil::trim($matches[3][$i]), $match2)) {
+                                                                               $column['data']['length'] = $match2[1];
+                                                                               if (!empty($match2[2])) $column['data']['decimals'] = $match2[2];
+                                                                       }
+                                                                       else {
+                                                                               throw new SystemException("Unsupported SQL statement '".$query."'");
+                                                                       }
+                                                               }
+                                                       }
+                                                       
+                                                       $columns[] = $column;
+                                               }
+                                       }
+                                       else {
+                                               throw new SystemException("Unsupported SQL statement '".$query."'");
+                                       }
+
+                                       // find indices
+                                       if (preg_match_all('~(?:\(|,)\s*(?:(?:(?:(UNIQUE|FULLTEXT)(?:\s+(?:INDEX|KEY))?|(?:INDEX|KEY))(?:\s+(\w+))?)|(PRIMARY) KEY)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)~is', $query, $matches)) {
+                                               for ($i = 0, $j = count($matches[0]); $i < $j; $i++) {
+                                                       $index = array('name' => $matches[2][$i], 'data' => array());
+                                                       $index['data']['type'] = strtoupper((!empty($matches[1][$i]) ? $matches[1][$i] : $matches[3][$i]));
+                                                       $index['data']['columns'] = $matches[4][$i];
+                                                       $indices[] = $index;
+                                               }
+                                       }
+                                       
+                                       $this->executeCreateTableStatement($tableName, $columns, $indices);
+                               }
+                               
+                               break;
+                       
+                       case 'ALTER TABLE':
+                               // add index
+                               if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+ADD\s+(?:(UNIQUE|FULLTEXT)\s+)?(?:INDEX|KEY)\s+(?:(\w+)\s*)?\((\s*\w+\s*(?:,\s*\w+\s*)*)\)~is', $query, $match)) {
+                                       $this->executeAddIndexStatement($match[1], $match[3], array('type' => strtoupper($match[2]), 'columns' => $match[4]));
+                               }
+                               // add foreign key
+                               else if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+ADD\s+FOREIGN KEY\s+(?:(\w+)\s*)?\((\s*\w+\s*(?:,\s*\w+\s*)*)\)\s+REFERENCES\s+(\w+)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)(?:\s+ON\s+(UPDATE|DELETE)\s+(CASCADE|SET NULL|NO ACTION))?~is', $query, $match)) {
+                                       $this->executeAddForeignKeyStatement($match[1], $match[2], array('columns' => $match[3], 'referencedTable' => $match[4], 'referencedColumns' => $match[5], 'operation' => $match[6], 'action' => $match[7]));
+                               }
+                               // add/change column
+                               else if (preg_match("~^ALTER\s+TABLE\s+(\w+)\s+(?:(ADD)\s+(?:COLUMN\s+)?|(CHANGE)\s+(?:COLUMN\s+)?(\w+)\s+)(\w+)\s+(\w+)(?:\s*\((\s*(?:\d+(?:\s*,\s*\d+)?|'[^']*'(?:\s*,\s*'[^']*')*))\))?(?:\s+UNSIGNED)?(?:\s+(NOT NULL|NULL))?(?:\s+DEFAULT\s+(\d+.\d+|\d+|NULL|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'))?(?:\s+(AUTO_INCREMENT))?(?:\s+(UNIQUE|PRIMARY)(?: KEY)?)?~is", $query, $match)) {
+                                       $columnType = strtolower($match[6]);
+                                       $columnData = array(
+                                               'type' => $columnType,
+                                               'notNull' => ((!empty($match[8]) && strtoupper($match[8]) == 'NOT NULL') ? true : false),
+                                               'default' => (isset($match[9]) ? $match[9] : ''),
+                                               'autoIncrement' => (!empty($match[10]) ? true : false),
+                                               'key' => (!empty($match[11]) ? strtoupper($match[11]) : '')
+                                       );
+                                       if (!empty($match[7])) {
+                                               if ($columnType == 'enum') $columnData['values'] = $match[7];
+                                               else {
+                                                       if (preg_match('~^(\d+)(?:\s*,\s*(\d+))?$~', StringUtil::trim($match[7]), $match2)) {
+                                                               $columnData['length'] = $match2[1];
+                                                               if (!empty($match2[2])) $columnData['decimals'] = $match2[2];
+                                                       }
+                                                       else {
+                                                               throw new SystemException("Unsupported SQL statement '".$query."'");
+                                                       }
+                                               }
+                                       }
+                                       
+                                       if (strtoupper($match[2]) == 'ADD') {
+                                               $this->executeAddColumnStatement($match[1], $match[5], $columnData);
+                                       }
+                                       else {
+                                               $this->executeAlterColumnStatement($match[1], $match[4], $match[5], $columnData);
+                                       }
+                               }
+                               // drop index
+                               else if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+DROP\s+(?:INDEX|KEY)\s+(\w+)~is', $query, $match)) {
+                                       $this->executeDropIndexStatement($match[1], $match[2]);
+                               }
+                               // drop column
+                               else if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+DROP\s+(?:COLUMN\s+)?(\w+)~is', $query, $match)) {
+                                       $this->executeDropColumnStatement($match[1], $match[2]);
+                               }
+                               else {
+                                       throw new SystemException("Unsupported SQL statement '".$query."'");
+                               }
+                               break;
+                       
+                       case 'CREATE INDEX': 
+                               if (preg_match('~^CREATE\s+(?:(UNIQUE|FULLTEXT)\s+)?INDEX\s+(\w+)\s+ON\s+(\w+)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)~is', $query, $match)) {
+                                       $this->executeAddIndexStatement($match[3], $match[2], array('type' => strtoupper($match[1]), 'columns' => $match[4]));
+                               }
+                               else {
+                                       throw new SystemException("Unsupported SQL statement '".$query."'");
+                               }
+                               break;
+                               
+                       case 'DROP INDEX':
+                               if (preg_match('~^DROP\s+INDEX\s+(\w+)\s+ON\s+(\w+)~i', $query, $match)) {
+                                       $this->executeDropIndexStatement($match[2], $match[1]);
+                               }
+                               else {
+                                       throw new SystemException("Unsupported SQL statement '".$query."'");
+                               }
+                               break;
+                       
+                       case 'DROP TABLE': 
+                               if (preg_match('~^DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?(\w+)~i', $query, $match)) {
+                                       $this->executeDropTableStatement($match[1]);
+                               }
+                               else {
+                                       throw new SystemException("Unsupported SQL statement '".$query."'");
+                               }
+                               break;
+                       
+                       // standard sql; execute directly
+                       case 'INSERT': 
+                       case 'UPDATE': 
+                       case 'DELETE': 
+                               $this->executeStandardStatement($query);
+                               break;
+               }
+       }
+       
+       /**
+        * Executes a 'CREATE TABLE' statement.
+        * 
+        * @param       string          $tableName
+        * @param       array           $columns
+        * @param       array           $indices
+        */
+       protected function executeCreateTableStatement($tableName, $columns, $indices = array()) {
+               WCF::getDB()->getEditor()->createTable($tableName, $columns, $indices);
+       }
+       
+       /**
+        * Executes an 'ALTER TABLE ... ADD COLUMN' statement.
+        * 
+        * @param       string          $tableName
+        * @param       string          $columnName
+        * @param       array           $columnData
+        */
+       protected function executeAddColumnStatement($tableName, $columnName, $columnData) {
+               WCF::getDB()->getEditor()->addColumn($tableName, $columnName, $columnData);
+       }
+       
+       /**
+        * Executes an 'ALTER TABLE ... CHANGE COLUMN' statement.
+        * 
+        * @param       string          $tableName
+        * @param       string          $oldColumnName
+        * @param       string          $newColumnName
+        * @param       array           $newColumnData
+        */
+       protected function executeAlterColumnStatement($tableName, $oldColumnName, $newColumnName, $newColumnData) {
+               WCF::getDB()->getEditor()->alterColumn($tableName, $oldColumnName, $newColumnName, $newColumnData);
+       }
+       
+       /**
+        * Executes a 'CREATE INDEX' statement.
+        * 
+        * @param       string          $tableName
+        * @param       string          $indexName
+        * @param       array           $indexData
+        */
+       protected function executeAddIndexStatement($tableName, $indexName, $indexData) {
+               WCF::getDB()->getEditor()->addIndex($tableName, $indexName, $indexData);
+       }
+       
+       /**
+        * Executes a 'ALTER TABLE ... ADD FOREIGN KEY' statement.
+        * 
+        * @param       string          $tableName
+        * @param       string          $indexName
+        * @param       array           $indexData
+        */
+       protected function executeAddForeignKeyStatement($tableName, $indexName, $indexData) {
+               WCF::getDB()->getEditor()->addForeignKey($tableName, $indexName, $indexData);
+       }
+       
+       /**
+        * Executes an 'ALTER TABLE ... DROP COLUMN' statement.
+        * 
+        * @param       string          $tableName
+        * @param       string          $columnName
+        */
+       protected function executeDropColumnStatement($tableName, $columnName) {
+               WCF::getDB()->getEditor()->dropColumn($tableName, $columnName);
+       }
+       
+       /**
+        * Executes a 'DROP INDEX' statement.
+        * 
+        * @param       string          $tableName
+        * @param       string          $indexName
+        */
+       protected function executeDropIndexStatement($tableName, $indexName) {
+               WCF::getDB()->getEditor()->dropIndex($tableName, $indexName);
+       }
+       
+       /**
+        * Executes a 'DROP TABLE' statement.
+        * 
+        * @param       string          $tableName
+        */
+       protected function executeDropTableStatement($tableName) {
+               WCF::getDB()->getEditor()->dropTable($tableName);
+       }
+       
+       /**
+        * Executes a standard ansi sql statement.
+        * 
+        * @param       string          $query
+        */
+       protected function executeStandardStatement($query) {
+               $statement = WCF::getDB()->prepareStatement($query);
+               $statement->execute();
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/event/EventHandler.class.php b/wcfsetup/install/files/lib/system/event/EventHandler.class.php
new file mode 100644 (file)
index 0000000..7619cb6
--- /dev/null
@@ -0,0 +1,191 @@
+<?php\r
+namespace wcf\system\event;\r
+use wcf\system\cache\CacheHandler;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\SingletonFactory;\r
+\r
+/**\r
+ * EventHandler executes all registered actions for a specific event.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.event\r
+ * @category   Community Framework\r
+ */\r
+class EventHandler extends SingletonFactory {\r
+       /**\r
+        * Registerd actions.\r
+        *\r
+        * @var array\r
+        */\r
+       protected $actions = null;\r
+       \r
+       /**\r
+        * Registerd inherit actions.\r
+        *\r
+        * @var array\r
+        */\r
+       protected $inheritedActions = null;\r
+       \r
+       /**\r
+        * Instances of registerd actions.\r
+        *\r
+        * @var array\r
+        */\r
+       protected $actionsObjects = array();\r
+       \r
+       /**\r
+        * Instances of registerd inherit actions.\r
+        *\r
+        * @var array\r
+        */\r
+       protected $inheritedActionsObjects = array();\r
+       \r
+       /**\r
+        * Instances of action objects.\r
+        *\r
+        * @var array\r
+        */\r
+       protected $listenerObjects = array();\r
+       \r
+       /**\r
+        * Loads all registered actions of the active package.\r
+        */\r
+       protected function loadActions() {\r
+               CacheHandler::getInstance()->addResource('eventListener-'.PACKAGE_ID, WCF_DIR.'cache/cache.eventListener-'.PACKAGE_ID.'.php', 'wcf\system\cache\CacheBuilderEventListener');\r
+               $cache = CacheHandler::getInstance()->get('eventListener-'.PACKAGE_ID);\r
+               if (isset($cache['actions'])) $this->actions = $cache['actions'];\r
+               if (isset($cache['inheritedActions'])) $this->inheritedActions = $cache['inheritedActions'];\r
+               unset($cache);\r
+               if (!is_array($this->actions)) $this->actions = array();\r
+               if (!is_array($this->inheritedActions)) $this->inheritedActions = array();\r
+       }\r
+       \r
+       /**\r
+        * Executes all inherited listeners for the given event.\r
+        *\r
+        * @param       mixed           $eventObj\r
+        * @param       string          $eventName\r
+        * @param       string          $className\r
+        * @param       string          $name\r
+        */\r
+       protected function executeInheritedActions($eventObj, $eventName, $className, $name) {\r
+               // create objects of the actions\r
+               if (!isset($this->inheritedActionsObjects[$name]) || !is_array($this->inheritedActionsObjects[$name])) {\r
+                       $this->inheritedActionsObjects[$name] = array();\r
+\r
+                       // get parent classes\r
+                       $familyTree = array();\r
+                       $member = (is_object($eventObj) ? get_class($eventObj) : $eventObj);\r
+                       while ($member != false) {\r
+                               $familyTree[] = $member;\r
+                               $member = get_parent_class($member);\r
+                       }\r
+\r
+                       foreach ($familyTree as $member) {\r
+                               if (isset($this->inheritedActions[$member])) {\r
+                                       $actions = $this->inheritedActions[$member];\r
+                                       if (isset($actions[$eventName]) && count($actions[$eventName]) > 0) {\r
+                                               foreach ($actions[$eventName] as $action) {\r
+                                                       if (isset($this->inheritedActionsObjects[$name][$action['listenerClassName']])) continue;\r
+\r
+                                                       // get class object\r
+                                                       if (isset($this->listenerObjects[$action['listenerClassName']])) {\r
+                                                               $object = $this->listenerObjects[$action['listenerClassName']];\r
+                                                       }\r
+                                                       else {\r
+                                                               $object = null;\r
+                                                               // instance action object\r
+                                                               if (!class_exists($action['listenerClassName'])) {\r
+                                                                       throw new SystemException("Unable to find class '".$action['listenerClassName']."'", 11001);\r
+                                                               }\r
+       \r
+                                                               $object = new $action['listenerClassName'];\r
+                                                               $this->listenerObjects[] = $object;\r
+                                                       }\r
+                                                       \r
+                                                       if ($object !== null) $this->inheritedActionsObjects[$name][$action['listenerClassName']] = $object;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // execute actions\r
+               foreach ($this->inheritedActionsObjects[$name] as $actionObj) {\r
+                       $actionObj->execute($eventObj, $className, $eventName);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Executes all registered listeners for the given event.\r
+        *\r
+        * @param       mixed           $eventObj\r
+        * @param       string          $eventName\r
+        */\r
+       public function fireAction($eventObj, $eventName) {\r
+               // get class name\r
+               if (is_object($eventObj)) $className = get_class($eventObj);\r
+               else $className = $eventObj;\r
+               \r
+               // load actions from cache if necessary\r
+               if ($this->actions === null && $this->inheritedActions === null) {\r
+                       $this->loadActions();\r
+               }\r
+               \r
+               // generate action name\r
+               $name = self::generateKey($className, $eventName);\r
+\r
+               // execute inherited actions first\r
+               if (count($this->inheritedActions) > 0) {\r
+                       $this->executeInheritedActions($eventObj, $eventName, $className, $name);\r
+               }\r
+               \r
+               // create objects of the actions\r
+               if (!isset($this->actionsObjects[$name]) || !is_array($this->actionsObjects[$name])) {\r
+                       if (!isset($this->actions[$name]) || !is_array($this->actions[$name])) {\r
+                               // no action registered\r
+                               return false;\r
+                       }\r
+               \r
+                       $this->actionsObjects[$name] = array();\r
+                       foreach ($this->actions[$name] as $action) {\r
+                               if (isset($this->actionsObjects[$name][$action['listenerClassName']])) continue;\r
+\r
+                               // get class object\r
+                               if (isset($this->listenerObjects[$action['listenerClassName']])) {\r
+                                       $object = $this->listenerObjects[$action['listenerClassName']];\r
+                               }\r
+                               else {\r
+                                       // instance action object\r
+                                       if (!class_exists($action['listenerClassName'])) {\r
+                                               throw new SystemException("Unable to find class '".$action['listenerClassName']."'", 11001);\r
+                                       }\r
+                               \r
+                                       $object = new $action['listenerClassName'];\r
+                                       $this->listenerObjects[$path] = $object;\r
+                               }\r
+                               \r
+                               $this->actionsObjects[$name][$action['listenerClassName']] = $object;\r
+                       }\r
+               }\r
+               \r
+               // execute actions\r
+               foreach ($this->actionsObjects[$name] as $actionObj) {\r
+                       $actionObj->execute($eventObj, $className, $eventName);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Generates an unique name for an action.\r
+        *\r
+        * @param       string          $className\r
+        * @param       string          $eventName\r
+        */\r
+       public static function generateKey($className, $eventName) {\r
+               return $eventName.'@'.$className;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/event/EventListener.class.php b/wcfsetup/install/files/lib/system/event/EventListener.class.php
new file mode 100644 (file)
index 0000000..c4975dd
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\event;\r
+\r
+/**\r
+ * EventListeners can be registered for a specific event in many controller objects.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.event\r
+ * @category   Community Framework\r
+ */\r
+interface EventListener {\r
+       /**\r
+        * Executes this action.\r
+        * \r
+        * @param       object          $eventObj\r
+        * @param       string          $className\r
+        * @param       string          $eventName\r
+        */\r
+       public function execute($eventObj, $className, $eventName);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/event/listener/SessionAccessLogListener.class.php b/wcfsetup/install/files/lib/system/event/listener/SessionAccessLogListener.class.php
new file mode 100644 (file)
index 0000000..9a0cccb
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+namespace wcf\system\event\listener;
+use wcf\data\acp\session\access\log\ACPSessionAccessLogEditor;
+use wcf\data\acp\session\log\ACPSessionLog;
+use wcf\data\acp\session\log\ACPSessionLogEditor;
+use wcf\system\event\EventListener;
+use wcf\system\WCF;
+
+/**
+ * Creates the session access log.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.event.listener
+ * @category   Community Framework
+ */
+class SessionAccessLogListener implements EventListener {
+       /**
+        * @see EventListener::execute()
+        */
+       public function execute($eventObj, $className, $eventName) {
+               if (WCF::getUser()->userID && WCF::getSession()->getPermission('admin.general.canUseAcp') && !defined(get_class($eventObj).'::DO_NOT_LOG')) {
+                       // try to find existing session log
+                       $sql = "SELECT  sessionLogID
+                               FROM    wcf".WCF_N."_acp_session_log
+                               WHERE   sessionID = ?
+                                       AND lastActivityTime >= ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(
+                               WCF::getSession()->sessionID,
+                               (TIME_NOW - SESSION_TIMEOUT)
+                       ));
+                       $row = $statement->fetchArray();
+                       if (!empty($row['sessionLogID'])) {
+                               $sessionLogID = $row['sessionLogID'];
+                               
+                               $sessionLogEditor = new ACPSessionLogEditor(new ACPSessionLog($sessionLogID));
+                               $sessionLogEditor->update(array(
+                                       'lastActivityTime' => TIME_NOW
+                               ));
+                       }
+                       else {
+                               // create new session log
+                               $sessionLog = ACPSessionLogEditor::create(array(
+                                       'sessionID' => WCF::getSession()->sessionID,
+                                       'userID' => WCF::getUser()->userID,
+                                       'ipAddress' => WCF::getSession()->ipAddress,
+                                       'hostname' => @gethostbyaddr(WCF::getSession()->ipAddress),
+                                       'userAgent' => WCF::getSession()->userAgent,
+                                       'time' => TIME_NOW,
+                                       'lastActivityTime' => TIME_NOW
+                               ));
+                               $sessionLogID = $sessionLog->sessionLogID;
+                       }
+                       
+                       // format request uri
+                       $requestURI = WCF::getSession()->requestURI;
+                       // remove directories
+                       $URIComponents = explode('/', $requestURI);
+                       $requestURI = array_pop($URIComponents);
+                       // remove session url
+                       $requestURI = preg_replace('/(?:\?|&)s=[a-f0-9]{40}/', '', $requestURI);
+                       
+                       // save access
+                       ACPSessionAccessLogEditor::create(array(
+                               'sessionLogID' => $sessionLogID,
+                               'packageID' => PACKAGE_ID,
+                               'ipAddress' => WCF::getSession()->ipAddress,
+                               'time' => TIME_NOW,
+                               'requestURI' => $requestURI,
+                               'requestMethod' => WCF::getSession()->requestMethod,
+                               'className' => get_class($eventObj)
+                       ));
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/exception/AJAXException.class.php b/wcfsetup/install/files/lib/system/exception/AJAXException.class.php
new file mode 100644 (file)
index 0000000..2dfa014
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\system\exception;\r
+use wcf\util\JSON;\r
+\r
+/**\r
+ * AJAXException provides JSON-encoded exceptions.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+class AJAXException extends \Exception {\r
+       /**\r
+        * Throws a JSON-encoded error message\r
+        * \r
+        * @param       string          $message\r
+        */\r
+       public function __construct($message) {\r
+               //header('HTTP/1.0 418 I\'m a Teapot');\r
+               header('HTTP/1.0 503 Service Unavailable');\r
+               header('Content-type: application/json');\r
+               echo JSON::encode(array(\r
+                       'message' => $message\r
+               ));\r
+               exit;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/IllegalLinkException.class.php b/wcfsetup/install/files/lib/system/exception/IllegalLinkException.class.php
new file mode 100644 (file)
index 0000000..a343431
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\system\exception;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * IllegalLinkException shows the unknown link error page.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+class IllegalLinkException extends NamedUserException {\r
+       /**\r
+        * Creates a new IllegalLinkException object.\r
+        */\r
+       public function __construct() {\r
+               parent::__construct(WCF::getLanguage()->get('wcf.global.error.illegalLink'));\r
+       }\r
+       \r
+       /**\r
+        * @see NamedUserException::show();\r
+        */\r
+       public function show() {\r
+               @header('HTTP/1.0 404 Not Found');\r
+               parent::show();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/NamedUserException.class.php b/wcfsetup/install/files/lib/system/exception/NamedUserException.class.php
new file mode 100644 (file)
index 0000000..ab35a6b
--- /dev/null
@@ -0,0 +1,39 @@
+<?php\r
+namespace wcf\system\exception;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * NamedUserException shows a (well) styled page with the given error message.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+class NamedUserException extends UserException {\r
+       /**\r
+        * Creates a new NamedUserException object.\r
+        * \r
+        * @param       string          $message\r
+        */\r
+       public function __construct($message) {\r
+               parent::__construct($message);\r
+       }\r
+       \r
+       /**\r
+        * Shows a styled page with the given error message.\r
+        */\r
+       public function show() {\r
+               WCF::getTPL()->assign(array(\r
+                       'name' => get_class($this),\r
+                       'file' => $this->getFile(),\r
+                       'line' => $this->getLine(),\r
+                       'message' => $this->getMessage(),\r
+                       'stacktrace' => $this->getTraceAsString()\r
+               ));\r
+               WCF::getTPL()->display('userException');\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/PermissionDeniedException.class.php b/wcfsetup/install/files/lib/system/exception/PermissionDeniedException.class.php
new file mode 100644 (file)
index 0000000..6b8fcae
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\system\exception;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * A PermissionDeniedException is thrown when a user has no permission to access to a specific area.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+class PermissionDeniedException extends UserException {\r
+       /**\r
+        * Creates a new IllegalLinkException object.\r
+        */\r
+       public function __construct() {\r
+               parent::__construct(WCF::getLanguage()->get('wcf.global.error.permissionDenied'));\r
+       }\r
+\r
+       /**\r
+        * Prints a permission denied exception.\r
+        */\r
+       public function show() {\r
+               @header('HTTP/1.0 403 Forbidden');\r
+               WCF::getTPL()->display('permissionDenied');\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/PrintableException.class.php b/wcfsetup/install/files/lib/system/exception/PrintableException.class.php
new file mode 100644 (file)
index 0000000..914c64e
--- /dev/null
@@ -0,0 +1,21 @@
+<?php\r
+namespace wcf\system\exception;\r
+\r
+/**\r
+ * WCF::handleException() calls the show method on exceptions that implement this interface.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+interface PrintableException {\r
+       /**\r
+        * Prints this exception.\r
+        * This method is called by WCF::handleException().\r
+        */\r
+       public function show();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/SystemException.class.php b/wcfsetup/install/files/lib/system/exception/SystemException.class.php
new file mode 100644 (file)
index 0000000..92f29bd
--- /dev/null
@@ -0,0 +1,149 @@
+<?php\r
+namespace wcf\system\exception;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * A SystemException is thrown when an unexpected error occurs.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+class SystemException extends \Exception implements PrintableException {\r
+       /**\r
+        * error description\r
+        * @var string\r
+        */\r
+       protected $description = null;\r
+       \r
+       /**\r
+        * additional information\r
+        * @var string\r
+        */\r
+       protected $information = '';\r
+       \r
+       /**\r
+        * additional information\r
+        * @var string\r
+        */\r
+       protected $functions = '';\r
+       \r
+       /**\r
+        * Creates a new SystemException.\r
+        * \r
+        * @param       string          $message        error message\r
+        * @param       integer         $code           error code\r
+        * @param       string          $description    description of the error        \r
+        */\r
+       public function __construct($message = '', $code = 0, $description = '') {\r
+               parent::__construct($message, $code);\r
+               $this->description = $description;\r
+       }\r
+       \r
+       /**\r
+        * Returns the description of this exception.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getDescription() {\r
+               return $this->description;\r
+       }\r
+       \r
+       /**\r
+        * Removes database password from stack trace.\r
+        * @see Exception::getTraceAsString()\r
+        */\r
+       public function __getTraceAsString() {\r
+               $string = preg_replace('/Database->__construct\(.*\)/', 'Database->__construct(...)', $this->getTraceAsString());\r
+               $string = preg_replace('/mysqli->mysqli\(.*\)/', 'mysqli->mysqli(...)', $string);\r
+               return $string;\r
+       }\r
+       \r
+       /**\r
+        * @see PrintableException::show()\r
+        */\r
+       public function show() {\r
+               // send status code\r
+               @header('HTTP/1.1 503 Service Unavailable');\r
+               \r
+               // print report\r
+               echo '<?xml version="1.0" encoding="UTF-8"?>';\r
+               ?>\r
+               \r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en">\r
+<head>\r
+<title>Fatal error: <?php echo StringUtil::encodeHTML($this->getMessage()); ?></title>\r
+<style type="text/css">\r
+/*<![CDATA[*/\r
+.systemException {\r
+       border: 1px outset lightgrey;\r
+       padding: 3px;\r
+       background-color: lightgrey;\r
+       text-align: left;\r
+       overflow: auto;\r
+       font-family: Verdana, Helvetica, sans-serif;\r
+       font-size: .8em;\r
+}\r
+.systemException div {\r
+       border: 1px inset lightgrey;\r
+       padding: 4px;\r
+}\r
+.systemException h1 {\r
+       background-color: #154268;\r
+       padding: 4px;\r
+       color: #fff;\r
+       margin: 0 0 3px 0;\r
+       font-size: 1.15em;\r
+}\r
+.systemException h2 {\r
+       font-size: 1.1em;\r
+       margin-bottom: 0;\r
+}\r
+.systemException pre, .systemException p {\r
+       margin: 0;\r
+}\r
+.systemException pre {\r
+       font-size: .85em;\r
+       font-family: "Courier New";\r
+}\r
+/*]]>*/\r
+</style>\r
+</head>\r
+<body>\r
+       <div class="systemException">\r
+               <h1>Fatal error: <?php echo StringUtil::encodeHTML($this->getMessage()); ?></h1>\r
+       \r
+               <div>\r
+                       <p><?php echo $this->getDescription(); ?></p>\r
+                       <?php if ($this->getCode()) { ?><p>You get more information about the problem in the official WoltLab knowledge base: <a href="http://www.woltlab.com/help/?code=<?php echo intval($this->getCode()); ?>">http://www.woltlab.com/help/?code=<?php echo intval($this->getCode()); ?></a></p><?php } ?>\r
+                       \r
+                       <h2>Information:</h2>\r
+                       <p>\r
+                               <b>error message:</b> <?php echo StringUtil::encodeHTML($this->getMessage()); ?><br />\r
+                               <b>error code:</b> <?php echo intval($this->getCode()); ?><br />                                \r
+                               <?php echo $this->information; ?>\r
+                               <b>file:</b> <?php echo StringUtil::encodeHTML($this->getFile()); ?> (<?php echo $this->getLine(); ?>)<br />\r
+                               <b>php version:</b> <?php echo StringUtil::encodeHTML(phpversion()); ?><br />\r
+                               <b>wcf version:</b> <?php echo WCF_VERSION; ?><br />\r
+                               <b>date:</b> <?php echo gmdate('r'); ?><br />\r
+                               <b>request:</b> <?php if (isset($_SERVER['REQUEST_URI'])) echo StringUtil::encodeHTML($_SERVER['REQUEST_URI']); ?><br />\r
+                               <b>referer:</b> <?php if (isset($_SERVER['HTTP_REFERER'])) echo StringUtil::encodeHTML($_SERVER['HTTP_REFERER']); ?><br />\r
+                       </p>\r
+                       \r
+                       <h2>Stacktrace:</h2>\r
+                       <pre><?php echo StringUtil::encodeHTML($this->__getTraceAsString()); ?></pre>\r
+               </div>\r
+               \r
+               <?php echo $this->functions; ?>\r
+       </div>\r
+</body>\r
+</html>\r
+\r
+<?php\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/UserException.class.php b/wcfsetup/install/files/lib/system/exception/UserException.class.php
new file mode 100644 (file)
index 0000000..59275a7
--- /dev/null
@@ -0,0 +1,22 @@
+<?php\r
+namespace wcf\system\exception;\r
+\r
+/**\r
+ * A UserException is thrown when a user gives invalid input data.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+abstract class UserException extends \Exception implements PrintableException {\r
+       /**\r
+        * @see PrintableException::show()\r
+        */\r
+       public function show() {\r
+               echo '<pre>' . $this->getTraceAsString() . '</pre>';\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/UserInputException.class.php b/wcfsetup/install/files/lib/system/exception/UserInputException.class.php
new file mode 100644 (file)
index 0000000..48b0267
--- /dev/null
@@ -0,0 +1,60 @@
+<?php\r
+namespace wcf\system\exception;\r
+\r
+/**\r
+ * UserInputException handles all formular input errors.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.exception\r
+ * @category   Community Framework\r
+ */\r
+class UserInputException extends UserException {\r
+       /**\r
+        * Name of error field.\r
+        *\r
+        * @var string\r
+        */\r
+       protected $field = null;\r
+       \r
+       /**\r
+        * Error type.\r
+        *\r
+        * @var string\r
+        */\r
+       protected $type = null;\r
+       \r
+       /**\r
+        * Creates a new UserInputException.\r
+        * \r
+        * @param       string          $field          affected formular field\r
+        * @param       string          $type           kind of this error\r
+        */\r
+       public function __construct($field = '', $type = 'empty') {\r
+               $this->field = $field;\r
+               $this->type = $type;\r
+               \r
+               parent::__construct();\r
+       }\r
+       \r
+       /**\r
+        * Returns the affected formular field of this error.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getField() {\r
+               return $this->field;\r
+       }\r
+       \r
+       /**\r
+        * Returns the kind of this error.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getType() {\r
+               return $this->type;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/exception/ValidateActionException.class.php b/wcfsetup/install/files/lib/system/exception/ValidateActionException.class.php
new file mode 100644 (file)
index 0000000..acc2560
--- /dev/null
@@ -0,0 +1,14 @@
+<?php\r
+namespace wcf\system\exception;\r
+\r
+/**\r
+ * @todo       Ableitung von welcher Exception und wie soll die\r
+ *             konkrete Anzeige sein, wenn diese Exception nicht\r
+ *             ordnungsgemäß abgefangen wird?\r
+ */\r
+class ValidateActionException extends \Exception {\r
+       public function __construct($message) {\r
+               die($message);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/FormDocument.class.php b/wcfsetup/install/files/lib/system/form/FormDocument.class.php
new file mode 100644 (file)
index 0000000..bfad7cd
--- /dev/null
@@ -0,0 +1,127 @@
+<?php\r
+namespace wcf\system\form;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * FormDocument holds the page structure based upon form element containers.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class FormDocument {\r
+       /**\r
+        * list of FormElementContainer objects\r
+        *\r
+        * @var FormElementContainer\r
+        */\r
+       protected $containers = array();\r
+       \r
+       /**\r
+        * form document name\r
+        *\r
+        * @var string\r
+        */\r
+       protected $name = '';\r
+       \r
+       /**\r
+        * Creates a new instance of FormDocument.\r
+        *\r
+        * @param       string          $name\r
+        */\r
+       public function __construct($name) {\r
+               $this->name = StringUtil::trim($name);\r
+       }\r
+       \r
+       /**\r
+        * Returns form document name.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getName() {\r
+               return $this->name;\r
+       }\r
+       \r
+       /**\r
+        * Appends a FormElementContainer object.\r
+        *\r
+        * @param       FormElementContainer            $container\r
+        */\r
+       public function appendContainer(FormElementContainer $container) {\r
+               $this->containers[] = $container;\r
+       }\r
+       \r
+       /**\r
+        * Prepends a FormElementContainer object.\r
+        *\r
+        * @param       FormElementContainer            $container\r
+        */\r
+       public function prependContainer(FormElementContainer $container) {\r
+               array_unshift($this->containers, $container);\r
+       }\r
+       \r
+       /**\r
+        * Returns assigned FormElementContainer objects.\r
+        *\r
+        * @return      array<FormElementContainer>\r
+        */\r
+       public function getContainers() {\r
+               return $this->containers;\r
+       }\r
+       \r
+       /**\r
+        * Returns the value of container's child element with given name.\r
+        *\r
+        * @param       string          $key\r
+        * @return      mixed\r
+        */\r
+       public function getValue($key) {\r
+               foreach ($this->containers as $container) {\r
+                       $value = $container->getValue($key);\r
+                       if ($value !== null) {\r
+                               return $value;\r
+                       }\r
+               }\r
+               \r
+               return null;\r
+       }\r
+       \r
+       /**\r
+        * Returns HTML-representation of current document.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getHTML() {\r
+               $content = '';\r
+               \r
+               foreach ($this->containers as $container) {\r
+                       $content .= $container->getHTML($this->getName().'_');\r
+               }\r
+               \r
+               return $content;\r
+       }\r
+       \r
+       /**\r
+        * Handles request input variables.\r
+        */\r
+       public function handleRequest() {\r
+               $variables = array();\r
+               \r
+               foreach ($_REQUEST as $key => $value) {\r
+                       if (StringUtil::indexOf($key, $this->getName().'_') !== false) {\r
+                               $key = StringUtil::replace($this->getName().'_', '', $key);\r
+                               $variables[$key] = $value;\r
+                       }\r
+               }\r
+               \r
+               if (!empty($variables)) {\r
+                       foreach ($this->containers as $container) {\r
+                               $container->handleRequest($variables);\r
+                       }\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/FormElement.class.php b/wcfsetup/install/files/lib/system/form/FormElement.class.php
new file mode 100644 (file)
index 0000000..ac0bb3b
--- /dev/null
@@ -0,0 +1,66 @@
+<?php\r
+namespace wcf\system\form;\r
+use wcf\system\form\FormElementContainer;\r
+\r
+/**\r
+ * Interface for form elements.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+interface FormElement {\r
+       /**\r
+        * Creates a new object of type FormElement.\r
+        *\r
+        * @param       FormElementContainer            $parent\r
+        */\r
+       public function __construct(FormElementContainer $parent);\r
+       \r
+       /**\r
+        * Returns help message.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getDescription();\r
+       \r
+       /**\r
+        * Sets help message.\r
+        *\r
+        * @param       string          $description\r
+        */\r
+       public function setDescription($description);\r
+       \r
+       /**\r
+        * Returns label.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getLabel();\r
+       \r
+       /**\r
+        * Sets label.\r
+        *\r
+        * @param       string          $label\r
+        */\r
+       public function setLabel($label);\r
+       \r
+       /**\r
+        * Returns element's parent container element.\r
+        *\r
+        * @return      FormElementContainer\r
+        */\r
+       public function getParent();\r
+       \r
+       /**\r
+        * Returns HTML-representation of current form element.\r
+        *\r
+        * @param       string          $formName\r
+        * @return      string\r
+        */\r
+       public function getHTML($formName);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/FormElementContainer.class.php b/wcfsetup/install/files/lib/system/form/FormElementContainer.class.php
new file mode 100644 (file)
index 0000000..f464029
--- /dev/null
@@ -0,0 +1,88 @@
+<?php\r
+namespace wcf\system\form;\r
+use wcf\system\form\FormElement;\r
+\r
+/**\r
+ * Interface for form element containers.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+interface FormElementContainer {\r
+       /**\r
+        * Returns help message.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getDescription();\r
+       \r
+       /**\r
+        * Sets help message.\r
+        *\r
+        * @param       string          $description\r
+        */\r
+       public function setDescription($description);\r
+       \r
+       /**\r
+        * Returns label.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getLabel();\r
+       \r
+       /**\r
+        * Sets label.\r
+        *\r
+        * @param       string          $label\r
+        */\r
+       public function setLabel($label);\r
+       \r
+       /**\r
+        * Returns the value of child element with given name.\r
+        *\r
+        * @param       string          $key\r
+        * @return      mixed\r
+        */\r
+       public function getValue($key);\r
+       \r
+       /**\r
+        * Returns a list of child elements.\r
+        *\r
+        * @return      array<FormElement>\r
+        */\r
+       public function getChildren();\r
+       \r
+       /**\r
+        * Appends a new child to stack.\r
+        *\r
+        * @param       FormElement             $element\r
+        */\r
+       public function appendChild(FormElement $element);\r
+       \r
+       /**\r
+        * Preprens a new child to stack.\r
+        *\r
+        * @param       FormElement             $element\r
+        */\r
+       public function prependChild(FormElement $element);\r
+       \r
+       /**\r
+        * Handles a POST or GET request.\r
+        *\r
+        * @param       array           $variables\r
+        */\r
+       public function handleRequest(array $variables);\r
+       \r
+       /**\r
+        * Returns HTML-representation of current form element container.\r
+        *\r
+        * @param       string          $formName\r
+        * @return      string\r
+        */\r
+       public function getHTML($formName);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/container/AbstractFormElementContainer.class.php b/wcfsetup/install/files/lib/system/form/container/AbstractFormElementContainer.class.php
new file mode 100644 (file)
index 0000000..e3beb98
--- /dev/null
@@ -0,0 +1,119 @@
+<?php\r
+namespace wcf\system\form\container;\r
+use wcf\system\form\FormElement;\r
+use wcf\system\form\FormElementContainer;\r
+use wcf\system\form\element\AbstractNamedFormElement;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Basic implementation for form element containers.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractFormElementContainer implements FormElementContainer {\r
+       /**\r
+        * list of FormElement objects\r
+        *\r
+        * @var array<FormElement>\r
+        */\r
+       protected $children = array();\r
+       \r
+       /**\r
+        * element description or help text\r
+        *\r
+        * @var string\r
+        */\r
+       protected $description = '';\r
+       \r
+       /**\r
+        * element label\r
+        *\r
+        * @var string\r
+        */\r
+       protected $label = '';\r
+       \r
+       /**\r
+        * @see FormElementContainer::setDescription()\r
+        */\r
+       public function setDescription($description) {\r
+               $this->description = StringUtil::trim($description);\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::getDescription()\r
+        */\r
+       public function getDescription() {\r
+               return $this->description;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::setLabel()\r
+        */\r
+       public function setLabel($label) {\r
+               $this->label = StringUtil::trim($label);\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::getLabel()\r
+        */\r
+       public function getLabel() {\r
+               return $this->label;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::appendChild()\r
+        */\r
+       public function appendChild(FormElement $element) {\r
+               $this->children[] = $element;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::prependChild()\r
+        */\r
+       public function prependChild(FormElement $element) {\r
+               array_unshift($this->children, $element);\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::getChildren()\r
+        */\r
+       public function getChildren() {\r
+               return $this->children;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::getValue()\r
+        */\r
+       public function getValue($key) {\r
+               foreach ($this->children as $element) {\r
+                       if ($element instanceof AbstractNamedFormElement) {\r
+                               if ($element->getName() == $key) {\r
+                                       return $element->getValue();\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               return null;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::handleRequest()\r
+        */\r
+       public function handleRequest(array $variables) {\r
+               foreach ($this->children as $element) {\r
+                       if (!($element instanceof AbstractNamedFormElement)) {\r
+                               return;\r
+                       }\r
+                       \r
+                       if (isset($variables[$element->getName()])) {\r
+                               $element->setValue($variables[$element->getName()]);\r
+                       }\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/container/GroupFormElementContainer.class.php b/wcfsetup/install/files/lib/system/form/container/GroupFormElementContainer.class.php
new file mode 100644 (file)
index 0000000..a3bfa78
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+namespace wcf\system\form\container;\r
+\r
+/**\r
+ * Provides a group form element container.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class GroupFormElementContainer extends AbstractFormElementContainer {\r
+       /**\r
+        * @see FormElementContainer::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               $content = '';\r
+               foreach ($this->children as $element) {\r
+                       $content .= $element->getHTML($formName);\r
+               }\r
+               \r
+               return <<<HTML\r
+<fieldset>\r
+       <legend>{$this->getLabel()}</legend>\r
+       \r
+       <p class="description">{$this->getDescription()}</p>\r
+       \r
+       {$content}\r
+</fieldset>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/container/MultipleSelectionFormElementContainer.class.php b/wcfsetup/install/files/lib/system/form/container/MultipleSelectionFormElementContainer.class.php
new file mode 100644 (file)
index 0000000..0726b43
--- /dev/null
@@ -0,0 +1,70 @@
+<?php\r
+namespace wcf\system\form\container;\r
+\r
+/**\r
+ * Provides a multiple selection form element container.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class MultipleSelectionFormElementContainer extends SelectionFormElementContainer {\r
+       /**\r
+        * container value\r
+        *\r
+        * @var array\r
+        */\r
+       protected $value = array();\r
+       \r
+       /**\r
+        * Sets container value.\r
+        *\r
+        * @param       array           $value\r
+        */\r
+       public function setValue(array $value) {\r
+               $this->value = $value;\r
+       }\r
+       \r
+       /**\r
+        * Returns container value.\r
+        *\r
+        * @return      array\r
+        */\r
+       public function getValue() {\r
+               return $this->value;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               $content = '';\r
+               foreach ($this->getChildren() as $element) {\r
+                       $content .= $element->getHTML($formName);\r
+               }\r
+               \r
+               return <<<HTML\r
+<div class="formGroup">\r
+       <div class="formGroupLabel">\r
+               <label>{$this->getLabel()}</label>\r
+       </div>\r
+       <div class="formGroupField">\r
+               <fieldset>\r
+                       <legend>{$this->getLabel()}</legend>\r
+                       \r
+                       <div class="formField">\r
+                               {$content}\r
+                       </div>\r
+               </fieldset>\r
+       </div>\r
+       <div class="formGroupFieldDesc">\r
+               <p>{$this->getDescription()}</p>\r
+       </div>\r
+</div>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/container/SelectionFormElementContainer.class.php b/wcfsetup/install/files/lib/system/form/container/SelectionFormElementContainer.class.php
new file mode 100644 (file)
index 0000000..89f6c9c
--- /dev/null
@@ -0,0 +1,40 @@
+<?php\r
+namespace wcf\system\form\container;\r
+\r
+/**\r
+ * Basic implementation for form selection element containers.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+abstract class SelectionFormElementContainer extends AbstractFormElementContainer {\r
+       /**\r
+        * container name\r
+        *\r
+        * @var string\r
+        */\r
+       protected $name = '';\r
+       \r
+       /**\r
+        * Sets container name.\r
+        *\r
+        * @param       string          $name\r
+        */\r
+       public function setName($name) {\r
+               $this->name = StringUtil::trim($name);\r
+       }\r
+       \r
+       /**\r
+        * Returns container name\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getName() {\r
+               return $this->name;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/container/SingleSelectionFormElementContainer.class.php b/wcfsetup/install/files/lib/system/form/container/SingleSelectionFormElementContainer.class.php
new file mode 100644 (file)
index 0000000..699b82b
--- /dev/null
@@ -0,0 +1,70 @@
+<?php\r
+namespace wcf\system\form\container;\r
+\r
+/**\r
+ * Provides a single selection form element container.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class SingleSelectionFormElementContainer extends SelectionFormElementContainer {\r
+       /**\r
+        * container value\r
+        *\r
+        * @var string\r
+        */\r
+       protected $value = '';\r
+       \r
+       /**\r
+        * Sets container value.\r
+        *\r
+        * @param       string          $value\r
+        */\r
+       public function setValue($value) {\r
+               $this->value = StringUtil::trim($value);\r
+       }\r
+       \r
+       /**\r
+        * Returns container value.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getValue() {\r
+               return $this->value;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElementContainer::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               $content = '';\r
+               foreach ($this->getChildren() as $element) {\r
+                       $content .= $element->getHTML($formName);\r
+               }\r
+               \r
+               return <<<HTML\r
+<div class="formGroup">\r
+       <div class="formGroupLabel">\r
+               <label>{$this->getLabel()}</label>\r
+       </div>\r
+       <div class="formGroupField">\r
+               <fieldset>\r
+                       <legend>{$this->getLabel()}</legend>\r
+                       \r
+                       <div class="formField">\r
+                               {$content}\r
+                       </div>\r
+               </fieldset>\r
+       </div>\r
+       <div class="formGroupFieldDesc">\r
+               <p>{$this->getDescription()}</p>\r
+       </div>\r
+</div>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/AbstractFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/AbstractFormElement.class.php
new file mode 100644 (file)
index 0000000..9827487
--- /dev/null
@@ -0,0 +1,81 @@
+<?php\r
+namespace wcf\system\form\element;\r
+use wcf\system\form\FormElement;\r
+use wcf\system\form\FormElementContainer;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Basic implementation for form elements.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractFormElement implements FormElement {\r
+       /**\r
+        * element description or help text\r
+        *\r
+        * @var string\r
+        */\r
+       protected $description = '';\r
+       \r
+       /**\r
+        * element label\r
+        *\r
+        * @var string\r
+        */\r
+       protected $label = '';\r
+       \r
+       /**\r
+        * FormElementContainer object\r
+        *\r
+        * @var FormElementContainer\r
+        */\r
+       protected $parent = null;\r
+       \r
+       /**\r
+        * @see FormElement::__construct()\r
+        */\r
+       public function __construct(FormElementContainer $parent) {\r
+               $this->parent = $parent;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElement::setDescription()\r
+        */\r
+       public function setDescription($description) {\r
+               $this->description = StringUtil::trim($description);\r
+       }\r
+       \r
+       /**\r
+        * @see FormElement::getDescription()\r
+        */\r
+       public function getDescription() {\r
+               return $this->description;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElement::setLabel()\r
+        */\r
+       public function setLabel($label) {\r
+               $this->label = StringUtil::trim($label);\r
+       }\r
+       \r
+       /**\r
+        * @see FormElement::getLabel()\r
+        */\r
+       public function getLabel() {\r
+               return $this->label;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElement::getParent()\r
+        */\r
+       public function getParent() {\r
+               return $this->parent;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/AbstractNamedFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/AbstractNamedFormElement.class.php
new file mode 100644 (file)
index 0000000..4d39148
--- /dev/null
@@ -0,0 +1,66 @@
+<?php\r
+namespace wcf\system\form\element;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Basic implementation for named form elements.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+abstract class AbstractNamedFormElement extends AbstractFormElement {\r
+       /**\r
+        * element name\r
+        *\r
+        * @var string\r
+        */\r
+       protected $name = '';\r
+       \r
+       /**\r
+        * element value\r
+        *\r
+        * @var string\r
+        */\r
+       protected $value = '';\r
+       \r
+       /**\r
+        * Sets element name.\r
+        *\r
+        * @param       string          $name\r
+        */\r
+       public function setName($name) {\r
+               $this->name = StringUtil::trim($name);\r
+       }\r
+       \r
+       /**\r
+        * Returns element name\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getName() {\r
+               return $this->name;\r
+       }\r
+       \r
+       /**\r
+        * Sets element value.\r
+        *\r
+        * @param       string          $value\r
+        */\r
+       public function setValue($value) {\r
+               $this->value = StringUtil::trim($value);\r
+       }\r
+       \r
+       /**\r
+        * Returns element value.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getValue() {\r
+               return $this->value;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/LabelFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/LabelFormElement.class.php
new file mode 100644 (file)
index 0000000..feadd64
--- /dev/null
@@ -0,0 +1,60 @@
+<?php\r
+namespace wcf\system\form\element;\r
+use wcf\system\util\StringUtil;\r
+\r
+/**\r
+ * Provides a label form element.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class LabelFormElement extends AbstractFormElement {\r
+       /**\r
+        * element text\r
+        *\r
+        * @var string\r
+        */\r
+       protected $text = '';\r
+       \r
+       /**\r
+        * Sets element text.\r
+        *\r
+        * @param       string          $text\r
+        */\r
+       public function setText($text) {\r
+               $text->text = StringUtil::trim($text);\r
+       }\r
+       \r
+       /**\r
+        * Returns element text.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getText() {\r
+               return $this->text;\r
+       }\r
+       \r
+       /**\r
+        * @see FormElement::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               return <<<HTML\r
+<div class="formElement">\r
+       <div class="formFieldLabel">\r
+               <label>{$this->getLabel()}</label>\r
+       </div>\r
+       <div class="formField">\r
+               {$this->getText()}\r
+       </div>\r
+       <div class="formFieldDesc">\r
+               <p>{$this->getDescription()}</p>\r
+       </div>\r
+</div>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/MultipleSelectionFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/MultipleSelectionFormElement.class.php
new file mode 100644 (file)
index 0000000..187def1
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\form\element;\r
+\r
+/**\r
+ * Provides a radio form element.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class MultipleSelectionFormElement extends AbstractNamedFormElement {\r
+       /**\r
+        * @see FormElement::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               return <<<HTML\r
+<label><input type="checkbox" name="{$formName}{$this->getParent()->getName()}[]" value="{$this->getValue()}" /> {$this->getLabel()}</label>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/PasswordInputFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/PasswordInputFormElement.class.php
new file mode 100644 (file)
index 0000000..f9de1fb
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+namespace wcf\system\form\element;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Provides a password input form element.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class PasswordInputFormElement extends AbstractNamedFormElement {\r
+       /**\r
+        * @see FormElement::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               return <<<HTML\r
+<div class="formElement">\r
+       <div class="formFieldLabel">\r
+               <label for="{$this->getName()}">{$this->getLabel()}</label>\r
+       </div>\r
+       <div class="formField">\r
+               <input type="password" name="{$formName}{$this->getName()}" id="{$this->getName()}" value="{$this->getValue()}" />\r
+       </div>\r
+       <div class="formFieldDesc">\r
+               <p>{$this->getDescription()}</p>\r
+       </div>\r
+</div>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/SingleSelectionFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/SingleSelectionFormElement.class.php
new file mode 100644 (file)
index 0000000..50d1a83
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\form\element;\r
+\r
+/**\r
+ * Provides a checkbox form element.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class SingleSelectionFormElement extends AbstractNamedFormElement {\r
+       /**\r
+        * @see FormElement::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               return <<<HTML\r
+<label><input type="radio" name="{$formName}{$this->getParent()->getName()}" value="{$this->getValue()}" /> {$this->getLabel()}</label>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/form/element/TextInputFormElement.class.php b/wcfsetup/install/files/lib/system/form/element/TextInputFormElement.class.php
new file mode 100644 (file)
index 0000000..53e1d7b
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+namespace wcf\system\form\element;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Provides a text input form element.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.form\r
+ * @category   Community Framework\r
+ */\r
+class TextInputFormElement extends AbstractNamedFormElement {\r
+       /**\r
+        * @see FormElement::getHTML()\r
+        */\r
+       public function getHTML($formName) {\r
+               return <<<HTML\r
+<div class="formElement">\r
+       <div class="formFieldLabel">\r
+               <label for="{$this->getName()}">{$this->getLabel()}</label>\r
+       </div>\r
+       <div class="formField">\r
+               <input type="text" name="{$formName}{$this->getName()}" id="{$this->getName()}" value="{$this->getValue()}" />\r
+       </div>\r
+       <div class="formFieldDesc">\r
+               <p>{$this->getDescription()}</p>\r
+       </div>\r
+</div>\r
+HTML;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/image/Thumbnail.class.php b/wcfsetup/install/files/lib/system/image/Thumbnail.class.php
new file mode 100644 (file)
index 0000000..e95ee9c
--- /dev/null
@@ -0,0 +1,448 @@
+<?php\r
+namespace wcf\system\image;\r
+use wcf\util\FileUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Generates a thumbnail of given source file image.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.image\r
+ * @category   Community Framework\r
+ */\r
+class Thumbnail {\r
+       /**\r
+        * path to source file\r
+        *\r
+        * @var string\r
+        */\r
+       protected $sourceFile = '';\r
+       \r
+       /**\r
+        * maximum image width\r
+        *\r
+        * @var integer\r
+        */\r
+       protected $maxWidth = 0;\r
+       \r
+       /**\r
+        * maximum image height\r
+        *\r
+        * @var integer\r
+        */\r
+       protected $maxHeight = 0;\r
+       \r
+       /**\r
+        * true, to show source information in thumbnail\r
+        *\r
+        * @var boolean\r
+        */\r
+       protected $appendSourceInfo = false;\r
+       \r
+       /**\r
+        * true, to prefer embedded thumbnails\r
+        *\r
+        * @var boolean\r
+        */\r
+       protected $useEmbedded = true;\r
+       \r
+       /**\r
+        * true, to generate quadratic thumbnails\r
+        * \r
+        * @var boolean\r
+        */\r
+       protected $quadratic = false;\r
+               \r
+       /**\r
+        * mime type of the thumbnail\r
+        *\r
+        * @var string\r
+        */\r
+       protected $mimeType = '';\r
+       \r
+       /**\r
+        * name of the source image\r
+        *\r
+        * @var string\r
+        */\r
+       protected $sourceName = '';\r
+       \r
+       /**\r
+        * width of the source image\r
+        * \r
+        * @var integer\r
+        */\r
+       protected $sourceWidth = 0;\r
+       \r
+       /**\r
+        * height of the source image\r
+        * \r
+        * @var integer\r
+        */\r
+       protected $sourceHeight = 0;\r
+       \r
+       /**\r
+        * file size of the source image\r
+        * \r
+        * @var integer\r
+        */\r
+       protected $sourceSize = 0;\r
+       \r
+       /**\r
+        * height of the source information\r
+        * \r
+        * @var integer\r
+        */\r
+       protected static $sourceInfoLineHeight = 16;\r
+       \r
+       /**\r
+        * image type of the source image\r
+        * \r
+        * @var integer\r
+        */\r
+       protected $imageType = 0;\r
+       \r
+       /**\r
+        * Creates a new Thumbnail object.\r
+        * \r
+        * @param       string          $sourceFile\r
+        * @param       integer         $maxWidth\r
+        * @param       integer         $maxHeight\r
+        * @param       boolean         $appendSourceInfo\r
+        */\r
+       public function __construct($sourceFile, $maxWidth = 100, $maxHeight = 100, $appendSourceInfo = false, $sourceName = null, $useEmbedded = true, $quadratic = false) {\r
+               $this->sourceFile = $sourceFile;\r
+               $this->maxWidth = $maxWidth;\r
+               $this->maxHeight = $maxHeight;\r
+               $this->appendSourceInfo = $appendSourceInfo;\r
+               $this->useEmbedded = $useEmbedded;\r
+               $this->quadratic = $quadratic;\r
+               if ($this->appendSourceInfo) {\r
+                       // get source info\r
+                       if ($sourceName != null) $this->sourceName = $sourceName;\r
+                       else $this->sourceName = basename($this->sourceFile);\r
+                       list($this->sourceWidth, $this->sourceHeight, $type) = @getImageSize($this->sourceFile);\r
+                       $this->sourceSize = @filesize($sourceFile);\r
+               }\r
+       }\r
+       \r
+       /** \r
+        * Creates a thumbnail picture (jpg/png) of a big image\r
+        * \r
+        * @param       boolean         $rescale\r
+        * @return      string          thumbnail \r
+        */\r
+       public function makeThumbnail($rescale = false) {\r
+               list($width, $height, $this->imageType) = @getImageSize($this->sourceFile);\r
+       \r
+               // check image size\r
+               if ($this->checkSize($width, $height, $rescale)) {\r
+                       return false;   \r
+               }\r
+\r
+               // try to extract the embedded thumbnail first (faster)\r
+               $thumbnail = false;\r
+               if (!$rescale && $this->useEmbedded) {\r
+                       $thumbnail = $this->extractEmbeddedThumbnail();\r
+               }\r
+               if (!$thumbnail) {\r
+                       // calculate uncompressed filesize\r
+                       // and cancel to avoid a memory_limit error\r
+                       $memoryLimit = ini_get('memory_limit');\r
+                       if ($memoryLimit != '') {\r
+                               $memoryLimit = substr($memoryLimit, 0, -1) * 1024 * 1024;\r
+                               $fileSize = $width * $height * ($this->imageType == 3 ? 4 : 3);\r
+               \r
+                               if (($fileSize * 2.1) + memory_get_usage() > ($memoryLimit)) {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       \r
+                       // calculate new picture size\r
+                       $x = $y = 0;\r
+                       if ($this->quadratic) {\r
+                               $newWidth = $newHeight = $this->maxWidth;\r
+                               if ($this->appendSourceInfo) $newHeight -= self::$sourceInfoLineHeight * 2;\r
+                               \r
+                               if ($width > $height) {\r
+                                       $x = ceil(($width - $height) / 2);\r
+                                       $width = $height;\r
+                               }\r
+                               else {\r
+                                       $y = ceil(($height - $width) / 2);\r
+                                       $height = $width;\r
+                               }\r
+                       }\r
+                       else {\r
+                               $maxHeight = $this->maxHeight;\r
+                               if ($this->appendSourceInfo) $maxHeight -= self::$sourceInfoLineHeight * 2;\r
+                               if ($this->maxWidth / $width < $maxHeight / $height) {\r
+                                       $newWidth = $this->maxWidth;\r
+                                       $newHeight = round($height * ($newWidth / $width));\r
+                               }\r
+                               else {\r
+                                       $newHeight = $maxHeight;        \r
+                                       $newWidth = round($width * ($newHeight / $height));\r
+                               }\r
+                       }\r
+                       \r
+                       // resize image\r
+                       $imageResource = false;\r
+                       \r
+                       // jpeg image\r
+                       if ($this->imageType == 2 && function_exists('imagecreatefromjpeg')) {\r
+                               $imageResource = @imageCreateFromJPEG($this->sourceFile);\r
+                       }\r
+                       // gif image\r
+                       if ($this->imageType == 1 && function_exists('imagecreatefromgif')) {\r
+                               $imageResource = @imageCreateFromGIF($this->sourceFile);\r
+                       }\r
+                       // png image\r
+                       if ($this->imageType == 3 && function_exists('imagecreatefrompng')) {\r
+                               $imageResource = @imageCreateFromPNG($this->sourceFile);\r
+                       }\r
+                       \r
+                       // could not create image\r
+                       if (!$imageResource) {\r
+                               return false;\r
+                       }\r
+                       \r
+                       // resize image\r
+                       if (function_exists('imageCreateTrueColor') && function_exists('imageCopyResampled')) {\r
+                               $imageNew = @imageCreateTrueColor($newWidth, $newHeight);\r
+                               imageAlphaBlending($imageNew, false);\r
+                               @imageCopyResampled($imageNew, $imageResource, 0, 0, $x, $y, $newWidth, $newHeight, $width, $height);\r
+                               imageSaveAlpha($imageNew, true);\r
+                       }\r
+                       else if (function_exists('imageCreate') && function_exists('imageCopyResized')) {\r
+                               $imageNew = @imageCreate($newWidth, $newHeight);\r
+                               imageAlphaBlending($imageNew, false);\r
+                               @imageCopyResized($imageNew, $imageResource, 0, 0, $x, $y, $newWidth, $newHeight, $width, $height);\r
+                               imageSaveAlpha($imageNew, true);\r
+                       }\r
+                       else return false;\r
+                       \r
+                       // create thumbnail\r
+                       ob_start();\r
+                       \r
+                       if ($this->imageType == 1 && function_exists('imageGIF')) {\r
+                               @imageGIF($imageNew);\r
+                               $this->mimeType = 'image/gif';\r
+                       }\r
+                       else if (($this->imageType == 1 || $this->imageType == 3) && function_exists('imagePNG')) {\r
+                               @imagePNG($imageNew);\r
+                               $this->mimeType = 'image/png';\r
+                       }\r
+                       else if (function_exists('imageJPEG')) {\r
+                               @imageJPEG($imageNew, '', 90);\r
+                               $this->mimeType = 'image/jpeg';\r
+                       }\r
+                       else {\r
+                               return false;\r
+                       }\r
+                       \r
+                       @imageDestroy($imageNew);\r
+                       $thumbnail = ob_get_contents();\r
+                       ob_end_clean();\r
+               }\r
+               \r
+               if ($thumbnail && $this->appendSourceInfo && !$rescale) {\r
+                       $thumbnail = $this->appendSourceInfo($thumbnail);\r
+               }\r
+               \r
+               return $thumbnail;\r
+       }\r
+       \r
+       /**\r
+        * Appends information about the source image to the thumbnail.\r
+        * \r
+        * @param       string          $thumbnail\r
+        * @return      string\r
+        */\r
+       protected function appendSourceInfo($thumbnail) {\r
+               if (!function_exists('imageCreateFromString') || !function_exists('imageCreateTrueColor')) {\r
+                       return $thumbnail;\r
+               }\r
+               \r
+               $imageSrc = imageCreateFromString($thumbnail);\r
+               \r
+               // get image size\r
+               $width = imageSX($imageSrc);\r
+               $height = imageSY($imageSrc);\r
+               \r
+               // increase height\r
+               $heightDst = $height + self::$sourceInfoLineHeight * 2;\r
+               \r
+               // create new image\r
+               $imageDst = imageCreateTrueColor($width, $heightDst);\r
+               imageAlphaBlending($imageDst, false);\r
+               \r
+               // set background color\r
+               $background = imageColorAllocate($imageDst, 102, 102, 102);\r
+               imageFill($imageDst, 0, 0, $background);\r
+\r
+               // copy image\r
+               imageCopy($imageDst, $imageSrc, 0, 0, 0, 0, $width, $height);\r
+               imageSaveAlpha($imageDst, true);\r
+               \r
+               // get font size\r
+               $font = 2;\r
+               $fontWidth = imageFontWidth($font);\r
+               $fontHeight = imageFontHeight($font);\r
+               $fontColor = imageColorAllocate($imageDst, 255, 255, 255);\r
+               \r
+               // write source info\r
+               $line1 = $this->sourceName;\r
+               \r
+               // imageString supports only ISO-8859-1 encoded strings\r
+               $line1 = StringUtil::convertEncoding('UTF-8', 'ISO-8859-1', $line1);\r
+               \r
+               // truncate text if necessary\r
+               $maxChars = floor($width / $fontWidth);\r
+               if (strlen($line1) > $maxChars) {\r
+                       $line1 = $this->truncateSourceName($line1, $maxChars);\r
+               }\r
+               \r
+               $line2 = $this->sourceWidth.'x'.$this->sourceHeight.' '.FileUtil::formatFilesize($this->sourceSize);\r
+               \r
+               // write line 1\r
+               // calculate text position\r
+               $textX = 0;\r
+               $textY = 0;\r
+               \r
+               if ($fontHeight < self::$sourceInfoLineHeight) {\r
+                       $textY = intval(round((self::$sourceInfoLineHeight - $fontHeight) / 2));\r
+               }\r
+               if (strlen($line1) * $fontWidth < $width) {\r
+                       $textX = intval(round(($width - strlen($line1) * $fontWidth) / 2));\r
+               }\r
+               \r
+               imageString($imageDst, $font, $textX, $height + $textY, $line1, $fontColor);\r
+               \r
+               // write line 2\r
+               // calculate text position\r
+               $textX = 0;\r
+               $textY = 0;\r
+               \r
+               if ($fontHeight < self::$sourceInfoLineHeight) {\r
+                       $textY = self::$sourceInfoLineHeight + intval(round((self::$sourceInfoLineHeight - $fontHeight) / 2));\r
+               }\r
+               if (strlen($line2) * $fontWidth < $width) {\r
+                       $textX = intval(round(($width - strlen($line2) * $fontWidth) / 2));\r
+               }\r
+               \r
+               imageString($imageDst, $font, $textX, $height + $textY, $line2, $fontColor);\r
+               \r
+               \r
+               // output image\r
+               ob_start();\r
+               \r
+               if ($this->imageType == 1 && function_exists('imageGIF')) {\r
+                       @imageGIF($imageDst);\r
+                       $this->mimeType = 'image/gif';\r
+               }\r
+               else if (($this->imageType == 1 || $this->imageType == 3) && function_exists('imagePNG')) {\r
+                       @imagePNG($imageDst);\r
+                       $this->mimeType = 'image/png';\r
+               }\r
+               else if (function_exists('imageJPEG')) {\r
+                       @imageJPEG($imageDst, '', 90);\r
+                       $this->mimeType = 'image/jpeg';\r
+               }\r
+               else {\r
+                       return false;\r
+               }\r
+               \r
+               @imageDestroy($imageDst);\r
+               $thumbnail = ob_get_contents();\r
+               ob_end_clean();\r
+               \r
+               return $thumbnail;\r
+       }\r
+       \r
+       \r
+       /** \r
+        * Extracts the embedded thumbnail picture of a jpeg or tiff image\r
+        * \r
+        * @return      string          thumbnail \r
+        */\r
+       protected function extractEmbeddedThumbnail() {\r
+               if (!function_exists('exif_thumbnail')) {\r
+                       return false;\r
+               }\r
+\r
+               $width = $height = $type = 0;\r
+               $thumbnail = @exif_thumbnail($this->sourceFile, $width, $height, $type);\r
+               if ($thumbnail && $type && $width && $height) {\r
+                       // resize the extracted thumbnail again if necessary\r
+                       // (normally the thumbnail size is set to 160px\r
+                       // which is recommended in EXIF >2.1 and DCF)\r
+                       $this->mimeType = image_type_to_mime_type($type);\r
+                       if (!$this->checkSize($width, $height)) {\r
+                               // get temporary file name\r
+                               $this->sourceFile = FileUtil::getTemporaryFilename('thumbnail_');\r
+                               \r
+                               // create tmp file\r
+                               $tmpFile = new File($this->sourceFile);\r
+                               $tmpFile->write($thumbnail);\r
+                               $tmpFile->close();\r
+                               unset($thumbnail, $tmpFile);\r
+                               \r
+                               // resize tmp file again\r
+                               return $this->makeThumbnail(true);\r
+                       }\r
+                       \r
+                       return $thumbnail;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Checks the size of an image.\r
+        */\r
+       protected function checkSize($width, $height, $rescale = true) {\r
+               $maxHeight = $this->maxHeight;\r
+               if ($this->appendSourceInfo && $rescale) {\r
+                       $maxHeight -= self::$sourceInfoLineHeight * 2;\r
+               }\r
+               \r
+               if ($width > $this->maxWidth || $height > $maxHeight) {\r
+                       return false;\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Returns the mime type of the generated thumbnail.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getMimeType() {\r
+               return $this->mimeType;\r
+       }\r
+       \r
+       /**\r
+        * Truncates the given file name to needed length.\r
+        * \r
+        * @param       string          $name\r
+        * @param       string          $maxChars\r
+        * @return      string\r
+        */\r
+       protected static function truncateSourceName($name, $maxChars) {\r
+               $extension = '';\r
+               $lastPosition = strrpos($name, '.');\r
+               if ($lastPosition !== null) {\r
+                       $extension = substr($name, $lastPosition);\r
+                       $name = substr($name, 0, $lastPosition);\r
+                       $maxChars -= strlen($extension);\r
+               }\r
+               \r
+               return substr($name, 0, $maxChars - 3) . '...' . $extension;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/FTP.class.php b/wcfsetup/install/files/lib/system/io/FTP.class.php
new file mode 100644 (file)
index 0000000..4fe520d
--- /dev/null
@@ -0,0 +1,51 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The FTP class handles all ftp operations.\r
+ *  \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class FTP {\r
+       /**\r
+        * file pointer resource\r
+        * @var resource\r
+        */\r
+       protected $resource = null;\r
+\r
+       /**\r
+        * Opens a new ftp connection to given host.\r
+        * \r
+        * @param       string          $host\r
+        * @param       string          $port\r
+        * @param       integer         $timeout\r
+        */\r
+       public function __construct($host = 'localhost', $port = 21, $timeout = 30) {\r
+               $this->resource = ftp_connect($host, $port, $timeout);\r
+               if ($this->resource === false) {\r
+                       throw new SystemException('Can not connect to ' . $host, 11008);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Calls the specified function on the open ftp connection.\r
+        * \r
+        * @param       string          $function\r
+        * @param       array           $arguments\r
+        */\r
+       public function __call($function, $arguments) {\r
+               array_unshift($arguments, $this->resource);\r
+               if (!function_exists('ftp_'.$function)) {\r
+                       throw new SystemException('Can not call method ' . $function, 11003);\r
+               }\r
+               \r
+               return call_user_func_array('ftp_' . $function, $arguments);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/File.class.php b/wcfsetup/install/files/lib/system/io/File.class.php
new file mode 100644 (file)
index 0000000..35591ef
--- /dev/null
@@ -0,0 +1,81 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The File class handles all file operations.\r
+ * \r
+ * Example:\r
+ * using php functions:\r
+ * $fp = fopen('filename', 'wb');\r
+ * fwrite($fp, '...');\r
+ * fclose($fp);\r
+ * \r
+ * using this class:\r
+ * $file = new File('filename');\r
+ * $file->write('...');\r
+ * $file->close();\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class File {\r
+       /**\r
+        * file pointer resource\r
+        * @var resource\r
+        */\r
+       protected $resource = null;\r
+       \r
+       /**\r
+        * filename\r
+        * @var string\r
+        */\r
+       protected $filename = '';\r
+       \r
+       /**\r
+        * Opens a new file.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       string          $mode\r
+        * @param       array           $options\r
+        */\r
+       public function __construct($filename, $mode = 'wb', $options = array()) {\r
+               $this->filename = $filename;\r
+               if (count($options)) {\r
+                       $context = stream_context_create($options);\r
+                       $this->resource = fopen($filename, $mode, false, $context);\r
+               }\r
+               else {\r
+                       $this->resource = fopen($filename, $mode);\r
+               }\r
+               if ($this->resource === false) {\r
+                       throw new SystemException('Can not open file ' . $filename, 11012);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Calls the specified function on the open file.\r
+        * Do not call this function directly. Use $file->write('') instead.\r
+        * \r
+        * @param       string          $function\r
+        * @param       array           $arguments\r
+        */\r
+       public function __call($function, $arguments) {\r
+               if (function_exists('f' . $function)) {\r
+                       array_unshift($arguments, $this->resource);\r
+                       return call_user_func_array('f' . $function, $arguments);\r
+               }\r
+               else if (function_exists($function)) {\r
+                       array_unshift($arguments, $this->filename);\r
+                       return call_user_func_array($function, $arguments);\r
+               }\r
+               else {\r
+                       throw new SystemException('Can not call file method ' . $function, 11003);\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/GZipFile.class.php b/wcfsetup/install/files/lib/system/io/GZipFile.class.php
new file mode 100644 (file)
index 0000000..7060b35
--- /dev/null
@@ -0,0 +1,78 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The File class handles all file operations on a gzip file.\r
+ *  \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class GZipFile extends File {\r
+       /**\r
+        * Opens a gzip file.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       string          $mode\r
+        */\r
+       public function __construct($filename, $mode = 'wb') {\r
+               $this->filename = $filename;\r
+               $this->resource = gzopen($filename, $mode);\r
+               if ($this->resource === false) {\r
+                       throw new SystemException('Can not open file ' . $filename, 11012);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Calls the specified function on the open file.\r
+        * \r
+        * @param       string          $function\r
+        * @param       array           $arguments\r
+        */\r
+       public function __call($function, $arguments) {\r
+               if (function_exists('gz' . $function)) {\r
+                       array_unshift($arguments, $this->resource);\r
+                       return call_user_func_array('gz' . $function, $arguments);\r
+               }\r
+               else if (function_exists($function)) {\r
+                       array_unshift($arguments, $this->filename);\r
+                       return call_user_func_array($function, $arguments);\r
+               }\r
+               else {\r
+                       throw new SystemException('Can not call method ' . $function, 11003);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the filesize of the unzipped file.\r
+        * \r
+        * @return      integer\r
+        */\r
+       public function getFileSize() {\r
+               $byteBlock = 1<<14;\r
+               $eof = $byteBlock;\r
+               \r
+               // the correction is for zip files that are too small \r
+               // to get in the first while loop \r
+               $correction = 1;\r
+               while ($this->seek($eof) == 0) {\r
+                       $eof += $byteBlock;\r
+                       $correction = 0;\r
+               }\r
+               \r
+               while ($byteBlock > 1) {\r
+                       $byteBlock >>= 1;\r
+                       $eof += $byteBlock * ($this->seek($eof) ? -1 : 1);\r
+               }\r
+               \r
+               if ($this->seek($eof) == -1) $eof -= 1;\r
+                               \r
+               $this->rewind();\r
+               return $eof - $correction;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/RemoteFile.class.php b/wcfsetup/install/files/lib/system/io/RemoteFile.class.php
new file mode 100644 (file)
index 0000000..fba2d87
--- /dev/null
@@ -0,0 +1,81 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The RemoteFile class opens a connection to a remote host as a file.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class RemoteFile extends File {\r
+       /**\r
+        * host address\r
+        * @var string\r
+        */\r
+       protected $host = '';\r
+       \r
+       /**\r
+        * port\r
+        * @var integer\r
+        */\r
+       protected $port = 0;\r
+       \r
+       /**\r
+        * error number\r
+        * @var integer\r
+        */\r
+       protected $errorNumber = 0;\r
+       \r
+       /**\r
+        * error description\r
+        * @var string\r
+        */\r
+       protected $errorDesc = '';\r
+       \r
+       /**\r
+        * Opens a new connection to a remote host.\r
+        * \r
+        * @param       string          $host\r
+        * @param       integer         $port\r
+        * @param       integer         $timeout\r
+        * @param       array           $options\r
+        */\r
+       public function __construct($host, $port, $timeout = 30, $options = array()) {\r
+               $this->host = $host;\r
+               $this->port = $port;\r
+               if (count($options)) {\r
+                       $context = stream_context_create($options);\r
+                       $this->resource = fsockopen($host, $port, $this->errorNumber, $this->errorDesc, $timeout, $context);\r
+               }\r
+               else {\r
+                       $this->resource = fsockopen($host, $port, $this->errorNumber, $this->errorDesc, $timeout);\r
+               }\r
+               if ($this->resource === false) {\r
+                       throw new SystemException('Can not connect to ' . $host, 14000);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the error number of the last error.\r
+        * \r
+        * @return      integer\r
+        */\r
+       public function getErrorNumber() {\r
+               return $this->errorNumber;\r
+       }\r
+       \r
+       /**\r
+        * Returns the error description of the last error.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getErrorDesc() {\r
+               return $this->errorDesc;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/Tar.class.php b/wcfsetup/install/files/lib/system/io/Tar.class.php
new file mode 100644 (file)
index 0000000..61a8c80
--- /dev/null
@@ -0,0 +1,322 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\system\exception\SystemException;\r
+use wcf\util\FileUtil;\r
+\r
+/**\r
+ * Opens tar or tar.gz archives.\r
+ * \r
+ * Usage:\r
+ * ------\r
+ * $tar = new Tar('archive.tar');\r
+ * $contentList = $tar->getContentList();\r
+ * foreach ($contentList as $key => $val) {\r
+ *     $tar->extract($key, DESTINATION);\r
+ * }\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class Tar {\r
+       protected $archiveName = '';\r
+       protected $contentList = array();\r
+       protected $opened = false;\r
+       protected $read = false;\r
+       protected $file = null;\r
+       protected $isZipped = false;\r
+       protected $mode = 'rb';\r
+       \r
+       /**\r
+        * Creates a new Tar object.\r
+        * archiveName must be tarball or gzipped tarball\r
+        * \r
+        * @param       string          $archiveName\r
+        */\r
+       public function __construct($archiveName) {\r
+               $match = array();\r
+               if (!is_file($archiveName)) {\r
+                       throw new SystemException("unable to find tar archive '".$archiveName."'", 11002);\r
+               }\r
+               \r
+               $this->archiveName = $archiveName;\r
+               $this->open();\r
+               $this->readContent();\r
+       }\r
+       \r
+       /**\r
+        * Destructor of this class, closes tar archive.\r
+        */\r
+       public function __destruct() {\r
+               $this->close();\r
+       }\r
+       \r
+       /**\r
+        * Opens the tar archive and stores filehandle.\r
+        */\r
+       public function open() {\r
+               if (!$this->opened) {\r
+                       if ($this->isZipped) $this->file = new GZipFile($this->archiveName, $this->mode);\r
+                       else {\r
+                               // test compression\r
+                               $this->file = new File($this->archiveName, $this->mode);\r
+                               if ($this->file->read(2) == "\37\213") {\r
+                                       $this->file->close();\r
+                                       $this->isZipped = true;\r
+                                       $this->file = new GZipFile($this->archiveName, $this->mode);\r
+                               }\r
+                               else {\r
+                                       $this->file->seek(0);\r
+                               }\r
+                       }\r
+                       $this->opened = true;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Closes the opened file.\r
+        */\r
+       public function close() {\r
+               if ($this->opened) {\r
+                       $this->file->close();\r
+                       $this->opened = false;\r
+               }\r
+       }\r
+       \r
+       /** \r
+        * Returns the table of contents (TOC) list for this tar archive.\r
+        * \r
+        * @return      array           list of content\r
+        */\r
+       public function getContentList() {\r
+               if (!$this->read) {\r
+                       $this->open();\r
+                       $this->readContent();\r
+               }\r
+               return $this->contentList;\r
+       }\r
+       \r
+       /**\r
+        * Returns an associative array with information\r
+        * about a specific file in the archive.\r
+        *\r
+        * @param       mixed   $fileindex      index or name of the requested file\r
+        * @return      array   $fileInfo\r
+        */\r
+       public function getFileInfo($fileIndex) {\r
+               if (!is_int($fileIndex)) {\r
+                       $fileIndex = $this->getIndexByFilename($fileIndex);\r
+               }\r
+               \r
+               if (!isset($this->contentList[$fileIndex])) {\r
+                       throw new SystemException("Tar: could find file '".$fileIndex."' in archive", 11013);\r
+               }\r
+               return $this->contentList[$fileIndex];\r
+       }\r
+       \r
+       /**\r
+        * Searchs a file in the tar archive\r
+        * and returns the numeric fileindex.\r
+        * Returns false if not found.\r
+        *\r
+        * @param       string          $filename\r
+        * @return      integer                         index of the requested file\r
+        */\r
+       public function getIndexByFilename($filename) {\r
+               foreach ($this->contentList as $index => $file) {\r
+                       if ($file['filename'] == $filename) {\r
+                               return $index;\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Extracts a specific file and returns the content as string.\r
+        * Returns false if extraction failed.\r
+        * \r
+        * @param       mixed           $index          index or name of the requested file\r
+        * @return      string                          content of the requested file\r
+        */\r
+       public function extractToString($index) {\r
+               if (!$this->read) {\r
+                       $this->open();\r
+                       $this->readContent();\r
+               }\r
+               $header = $this->getFileInfo($index);\r
+               \r
+               // can not extract a folder\r
+               if ($header['type'] != 'file') {\r
+                       return false;\r
+               }\r
+               \r
+               // seek to offset\r
+               $this->file->seek($header['offset']);\r
+               \r
+               // read data\r
+               $content = '';\r
+               $n = floor($header['size'] / 512);\r
+               for ($i = 0; $i < $n; $i++) {\r
+                       $content .= $this->file->read(512);\r
+               }\r
+               if (($header['size'] % 512) != 0) {\r
+                       $buffer = $this->file->read(512);\r
+                       $content .= substr($buffer, 0, ($header['size'] % 512));\r
+               }\r
+               \r
+               return $content;\r
+       }\r
+       \r
+       /**\r
+        * Extracts a specific file and writes it's content\r
+        * to the file specified with $destination.\r
+        * \r
+        * @param       mixed           $index          index or name of the requested file\r
+        * @param       string          $destination\r
+        * @return      boolean         $success\r
+        */\r
+       public function extract($index, $destination) {\r
+               if (!$this->read) {\r
+                       $this->open();\r
+                       $this->readContent();\r
+               }\r
+               $header = $this->getFileInfo($index);\r
+               \r
+               // can not extract a folder\r
+               if ($header['type'] != 'file') {\r
+                       return false;\r
+               }\r
+               \r
+               // seek to offset\r
+               $this->file->seek($header['offset']);\r
+               \r
+               $targetFile = new File($destination);\r
+               \r
+               // read data\r
+               $n = floor($header['size'] / 512);\r
+               for ($i = 0; $i < $n; $i++) {\r
+                       $content = $this->file->read(512);\r
+                       $targetFile->write($content, 512);\r
+               }\r
+               if (($header['size'] % 512) != 0) {\r
+                       $content = $this->file->read(512);\r
+                       $targetFile->write($content, ($header['size'] % 512));\r
+               }\r
+               \r
+               $targetFile->close();\r
+               if (FileUtil::isApacheModule() || !@$targetFile->is_writable()) {\r
+                       @$targetFile->chmod(0777);\r
+               }\r
+               else {\r
+                       @$targetFile->chmod(0755);\r
+               }\r
+               \r
+               if ($header['mtime']) {\r
+                       @$targetFile->touch($header['mtime']);\r
+               }\r
+               \r
+               // check filesize\r
+               if (filesize($destination) != $header['size']) {\r
+                       throw new SystemException("Could not untar file '".$header['filename']."' to '".$destination."'. Maybe disk quota exceeded in folder '".dirname($destination)."'.", 11015);\r
+               }\r
+               \r
+               return true;\r
+       }       \r
+       \r
+       /**\r
+        * Reads table of contents (TOC) from tar archive.\r
+        * This does not get the entire to memory but only parts of it.\r
+        */\r
+       protected function readContent() {\r
+               $this->contentList = array();\r
+               $this->read = true;\r
+               $i = 0;\r
+               \r
+               // Read the 512 bytes header\r
+               while (strlen($binaryData = $this->file->read(512)) != 0) {\r
+                       // read header\r
+                       $header = $this->readHeader($binaryData);\r
+                       if ($header === false) {\r
+                               continue;       \r
+                       }\r
+                       $this->contentList[$i] = $header;\r
+                       $this->contentList[$i]['index'] = $i;\r
+                       $i++;\r
+                       \r
+                       $this->file->seek($this->file->tell() + (512 * ceil(($header['size'] / 512))));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Unpacks file header for one file entry.\r
+        *\r
+        * @param       string          $binaryData\r
+        * @return      array           $fileheader\r
+        */\r
+       protected function readHeader($binaryData) {\r
+               if (strlen($binaryData) != 512) {\r
+                       return false;   \r
+               }\r
+\r
+               $header = array();\r
+               $checksum = 0;\r
+               // First part of the header\r
+               for ($i = 0; $i < 148; $i++) {\r
+                       $checksum += ord(substr($binaryData, $i, 1));\r
+               }\r
+               // Calculate the checksum\r
+               // Ignore the checksum value and replace it by ' ' (space)\r
+               for ($i = 148; $i < 156; $i++) {\r
+                       $checksum += ord(' ');\r
+               }\r
+               // Last part of the header\r
+               for ($i = 156; $i < 512; $i++) {\r
+                       $checksum += ord(substr($binaryData, $i, 1));\r
+               }\r
+\r
+               // Extract the values\r
+               //$data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $binaryData);\r
+               $data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $binaryData);\r
+               \r
+               // Extract the properties\r
+               $header['checksum'] = octDec(trim($data['checksum']));\r
+               if ($header['checksum'] == $checksum) {\r
+                       $header['filename'] = trim($data['filename']);\r
+                       $header['mode'] = octDec(trim($data['mode']));\r
+                       $header['uid'] = octDec(trim($data['uid']));\r
+                       $header['gid'] = octDec(trim($data['gid']));\r
+                       $header['size'] = octDec(trim($data['size']));\r
+                       $header['mtime'] = octDec(trim($data['mtime']));\r
+                       $header['prefix'] = trim($data['prefix']);\r
+                       if ($header['prefix']) {\r
+                               $header['filename'] = $header['prefix'].'/'.$header['filename'];\r
+                       }\r
+                       if (($header['typeflag'] = $data['typeflag']) == '5') {\r
+                               $header['size'] = 0;\r
+                               $header['type'] = 'folder';\r
+                       }\r
+                       else {\r
+                               $header['type'] = 'file';\r
+                       }\r
+                       $header['offset'] = $this->file->tell();\r
+                       \r
+                       return $header;\r
+               }\r
+               else {\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if this tar is (g)zipped.\r
+        * \r
+        * @return      boolean\r
+        */\r
+       public function isZipped() {\r
+               return $this->isZipped;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/TarWriter.class.php b/wcfsetup/install/files/lib/system/io/TarWriter.class.php
new file mode 100644 (file)
index 0000000..31aadcd
--- /dev/null
@@ -0,0 +1,272 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\system\exception\SystemException;\r
+use wcf\util\FileUtil;\r
+\r
+/**\r
+ * Creates a tar file archive.\r
+ * \r
+ * Usage:\r
+ * ------\r
+ * $tar = new TarWriter('archive.tar', true);\r
+ * $tar->add(array('file1', 'file2'));\r
+ * $tar->create();\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class TarWriter extends Tar {\r
+       protected $mode = 'wb+';\r
+       \r
+       /**\r
+        * Creates a new TarWriter object.\r
+        * \r
+        * @param       string          $archiveName\r
+        * @param       boolean         $compress       enables gzip compression\r
+        */\r
+       public function __construct($archiveName, $compress = false) {\r
+               $this->archiveName = $archiveName;\r
+               $this->isZipped = $compress;\r
+               if ($compress) $this->mode = 'wb9'; // set compression level\r
+               $this->open();\r
+       }\r
+       \r
+       /**\r
+        * Writes the last 0 filled block for end of archive.\r
+        */\r
+       protected function writeFooter() {\r
+               $this->file->write(pack('a512', ''));\r
+       }\r
+       \r
+       /**\r
+        * Creates the tar archive.\r
+        */\r
+       public function create() {\r
+               $this->writeFooter();\r
+               $this->close();\r
+       }\r
+       \r
+       /**\r
+        * Adds a string to the tar archive.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       string          $string         file content\r
+        * @return      boolean         result\r
+        */\r
+       public function addString($filename, $string) {\r
+               if (empty($filename)) return false;\r
+               \r
+               $filename = FileUtil::unifyDirSeperator($filename);\r
+\r
+               if (!$this->writeHeaderBlock($filename, strlen($string), TIME_NOW, 33279)) {\r
+                       return false;\r
+               }\r
+\r
+               $i = 0;\r
+               while (($buffer = substr($string, (($i++) * 512), 512)) != '') {\r
+                       $this->file->write(pack("a512", $buffer));\r
+               }\r
+\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Adds a list of files or directories to the tar archive.\r
+        * \r
+        * @param       mixed           $files\r
+        * @param       string          $addDir\r
+        * @param       string          $removeDir\r
+        * @return      boolean         result\r
+        */\r
+       public function add($files, $addDir = '', $removeDir = '') {\r
+               if (!is_array($files)) $files = array($files);\r
+               if (!count($files)) return false;\r
+               \r
+               $result = true;\r
+               \r
+               // unify dir seperator\r
+               $addDir = FileUtil::unifyDirSeperator($addDir);\r
+               $removeDir = FileUtil::unifyDirSeperator($removeDir);\r
+\r
+               foreach ($files as $filename) {\r
+                       if (!$result) {\r
+                               break;\r
+                       }\r
+\r
+                       if (!$filename || $filename == $this->archiveName) {\r
+                               continue;\r
+                       }\r
+\r
+                       if (!file_exists($filename)) {\r
+                               throw new SystemException("Unable to find file '".$filename."'", 11002);\r
+                       }\r
+\r
+                       // add file\r
+                       if (!$this->addFile($filename, $addDir, $removeDir)) {\r
+                               return false;\r
+                       }\r
+\r
+                       // handle directories\r
+                       if (@is_dir($filename)) {\r
+                               $handle = opendir($filename);\r
+\r
+                               while (($dirFile = readdir($handle)) !== false) {\r
+                                       if (($dirFile != '.') && ($dirFile != '..')) {\r
+                                               if ($filename != ".") $dirFile = $filename.'/'.$dirFile;\r
+                                               $result = $this->add($dirFile, $addDir, $removeDir);\r
+                                       }\r
+                               }\r
+                               \r
+                               closedir($handle);\r
+                       }\r
+               }\r
+\r
+               return $result;\r
+       }\r
+\r
+       /**\r
+        * Adds a file to the tar archive.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       string          $addDir\r
+        * @param       string          $removeDir\r
+        * @return      boolean         result\r
+        */\r
+       protected function addFile($filename, $addDir, $removeDir) {\r
+               $filename = FileUtil::unifyDirSeperator($filename);\r
+               $storedFilename = $filename;\r
+               if (!empty($removeDir)) $storedFilename = StringUtil::replaceIgnoreCase($removeDir, '', $filename);\r
+               if (!empty($addDir)) $storedFilename = $addDir . $storedFilename;\r
+               if (is_file($filename)) {\r
+                       // open file\r
+                       $file = new File($filename, 'rb');\r
+                       \r
+                       // write header\r
+                       if (!$this->writeFileHeader($filename, $storedFilename)) {\r
+                               return false;\r
+                       }\r
+                       \r
+                       // write file content\r
+                       while (($buffer = $file->read(512)) != '') {\r
+                               $this->file->write(pack('a512', $buffer));\r
+                       }\r
+                       \r
+                       // close file\r
+                       $file->close();\r
+               }\r
+               else {\r
+                       // only directory header\r
+                       if (!$this->writeFileHeader($filename, $storedFilename)) {\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Writes the file header.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       string          $storedFilename\r
+        * @return      boolean         result\r
+        */\r
+       protected function writeFileHeader($filename, $storedFilename) {\r
+               $fileInfo = stat($filename);\r
+               $permissions = fileperms($filename);\r
+               $mtime = filemtime($filename);\r
+               if (@is_dir($filename)) {\r
+                       $typeFlag = '5';\r
+                       $size = 0;\r
+               }\r
+               else {\r
+                       $typeFlag = '';\r
+                       clearstatcache();\r
+                       $size = filesize($filename);\r
+               }\r
+               \r
+               return $this->writeHeaderBlock($storedFilename, $size, $mtime, $permissions, $typeFlag, $fileInfo[4], $fileInfo[5]);\r
+       }\r
+       \r
+       /**\r
+        * Writes header block.\r
+        * \r
+        * @param       string          $filename\r
+        * @param       integer         $size\r
+        * @param       integer         $mtime\r
+        * @param       integer         $permissions\r
+        * @param       string          $typeFlag\r
+        * @param       integer         $uid\r
+        * @param       integer         $gid\r
+        * @return      boolean         result\r
+        */\r
+       public function writeHeaderBlock($filename, $size, $mtime = 0, $permissions = 0, $typeFlag = '', $uid = 0, $gid = 0) {\r
+               if (strlen($filename) > 99) {\r
+                       if (!$this->writeLongHeaderBlock($filename)) {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               if ($typeFlag == "5") {\r
+                       $size = sprintf("%11s ", decOct(0));\r
+               }\r
+               else {\r
+                       $size = sprintf("%11s ", decOct($size));\r
+               }\r
+\r
+               $uid = sprintf("%6s ", decOct($uid));\r
+               $gid = sprintf("%6s ", decOct($gid));\r
+               $permissions = sprintf("%6s ", decOct($permissions));\r
+               $mtime = sprintf("%11s", decOct($mtime));\r
+\r
+               $binaryDataFirst = pack('a100a8a8a8a12A12', $filename, $permissions, $uid, $gid, $size, $mtime);\r
+               $binaryDataLast = pack('a1a100a6a2a32a32a8a8a155a12', $typeFlag, '', '', '', '', '', '', '', '', '');\r
+\r
+               // calculate the checksum\r
+               $checksum = 0;\r
+               for ($i = 0; $i < 148; $i++) $checksum += ord(substr($binaryDataFirst, $i, 1));\r
+               for ($i = 148; $i < 156; $i++) $checksum += ord(' ');\r
+               for ($i = 156, $j = 0; $i < 512; $i++, $j++) $checksum += ord(substr($binaryDataLast, $j, 1));\r
+               \r
+               $this->file->write($binaryDataFirst, 148);\r
+               $this->file->write(pack("a8", sprintf("%6s ", decOct($checksum))), 8); // write the checksum\r
+               $this->file->write($binaryDataLast, 356);\r
+       \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Writes a long header block.\r
+        * \r
+        * @param       string          $filename\r
+        * @return      boolean\r
+        */\r
+       protected function writeLongHeaderBlock($filename) {\r
+               $size = sprintf("%11s ", decOct(strlen($filename)));\r
+               $typeFlag = 'L';\r
+               $binaryDataFirst = pack("a100a8a8a8a12A12", '././@LongLink', 0, 0, 0, $size, 0);\r
+               $binaryDataLast = pack("a1a100a6a2a32a32a8a8a155a12", $typeFlag, '', '', '', '', '', '', '', '', '');\r
+\r
+               // calculate the checksum\r
+               $checksum = 0;\r
+               for ($i = 0; $i < 148; $i++) $checksum += ord(substr($binaryDataFirst, $i, 1));\r
+               for ($i = 148; $i < 156; $i++) $checksum += ord(' ');\r
+               for ($i = 156, $j = 0; $i < 512; $i++, $j++) $checksum += ord(substr($binaryDataLast, $j, 1));\r
+\r
+               $this->file->write($binaryDataFirst, 148);\r
+               $this->file->write(pack("a8", sprintf("%6s ", decOct($checksum))), 8); // write the checksum\r
+               $this->file->write($binaryDataLast, 356);\r
+\r
+               $i = 0;\r
+               while (($buffer = substr($filename, (($i++) * 512), 512)) != '') {\r
+                       $this->file->write(pack("a512", $buffer));\r
+               }\r
+\r
+               return true;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/io/ZipWriter.class.php b/wcfsetup/install/files/lib/system/io/ZipWriter.class.php
new file mode 100644 (file)
index 0000000..321b71b
--- /dev/null
@@ -0,0 +1,213 @@
+<?php\r
+namespace wcf\system\io;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Creates a Zip file archive.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.io\r
+ * @category   Community Framework\r
+ */\r
+class ZipWriter {\r
+       protected $headers = array();\r
+       protected $data = array();\r
+       protected $endOfData = "\x50\x4b\x05\x06\x00\x00\x00\x00";\r
+       protected $lastOffset = 0;\r
+\r
+       /**\r
+        * Adds a folder to the Zip archive.\r
+        * \r
+        * @param       string          $name           dirname\r
+        */\r
+       public function addDir($name) {\r
+               // replace backward slashes with forward slashes in the dirname\r
+               $name = StringUtil::replace("\\", "/", $name);\r
+\r
+               // construct the general header information for the directory\r
+               $header = "\x50\x4b\x03\x04";\r
+               $header .= "\x0a\x00\x00\x00";\r
+               $header .= "\x00\x00\x00\x00";\r
+               $header .= "\x00\x00";\r
+\r
+               // construct the directory header specific information\r
+               $header .= pack("V", 0);\r
+               $header .= pack("V", 0);\r
+               $header .= pack("V", 0);\r
+               $header .= pack("v", strlen($name));\r
+               $header .= pack("v", 0);\r
+               $header .= $name;\r
+               $header .= pack("V", 0);\r
+               $header .= pack("V", 0);\r
+               $header .= pack("V", 0);\r
+\r
+               // store the complete header information into the $headers array\r
+               $this->headers[] = $header;\r
+\r
+               // calculate the new offset that will be used the next time a segment is added\r
+               $newOffset = strlen(implode('', $this->headers));\r
+\r
+               // construct the general header for the central index record\r
+               $record = "\x50\x4b\x01\x02";\r
+               $record .= "\x00\x00\x0a\x00";\r
+               $record .= "\x00\x00\x00\x00";\r
+               $record .= "\x00\x00\x00\x00";\r
+               $record .= pack("V", 0);\r
+               $record .= pack("V", 0);\r
+               $record .= pack("V", 0);\r
+               $record .= pack("v", strlen($name));\r
+               $record .= pack("v", 0);\r
+               $record .= pack("v", 0);\r
+               $record .= pack("v", 0);\r
+               $record .= pack("v", 0);\r
+               //$ext = "\x00\x00\x10\x00";\r
+               //$ext = "\xff\xff\xff\xff";\r
+               $record .= pack("V", 16 );\r
+               $record .= pack("V", $this->lastOffset);\r
+               $record .= $name;\r
+\r
+               // save the central index record in the array $data\r
+               $this->data[] = $record;\r
+               $this->lastOffset = $newOffset;\r
+       }\r
+\r
+       /**\r
+        * Adds a file to the Zip archive.\r
+        * \r
+        * @param       string          $data           content of the file\r
+        * @param       string          $name           filename\r
+        * @param       integer         $date           file creation time as unix timestamp\r
+        */\r
+       public function addFile($data, $name, $date = 0) {\r
+               // replace backward slashes with forward slashes in the filename\r
+               $name = StringUtil::replace("\\", "/", $name);\r
+               \r
+               // calculate the size of the file being uncompressed\r
+               $sizeUncompressed = strlen($data);\r
+               \r
+               // get data checksum\r
+               $crc = crc32($data);\r
+               \r
+               // compress the file data\r
+               $compressedData = gzcompress($data);\r
+               \r
+               // calculate the size of the file being compressed\r
+               $compressedData = substr($compressedData, 2, - 4);\r
+               $sizeCompressed = strlen($compressedData);\r
+\r
+               // construct the general header for the file record complete with checksum information, etc.\r
+               $header = "\x50\x4b\x03\x04";\r
+               $header .= "\x14\x00\x00\x00";\r
+               $header .= "\x08\x00\x00\x00";\r
+               $header .= "\x00\x00";\r
+               $header .= pack("V", $crc);\r
+               $header .= pack("V", $sizeCompressed);\r
+               $header .= pack("V", $sizeUncompressed);\r
+               $header .= pack("v", strlen($name));\r
+               $header .= pack("v", 0);\r
+               $header .= $name;\r
+               \r
+               // store the compressed data immediately following the file header\r
+               $header .= $compressedData;\r
+               \r
+               // complete the file record by adding an additional footer directly following the file data\r
+               //$header .= pack("V", $crc);\r
+               //$header .= pack("V", $sizeCompressed);\r
+               //$header .= pack("V", $sizeUncompressed);\r
+\r
+               // store the completed file record in the $headers array\r
+               $this->headers[] = $header;\r
+\r
+               // calculate the new offset for the central index record\r
+               $newOffset = strlen(implode('', $this->headers));\r
+               \r
+               // construct the record\r
+               $record = "\x50\x4b\x01\x02";\r
+               $record .= "\x00\x00\x14\x00";\r
+               $record .= "\x00\x00\x08\x00";\r
+               $record .= $this->getDosDatetime($date);\r
+               $record .= pack("V", $crc);\r
+               $record .= pack("V", $sizeCompressed);\r
+               $record .= pack("V", $sizeUncompressed);\r
+               $record .= pack("v", strlen($name));\r
+               $record .= pack("v", 0);\r
+               $record .= pack("v", 0);\r
+               $record .= pack("v", 0);\r
+               $record .= pack("v", 0);\r
+               $record .= pack("V", 32);\r
+               $record .= pack("V", $this->lastOffset);\r
+\r
+               // update the offset for the next record to be stored\r
+               $this->lastOffset = $newOffset;\r
+\r
+               $record .= $name;\r
+\r
+               // store the record in the $data array\r
+               $this->data[] = $record;\r
+       }\r
+\r
+       /**\r
+        * Constructs the final Zip file structure and return it.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getFile() {\r
+               // implode the $headers array into a single string\r
+               $headers = implode('', $this->headers);\r
+               \r
+               // implode the $data array into a single string\r
+               $data = implode('', $this->data);\r
+\r
+               // construct the final Zip file structure and return it\r
+               return\r
+                       $headers.\r
+                       $data.\r
+                       $this->endOfData.\r
+                       pack("v", sizeof($this->data)).\r
+                       pack("v", sizeof($this->data)).\r
+                       pack("V", strlen($data)).\r
+                       pack("V", strlen($headers)).\r
+                       "\x00\x00";\r
+       }\r
+       \r
+       /**\r
+        * Converts an unix timestamp to Zip file time.\r
+        * \r
+        * @param       integer         $date           unix timestamp\r
+        * @return      string\r
+        */\r
+       protected static function getDosDatetime($date = 0) {\r
+               $day = gmdate('d', $date);\r
+               $month = gmdate('m', $date);\r
+               $year = gmdate('Y', $date);\r
+               $year -= 1980;\r
+               $hour = gmdate('H', $date);\r
+               $minute = gmdate('i', $date);\r
+               $second = gmdate('s', $date);\r
+               \r
+               // calculate time\r
+               $time = $hour;\r
+               $time = ($time << 6) + $minute;\r
+               $time = ($time << 5) + number_format($second / 2, 0);\r
+               $timeRight = $time >> 8;\r
+               $timeLeft = $time - ($timeRight << 8);\r
+               \r
+               // calculate date\r
+               $date = $year;\r
+               $date = ($date << 4) + $month;\r
+               $date = ($date << 5) + $day;\r
+               $dateRight = $date >> 8;\r
+               $dateLeft = $date - ($dateRight << 8);\r
+               \r
+               $timeLeft = sprintf("%02x", $timeLeft);\r
+               $timeRight = sprintf("%02x", $timeRight);\r
+               $dateLeft = sprintf("%02x", $dateLeft);\r
+               $dateRight = sprintf("%02x", $dateRight);\r
+               \r
+               return pack("H*H*H*H*", $timeLeft, $timeRight, $dateLeft, $dateRight);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/language/LanguageFactory.class.php b/wcfsetup/install/files/lib/system/language/LanguageFactory.class.php
new file mode 100644 (file)
index 0000000..8273b31
--- /dev/null
@@ -0,0 +1,358 @@
+<?php
+namespace wcf\system\language;
+use wcf\data\language\Language;
+use wcf\system\cache\CacheHandler;
+use wcf\system\template\TemplateScriptingCompiler;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Handles language related functions.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.language
+ * @category   Community Framework
+ */
+abstract class LanguageFactory {
+       /**
+        * Language cache.
+        *
+        * @var array<array>
+        */
+       private static $cache = null;
+       
+       /**
+        * Initialized languages.
+        *
+        * @var array<Language>
+        */
+       private static $languages = array();
+       
+       /**
+        * Active template scripting compiler
+        *
+        * @var TemplateScriptingCompiler
+        */
+       private static $scriptingCompiler = null;
+       
+       /**
+        * Returns a Language-object for each requested language id.
+        *
+        * @param       integer         $languageID
+        * @return      Language
+        */
+       public static function getLanguage($languageID) {
+               if (self::$cache === null) self::loadCache();
+               
+               if (!isset(self::$languages[$languageID])) {
+                       $language = new Language($languageID);
+                       
+                       if (!$language->languageID) {
+                               $languageID = self::findPreferredLanguage();
+                               $language = new Language($languageID);
+                       }
+                       
+                       self::$languages[$language->languageID] = $language;
+                       self::defineConstants($languageID);
+               }
+               
+               return self::$languages[$languageID];
+       }
+       
+       /**
+        * Validates if given category is known.
+        *
+        * @param       string          $category
+        * @return      boolean
+        */
+       public static function isValidCategory($category) {
+               self::loadCache();
+               
+               return (isset(self::$cache['categories'][$category])) ? true : false;
+       }
+       
+       /**
+        * Returns data for a specific category.
+        *
+        * @param       string          $category
+        * @return      array
+        */
+       public static function getCategory($category) {
+               if (isset(self::$cache['categories'][$category])) {
+                       return self::$cache['categories'][$category];
+               }
+               
+               return array();
+       }
+       
+       /**
+        * Returns a list of available language categories.
+        * 
+        * @return      array
+        */     
+       public static function getCategories() {
+               $categories = array();
+               foreach (self::$cache['categories'] as $categoryName => $category) {
+                       $categories[$category['languageCategoryID']] = $categoryName;
+               }
+               
+               return $categories;
+       }
+       
+       /**
+        * Searches the preferred language of the current user.
+        */
+       private static function findPreferredLanguage() {
+               // get available language codes
+               $availableLanguageCodes = array();
+               foreach (self::getAvailableLanguages(PACKAGE_ID) as $language) {
+                       $availableLanguageCodes[] = $language['languageCode'];
+               }
+               
+               // get default language
+               $defaultLanguageCode = self::$cache['languages'][self::$cache['default']]['languageCode'];
+               
+               // get preferred language
+               $languageCode = self::getPreferredLanguage($availableLanguageCodes, $defaultLanguageCode);
+               
+               // get language id of preferred language
+               foreach (self::$cache['languages'] as $key => $language) {
+                       if ($language['languageCode'] == $languageCode) {
+                               return $key;
+                       }
+               }
+       }
+       
+       /**
+        * Determines the preferred language of the current user.
+        *
+        * @param       array           $availableLanguages
+        * @param       string          $defaultLanguageCode
+        * @return      string
+        */
+       public static function getPreferredLanguage($availableLanguageCodes, $defaultLanguageCode) {
+               if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && $_SERVER['HTTP_ACCEPT_LANGUAGE']) {
+                       $acceptedLanguages = explode(',', str_replace('_', '-', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])));
+                       foreach ($acceptedLanguages as $acceptedLanguage) {
+                               foreach ($availableLanguageCodes as $availableLanguageCode) {
+                                       $fixedCode = strtolower(self::fixLanguageCode($availableLanguageCode));
+                                       
+                                       if ($fixedCode == $acceptedLanguage || $fixedCode == preg_replace('%^([a-z]{2}).*$%i', '$1', $acceptedLanguage)) {
+                                               return $availableLanguageCode;
+                                       }
+                               }
+                       }
+               }
+               
+               return $defaultLanguageCode;
+       }
+       
+       /**
+        * Returns all available languages for given package
+        *
+        * @param       integer         $packageID
+        * @return      array           $availableLanguages     infos about each language (code, id, encoding, etc)
+        */
+       public static function getAvailableLanguages($packageID = PACKAGE_ID) {
+               // get list of all available languages
+               $availableLanguages = array();
+               if (isset(self::$cache['packages'][$packageID])) {
+                       foreach (self::$cache['packages'][$packageID] as $availableLanguageID) {
+                               $availableLanguages[] = self::$cache['languages'][$availableLanguageID];
+                       }
+               }
+               return $availableLanguages;
+       }
+       
+       /**
+        * Returns an instance of Language or NULL for a given language code.
+        *
+        * @param       string          $languageCode
+        * @return      Language
+        */
+       public static function getLanguageByCode($languageCode) {
+               if (self::$cache === null) self::loadCache();
+               
+               // called within WCFSetup
+               if (self::$cache === false || !count(self::$cache['codes'])) {
+                       $sql = "SELECT  languageID
+                               FROM    wcf".WCF_N."_language
+                               WHERE   languageCode = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($languageCode));
+                       $row = $statement->fetchArray();
+                       if (isset($row['languageID'])) return new Language($row['languageID']);
+               }
+               else if (isset(self::$cache['codes'][$languageCode])) {
+                       return self::getLanguage(self::$cache['codes'][$languageCode]);
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Returns the active scripting compiler object.
+        *
+        * @return      TemplateScriptingCompiler
+        */
+       public static function getScriptingCompiler() {
+               if (self::$scriptingCompiler === null) {
+                       self::$scriptingCompiler = new TemplateScriptingCompiler(WCF::getTPL());
+               }
+               
+               return self::$scriptingCompiler;
+       }
+       
+       /**
+        * Loads the language cache.
+        */
+       private static function loadCache() {
+               if (self::$cache === null) {
+                       CacheHandler::getInstance()->addResource(
+                               'languages',
+                               WCF_DIR.'cache/cache.languages.php',
+                               'wcf\system\cache\CacheBuilderLanguage'
+                       );
+                       
+                       self::$cache = CacheHandler::getInstance()->get('languages');
+               }
+       }
+       
+       /**
+        * Clears languages cache.
+        */
+       public static function clearCache() {
+               self::$cache = null;
+               
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache/', 'cache.languages.php');
+       }
+       
+       /**
+        * Defines all global constants once first language is being initialized.
+        *
+        * @param       integer         $languageID
+        */
+       private static function defineConstants($languageID) {
+               if (!defined('LANGUAGE_CODE')) {
+                       define('LANGUAGE_CODE', self::fixLanguageCode(self::$languages[$languageID]->languageCode));
+                       mb_internal_encoding('UTF-8');
+                       if (function_exists('mb_regex_encoding')) mb_regex_encoding('UTF-8');
+                       mb_language('uni');
+               }
+               
+               self::setLocale($languageID);
+       }
+       
+       /**
+        * Sets the local language.
+        * Recall this function after language changed.
+        *
+        * @param       integer         $languageID
+        */
+       private static function setLocale($languageID) {
+               // set locale for
+               // string comparison
+               // character classification and conversion
+               // date and time formatting
+               if (!defined('PAGE_DIRECTION')) define('PAGE_DIRECTION', self::$languages[$languageID]->get('wcf.global.pageDirection'));
+               setlocale(LC_COLLATE, self::$languages[$languageID]->get('wcf.global.locale.unix').'.UTF-8', self::$languages[$languageID]->get('wcf.global.locale.unix'), self::$languages[$languageID]->get('wcf.global.locale.win'));
+               setlocale(LC_CTYPE, self::$languages[$languageID]->get('wcf.global.locale.unix').'.UTF-8', self::$languages[$languageID]->get('wcf.global.locale.unix'), self::$languages[$languageID]->get('wcf.global.locale.win'));
+       }
+       
+       /**
+        * Removes additional language identifier from given language code.
+        * Converts e.g. 'de-informal' to 'de'.
+        *
+        * @param       string          $languageCode
+        * @return      string          $languageCode
+        */
+       public static function fixLanguageCode($languageCode) {
+               return preg_replace('/-[a-z0-9]+/', '', $languageCode);
+       }
+       
+       /**
+        * Returns the default language id
+        *
+        * @return      integer
+        */
+       public static function getDefaultLanguageID() {
+               return self::$cache['default'];
+       }
+       
+       /**
+        * Returns all available content languages for given package.
+        *
+        * @param       integer         $packageID
+        * @return      array           $availableLanguages     infos about each language (code, id, encoding, etc)
+        */
+       public static function getAvailableContentLanguages($packageID = PACKAGE_ID) {
+               $availableLanguages = array();
+               if (isset(self::$cache['packages'][$packageID])) {
+                       foreach (self::$cache['packages'][$packageID] as $availableLanguageID) {
+                               if (self::$cache['languages'][$availableLanguageID]['hasContent']) {
+                                       $availableLanguages[$availableLanguageID] = self::$cache['languages'][$availableLanguageID];
+                               }
+                       }
+               }
+               return $availableLanguages;
+       }
+       
+       /**
+        * Makes given language the default language.
+        *
+        * @param       integer         $languageID
+        */
+       public static function makeDefault($languageID) {
+               // remove old default language
+               $sql = "UPDATE  wcf".WCF_N."_language
+                       SET     isDefault = 0
+                       WHERE   isDefault = 1";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               
+               // make this language to default
+               $sql = "UPDATE  wcf".WCF_N."_language
+                       SET     isDefault = 1
+                       WHERE   languageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($languageID));
+               
+               // rebuild language cache
+               self::clearCache();
+       }
+       
+       /**
+        * Returns an ordered list of all installed languages.
+        * 
+        * @return      array
+        */     
+       public static function getLanguages() {
+               $languages = array();
+               foreach (self::$cache['codes'] as $languageCode => $languageID) {
+                       $languages[$languageID] = WCF::getLanguage()->getDynamicVariable('wcf.global.language.'.$languageCode);
+               }
+               
+               StringUtil::sort($languages);
+               
+               return $languages;
+       }
+       
+       /**
+        * Returns a sorted list of all installed language codes.
+        * 
+        * @return      array
+        */
+       public static function getLanguageCodes() {
+               $languages = array();
+               foreach (self::$cache['codes'] as $languageCode => $languageID) {
+                       $languages[$languageID] = $languageCode;
+               }
+               
+               StringUtil::sort($languages);
+               return $languages;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/mail/DebugMailSender.class.php b/wcfsetup/install/files/lib/system/mail/DebugMailSender.class.php
new file mode 100644 (file)
index 0000000..969e664
--- /dev/null
@@ -0,0 +1,47 @@
+<?php\r
+namespace wcf\system\mail;\r
+use wcf\sytem\io\File;\r
+\r
+/**\r
+ * DebugMailSender is a debug implementation of mailsender.\r
+ * It writes e-mails in a log file.\r
+ * \r
+ * @author     Michael Schaefer\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.mail\r
+ * @category   Community Framework\r
+ */\r
+class DebugMailSender extends MailSender {\r
+       protected $log = null;\r
+       \r
+       /**\r
+        * Writes the given e-mail in a log file.\r
+        * \r
+        * @param       Mail    $mail\r
+        */\r
+       public function sendMail(Mail $mail) {\r
+               if ($this->log === null) {\r
+                       $this->log = new File(MAIL_DEBUG_LOGFILE_PATH.'mail.log', 'ab');\r
+               }\r
+               \r
+               $this->log->write($this->printMail($mail));\r
+       }\r
+       \r
+       /**\r
+        * Prints the given mail.\r
+        * \r
+        * @param       Mail    $mail\r
+        * @return      string\r
+        */\r
+       protected static function printMail(Mail $mail) {\r
+               return  "Date: ".gmdate('r')."\n".\r
+                       "To: ".$mail->getToString()."\n".\r
+                       "Subject: ".$mail->getSubject()."\n".\r
+                       $mail->getHeader()."\n".\r
+                       "Attachments: ".print_r($mail->getAttachments(), true)."\n\n".\r
+                       $mail->getMessage()."\n\n";\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/mail/Mail.class.php b/wcfsetup/install/files/lib/system/mail/Mail.class.php
new file mode 100644 (file)
index 0000000..5929467
--- /dev/null
@@ -0,0 +1,460 @@
+<?php\r
+namespace wcf\system\mail;\r
+use wcf\util\FileUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * This class represents an e-mail.\r
+ * \r
+ * @author     Michael Schaefer\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.mail\r
+ * @category   Community Framework\r
+ */\r
+class Mail {\r
+       protected $header = '';\r
+       protected $boundary;\r
+       protected $contentType = "text/plain";\r
+       protected $to;\r
+       protected $subject;\r
+       protected $message;\r
+       protected $from;\r
+       protected $cc;\r
+       protected $bcc;\r
+       protected $attachments = array();\r
+       protected $priority;\r
+       protected $body;\r
+       \r
+       public static $crlf = "\n";\r
+\r
+       /**\r
+        * Creates a new Mail object.\r
+        * \r
+        * @param       string          $to\r
+        * @param       string          $subject\r
+        * @param       string          $message\r
+        * @param       string          $from\r
+        * @param       string          $cc\r
+        * @param       string          $bcc\r
+        * @param       array           $attachments\r
+        * @param       integer         $priority\r
+        * @param       string          $header\r
+        */\r
+       public function __construct($to = '', $subject = '', $message = '', $from = '', $cc = '', $bcc = '', $attachments = array(), $priority = '', $header = '') {\r
+               $this->setBoundary();\r
+               \r
+               if (empty($from))       $from           = array(MAIL_FROM_NAME => MAIL_FROM_ADDRESS);\r
+               if (empty($priority))   $priority       = 3;\r
+                       \r
+               $this->setFrom($from);\r
+               $this->setSubject($subject);\r
+               $this->setMessage($message);\r
+               $this->setPriority($priority);\r
+               $this->setHeader($header);\r
+               \r
+               if (!empty($to))        $this->addTo($to);\r
+               if (!empty($cc))        $this->addCC($cc);\r
+               if (!empty($bcc))       $this->addBCC($bcc);\r
+               \r
+               if (count($attachments) > 0) $this->setAttachments($attachments);\r
+       }\r
+       \r
+       /**\r
+        * Creates a Basic Header for the Mail\r
+        * Returns this Header to the function which invoke this class\r
+        * \r
+        * @return      string          mail header\r
+        */\r
+       public function getHeader() {\r
+               if (!empty($this->header)) {\r
+                       $this->header = preg_replace('%(\r\n|\r|\n)%', self::$crlf, $this->header);\r
+               }\r
+               \r
+               $this->header .=\r
+                       'X-Priority: 3'.self::$crlf\r
+                       .'X-Mailer: WoltLab Community Framework Mail Package'.self::$crlf                                                                       \r
+                       .'MIME-Version: 1.0'.self::$crlf\r
+                       .'From: '.$this->getFrom().self::$crlf\r
+                       .($this->getCCString() != '' ? 'CC:'.$this->getCCString().self::$crlf : '')\r
+                       .($this->getBCCString() != '' ? 'BCC:'.$this->getBCCString().self::$crlf : '');                                 \r
+                       \r
+               if (count($this->getAttachments())) {\r
+                       $this->header .= 'Content-Transfer-Encoding: 8bit'.self::$crlf;\r
+                       $this->header .= 'Content-Type: multipart/mixed;'.self::$crlf;\r
+                       $this->header .= "\tboundary=".'"'.$this->getBoundary().'";'.self::$crlf;\r
+               }\r
+               else {\r
+                       $this->header .= 'Content-Transfer-Encoding: 8bit'.self::$crlf;\r
+                       $this->header .= 'Content-Type: '.$this->getContentType().'; charset=UTF-8'.self::$crlf;\r
+               }\r
+               \r
+               return $this->header;\r
+       }\r
+       \r
+       /**\r
+        * Creates the Recipients List (To, CC, BCC) \r
+        * Returns this List to the function which invoke this class\r
+        * \r
+        * @param       boolean         $withTo\r
+        * @return      string\r
+        */\r
+       public function getRecipients($withTo = false) {\r
+               $recipients = '';\r
+               if ($withTo && $this->getToString() != '') $recipients .= 'TO:'.$this->getToString().self::$crlf;\r
+               if ($this->getCCString() != '') $recipients .= 'CC:'.$this->getCCString().self::$crlf;\r
+               if ($this->getBCCString() != '') $recipients .= 'BCC:'.$this->getBCCString().self::$crlf;\r
+               return $recipients;     \r
+       }\r
+       \r
+       /**\r
+        * Creates the Body (Message, Attachments) for the Mail\r
+        * Returns the created Body to the function which invoke this class\r
+        * \r
+        * @return      string          mail body\r
+        */\r
+       public function getBody() {\r
+               $counter = 1;\r
+               $this->body = '';\r
+\r
+               if (count($this->getAttachments())) {\r
+                       // add message\r
+                       $this->body     .= '--'.$this->getBoundary().self::$crlf;\r
+                       $this->body     .= 'Content-Type: '.$this->getContentType().'; charset="UTF-8"'.self::$crlf;\r
+                       $this->body     .= 'Content-Transfer-Encoding: 8bit'.self::$crlf;\r
+                       //$this->body   .= self::$crlf.self::$crlf;\r
+                       $this->body     .= self::$crlf;\r
+                       \r
+                       // wrap lines after 70 characters\r
+                       $this->body     .= wordwrap($this->getMessage(), 70); \r
+                       $this->body     .= self::$crlf.self::$crlf;\r
+                       $this->body     .= '--'.$this->getBoundary().self::$crlf;\r
+                       \r
+                       // add attachments\r
+                       foreach ($this->getAttachments() as $attachment) {\r
+                               $fileName       = $attachment['name'];\r
+                               $path           = $attachment['path'];\r
+                               \r
+                               // download file\r
+                               if (FileUtil::isURL($path)) {\r
+                                       $tmpPath = FileUtil::getTemporaryFilename('mailAttachment_');\r
+                                       if (!@copy($path, $tmpPath)) continue;\r
+                                       $path = $tmpPath;\r
+                               }\r
+                               \r
+                               // get file contents\r
+                               $data = @file_get_contents($path);\r
+                               $data = chunk_split(base64_encode($data), 70, self::$crlf);     \r
+                               \r
+                               $this->body .= 'Content-Type: application/octetstream; name="'.$fileName.'"'.self::$crlf;\r
+                               $this->body .= 'Content-Transfer-Encoding: base64'.self::$crlf;\r
+                               $this->body .= 'Content-Disposition: attachment; filename="'.$fileName.'"'.self::$crlf.self::$crlf;\r
+                               $this->body .= $data.self::$crlf.self::$crlf;\r
+                               \r
+                               if ($counter < count($this->getAttachments())) $this->body .= '--'.$this->getBoundary().self::$crlf;\r
+                               $counter++;\r
+                       }\r
+                       \r
+                       $this->body .= self::$crlf.'--'.$this->getBoundary().'--';\r
+               }\r
+               else {\r
+                       //$this->body   .= self::$crlf;\r
+                       $this->body     .= $this->getMessage();\r
+               }\r
+               return $this->body;\r
+       }\r
+       \r
+       /**\r
+        * Builds a formatted address: "$name" <$email>\r
+        * \r
+        * @param       string          $name\r
+        * @param       string          $email\r
+        * @param       boolean         $encodeName\r
+        * @return      string\r
+        */\r
+       public static function buildAddress($name, $email, $encodeName = true) {\r
+               if (!empty($name) && MAIL_USE_FORMATTED_ADDRESS) {\r
+                       if ($encodeName) $name = Mail::encodeMIMEHeader($name);\r
+                       if (!preg_match('/^[a-z0-9 ]*$/i', $name)) return '"'.str_replace('"', '\"', $name).'" <'.$email.'>';\r
+                       else return $name . ' <'.$email.'>';\r
+               }\r
+               return $email;\r
+       }\r
+\r
+       /**\r
+        * Sends this mail.\r
+        */\r
+       public function send() {\r
+               MailSender::getInstance()->sendMail($this);\r
+       }\r
+       \r
+       /**\r
+        * Sets the recpients of this mail.\r
+        * \r
+        * @param       mixed           $to\r
+        */\r
+       public function addTo($to) {\r
+               if (is_array($to)) {\r
+                       foreach ($to as $name => $recipient) {\r
+                               $this->to[] = self::buildAddress($name, $recipient);\r
+                       }\r
+               }\r
+               else {\r
+                       $this->to[] = $to;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the recipients of this mail.\r
+        * \r
+        * @return      mixed\r
+        */\r
+       public function getTo() {\r
+               return $this->to;\r
+       }\r
+       \r
+       /**\r
+        * Returns the list of recipients.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getToString() {\r
+               if (!empty($this->to)) return implode(', ', $this->to);\r
+               else return '';\r
+       }\r
+       \r
+       /**\r
+        * Sets the subject of this mail.\r
+        * \r
+        * @param       string          $subject\r
+        */\r
+       public function setSubject($subject) {\r
+               $this->subject = $subject;\r
+       }\r
+       \r
+       /**\r
+        * Returns the subject of this mail.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getSubject() {\r
+               return $this->subject;\r
+       }\r
+       \r
+       /**\r
+        * Sets the message of this mail.\r
+        * \r
+        * @param       string          $message\r
+        */\r
+       public function setMessage($message) {\r
+               $this->message = $message;\r
+       }\r
+       \r
+       /**\r
+        * Returns the message of this mail.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getMessage() {\r
+               return preg_replace('%(\r\n|\r|\n)%', self::$crlf, $this->message . (MAIL_SIGNATURE ? self::$crlf . self::$crlf . MAIL_SIGNATURE : ''));\r
+       }\r
+       \r
+       /**\r
+        * Sets the sender of this mail.\r
+        * \r
+        * @param       mixed           $from\r
+        */\r
+       public function setFrom($from) {\r
+               if (is_array($from)) {\r
+                       $this->from = self::buildAddress(key($from), current($from), false);\r
+               }\r
+               else {\r
+                       $this->from = $from;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Gets the sender of this mail.\r
+        * \r
+        * @return      mixed\r
+        */\r
+       public function getFrom() {\r
+               return $this->from;\r
+       }\r
+       \r
+       /**\r
+        * Sets the carbon copy recipients of this mail.\r
+        * \r
+        * @param       mixed           $cc\r
+        */\r
+       public function addCC($cc) {\r
+               if (is_array($cc)) {\r
+                       foreach ($cc as $name => $recipient) {\r
+                               $this->cc[] = self::buildAddress($name, $recipient);\r
+                       }\r
+               }\r
+               else {\r
+                       $this->cc[] = $cc;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the carbon copy recipients of this mail.\r
+        * \r
+        * @return      mixed\r
+        */\r
+       public function getCC() {\r
+               return $this->cc;\r
+       }\r
+       \r
+       /**\r
+        * Returns the carbon copy recipients of this mail as String.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getCCString() {\r
+               if (!empty($this->cc)) return implode(', ', $this->cc);\r
+               else return '';\r
+       }\r
+       \r
+       /**\r
+        * Sets the blind carbon copy recipients of this mail.\r
+        * \r
+        * @param       mixed           $bcc\r
+        */\r
+       public function addBCC($bcc) {\r
+               if (is_array($bcc)) {\r
+                       foreach ($bcc as $name => $recipient) {\r
+                               $this->bcc[] = self::buildAddress($name, $recipient);\r
+                       }\r
+               }\r
+               else {\r
+                       $this->bcc[] = $bcc;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the blind carbon copy recipients of this mail.\r
+        * \r
+        * @return      mixed\r
+        */\r
+       public function getBCC() {\r
+               return $this->bcc;\r
+       }\r
+       \r
+       /**\r
+        * Returns the blind carbon copy recipients of this mail as String.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getBCCString() {\r
+               if (!empty($this->bcc)) return implode(', ', $this->bcc);\r
+               else return '';\r
+       }\r
+       \r
+       /**\r
+        * Sets the attachments of this mail.\r
+        * \r
+        * @param       array           $attachments\r
+        */\r
+       public function setAttachments($attachments) {\r
+               $this->attachments = $attachments;\r
+       }\r
+       \r
+       /**\r
+        * Returns the attachments of this mail.\r
+        * \r
+        * @return      array\r
+        */\r
+       public function getAttachments() {\r
+               return $this->attachments;\r
+       }\r
+       \r
+       /**\r
+        * Adds an attachment to this mail.\r
+        * \r
+        * @param       string          $path\r
+        */\r
+       public function addAttachment($path) {\r
+               $this->attachments[] = array('path' => $path, 'name' => basename($path));\r
+       }\r
+       \r
+       /**\r
+        * Sets the Priority of the Mail; Default = 3\r
+        * \r
+        * @param       integer         $priority\r
+        */\r
+       public function setPriority($priority) {\r
+               $this->priority = $priority;\r
+       }\r
+       \r
+       /**\r
+        * Returns the Priority of the Mail\r
+        * \r
+        * @return      integer\r
+        */\r
+       public function getPriority() {\r
+               return $this->priority;\r
+       }\r
+       \r
+       /**\r
+        * Creates a boundary for mutlipart/mixed Mail \r
+        */\r
+       protected function setBoundary() {\r
+               $this->boundary = "==Multipart_Boundary_x".StringUtil::getRandomID()."x";\r
+       }\r
+       \r
+       /**\r
+        * Returns the created Boundary\r
+        * \r
+        * @return      string\r
+        */\r
+       protected function getBoundary() {\r
+               return $this->boundary;\r
+       }\r
+       \r
+       /**\r
+        * Returns the Content Type\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getContentType() {\r
+               return $this->contentType;\r
+       }\r
+       \r
+       /**\r
+        * Sets the content type.\r
+        * \r
+        * @param       string          $contentType\r
+        */\r
+       public function setContentType($contentType) {\r
+               $this->contentType = $contentType;\r
+       }\r
+       \r
+       /**\r
+        * Sets additional headers\r
+        * \r
+        * @param       string          $header\r
+        */\r
+       public function setHeader($header) {\r
+               if (!empty($header)) {\r
+                       $this->header .= $header.self::$crlf;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Encodes string for MIME header.\r
+        */\r
+       public static function encodeMIMEHeader($string) {\r
+               if (function_exists('mb_encode_mimeheader')) {\r
+                       $string = mb_encode_mimeheader($string, 'UTF-8', 'Q', Mail::$crlf);\r
+               }\r
+               else {\r
+                       $string = '=?UTF-8?Q?'.preg_replace('/[^\r\n]{73}[^=\r\n]{2}/', "$0=\r\n", str_replace("%", "=", str_replace("%0D%0A", "\r\n", str_replace("%20", " ", rawurlencode($string))))).'?=';\r
+               }\r
+               \r
+               return $string;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/mail/MailSender.class.php b/wcfsetup/install/files/lib/system/mail/MailSender.class.php
new file mode 100644 (file)
index 0000000..8e741b5
--- /dev/null
@@ -0,0 +1,53 @@
+<?php\r
+namespace wcf\system\mail;\r
+\r
+/**\r
+ * Mailsender sends e-mails.\r
+ * \r
+ * @author     Michael Schaefer\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.mail\r
+ * @category   Community Framework\r
+ */\r
+abstract class MailSender {\r
+       /**\r
+        * unique mail server instance\r
+        * @var MailSender\r
+        */\r
+       protected static $instance = null;\r
+       \r
+       /**\r
+        * Returns the default mail sender.\r
+        * \r
+        * @return      MailSender\r
+        */\r
+       public static function getInstance() {\r
+               if (self::$instance == null) {\r
+                       switch (MAIL_SEND_METHOD) {\r
+                               case 'php':\r
+                                       self::$defaultMailSender = new PHPMailSender();\r
+                                       break;\r
+                               \r
+                               case 'smtp':\r
+                                       self::$defaultMailSender = new SMTPMailSender();\r
+                                       break;\r
+                               \r
+                               case 'debug':\r
+                                       self::$defaultMailSender = new DebugMailSender();\r
+                                       break;\r
+                       }\r
+               }\r
+               \r
+               return self::$instance;\r
+       }\r
+       \r
+       /**\r
+        * Sends an e-mail.\r
+        * \r
+        * @param       Mail    $mail\r
+        */\r
+       public abstract function sendMail(Mail $mail); \r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/mail/PHPMailSender.class.php b/wcfsetup/install/files/lib/system/mail/PHPMailSender.class.php
new file mode 100644 (file)
index 0000000..15b5ee6
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+namespace wcf\system\mail;\r
+\r
+/**\r
+ * Sends a Mail with the php mail function.\r
+ * \r
+ * @author     Michael Schaefer\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.mail\r
+ * @category   Community Framework\r
+ */\r
+class PHPMailSender extends MailSender {\r
+       /**\r
+        * @see MailSender::sendMail()\r
+        */\r
+       public function sendMail(Mail $mail) {\r
+               if (MAIL_USE_F_PARAM) return @mb_send_mail($mail->getToString(), $mail->getSubject(), $mail->getBody(), $mail->getHeader(), '-f'.MAIL_FROM_ADDRESS);\r
+               else return @mb_send_mail($mail->getToString(), $mail->getSubject(), $mail->getBody(), $mail->getHeader());\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/mail/SMTPMailSender.class.php b/wcfsetup/install/files/lib/system/mail/SMTPMailSender.class.php
new file mode 100644 (file)
index 0000000..561ae7a
--- /dev/null
@@ -0,0 +1,215 @@
+<?php\r
+namespace wcf\system\mail;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\io\RemoteFile;\r
+\r
+/**\r
+ * Sends a Mail with a connection to a smtp server.\r
+ * \r
+ * @author     Michael Schaefer\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage data.mail\r
+ * @category   Community Framework\r
+ */\r
+class SMTPMailSender extends MailSender {\r
+       protected $connection = null;\r
+       protected $statusCode = '';\r
+       protected $statusMsg = '';\r
+       protected $recipients;\r
+       \r
+       /**\r
+        * Creates a new SMTPMailSender object.\r
+        */\r
+       public function __construct() {\r
+               Mail::$crlf = "\r\n";\r
+       }\r
+       \r
+       /**\r
+        * Destroys the SMTPMailSender object.\r
+        */\r
+       public function __destruct() {\r
+               $this->disconnect();\r
+       }\r
+\r
+       /**\r
+        * Connects to the smtp-server\r
+        */\r
+       protected function connect() {\r
+               // connect\r
+               $this->connection = new RemoteFile(MAIL_SMTP_HOST, MAIL_SMTP_PORT);\r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode != 220) {\r
+                       throw new SystemException($this->formatError("can not connect to '".MAIL_SMTP_HOST.":".MAIL_SMTP_PORT."'"), 17000);\r
+               }\r
+               \r
+               // send ehlo\r
+               $this->write('EHLO '.$_SERVER['HTTP_HOST']);\r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode == 250) {\r
+                       // do authentication\r
+                       if (MAIL_SMTP_USER != '' || MAIL_SMTP_PASSWORD != '') {\r
+                               $this->auth();\r
+                       }\r
+               }\r
+               else {\r
+                       // send helo\r
+                       $this->write('HELO '.$_SERVER['HTTP_HOST']);\r
+                       $this->getSMTPStatus();\r
+                       if ($this->statusCode != 250) {\r
+                               throw new SystemException($this->formatError("can not connect to '".MAIL_SMTP_HOST.":".MAIL_SMTP_PORT."'"), 17000);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Formats a smtp error message.\r
+        * \r
+        * @param       string          $message\r
+        * @return      string\r
+        */\r
+       protected function formatError($message) {\r
+               return $message.': '.$this->statusMsg.' ('.$this->statusCode.')';\r
+       }\r
+       \r
+       /**\r
+        * Does the Authentification of the Client at the Server\r
+        */\r
+       protected function auth() {\r
+               // Init Authentication\r
+               $this->write('AUTH LOGIN');\r
+               $this->getSMTPStatus();\r
+               \r
+               // checks if auth is supported\r
+               if ($this->statusCode != 334) {\r
+                       throw new SystemException($this->formatError("smtp mail server '".MAIL_SMTP_HOST.":".MAIL_SMTP_PORT."' does not support user authentication"), 17001);\r
+               }\r
+               \r
+               // sending user information to smtp-server\r
+               $this->write(base64_encode(MAIL_SMTP_USER));\r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode != 334) {\r
+                       throw new SystemException($this->formatError("unknown smtp user '".MAIL_SMTP_USER."'"), 17002);\r
+               }\r
+                       \r
+               $this->write(base64_encode(MAIL_SMTP_PASSWORD));\r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode != 235) {\r
+                       throw new SystemException($this->formatError("invalid password for smtp user '".MAIL_SMTP_USER."'"), 17003);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see MailSender::sendMail()\r
+        */\r
+       public function sendMail(Mail $mail) {\r
+               $this->recipients = array();\r
+               if (count($mail->getTo()) > 0)  $this->recipients = $mail->getTo();\r
+               if (count($mail->getCC()) > 0)  $this->recipients = array_merge($this->recipients, $mail->getCC());\r
+               if (count($mail->getBCC())> 0)  $this->recipients = array_merge($this->recipients, $mail->getBCC());\r
+               \r
+               // apply connection\r
+               if ($this->connection === null) {\r
+                       $this->connect();\r
+               }\r
+               \r
+               // send mail\r
+               $this->write('MAIL FROM:<'.$mail->getFrom().'>');\r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode != 250) {\r
+                       throw new SystemException($this->formatError("wrong from format '".$mail->getFrom()."'"), 17004);\r
+               }\r
+               \r
+               // recipients\r
+               $recipientCounter = 0;\r
+               foreach ($this->recipients as $recipient) {\r
+                       $this->write('RCPT TO:<'.$recipient.'>');\r
+                       $this->getSMTPStatus();\r
+                       if ($this->statusCode != 250 && $this->statusCode != 251) {\r
+                               if ($this->statusCode < 550) {\r
+                                       throw new SystemException($this->formatError("wrong recipient format '".$recipient."'"), 17004);\r
+                               }\r
+                               continue;\r
+                       }\r
+                       $recipientCounter++;\r
+               }\r
+               if (!$recipientCounter) {\r
+                       $this->write("RSET");\r
+                       return;\r
+               }\r
+               \r
+               // data\r
+               $this->write("DATA");\r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode != 354) {\r
+                       throw new SystemException($this->formatError("smtp error"), 17005);\r
+               }\r
+                                               \r
+               $header =\r
+                       "Date: ".gmdate('r').Mail::$crlf\r
+                       ."To: ".$mail->getToString().Mail::$crlf\r
+                       ."Message-ID: <".md5(uniqid())."@".$_SERVER['SERVER_NAME'].">".Mail::$crlf\r
+                       ."Subject: ".Mail::encodeMIMEHeader($mail->getSubject()).Mail::$crlf\r
+                       .$mail->getHeader();\r
+\r
+               $this->write($header);\r
+               $this->write("");\r
+               $this->write($mail->getBody());\r
+               $this->write(".");\r
+                       \r
+               $this->getSMTPStatus();\r
+               if ($this->statusCode != 250) {\r
+                       throw new SystemException($this->formatError("message sending failed"), 17005);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Disconnects the Client-Server connection\r
+        */\r
+       function disconnect() {\r
+               if ($this->connection === null) {\r
+                       return;\r
+               }\r
+\r
+               $this->write("QUIT");\r
+               $this->read();\r
+               $this->connection->close();\r
+               $this->connection = null;\r
+       }\r
+       \r
+       /**\r
+        * Reads the Information wich the Server sends back.\r
+        * \r
+        * @return      string\r
+        */\r
+       protected function read() {\r
+               $result = '';\r
+               while ($read = $this->connection->gets()) {\r
+                       $result .= $read;\r
+                       if (substr($read, 3, 1) == " ") break;\r
+               }\r
+               return $result; \r
+       }\r
+       \r
+       /**\r
+        * Gets error code and message from a server message.\r
+        * \r
+        * @param       string          $data\r
+        */\r
+       protected function getSMTPStatus($data = null) {\r
+               if ($data === null) $data = $this->read();\r
+               $this->statusCode = intval(substr($data, 0, 3));\r
+               $this->statusMsg  = substr($data, 4);\r
+       }\r
+       \r
+       /**\r
+        * Sends Information to the smtp-Server\r
+        * \r
+        * @param       string          $data\r
+        */\r
+       protected function write($data) {\r
+               $this->connection->puts($data.Mail::$crlf);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/menu/TreeMenu.class.php b/wcfsetup/install/files/lib/system/menu/TreeMenu.class.php
new file mode 100644 (file)
index 0000000..70f52e1
--- /dev/null
@@ -0,0 +1,211 @@
+<?php\r
+namespace wcf\system\menu;\r
+use wcf\system\event\EventHandler;\r
+use wcf\system\SingletonFactory;\r
+use wcf\system\WCF;\r
+use wcf\util\FileUtil;\r
+\r
+/**\r
+ * Basis class for a tree menu.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.menu\r
+ * @category   Community Framework\r
+ */\r
+abstract class TreeMenu extends SingletonFactory {\r
+       /**\r
+        * List of visible menu items.\r
+        * \r
+        * @var array\r
+        */\r
+       public $menuItemList = array();\r
+       \r
+       /**\r
+        * List of active menu items.\r
+        * \r
+        * @var array\r
+        */\r
+       public $activeMenuItems = array();\r
+       \r
+       /**\r
+        * List of all menu items.\r
+        * \r
+        * @var array\r
+        */\r
+       public $menuItems = null;\r
+\r
+       /**\r
+        * @see SingletonFactory::init()\r
+        */\r
+       protected function init() {\r
+               // get menu items from cache\r
+               $this->loadCache();\r
+               \r
+               // check menu items\r
+               $this->checkMenuItems();\r
+               \r
+               // remove items without children\r
+               $this->removeEmptyItems();\r
+               \r
+               // build plain menu item list\r
+               $this->buildMenuItemList();\r
+               \r
+               // call init event\r
+               EventHandler::getInstance()->fireAction($this, 'init');\r
+       }\r
+       \r
+       /**\r
+        * Loads cached menu items.\r
+        */\r
+       protected function loadCache() {\r
+               // call loadCache event\r
+               EventHandler::getInstance()->fireAction($this, 'loadCache');\r
+               \r
+               $this->menuItems = array();\r
+       }\r
+       \r
+       /**\r
+        * Checks the options and permissions of given menu item.\r
+        * \r
+        * @param       mixed           $item\r
+        * @return      boolean\r
+        */\r
+       protected function checkMenuItem(TreeMenuItem $item) {\r
+               // check the options of this item\r
+               $hasEnabledOption = true;\r
+               if (!empty($item->options)) {\r
+                       $hasEnabledOption = false;\r
+                       $options = explode(',', strtoupper($item->options));\r
+                       foreach ($options as $option) {\r
+                               if (defined($option) && constant($option)) {\r
+                                       $hasEnabledOption = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               if (!$hasEnabledOption) return false;\r
+               \r
+               // check the permission of this item for the active user\r
+               $hasPermission = true;\r
+               if (!empty($item->permissions)) {\r
+                       $hasPermission = false;\r
+                       $permissions = explode(',', $item->permissions);\r
+                       foreach ($permissions as $permission) {\r
+                               if (WCF::getSession()->getPermission($permission)) {\r
+                                       $hasPermission = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               if (!$hasPermission) return false;\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Checks the options and permissions of the menu items.\r
+        * \r
+        * @param       string          $parentMenuItem\r
+        */\r
+       protected function checkMenuItems($parentMenuItem = '') {\r
+               if (!isset($this->menuItems[$parentMenuItem])) return;\r
+               \r
+               foreach ($this->menuItems[$parentMenuItem] as $key => $item) {\r
+                       if ($this->checkMenuItem($item)) {\r
+                               // check children\r
+                               $this->checkMenuItems($item->menuItem);\r
+                       }\r
+                       else {\r
+                               // remove this item\r
+                               unset($this->menuItems[$parentMenuItem][$key]);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Removes items without children.\r
+        * \r
+        * @param       string          $parentMenuItem\r
+        */\r
+       protected function removeEmptyItems($parentMenuItem = '') {\r
+               if (!isset($this->menuItems[$parentMenuItem])) return;\r
+               \r
+               foreach ($this->menuItems[$parentMenuItem] as $key => $item) {\r
+                       $this->removeEmptyItems($item->menuItem);\r
+                       if (empty($item->menuItemLink) && (!isset($this->menuItems[$item->menuItem]) || !count($this->menuItems[$item->menuItem]))) {\r
+                               // remove this item\r
+                               unset($this->menuItems[$parentMenuItem][$key]);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Builds a plain menu item list.\r
+        * \r
+        * @param       string          $parentMenuItem\r
+        */\r
+       protected function buildMenuItemList($parentMenuItem = '') {\r
+               if (!isset($this->menuItems[$parentMenuItem])) return;\r
+               \r
+               foreach ($this->menuItems[$parentMenuItem] as $key => $item) {\r
+                       $this->menuItemList[$item->menuItem] = $item;\r
+                       $this->buildMenuItemList($item->menuItem);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Sets the active menu item. \r
+        * This should be done before the menu.tpl template calls the function getMenu().\r
+        * \r
+        * This function should be used in each script which uses a template that includes the menu.tpl.\r
+        * \r
+        * @param       string          $menuItem       name of the active menu item\r
+        */\r
+       public function setActiveMenuItem($menuItem) {\r
+               $this->activeMenuItems = array(); \r
+               \r
+               // build active menu list\r
+               while (isset($this->menuItemList[$menuItem])) {\r
+                       $this->activeMenuItems[] = $menuItem;\r
+                       $menuItem = $this->menuItemList[$menuItem]->parentMenuItem;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns a list of the active menu items.\r
+        * \r
+        * @return      array\r
+        */\r
+       public function getActiveMenuItems() {\r
+               return $this->activeMenuItems;\r
+       }\r
+       \r
+       /**\r
+        * Returns the active menu item.\r
+        * \r
+        * @param       integer         $level\r
+        * @return      string\r
+        */\r
+       public function getActiveMenuItem($level = 0) {\r
+               if ($level < count($this->activeMenuItems)) {\r
+                       return $this->activeMenuItems[(count($this->activeMenuItems) - ($level + 1))];\r
+               }\r
+               return null;\r
+       }\r
+       \r
+       /**\r
+        * Returns the list of menu items.\r
+        * \r
+        * @param       string          $parentMenuItem\r
+        * @return      array\r
+        */\r
+       public function getMenuItems($parentMenuItem = null) {\r
+               if ($parentMenuItem === null) return $this->menuItems;\r
+               if (isset($this->menuItems[$parentMenuItem])) return $this->menuItems[$parentMenuItem];\r
+               return array();\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/menu/TreeMenuItem.class.php b/wcfsetup/install/files/lib/system/menu/TreeMenuItem.class.php
new file mode 100644 (file)
index 0000000..cd53432
--- /dev/null
@@ -0,0 +1,22 @@
+<?php\r
+namespace wcf\system\menu;\r
+\r
+/**\r
+ * Any tree menu item should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.menu\r
+ * @category   Community Framework\r
+ */\r
+interface TreeMenuItem {\r
+       /**\r
+        * Returns the link of this item.\r
+        * \r
+        * @return string\r
+        */\r
+       public function getLink();\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/menu/acp/ACPMenu.class.php b/wcfsetup/install/files/lib/system/menu/acp/ACPMenu.class.php
new file mode 100644 (file)
index 0000000..f03acd7
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\system\menu\acp;\r
+use wcf\system\menu\TreeMenu;\r
+use wcf\system\cache\CacheHandler;\r
+\r
+/**\r
+ * Builds the acp menu.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.menu.acp\r
+ * @category   Community Framework\r
+ */\r
+class ACPMenu extends TreeMenu {\r
+       /**\r
+        * @see TreeMenu::loadCache()\r
+        */\r
+       protected function loadCache() {\r
+               parent::loadCache();\r
+               \r
+               if (PACKAGE_ID == 0) {\r
+                       return;\r
+               }\r
+               \r
+               CacheHandler::getInstance()->addResource('menu-'.PACKAGE_ID, WCF_DIR.'cache/cache.menu-'.PACKAGE_ID.'.php', 'wcf\system\cache\CacheBuilderACPMenu');\r
+               $this->menuItems = CacheHandler::getInstance()->get('menu-'.PACKAGE_ID);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/menu/page/DefaultPageMenuItemProvider.class.php b/wcfsetup/install/files/lib/system/menu/page/DefaultPageMenuItemProvider.class.php
new file mode 100644 (file)
index 0000000..08b7b76
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+namespace wcf\system\menu\page;\r
+\r
+/**\r
+ * Provides default implementations for page menu item providers.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.menu.page\r
+ * @category   Community Framework\r
+ */\r
+class DefaultPageMenuItemProvider implements PageMenuItemProvider {\r
+       /**\r
+        * @see PageMenuItemProvider::isVisible()\r
+        */\r
+       public function isVisible() {\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * @see PageMenuItemProvider::getNotifications()\r
+        */\r
+       public function getNotifications() {\r
+               return 0;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/menu/page/PageMenu.class.php b/wcfsetup/install/files/lib/system/menu/page/PageMenu.class.php
new file mode 100644 (file)
index 0000000..29c6192
--- /dev/null
@@ -0,0 +1,39 @@
+<?php\r
+namespace wcf\system\menu\page;\r
+use wcf\data\page\menu\item\PageMenuItem;\r
+use wcf\system\menu\TreeMenu;\r
+use wcf\system\menu\TreeMenuItem;\r
+use wcf\system\cache\CacheHandler;\r
+\r
+/**\r
+ * Builds the page menu.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.menu.page\r
+ * @category   Community Framework\r
+ */\r
+class PageMenu extends TreeMenu {\r
+       /**\r
+        * @see TreeMenu::loadCache()\r
+        */\r
+       protected function loadCache() {\r
+               parent::loadCache();\r
+               \r
+               // get cache\r
+               CacheHandler::getInstance()->addResource('pageMenu-'.PACKAGE_ID, WCF_DIR.'cache/cache.pageMenu-'.PACKAGE_ID.'.php', 'wcf\system\cache\CacheBuilderPageMenu');\r
+               $this->menuItems = CacheHandler::getInstance()->get('pageMenu-'.PACKAGE_ID);\r
+       }\r
+       \r
+       /**\r
+        * @see TreeMenu::checkMenuItem()\r
+        */\r
+       protected function checkMenuItem(TreeMenuItem $item) {\r
+               if (!parent::checkMenuItem($item)) return false;\r
+               \r
+               return $item->getProvider()->isVisible();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/menu/page/PageMenuItemProvider.class.php b/wcfsetup/install/files/lib/system/menu/page/PageMenuItemProvider.class.php
new file mode 100644 (file)
index 0000000..1813bed
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+namespace wcf\system\menu\page;\r
+\r
+/**\r
+ * Any page menu item provider should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.menu.page\r
+ * @category   Community Framework\r
+ */\r
+interface PageMenuItemProvider {\r
+       /**\r
+        * Returns true if the associated menu item should be visible for the active user.\r
+        * \r
+        * @return boolean\r
+        */\r
+       public function isVisible();\r
+       \r
+       /**\r
+        * Returns the number of notifications for the associated menu item.\r
+        * \r
+        * @return boolean\r
+        */\r
+       public function getNotifications();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionType.class.php b/wcfsetup/install/files/lib/system/option/OptionType.class.php
new file mode 100644 (file)
index 0000000..852331e
--- /dev/null
@@ -0,0 +1,43 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+\r
+/**\r
+ * Any option type should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+interface OptionType {\r
+       /**\r
+        * Returns the html code for the form element of this option.\r
+        * \r
+        * @param       Option          $option\r
+        * @param       mixed           $value\r
+        * @return      string          html\r
+        */\r
+       public function getFormElement(Option $option, $value);\r
+       \r
+       /**\r
+        * Validates the form input for this option.\r
+        * Throws an exception, if validation fails.\r
+        * \r
+        * @param       Option          $option\r
+        * @param       string          $newValue\r
+        */\r
+       public function validate(Option $option, $newValue);\r
+       \r
+       /**\r
+        * Returns the value of this option for saving in the database.\r
+        * \r
+        * @param       Option          $option\r
+        * @param       string          $newValue\r
+        * @return      string\r
+        */\r
+       public function getData(Option $option, $newValue);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeBoolean.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeBoolean.class.php
new file mode 100644 (file)
index 0000000..958c96f
--- /dev/null
@@ -0,0 +1,65 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\WCF;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * OptionTypeBoolean is an implementation of OptionType for boolean values.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeBoolean implements OptionType, SearchableUserOption {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               $options = Option::parseEnableOptions($option->enableOptions);\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'disableOptions' => $options['disableOptions'],\r
+                       'enableOptions' => $options['enableOptions'],\r
+                       'option' => $option,\r
+                       'value' => $value\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeBoolean');\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(Option $option, $newValue) {}\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               if ($newValue !== null) return 1;\r
+               return 0;\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getSearchFormElement()\r
+        */\r
+       public function getSearchFormElement(Option $option, $value) {\r
+               return $this->getFormElement($option, $value);\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getCondition()\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value) {\r
+               $value = intval($value);\r
+               if (!$value) return false;\r
+               \r
+               $conditions->add("option_value.userOption".$option->optionID." = ?", array(1));\r
+               return true;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeCustomselect.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeCustomselect.class.php
new file mode 100644 (file)
index 0000000..31a85ee
--- /dev/null
@@ -0,0 +1,47 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\option\OptionTypeSelect;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * OptionTypeSelect is an implementation of OptionType for 'select' tags with a text field for custom inputs.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeCustomselect extends OptionTypeSelect {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               WCF::getTPL()->assign(array(\r
+                       'option' => $option,\r
+                       'selectOptions' => $option->parseSelectOptions(),\r
+                       'value' => $value,\r
+                       'customValue' => (!isset($options[$value]) ? $value : '')\r
+               ));\r
+               \r
+               return WCF::getTPL()->fetch('optionTypeCustomselect');\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(Option $option, $newValue) {}\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               if (empty($newValue) && isset($_POST['values'][$option->optionName.'_custom'])) {\r
+                       return $_POST['values'][$option->optionName.'_custom'];\r
+               }\r
+               return $newValue;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeDate.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeDate.class.php
new file mode 100644 (file)
index 0000000..2dd739b
--- /dev/null
@@ -0,0 +1,145 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\option\OptionType;\r
+use wcf\system\option\SearchableUserOption;\r
+use wcf\system\WCF;\r
+use wcf\util\DateUtil;\r
+\r
+/**\r
+ * OptionTypeDate is an implementation of OptionType for date inputs.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeDate implements OptionType, SearchableUserOption {\r
+       protected $yearRequired = true;\r
+       \r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(array &$optionData) {\r
+               if (!isset($optionData['optionValue'])) {\r
+                       if (isset($optionData['defaultValue'])) $optionData['optionValue'] = $optionData['defaultValue'];\r
+                       else $optionData['optionValue'] = '';\r
+               }\r
+               $optionData['isOptionGroup'] = true;\r
+               $optionData['divClass'] = 'formDate';\r
+               \r
+               $year = $month = $day = '';\r
+               $optionValue = explode('-', (is_array($optionData['optionValue']) ? implode('-', $optionData['optionValue']) : $optionData['optionValue']));\r
+               if (isset($optionValue[0])) $year = intval($optionValue[0]);\r
+               if (empty($year)) $year = '';\r
+               if (isset($optionValue[1])) $month = $optionValue[1];\r
+               if (isset($optionValue[2])) $day = $optionValue[2];\r
+               $dateInputOrder = explode('-', WCF::getLanguage()->get('wcf.global.dateInputOrder'));\r
+               \r
+               // generate days\r
+               $days = array();\r
+               $days[0] = '';\r
+               for ($i = 1; $i < 32; $i++) {\r
+                       $days[$i] = $i;         \r
+               }\r
+               \r
+               // generate months\r
+               $months = array();\r
+               $months[0] = '';\r
+               // TODO: $dateFormatLocalized is no longer available, fix this!\r
+               $monthFormat = (Language::$dateFormatLocalized ? '%B' : '%m');\r
+               for ($i = 1; $i < 13; $i++) {\r
+                       $months[$i] = DateUtil::formatDate($monthFormat, gmmktime(0, 0, 0, $i, 10, 2006), false, true);\r
+               }\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'year' => $year,\r
+                       'month' => $month,\r
+                       'day' => $day,\r
+                       'days' => $days,\r
+                       'months' => $months,\r
+                       'optionData' => $optionData,\r
+                       'dateInputOrder' => $dateInputOrder,\r
+                       'yearRequired' => $this->yearRequired\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeDate');\r
+       }\r
+       \r
+       /**\r
+        * Formats the user input.\r
+        * \r
+        * @param       array           $newValue\r
+        */\r
+       protected function getValue(array &$newValue) {\r
+               if (isset($newValue['year'])) $newValue['year'] = intval($newValue['year']);\r
+               else $newValue['year'] = 0;\r
+               if (isset($newValue['month'])) $newValue['month'] = intval($newValue['month']);\r
+               else $newValue['month'] = 0;\r
+               if (isset($newValue['day'])) $newValue['day'] = intval($newValue['day']);\r
+               else $newValue['day'] = 0;\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(array $optionData, $newValue) {\r
+               $this->getValue($newValue);\r
+               \r
+               if ($newValue['year'] || $newValue['month'] || $newValue['day']) {\r
+                       if (strlen($newValue['year']) == 2) {\r
+                               $newValue['year'] = '19'.$newValue['year'];\r
+                       }\r
+                       \r
+                       if (!checkdate(intval($newValue['month']), intval($newValue['day']), ((!$this->yearRequired && !$newValue['year']) ? 2000 : intval($newValue['year'])))) {\r
+                               throw new UserInputException($optionData['optionName'], 'validationFailed');\r
+                       }\r
+                       if (($newValue['year'] || $this->yearRequired) && ((strlen($newValue['year']) != 4 && strlen($newValue['year']) != 2) || $newValue['year'] < 1902)) {\r
+                               throw new UserInputException($optionData['optionName'], 'validationFailed');\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(array $optionData, $newValue) {\r
+               $this->getValue($newValue);\r
+               \r
+               if ($newValue['year'] || $newValue['month'] || $newValue['day']) {\r
+                       if ($newValue['month'] < 10) $newValue['month'] = '0'.$newValue['month'];\r
+                       if ($newValue['day'] < 10) $newValue['day'] = '0'.$newValue['day'];\r
+                       if (strlen($newValue['year']) == 2) {\r
+                               $newValue['year'] = '19'.$newValue['year'];\r
+                       }\r
+                       if (!$this->yearRequired && strlen($newValue['year']) < 2) {\r
+                               $newValue['year'] = '0000';\r
+                       }\r
+                       return $newValue['year'].'-'.$newValue['month'].'-'.$newValue['day'];\r
+               }\r
+               \r
+               return '';\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getSearchFormElement()\r
+        */\r
+       public function getSearchFormElement(array &$optionData) {\r
+               return $this->getFormElement($optionData);\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getCondition()\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value) {\r
+               $value = $this->getData($optionData, $value);\r
+               if ($value == '') return false;\r
+               \r
+               $conditions->add("option_value.userOption".$option->optionID." = ?", array($value));\r
+               return true;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeFloat.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeFloat.class.php
new file mode 100644 (file)
index 0000000..d1ed7e7
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace wcf\system\option;
+use wcf\data\option\Option;
+use wcf\system\option\OptionTypeText;
+use wcf\system\WCF;
+
+/**
+ * OptionTypeFloat is an implementation of OptionType for float fields.
+ *
+ * @author     Tobias Friebel
+ * @copyright  2001-2011 Tobias Friebel
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.option
+ * @category   Community Framework
+ */
+class OptionTypeFloat extends OptionTypeText {
+       /**
+        * @see OptionType::getFormElement()
+        */
+       public function getFormElement(Option $option, $value) {
+               $value = str_replace('.', WCF::getLanguage()->get('wcf.global.decimalPoint'), $value);
+               
+               return parent::getFormElement($option, $value);
+       }
+       
+       /**
+        * @see OptionType::getData()
+        */
+       public function getData(Option $option, $newValue) {
+               $newValue = str_replace(' ', '', $newValue);
+               $newValue = str_replace(WCF::getLanguage()->get('wcf.global.thousandsSeparator'), '', $newValue);
+               $newValue = str_replace(WCF::getLanguage()->get('wcf.global.decimalPoint'), '.', $newValue);
+               return floatval($newValue);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeInteger.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeInteger.class.php
new file mode 100644 (file)
index 0000000..e163cd0
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\option\OptionTypeText;\r
+\r
+/**\r
+ * OptionTypeText is an implementation of OptionType for integer fields.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeInteger extends OptionTypeText {\r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               return intval($newValue);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeMultiselect.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeMultiselect.class.php
new file mode 100644 (file)
index 0000000..589129d
--- /dev/null
@@ -0,0 +1,83 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\option\OptionTypeSelect;\r
+use wcf\system\option\SearchableUserOption;\r
+use wcf\system\WCF;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\OptionUtil;\r
+\r
+/**\r
+ * OptionTypeSelect is an implementation of OptionType for multiple 'select' tags.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeMultiselect extends OptionTypeSelect {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(array &$optionData) {\r
+               if (!isset($optionData['optionValue'])) {\r
+                       if (isset($optionData['defaultValue'])) $optionData['optionValue'] = explode("\n", $optionData['defaultValue']);\r
+                       else $optionData['optionValue'] = array();\r
+               }\r
+               else if (!is_array($optionData['optionValue'])) {\r
+                       $optionData['optionValue'] = explode("\n", $optionData['optionValue']);\r
+               }\r
+               \r
+               // get options\r
+               $options = OptionUtil::parseSelectOptions($optionData['selectOptions']);\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'optionData' => $optionData,\r
+                       'options' => $options\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeMultiselect');\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(array $optionData, $newValue) {\r
+               if (!is_array($newValue)) $newValue = array();\r
+               $options = OptionUtil::parseSelectOptions($optionData['selectOptions']);\r
+               foreach ($newValue as $value) {\r
+                       if (!isset($options[$value])) throw new UserInputException($optionData['optionName'], 'validationFailed');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(array $optionData, $newValue) {\r
+               if (!is_array($newValue)) $newValue = array();\r
+               return implode("\n", $newValue);\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getSearchFormElement()\r
+        */\r
+       public function getSearchFormElement(array &$optionData) {\r
+               return $this->getFormElement($optionData);\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getCondition()\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $options, $value) {\r
+               if (!is_array($value) || !count($value)) return false;\r
+               $value = ArrayUtil::trim($value);\r
+               if (!count($value)) return false;\r
+               \r
+               $conditions->add("option_value.userOption".$option->optionID." = ?", array(implode("\n", $value)));\r
+               return true;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypePassword.class.php b/wcfsetup/install/files/lib/system/option/OptionTypePassword.class.php
new file mode 100644 (file)
index 0000000..680921f
--- /dev/null
@@ -0,0 +1,30 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\option\OptionTypeText;\r
+\r
+/**\r
+ * OptionTypeText is an implementation of OptionType for 'input type="password"' tags.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypePassword extends OptionTypeText {\r
+       /**\r
+        * @see OptionTypeText::$inputType\r
+        */\r
+       protected $inputType = 'password';\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getCondition()\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value) {\r
+               return false;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeRadiobuttons.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeRadiobuttons.class.php
new file mode 100644 (file)
index 0000000..4296bcd
--- /dev/null
@@ -0,0 +1,91 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\option\OptionType;\r
+use wcf\system\option\SearchableUserOption;\r
+use wcf\system\WCF;\r
+use wcf\system\UserInputException;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * OptionTypeRadiobuttons is an implementation of OptionType for 'input type="radio"' tags.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeRadiobuttons implements OptionType, SearchableUserOption {\r
+       public $templateName = 'optionTypeRadiobuttons';\r
+\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               // get options\r
+               $selectOptions = $option->parseSelectOptions();\r
+\r
+               $availableOptions = $option->parseMultipleEnableOptions();\r
+               $options = array(\r
+                       'disableOptions' => array(),\r
+                       'enableOptions' => array()\r
+               );\r
+               \r
+               foreach ($availableOptions as $key => $enableOptions) {\r
+                       $optionData = Option::parseEnableOptions($enableOptions);\r
+                       \r
+                       $options['disableOptions'][$key] = $optionData['disableOptions'];\r
+                       $options['enableOptions'][$key] = $optionData['enableOptions'];\r
+               }\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'disableOptions' => $options['disableOptions'],\r
+                       'enableOptions' => $options['enableOptions'],\r
+                       'option' => $option,\r
+                       'selectOptions' => $selectOptions,\r
+                       'value' => $value\r
+               ));\r
+               return WCF::getTPL()->fetch($this->templateName);\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(Option $option, $newValue) {\r
+               if (!empty($newValue)) {\r
+                       $options = $option->parseSelectOptions();\r
+                       if (!isset($options[$newValue])) {\r
+                               throw new UserInputException($option->optionName, 'validationFailed');\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               return $newValue;\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getSearchFormElement()\r
+        */\r
+       public function getSearchFormElement(Option $option, $value) {\r
+               return $this->getFormElement($optionData, $value);\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getCondition()\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value) {\r
+               $value = StringUtil::trim($value);\r
+               if (!$value) return false;\r
+               \r
+               $conditions->add("option_value.userOption".$option->optionID." = ?", array($value));\r
+               return true;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeSelect.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeSelect.class.php
new file mode 100644 (file)
index 0000000..c7fd1ce
--- /dev/null
@@ -0,0 +1,75 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\option\OptionTypeRadiobuttons;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * OptionTypeSelect is an implementation of OptionType for 'select' tags.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeSelect extends OptionTypeRadiobuttons {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               // get options\r
+               $options = $this->parseEnableOptions($option);\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'disableOptions' => $options['disableOptions'],\r
+                       'enableOptions' => $options['enableOptions'],\r
+                       'option' => $option,\r
+                       'selectOptions' => $option->parseSelectOptions(),\r
+                       'value' => $value\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeSelect');\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getSearchFormElement()\r
+        */\r
+       public function getSearchFormElement(Option $option, $value) {\r
+               return $this->getFormElement($optionData, $value);\r
+       }\r
+       \r
+       /**\r
+        * @todo        This is not really tested yet!\r
+        * @param       Option          $option\r
+        * @return      array\r
+        */\r
+       protected function parseEnableOptions(Option $option) {\r
+               $disableOptions = $enableOptions = '';\r
+               \r
+               if (!empty($option->enableOptions)) {\r
+                       $options = $option->parseMultipleEnableOptions();\r
+                       \r
+                       foreach ($options as $key => $optionData) {\r
+                               $tmp = explode(',', $optionData);\r
+                               \r
+                               foreach ($optionData as $item) {\r
+                                       if ($item{0} == '!') {\r
+                                               if (!empty($disableOptions)) $disableOptions .= ',';\r
+                                               $disableOptions .= "{ value: '".$key."', option: '".StringUtil::substring($item, 1)."' }";\r
+                                       }\r
+                                       else {\r
+                                               if (!empty($enableOptions)) $enableOptions .= ',';\r
+                                               $enableOptions .= "{ value: '".$key."', option: '".$item."' }";\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               return array(\r
+                       'disableOptions' => $disableOptions,\r
+                       'enableOptions' => $enableOptions\r
+               );\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeText.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeText.class.php
new file mode 100644 (file)
index 0000000..7a1a259
--- /dev/null
@@ -0,0 +1,69 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+use wcf\system\option\OptionType;\r
+use wcf\system\option\SearchableUserOption;\r
+use wcf\system\WCF;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * OptionTypeText is an implementation of OptionType for 'input type="text"' tags.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeText implements OptionType, SearchableUserOption {\r
+       /**\r
+        * input type\r
+        * @var string\r
+        */\r
+       protected $inputType = 'text';\r
+       \r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               WCF::getTPL()->assign(array(\r
+                       'option' => $option,\r
+                       'inputType' => $this->inputType,\r
+                       'value' => $value\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeText');\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(Option $option, $newValue) {}\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               return $newValue;\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getSearchFormElement()\r
+        */\r
+       public function getSearchFormElement(Option $option, $value) {\r
+               return $this->getFormElement($optionData, $value);\r
+       }\r
+       \r
+       /**\r
+        * @see SearchableUserOption::getCondition()\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value) {\r
+               $value = StringUtil::trim($value);\r
+               if (empty($value)) return false;\r
+               \r
+               $conditions->add("option_value.userOption".$option->optionID." LIKE ?", array('%'.addcslashes($value, '_%').'%'));\r
+               return true;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeTextarea.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeTextarea.class.php
new file mode 100644 (file)
index 0000000..f39422c
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\option\OptionTypeText;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * OptionTypeTextarea is an implementation of OptionType for 'textarea' tags.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeTextarea extends OptionTypeText {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               WCF::getTPL()->assign(array(\r
+                       'option' => $option,\r
+                       'value' => $value\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeTextarea');\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/OptionTypeTimezone.class.php b/wcfsetup/install/files/lib/system/option/OptionTypeTimezone.class.php
new file mode 100644 (file)
index 0000000..2627efd
--- /dev/null
@@ -0,0 +1,53 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\option\OptionType;\r
+use wcf\system\exception\UserInputException;\r
+use wcf\system\WCF;\r
+use wcf\util\DateUtil;\r
+\r
+/**\r
+ * OptionTypeTimezone is an implementation of OptionType for a select box, which list the available time zones.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+class OptionTypeTimezone implements OptionType {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               $timezoneOptions = array();\r
+               foreach (DateUtil::getAvailableTimezones() as $timezone) {\r
+                       $timezoneOptions[$timezone] = WCF::getLanguage()->get('wcf.global.date.timezone.'.str_replace('/', '.', strtolower($timezone)));\r
+               }\r
+               \r
+               WCF::getTPL()->assign(array(\r
+                       'option' => $option,\r
+                       'selectOptions' => $timezoneOptions,\r
+                       'value' => $value\r
+               ));\r
+               return WCF::getTPL()->fetch('optionTypeSelect');\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(Option $option, $newValue) {\r
+               if (!in_array($newValue, DateUtil::getAvailableTimezones())) {\r
+                       throw new UserInputException($option->optionName, 'validationFailed');\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               return $newValue;               \r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/SearchableUserOption.class.php b/wcfsetup/install/files/lib/system/option/SearchableUserOption.class.php
new file mode 100644 (file)
index 0000000..3b0897d
--- /dev/null
@@ -0,0 +1,36 @@
+<?php\r
+namespace wcf\system\option;\r
+use wcf\data\option\Option;\r
+use wcf\system\database\util\PreparedStatementConditionBuilder;\r
+\r
+/**\r
+ * Any searchable option type should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option\r
+ * @category   Community Framework\r
+ */\r
+interface SearchableUserOption {\r
+       /**\r
+        * Returns the html code for the search form element of this option.\r
+        * \r
+        * @param       wcf\data\option\Option  $option\r
+        * @param       string          $value\r
+        * @return      string          html\r
+        */\r
+       public function getSearchFormElement(Option $option, $value);\r
+       \r
+       /**\r
+        * Returns a condition for search sql query.\r
+        * \r
+        * @param       wcf\system\database\condition\PreparedStatementConditionBuilder $conditions\r
+        * @param       wcf\data\option\Option  $option\r
+        * @param       string          $value\r
+        * @param       boolean\r
+        */\r
+       public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value);\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionType.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionType.class.php
new file mode 100644 (file)
index 0000000..0430200
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\option\group;\r
+use wcf\system\option\OptionType;\r
+\r
+/**\r
+ * Any group permission type should implement this interface.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+interface GroupOptionType extends OptionType {\r
+       /**\r
+        * Merges the different values of an option to a single value.\r
+        * \r
+        * @param       array           $values\r
+        * @return      mixed           $value\r
+        */\r
+       public function merge(array $values);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeBoolean.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeBoolean.class.php
new file mode 100644 (file)
index 0000000..dec2f00
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+namespace wcf\system\option\group;\r
+use wcf\system\option\OptionTypeBoolean;\r
+\r
+/**\r
+ * GroupOptionTypeBoolean is an implementation of GroupOptionType for boolean values.\r
+ * The merge of option values returns true, if at least one value is true. Otherwise false.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeBoolean extends OptionTypeBoolean implements GroupOptionType {\r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               foreach ($values as $value) {\r
+                       if ($value) return true;\r
+               }\r
+\r
+               return false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeGroups.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeGroups.class.php
new file mode 100644 (file)
index 0000000..8fc7393
--- /dev/null
@@ -0,0 +1,82 @@
+<?php\r
+namespace wcf\system\option\group;\r
+use wcf\data\option\Option;\r
+use wcf\data\user\group\UserGroup;\r
+use wcf\util\ArrayUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * GroupOptionTypeGroups generates a select-list of all available user groups.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeGroups implements GroupOptionType {\r
+       /**\r
+        * @see OptionType::getFormElement()\r
+        */\r
+       public function getFormElement(Option $option, $value) {\r
+               // get selected group\r
+               $selectedGroups = explode(',', $value);\r
+               \r
+               // get all groups\r
+               $groups = UserGroup::getGroupsByType();\r
+               \r
+               // generate html\r
+               $html = '';\r
+               foreach ($groups as $group) {\r
+                       $html .= '<label><input type="checkbox" name="values['.StringUtil::encodeHTML($option->optionName).'][]" value="'.$group->groupID.'" '.(in_array($group->groupID, $selectedGroups) ? 'checked="checked" ' : '').'/> '.StringUtil::encodeHTML($group->groupName).'</label>';\r
+               }\r
+               \r
+               return $html;\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::validate()\r
+        */\r
+       public function validate(Option $option, $newValue) {\r
+               // get all groups\r
+               $groups = UserGroup::getGroupsByType();\r
+               \r
+               // get new value\r
+               if (!is_array($newValue)) $newValue = array();\r
+               $selectedGroups = ArrayUtil::toIntegerArray($newValue);\r
+               \r
+               // check groups\r
+               foreach ($selectedGroups as $groupID) {\r
+                       if (!isset($groups[$groupID])) {\r
+                               throw new UserInputException($option->optionName, 'validationFailed');\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see OptionType::getData()\r
+        */\r
+       public function getData(Option $option, $newValue) {\r
+               if (!is_array($newValue)) $newValue = array();\r
+               $newValue = ArrayUtil::toIntegerArray($newValue);\r
+               sort($newValue, SORT_NUMERIC);\r
+               return implode(',', $newValue);\r
+       }\r
+       \r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               $result = array();\r
+               foreach ($values as $value) {\r
+                       $value = explode(',', $value);\r
+                       $result = array_merge($result, $value);\r
+               }\r
+               \r
+               $result = array_unique($result);\r
+\r
+               return implode(',', $result);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInfiniteInteger.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInfiniteInteger.class.php
new file mode 100644 (file)
index 0000000..157db09
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\option\group;\r
+\r
+/**\r
+ * GroupOptionTypeInfiniteinteger is an implementation of GroupOptionType for integer values with the infinite option.\r
+ * The merge of option values returns true, if at least one value is -1. Otherwise it returns the highest value.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeInfiniteInteger extends GroupOptionTypeInteger {\r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               if (in_array(-1, $values)) return -1;\r
+               return parent::merge($values);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInfiniteInverseInteger.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInfiniteInverseInteger.class.php
new file mode 100644 (file)
index 0000000..f69504f
--- /dev/null
@@ -0,0 +1,28 @@
+<?php\r
+namespace wcf\system\option\group;\r
+\r
+/**\r
+ * GroupOptionTypeInfiniteinverseinteger is an implementation of GroupOptionType for integer values.\r
+ * The merge of option values returns -1 if all values are -1 otherwise the lowest value.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeInfiniteInverseInteger extends GroupOptionTypeInverseinteger {\r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               foreach ($values as $key => $value) {\r
+                       if ($value == -1) unset($values[$key]);\r
+               }\r
+               \r
+               if (count($values) == 0) return -1;\r
+               return min($values);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInteger.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInteger.class.php
new file mode 100644 (file)
index 0000000..af455b5
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\option\group;\r
+use wcf\system\option\OptionTypeInteger;\r
+\r
+/**\r
+ * GroupOptionTypeInteger is an implementation of GroupOptionType for integer values.\r
+ * The merge of option values returns the highest value.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeInteger extends OptionTypeInteger implements GroupOptionType {\r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               return max($values);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInverseInteger.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeInverseInteger.class.php
new file mode 100644 (file)
index 0000000..3711dfe
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\option\group;\r
+use wcf\system\option\OptionTypeInteger;\r
+\r
+/**\r
+ * GroupOptionTypeInverseInteger is an implementation of GroupOptionType for integer values.\r
+ * The merge of option values returns the lowest value.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeInverseInteger extends OptionTypeInteger implements GroupOptionType {\r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               return min($values);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeText.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeText.class.php
new file mode 100644 (file)
index 0000000..4f2fbcb
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+namespace wcf\system\option\group;
+use wcf\system\option\OptionTypeText;
+
+/**
+ * GroupOptionTypeText is an implementation of GroupOptionType for text values.
+ * The merge of option values returns merge of all text values.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.option.group
+ * @category   Community Framework
+ */
+class GroupOptionTypeText extends OptionTypeText implements GroupOptionType {
+       /**
+        * @see GroupOptionType::merge()
+        */
+       public function merge(array $values) {
+               $result = '';
+               
+               foreach ($values as $value) {
+                       if (!empty($result)) $result .= "\n";
+                       $result .= $value;
+               }
+
+               return $result;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeTextarea.class.php b/wcfsetup/install/files/lib/system/option/group/GroupOptionTypeTextarea.class.php
new file mode 100644 (file)
index 0000000..4edfc6e
--- /dev/null
@@ -0,0 +1,31 @@
+<?php\r
+namespace wcf\system\option\group;\r
+use wcf\system\option\OptionTypeTextarea;\r
+\r
+/**\r
+ * GroupOptionTypeTextarea is an implementation of GroupOptionType for text values.\r
+ * The merge of option values returns merge of all text values.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.option.group\r
+ * @category   Community Framework\r
+ */\r
+class GroupOptionTypeTextarea extends OptionTypeTextarea implements GroupOptionType {\r
+       /**\r
+        * @see GroupOptionType::merge()\r
+        */\r
+       public function merge(array $values) {\r
+               $result = '';\r
+               \r
+               foreach ($values as $value) {\r
+                       if (!empty($result)) $result .= "\n";\r
+                       $result .= $value;\r
+               }\r
+\r
+               return $result;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/package/ACPTemplatesFileHandler.class.php b/wcfsetup/install/files/lib/system/package/ACPTemplatesFileHandler.class.php
new file mode 100644 (file)
index 0000000..45f7e80
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+namespace wcf\system\package;
+use wcf\data\package\Package;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * ACPTemplatesFileHandler is a FileHandler implementation for the installation of ACP-template files.
+ * 
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class ACPTemplatesFileHandler extends PackageInstallationFileHandler {
+       protected $tableName = '_acp_template';
+       
+       /**
+        * @see FileHandler::checkFiles()
+        */
+       public function checkFiles(array $files) {
+               if ($this->packageInstallation->getPackage()->package != 'com.woltlab.wcf') {
+                       $packageID = $this->packageInstallation->getPackageID();
+                       
+                       // build sql string with ACP-templateNames
+                       $fileNames = array();
+                       foreach ($files as $file) {
+                               $fileName = preg_replace("~\.tpl$~", "", $file);
+                               $fileNames[] = $fileName;
+                       }
+                       
+                       // check if files are existing already
+                       if (!empty($fileNames)) {
+                               // get by other packages registered files
+                               $conditions = new PreparedStatementConditionBuilder();
+                               $conditions->add("packageID <> ?", array($packageID));
+                               $conditions->add("packageID IN (SELECT packageID FROM wcf".WCF_N."_package WHERE packageDir = ? AND standalone = ?)", array($this->packageInstallation->getPackage()->packageDir, 0));
+                               $conditions->add("templateName IN (?)", array($fileNames));
+                               
+                               $sql = "SELECT          *
+                                       FROM            wcf".WCF_N.$this->tableName."
+                                       ".$conditions;
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute($conditions->getParameters());
+                               
+                               $lockedFiles = array();
+                               while ($row = $statement->fetchArray()) {
+                                       $lockedFiles[$row['templateName']] = $row['packageID'];
+                               }
+                               
+                               // check if files from installing package are in conflict with already installed files
+                               if (!$this->packageInstallation->getPackage()->standalone && count($lockedFiles) > 0) {
+                                       foreach ($fileNames as $key => $file) {
+                                               if (isset($lockedFiles[$file]) && $packageID != $lockedFiles[$file]) {
+                                                       $owningPackage = new Package($lockedFiles[$file]);
+                                                       throw new SystemException("A non-standalone package can't overwrite template files. Only an update from the package which owns the template can do that. (Package '".$this->packageInstallation->getPackage()->getPackage()."' tries to overwrite template '".$file."', which is owned by package '".$owningPackage->package."')", 13026);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * @see FileHandler::logFiles()
+        */
+       public function logFiles(array $files) {
+               $packageID = $this->packageInstallation->getPackageID();
+               
+               // remove file extension
+               foreach ($files as &$file) {
+                       $file = preg_replace('~.tpl$~','', $file);
+               }
+               unset($file);
+               
+               // get existing templates
+               $sql = "SELECT  templateName
+                       FROM    wcf".WCF_N.$this->tableName."
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               
+               while ($row = $statement->fetchArray()) {
+                       $index = array_search($row['templateName'], $files);
+                       
+                       if ($index !== false) {
+                               unset($files[$index]);
+                       }
+               }
+               
+               if (count($files)) {
+                       $sql = "INSERT INTO     wcf".WCF_N.$this->tableName."
+                                               (packageID, templateName)
+                               VALUES          (?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($files as $file) {
+                               $statement->execute(array(
+                                       $packageID,
+                                       $file
+                               ));
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/FilesFileHandler.class.php b/wcfsetup/install/files/lib/system/package/FilesFileHandler.class.php
new file mode 100644 (file)
index 0000000..555900c
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+namespace wcf\system\package;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * FilesFileHandler is a FileHandler implementation for the installation of regular files.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class FilesFileHandler extends PackageInstallationFileHandler {
+       /**
+        * @see FileHandler::checkFiles()
+        */
+       public function checkFiles(array $files) {
+               if ($this->packageInstallation->getPackage()->package != 'com.woltlab.wcf') {
+                       if (!empty($files)) {
+                               // get by other packages registered files
+                               $conditions = new PreparedStatementConditionBuilder();
+                               $conditions->add("file_log.packageID <> ?", array($this->packageInstallation->getPackageID()));
+                               $conditions->add("file_log.filename IN (?)", array($files));
+                               
+                               $sql = "SELECT          file_log.filename, package.packageDir
+                                       FROM            wcf".WCF_N."_package_installation_file_log file_log
+                                       LEFT JOIN       wcf".WCF_N."_package package
+                                       ON              (package.packageID = file_log.packageID)
+                                       ".$conditions;
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute($conditions->getParameters());
+                               $lockedFiles = array();
+                               while ($row = $statement->fetchArray()) {
+                                       $lockedFiles[$row['packageDir'].$row['filename']] = true;
+                               }
+                               
+                               // check delivered files
+                               if (count($lockedFiles) > 0) {
+                                       $dir = $this->packageInstallation->getPackage()->packageDir;
+                                       foreach ($files as $key => $file) {
+                                               if (isset($lockedFiles[$dir.$file])) {
+                                                       unset($files[$key]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * @see FileHandler::logFiles()
+        */
+       public function logFiles(array $files) {
+               if (empty($files)) {
+                       return;
+               }
+               
+               // fetch already installed files
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("packageID = ?", array($this->packageInstallation->getPackageID()));
+               $conditions->add("filename IN (?)", array($files));
+               
+               $sql = "SELECT  filename
+                       FROM    wcf".WCF_N."_package_installation_file_log
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               $installedFiles = array();
+               while ($row = $statement->fetchArray()) {
+                       $installedFiles[] = $row['filename'];
+               }
+               
+               // ignore files which have already been installed
+               $installFiles = array();
+               foreach ($files as $file) {
+                       if (in_array($file, $files)) {
+                               continue;
+                       }
+                       
+                       $installFiles[] = $file;
+               }
+               
+               if (!empty($installedFiles)) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_file_log
+                                               (packageID, filename)
+                               VALUES          (?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($installFiles as $file) {
+                               $statement->execute(array(
+                                       $this->packageInstallation->getPackageID(),
+                                       $file
+                               ));
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageArchive.class.php b/wcfsetup/install/files/lib/system/package/PackageArchive.class.php
new file mode 100644 (file)
index 0000000..9b78469
--- /dev/null
@@ -0,0 +1,881 @@
+<?php
+namespace wcf\system\package;
+use wcf\data\package\Package;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\io\Tar;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\StringUtil;
+use wcf\util\XML;
+
+/**
+ * This class holds all information of a package archive. 
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageArchive {
+       /**
+        * path to archive
+        *
+        * @var string
+        */
+       protected $archive = null;
+       
+       /**
+        * package object of an existing package
+        *
+        * @var Package
+        */
+       protected $package = null;
+       
+       /**
+        * tar archive object
+        *
+        * @var Tar
+        */
+       protected $tar = null;
+       
+       /**
+        * general package information
+        *
+        * @var array
+        */
+       protected $packageInfo = array();
+       
+       /**
+        * author information
+        *
+        * @var array
+        */
+       protected $authorInfo = array();
+       
+       /**
+        * list of requirements
+        *
+        * @var array
+        */
+       protected $requirements = array();
+       
+       /**
+        * list of optional packages
+        *
+        * @var array
+        */
+       protected $optionals = array();
+       
+       /**
+        * list of excluded packages
+        * 
+        * @var array
+        */
+       protected $excludedPackages = array();
+       
+       /**
+        * list of instructions
+        * 
+        * @var array<array>
+        */     
+       protected $instructions = array(
+               'install' => array(),
+               'update' => array()
+       );
+       
+       /**
+        * list of php requirements
+        * 
+        * @var array<array>
+        */
+       protected $phpRequirements = array();
+       
+       /**
+        * default name of the package.xml file
+        *
+        * @var string
+        */
+       const INFO_FILE = 'package.xml';
+       
+       /**
+        * Creates a new PackageArchive object.
+        * 
+        * @param       string          $archive
+        * @param       Package         $package
+        */
+       public function __construct($archive, Package $package = null) {
+               $this->archive = $archive;      // be careful: this is a string within this class, 
+                                               // but an object in the packageStartInstallForm.class!
+               $this->package = $package;
+       }
+       
+       /**
+        * Returns the name of the package archive.
+        * 
+        * @return      string
+        */
+       public function getArchive() {
+               return $this->archive;
+       }
+       
+       /**
+        * Returns the object of the package archive.
+        * 
+        * @return      Tar
+        */
+       public function getTar() {
+               return $this->tar;
+       }
+       
+       /**
+        * Opens the package archive and reads package information.
+        */
+       public function openArchive() {
+               // check whether archive exists and is a TAR archive
+               if (!file_exists($this->archive)) {
+                       throw new SystemException("unable to find package file '".$this->archive."'", 11002);
+               }
+
+               // open archive and read package information
+               $this->tar = new Tar($this->archive);
+               $this->readPackageInfo();
+       }
+       
+       /**
+        * Extracts information about this package (parses package.xml).
+        */
+       protected function readPackageInfo() {
+               // search package.xml in package archive
+               // throw error message if not found
+               if ($this->tar->getIndexByFilename(self::INFO_FILE) === false) {
+                       throw new SystemException("package information file '".(self::INFO_FILE)."' not found in '".$this->archive."'", 13000);
+               }
+               
+               // extract package.xml, parse with SimpleXML
+               // and compile an array with XML::getElementTree()
+               $xml = new XML();
+               try {
+                       $xml->loadXML(self::INFO_FILE, $this->tar->extractToString(self::INFO_FILE));
+               }
+               catch (Exception $e) { // bugfix to avoid file caching problems
+                       $xml->loadXML(self::INFO_FILE, $this->tar->extractToString(self::INFO_FILE));
+               }
+               
+               // parse xml
+               $xpath = $xml->xpath();
+               $package = $xpath->query('/ns:package')->item(0);
+               
+               // package name
+               $packageName = $package->getAttribute('name');
+               if (!Package::isValidPackageName($packageName)) {
+                       // package name is not a valid package identifier
+                       throw new SystemException("'".$packageName."' is not a valid package name.", 13002);
+               }
+               
+               $this->packageInfo['name'] = $packageName;
+               
+               // get package information
+               $packageInformation = $xpath->query('./ns:packageinformation', $package)->item(0);
+               $elements = $xpath->query('child::*', $packageInformation);
+               foreach ($elements as $element) {
+                       switch ($element->tagName) {
+                               case 'packagename':
+                               case 'packagedescription':
+                               case 'readme':
+                               case 'license':
+                                       if (!isset($this->packageInfo[$element->tagName])) $this->packageInfo[$element->tagName] = array();
+                                       
+                                       $languageCode = 'default';
+                                       if ($element->hasAttribute('language')) {
+                                               $languageCode = $element->getAttribute('language');
+                                       }
+                                       
+                                       // fix case-sensitive names
+                                       $name = $element->tagName;
+                                       if ($name == 'packagename') $name = 'packageName';
+                                       else if ($name == 'packagedescription') $name = 'packageDescription';
+                                       
+                                       $this->packageInfo[$name][$languageCode] = $element->nodeValue;
+                               break;
+                               
+                               case 'standalone':
+                                       $this->packageInfo['standalone'] = intval($element->nodeValue);
+                               break;
+                               
+                               case 'plugin':
+                                       if ($element->nodeValue && !Package::isValidPackageName($element->nodeValue)) {
+                                               throw new SystemException("'".$element->nodeValue."' is not a valid package name.", 13002);
+                                       }
+                                       
+                                       $this->packageInfo['plugin'] = $element->nodeValue;
+                               break;
+                               
+                               case 'packageurl':
+                                       $this->packageInfo['packageURL'] = $element->nodeValue;
+                               break;
+                               
+                               case 'version':
+                                       if (!preg_match('~^([0-9]+)\.([0-9]+)\.([0-9]+)(\ (a|alpha|b|beta|d|dev|rc|pl)\ ([0-9]+))?$~is', $element->nodeValue)) {
+                                               throw new SystemException("package version '".$element->nodeValue."' is invalid");
+                                       }
+                                       
+                                       $this->packageInfo['version'] = $element->nodeValue;
+                               break;
+                               
+                               case 'date':
+                                       // matches almost any valid date between year 2000 and 2038
+                                       if (!preg_match('~^(20[0-2][0-9]|203[0-8])\-(0[1-9]|1[0-2])\-(0[1-9]|[1-2][0-9]|3[0-1])$~', $element->nodeValue)) {
+                                               throw new SystemException("package date '".$element->nodeValue."' is invalid, violating ISO-8601 date format.");
+                                       }
+                                       
+                                       $this->packageInfo['date'] = strtotime($element->nodeValue) + 43201; // TODO: Is this even neccessary?
+                               break;
+                       }
+               }
+               
+               // get author information
+               $authorInformation = $xpath->query('./ns:authorinformation', $package)->item(0);
+               $elements = $xpath->query('child::*', $authorInformation);
+               foreach ($elements as $element) {
+                       $tagName = ($element->tagName == 'authorurl') ? 'authorURL' : $element->tagName;
+                       $this->authorInfo[$tagName] = $element->nodeValue;
+               }
+               
+               // get required packages
+               $elements = $xpath->query('child::ns:requiredpackages/ns:requiredpackage', $package);
+               foreach ($elements as $element) {
+                       if (!Package::isValidPackageName($element->nodeValue)) {
+                               throw new SystemException("'".$element->nodeValue."' is not a valid package name.", 13002);
+                       }
+                       
+                       // read attributes
+                       $data = array('name' => $element->nodeValue);
+                       $attributes = $xpath->query('attribute::*', $element);
+                       foreach ($attributes as $attribute) {
+                               $data[$attribute->name] = $attribute->value;
+                       }
+                                       
+                       $this->requirements[$element->nodeValue] = $data;
+               }
+                
+                // get optional packages
+               $elements = $xpath->query('child::ns:optionalpackages/ns:optionalpackage', $package);
+               foreach ($elements as $element) {
+                       if (!Package::isValidPackageName($element->nodeValue)) {
+                               throw new SystemException("'".$element->nodeValue."' is not a valid package name.", 13002);
+                       }
+                       
+                       // read attributes
+                       $data = array('name' => $element->nodeValue);
+                       $attributes = $xpath->query('attribute::*', $element);
+                       foreach ($attributes as $attribute) {
+                               $data[$attribute->name] = $attribute->value;
+                       }
+                                       
+                       $this->optionals[] = $data;
+               }
+               
+               // get excluded packages
+               $elements = $xpath->query('child::ns:excludedpackages/ns:excludedpackage', $package);
+               foreach ($elements as $element) {
+                       if (!Package::isValidPackageName($element->nodeValue)) {
+                               throw new SystemException("'".$element->nodeValue."' is not a valid package name.", 13002);
+                       }
+                       
+                       // read attributes
+                       $data = array('name' => $element->nodeValue);
+                       $attributes = $xpath->query('attribute::*', $element);
+                       foreach ($attributes as $attribute) {
+                               $data[$attribute->name] = $attribute->value;
+                       }
+                       
+                       $this->excludedPackages[] = $data;
+               }
+               
+               // get instructions
+               $elements = $xpath->query('./ns:instructions', $package);
+               foreach ($elements as $element) {
+                       $instructionData = array();
+                       $instructions = $xpath->query('./ns:instruction', $element);
+                       foreach ($instructions as $instruction) {
+                               $data = array();
+                               $attributes = $xpath->query('attribute::*', $instruction);
+                               foreach ($attributes as $attribute) {
+                                       $data[$attribute->name] = $attribute->value;
+                               }
+                               
+                               $instructionData[] = array(
+                                       'attributes' => $data,
+                                       'pip' => $instruction->getAttribute('type'),
+                                       'value' => $instruction->nodeValue
+                               );
+                       }
+                       
+                       $fromVersion = $element->getAttribute('fromversion');
+                       $type = $element->getAttribute('type');
+                       
+                       if ($type == 'install') {
+                               $this->instructions['install'] = $instructionData;
+                       }
+                       else {
+                               $this->instructions['update'][$fromVersion][] = $instructionData;
+                       }
+               }
+               
+               // get php requirements
+               $requirements = $xpath->query('./ns:phprequirements', $package);
+               foreach ($requirements as $requirement) {
+                       $elements = $xpath->query('child::*', $requirement);
+                       foreach ($elements as $element) {
+                               switch ($element->tagName) {
+                                       case 'version':
+                                               $this->phpRequirements['version'] = $element->nodeValue;
+                                               break;
+                                       
+                                       case 'setting':
+                                               $this->phpRequirements['settings'][$element->getAttribute('name')] = $element->nodeValue;
+                                               break;
+                                       
+                                       case 'extension':
+                                               $this->phpRequirements['extensions'][] = $element->nodeValue;
+                                               break;
+                                       
+                                       case 'function':
+                                               $this->phpRequirements['functions'][] = $element->nodeValue;
+                                               break;
+                                       
+                                       case 'class':
+                                               $this->phpRequirements['classes'][] = $element->nodeValue;
+                                               break;
+                               }
+                       }
+               }
+               
+               // add com.woltlab.wcf to package requirements
+               if (!isset($this->requirements['com.woltlab.wcf']) && $this->packageInfo['name'] != 'com.woltlab.wcf') {
+                       $this->requirements['com.woltlab.wcf'] = array('name' => 'com.woltlab.wcf');
+               }
+               
+               if ($this->package != null) {
+                       $validFromVersion = null;
+                       foreach ($this->update as $fromVersion => $update) {
+                               if (Package::checkFromversion($this->package->packageVersion, $fromVersion)) {
+                                       $validFromVersion = $fromVersion;
+                                       break;
+                               }
+                       }
+                       if ($validFromVersion === null) {
+                               $this->instructions['update'] = array();
+                       }
+                       else {
+                               $this->instructions['update'] = $this->instructions['update'][$validFromVersion];
+                       }
+               }
+               
+               // set default values
+               if (!isset($this->packageInfo['standalone'])) $this->packageInfo['standalone'] = 0;
+               if (!isset($this->packageInfo['plugin'])) $this->packageInfo['plugin'] = '';
+               if (!isset($this->packageInfo['packageURL'])) $this->packageInfo['packageURL'] = '';
+               
+               // get package name in selected language
+               $this->getLocalizedInformation('packageName');
+               
+               // get package description in selected language
+               if (isset($this->packageInfo['packageDescription'])) {
+                       $this->getLocalizedInformation('packageDescription');
+               }
+               
+               // get package license in selected language
+               if (isset($this->packageInfo['license'])) {
+                       $this->getLocalizedInformation('license');
+               }
+               
+               // get package information in selected language
+               if (isset($this->packageInfo['readme'])) {
+                       $this->getLocalizedInformation('readme');
+               }
+               
+               // add plugin to requirements
+               if ($this->packageInfo['plugin'] && !isset($this->requirements[$this->packageInfo['plugin']])) {
+                       $this->requirements[$this->packageInfo['plugin']] = array('name' => $this->packageInfo['plugin']);
+               }
+       }
+       
+       /**
+        * Gets localized package information strings.
+        * 
+        * @param       string          $key
+        */
+       protected function getLocalizedInformation($key) {
+               if (isset($this->packageInfo[$key][LANGUAGE_CODE])) {
+                       $this->packageInfo[$key] = $this->packageInfo[$key][LANGUAGE_CODE];
+               }
+               else if (isset($this->packageInfo[$key]['default'])) {
+                       $this->packageInfo[$key] = $this->packageInfo[$key]['default'];
+               }
+               else {
+                       $this->packageInfo[$key] = array_shift($this->packageInfo[$key]);
+               }
+       }
+       
+       /**
+        * Downloads the package archive.
+        * 
+        * @return      string          path to the dowloaded file
+        */
+       public function downloadArchive() {
+               $parsedUrl = parse_url($this->archive);
+               $prefix = 'package';
+               
+               // file transfer via hypertext transfer protocol.
+               $this->archive = FileUtil::downloadFileFromHttp($this->archive, $prefix);
+               
+               // unzip tar
+               $this->archive = self::unzipPackageArchive($this->archive);
+               
+               return $this->archive;
+       }
+       
+       /**
+        * Closes and deletes the tar archive of this package. 
+        */
+       public function deleteArchive() {
+               if ($this->tar instanceof Tar) {
+                       $this->tar->close();
+               }
+               
+               @unlink($this->archive);
+       }
+       
+       /**
+        * Return true, if the package archive supports a new installation.
+        * 
+        * @return      boolean
+        */
+       public function isValidInstall() {
+               return !empty($this->instructions['install']);
+       }
+       
+       /**
+        * Checks if the new package is compatible with
+        * the package that is about to be updated.
+        *
+        * @return      boolean         isValidUpdate
+        */
+       public function isValidUpdate() {
+               // Check name of the installed package against the name of the update. Both must be identical.
+               if ($this->packageInfo['name'] != $this->package->package) {
+                       return false;
+               }
+               
+               // Check if the version number of the installed package is lower than the version number to which
+               // it's about to be updated.
+               if (Package::compareVersion($this->packageInfo['version'], $this->package->packageVersion) != 1) {
+                       return false;
+               }
+               // Check if the package provides an instructions block for the update from the installed package version
+               if (empty($this->instructions['update'])) {
+                       return false;
+               }
+               return true;
+       }
+       
+       /**
+        * checks if the current package is already installed
+        * 
+        * if the package is not a unique package, this method
+        * returns false, because a non-unique package may be
+        * installed as many times as one wants while a unique 
+        * package can only be installed once.
+        *
+        * @return      boolean         isAlreadyInstalled
+        * @todo        FIX THIS (isUnique is deprecated)
+        */
+       public function isAlreadyInstalled() {
+               // is not a unique package and can be
+               // installed as many times as you want
+               //if ($this->packageInfo['isUnique'] == 0) {
+               //      return false;
+               //}
+               // this package may only be installed
+               // once (e. g. library package)
+               //else {
+                       return (count($this->getDuplicates()) != 0);
+               //}
+       }
+       
+       /**
+        * Returns a list of all installed instances of this package.
+        * 
+        * @return      array           packages
+        */
+       public function getDuplicates() {
+               $packages = array();
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_package 
+                       WHERE   package = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->packageInfo['name']));
+               while ($row = $statement->fetchArray()) {
+                       $packages[$row['packageID']] = $row;
+               }
+               
+               return $packages;
+       }
+       
+       /**
+        * Returns a list of all updatable instances of this package.
+        * 
+        * @return      array           packages
+        */
+       public function getUpdatableInstances() {
+               $packages = $this->getDuplicates();
+               $updatable = array();
+               $newVersion = $this->packageInfo['version'];
+               
+               foreach ($packages as $package) {
+                       if (Package::compareVersion($newVersion, $package['packageVersion']) == 1) {
+                               $updatable[$package['packageID']] = $package;
+                       }
+               }
+               
+               return $updatable;
+       }
+       
+       /**
+        * Returns information about the author of this package archive.
+        * 
+        * @param       string          $name           name of the requested information
+        * @return      string
+        */
+       public function getAuthorInfo($name) {
+               if (isset($this->authorInfo[$name])) return $this->authorInfo[$name];
+               return null;
+       }
+       
+       /**
+        * Returns information about this package.
+        * 
+        * @param       string          $name           name of the requested information
+        * @return      mixed
+        */
+       public function getPackageInfo($name) {
+               if (isset($this->packageInfo[$name])) return $this->packageInfo[$name];
+               return null;
+       }
+       
+       /**
+        * Returns a list of all requirements of this package.
+        * 
+        * @return      array
+        */
+       public function getRequirements() {
+               return $this->requirements;
+       }
+       
+       /**
+        * Returns a list of all delivered optional packages of this package.
+        * 
+        * @return      array
+        */
+       public function getOptionals() {
+               return $this->optionals;
+       }
+       
+       /**
+        * Returns a list of excluded packages.
+        * 
+        * @return      array
+        */
+       public function getExcludedPackages() {
+               return $this->excludedPackages;
+       }
+       
+       /**
+        * Returns the package installation instructions.
+        * 
+        * @return      array
+        */
+       public function getInstallInstructions() {
+               return $this->instructions['install'];
+       }
+       
+       /**
+        * Returns the package update instructions.
+        * 
+        * @return      array
+        */
+       public function getUpdateInstructions() {
+               return $this->instructions['update'];
+       }
+       
+       /**
+        * Checks which package requirements do already exist in right version.
+        * Returns a list with all existing requirements.
+        * 
+        * @return      array
+        */
+       public function getAllExistingRequirements() {
+               $existingRequirements = array();
+               $existingPackages = array();
+               if ($this->package !== null) {
+                       $sql = "SELECT          package.*, CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                               FROM            wcf".WCF_N."_package_requirement requirement
+                               LEFT JOIN       wcf".WCF_N."_package package
+                               ON              (package.packageID = requirement.requirement)
+                               WHERE           requirement.packageID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->package->packageID));
+                       while ($row = $statement->fetchArray()) {
+                               $existingRequirements[$row['package']] = $row;
+                       }
+               }
+
+               // build sql
+               $packageNames = array();
+               $requirements = $this->getRequirements();
+               foreach ($requirements as $requirement) {
+                       if (isset($existingRequirements[$requirement['name']])) {
+                               $existingPackages[$requirement['name']] = array();
+                               $existingPackages[$requirement['name']][$existingRequirements[$requirement['name']]['packageID']] = $existingRequirements[$requirement['name']];
+                       }
+                       else {
+                               $packageNames[] = $requirement['name'];
+                       }
+               }
+       
+               // check whether the required packages do already exist
+               if (!empty($packageNames)) {
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("package.package IN (?)", array($packageNames));
+                       
+                       $sql = "SELECT  package.*, CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                               FROM    wcf".WCF_N."_package package
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               // check required package version
+                               if (isset($requirements[$row['package']]['minversion']) && Package::compareVersion($row['packageVersion'], $requirements[$row['package']]['minversion']) == -1) {
+                                       continue;
+                               }
+                               
+                               if (!isset($existingPackages[$row['package']])) {
+                                       $existingPackages[$row['package']] = array();
+                               }
+                               
+                               $existingPackages[$row['package']][$row['packageID']] = $row;
+                       }
+               }
+               
+               return $existingPackages;
+       }
+       
+       /**
+        * Checks which package requirements do already exist in database.
+        * Returns a list with the existing requirements.
+        * 
+        * @return      array
+        */
+       public function getExistingRequirements() {
+               // build sql
+               $packageNames = array();
+               foreach ($this->requirements as $requirement) {
+                       $packageNames[] = $requirement['name'];
+               }
+       
+               // check whether the required packages do already exist
+               $existingPackages = array();
+               if (!empty($packageNames)) {
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("package IN (?)", array($packageNames));
+                       
+                       $sql = "SELECT  *
+                               FROM    wcf".WCF_N."_package
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               if (!isset($existingPackages[$row['package']])) {
+                                       $existingPackages[$row['package']] = array();
+                               }
+                               
+                               $existingPackages[$row['package']][$row['packageVersion']] = $row;
+                       }
+                       
+                       // sort multiple packages by version number
+                       foreach ($existingPackages as $packageName => $instances) {
+                               uksort($instances, array('wcf\data\package\Package', 'compareVersion'));
+                               
+                               // get package with highest version number (get last package)
+                               $existingPackages[$packageName] = array_pop($instances);        
+                       }
+               }
+               
+               return $existingPackages;
+       }
+       
+       /**
+        * Returns a list of all open requirements of this package.
+        * 
+        * @return      array
+        */
+       public function getOpenRequirements() {
+               // get all existing requirements
+               $existingPackages = $this->getExistingRequirements();
+               
+               // check for open requirements
+               $openRequirements = array();
+               foreach ($this->requirements as $requirement) {
+                       if (isset($existingPackages[$requirement['name']])) {
+                               // package does already exist
+                               // maybe an update is necessary
+                               if (!isset($requirement['minversion']) || Package::compareVersion($existingPackages[$requirement['name']]['packageVersion'], $requirement['minversion']) >= 0) {
+                                       // package does already exist in needed version
+                                       // skip installation of requirement 
+                                       continue;
+                               }
+                               
+                               $requirement['packageID'] = $existingPackages[$requirement['name']]['packageID'];
+                               $requirement['action'] = 'update';
+                       }
+                       else {
+                               // package does not exist
+                               // new installation is necessary
+                               $requirement['packageID'] = 0;
+                               $requirement['action'] = 'install';
+                       }
+                       
+                       $openRequirements[$requirement['name']] = $requirement;
+               }
+               
+               return $openRequirements;
+       }
+       
+       /**
+        * Extracts the requested file in the package archive to the temp folder.
+        * 
+        * @param       string          $filename
+        * @param       string          $tempPrefix
+        * @return      string          path to the extracted file
+        */
+       public function extractTar($filename, $tempPrefix = 'package_') {
+               // search the requested tar archive in our package archive.
+               // throw error message if not found.
+               if (($fileIndex = $this->tar->getIndexByFilename($filename)) === false) {
+                       throw new SystemException("tar archive '".$filename."' not found in '".$this->archive."'.", 13007);
+               }
+               
+               // requested tar archive was found
+               $fileInfo = $this->tar->getFileInfo($fileIndex);
+               $filename = FileUtil::getTemporaryFilename($tempPrefix, preg_replace('!^.*?(\.(?:tar\.gz|tgz|tar))$!i', '\\1', $fileInfo['filename']));
+               $this->tar->extract($fileIndex, $filename);
+               
+               return $filename;
+       }
+       
+       /**
+        * Unzips compressed package archives.
+        * 
+        * @param       string          $archive        filename
+        * @return      string          new filename
+        */
+       public static function unzipPackageArchive($archive) {
+               if (!FileUtil::isURL($archive)) {
+                       $tar = new Tar($archive);
+                       $tar->close();
+                       if ($tar->isZipped()) {
+                               $tmpName = FileUtil::getTemporaryFilename('package_');
+                               if (FileUtil::uncompressFile($archive, $tmpName)) {
+                                       return $tmpName;
+                               }
+                       }
+               }
+               
+               return $archive;
+       }
+       
+       /**
+        * Returns a list of packages, which excluding this package.
+        * 
+        * @return      array
+        */
+       public function getConflictedExcludingPackages() {
+               $conflictedPackages = array();
+               $sql = "SELECT          package.*, package_exclusion.*
+                       FROM            wcf".WCF_N."_package_exclusion package_exclusion
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = package_exclusion.packageID)       
+                       WHERE           excludedPackage = ?'".$this->packageInfo['name']."'";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->packageInfo['name']));
+               while ($row = $statement->fetchArray()) {
+                       if (!empty($row['excludedPackageVersion'])) {
+                               if (Package::compareVersion($this->packageInfo['version'], $row['excludedPackageVersion'], '<')) {
+                                       continue;
+                               }
+                       }
+                       
+                       $conflictedPackages[$row['packageID']] = $row;
+               }
+               
+               return $conflictedPackages;
+       }
+       
+       /**
+        * Returns a list of packages, which are excluded by this package.
+        * 
+        * @return      array
+        */
+       public function getConflictedExcludedPackages() {
+               $conflictedPackages = array();
+               if (count($this->excludedPackages) > 0) {
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("package IN (?)", array(array_keys($this->excludedPackages)));
+                       
+                       $sql = "SELECT  *
+                               FROM    wcf".WCF_N."_package
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               if (!empty($this->excludedPackages[$row['package']]['version'])) {
+                                       if (Package::compareVersion($row['packageVersion'], $this->excludedPackages[$row['package']]['version'], '<')) {
+                                               continue;
+                                       }
+                               }
+                               
+                               $conflictedPackages[$row['packageID']] = $row;
+                       }
+               }
+               
+               return $conflictedPackages;
+       }
+       
+       /**
+        * Returns a list of instructions for installation or update.
+        * 
+        * @param       string          $type
+        * @return      array
+        */
+       public function getInstructions($type) {
+               if (isset($this->instructions[$type])) {
+                       return $this->instructions[$type];
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Returns a list of php requirements for current package.
+        * 
+        * @return      array<array>
+        */
+       public function getPhpRequirements() {
+               return $this->phpRequirements;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageDependencyHandler.class.php b/wcfsetup/install/files/lib/system/package/PackageDependencyHandler.class.php
new file mode 100644 (file)
index 0000000..a864c5b
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+namespace wcf\system\package;
+use wcf\system\cache\CacheHandler;
+
+/**
+ * PackageDependencyHandler stores package dependencies and providing a consistent interface for accessing.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+abstract class PackageDependencyHandler {
+       /**
+        * cache of package dependencies
+        *
+        * @var array
+        */     
+       protected static $packageDependencyCache = null;
+       
+       /**
+        * Returns the id of a specific package in the active dependencies.
+        *
+        * @param       string          $package        package identifier
+        * @return      mixed
+        */     
+       public static function getPackageID($package) {
+               if (!defined('PACKAGE_ID')) {
+                       return null;
+               }
+               
+               if (self::$packageDependencyCache === null) {
+                       self::readCache();
+               }
+               
+               if (isset(self::$packageDependencyCache['resolve'][$package])) {
+                       $packageID = self::$packageDependencyCache['resolve'][$package];
+                       
+                       if (is_array($packageID)) {
+                               $packageID = array_shift($packageID);
+                       }
+                       
+                       return $packageID;
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Returns the package ids of all dependent packages.
+        *
+        * @return      array
+        */     
+       public static function getDependencies() {
+               if (!defined('PACKAGE_ID')) {
+                       return null;
+               }
+               
+               if (self::$packageDependencyCache === null) {
+                       self::readCache();
+               }
+               
+               return self::$packageDependencyCache['dependency'];
+       }
+       
+       /**
+        * Reads package dependency cache.
+        */     
+       protected static function readCache() {
+               CacheHandler::getInstance()->addResource(
+                       'packageDependencies-'.PACKAGE_ID,
+                       WCF_DIR.'cache/cache.packageDependencies-'.PACKAGE_ID.'.php',
+                       'wcf\system\cache\CacheBuilderPackageDependency'
+               );
+               
+               self::$packageDependencyCache = CacheHandler::getInstance()->get('packageDependencies-'.PACKAGE_ID);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php
new file mode 100644 (file)
index 0000000..31042ac
--- /dev/null
@@ -0,0 +1,777 @@
+<?php
+namespace wcf\system\package;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\data\application\ApplicationEditor;
+use wcf\data\language\LanguageEditor;
+use wcf\data\package\installation\queue\PackageInstallationQueue;
+use wcf\data\package\installation\queue\PackageInstallationQueueEditor;
+use wcf\data\package\Package;
+use wcf\data\package\PackageEditor;
+use wcf\system\cache\CacheHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\form;
+use wcf\system\form\container;
+use wcf\system\form\element;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\HeaderUtil;
+use wcf\util\StringUtil;
+
+/**
+ * PackageInstallationDispatcher handles the whole installation process.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageInstallationDispatcher {
+       /**
+        * current installation type
+        *
+        * @var string
+        */
+       protected $action = '';
+       
+       /**
+        * instance of PackageArchive
+        *
+        * @var PackageArchive
+        */
+       public $archive = null;
+       
+       /**
+        * instance of PackageInstallationNodeBuilder
+        *
+        * @var PackageInstallationNodeBuilder
+        */
+       public $nodeBuilder = null;
+       
+       /**
+        * instance of Package
+        *
+        * @var Package
+        */
+       public $package = null;
+       
+       /**
+        * instance of PackageInstallationQueue
+        *
+        * @var PackageInstallationQueue
+        */
+       public $queue = null;
+       
+       /**
+        * default name of the config file
+        *
+        * @var string
+        */
+       const CONFIG_FILE = 'config.inc.php';
+       
+       /**
+        * Creates a new instance of PackageInstallationDispatcher.
+        *
+        * @param       PackageInstallationQueue        $queue
+        */
+       public function __construct(PackageInstallationQueue $queue) {
+               $this->queue = $queue;
+               $this->nodeBuilder = new PackageInstallationNodeBuilder($this);
+               
+               $this->action = $this->queue->action;
+       }
+       
+       /**
+        * Installs node components and returns next node.
+        *
+        * @param       string          $node
+        * @return      PackageInstallationStep
+        */
+       public function install($node) {
+               $nodes = $this->nodeBuilder->getNodeData($node);
+               
+               // invoke node-specific actions
+               foreach ($nodes as $data) {
+                       $nodeData = unserialize($data['nodeData']);
+                       
+                       switch ($data['nodeType']) {
+                               case 'package':
+                                       $step = $this->installPackage($nodeData);
+                               break;
+                               
+                               case 'pip':
+                                       $step = $this->executePIP($nodeData);
+                               break;
+                       }
+                       
+                       if ($step->splitNode()) {
+                               $this->nodeBuilder->insertNode($node, $data['sequenceNo']);
+                               break;
+                       }
+               }
+               
+               // mark node as completed
+               $this->nodeBuilder->completeNode($node);
+               
+               // assign next node
+               $step->setNode($this->nodeBuilder->getNextNode($node));
+               
+               return $step;
+       }
+       
+       /**
+        * Returns current package archive.
+        *
+        * @return      PackageArchive
+        */
+       public function getArchive() {
+               if ($this->archive === null) {
+                       $this->archive = new PackageArchive($this->queue->archive);
+                       
+                       if (FileUtil::isURL($this->archive->getArchive())) {
+                               // get return value and update entry in
+                               // package_installation_queue with this value
+                               $archive = $this->archive->downloadArchive();
+                               $queueEditor = new PackageInstallationQueueEditor($this->queue);
+                               $queueEditor->update(array(
+                                       'archive' => $archive
+                               ));
+                       }
+                       
+                       $this->archive->openArchive();
+               }
+               
+               return $this->archive;
+       }
+       
+       /**
+        * Installs current package.
+        *
+        * @param       array           $nodeData
+        */
+       protected function installPackage(array $nodeData) {
+               $installationStep = new PackageInstallationStep();
+               
+               if (!$this->queue->packageID) {
+                       // create package entry
+                       $package = PackageEditor::create($nodeData);
+                       
+                       // update package id for current queue
+                       $queueEditor = new PackageInstallationQueueEditor($this->queue);
+                       $queueEditor->update(array(
+                               'packageID' => $package->packageID
+                       ));
+                       
+                       // save excluded packages
+                       if (count($this->getArchive()->getExcludedPackages()) > 0) {
+                               $sql = "INSERT INTO     wcf".WCF_N."_package_exclusion 
+                                                       (packageID, excludedPackage, excludedPackageVersion)
+                                       VALUES          (?, ?, ?)";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               
+                               foreach ($this->getArchive()->getExcludedPackages() as $excludedPackage) {
+                                       $statement->execute(array($package->packageID, $excludedPackage['name'], (!empty($excludedPackage['version']) ? $excludedPackage['version'] : '')));
+                               }
+                       }
+                       
+                       // insert requirements and dependencies
+                       $requirements = $this->getArchive()->getAllExistingRequirements();
+                       if (count($requirements) > 0) {
+                               $sql = "INSERT INTO     wcf".WCF_N."_package_requirement
+                                                       (packageID, requirement)
+                                       VALUES          (?, ?)";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               
+                               foreach ($requirements as $identifier => $possibleRequirements) {
+                                       if (count($possibleRequirements) == 1) $requirement = array_shift($possibleRequirements);
+                                       else {
+                                               $requirement = $possibleRequirements[$this->selectedRequirements[$identifier]];
+                                       }
+                                       
+                                       $statement->execute(array($package->packageID, $requirement['packageID']));
+                               }
+                       }
+                       
+                       // build requirement map
+                       Package::rebuildPackageRequirementMap($package->packageID);
+                       
+                       // rebuild dependencies
+                       Package::rebuildPackageDependencies($package->packageID);
+                       if ($this->action == 'update') {
+                               Package::rebuildParentPackageDependencies($package->packageID);
+                       }
+                       
+                       // reload queue
+                       $this->queue = new PackageInstallationQueue($this->queue->queueID);
+                       $this->package = null;
+                       
+                       if ($package->standalone) {
+                               // insert as application
+                               ApplicationEditor::create(array(
+                                       'domainName' => '',
+                                       'packageID' => $package->packageID
+                               ));
+                       }
+                       
+                       // insert dependencies on parent package if applicable
+                       $this->installPackageParent();
+               }
+               
+               if ($this->getPackage()->standalone && $this->getPackage()->package != 'com.woltlab.wcf' && $this->getAction() == 'install') {
+                       if (empty($this->getPackage()->packageDir)) {
+                               $document = $this->promptPackageDir();
+                               if ($document !== null && $document instanceof form\FormDocument) {
+                                       $installationStep->setDocument($document);
+                               }
+                               
+                               $installationStep->setSplitNode();
+                       }
+               }
+               else if ($this->getPackage()->parentPackageID) {
+                       $packageEditor = new PackageEditor($this->getPackage());
+                       $packageEditor->update(array(
+                               'packageDir' => $this->getPackage()->getParentPackage()->packageDir
+                       ));
+               }
+               
+               return $installationStep;
+       }
+       
+       /**
+        * Sets parent package and rebuilds dependencies for both.
+        */     
+       protected function installPackageParent() {
+               // do not handle parent package if current package is standalone or does not have a plugin tag while within installation process
+               if ($this->getArchive()->getPackageInfo('standalone') || $this->getAction() != 'install' || !$this->getArchive()->getPackageInfo('plugin')) {
+                       return;
+               }
+               
+               // get parent package from requirements
+               $sql = "SELECT  requirement
+                       FROM    wcf".WCF_N."_package_requirement
+                       WHERE   packageID = ?
+                               AND requirement IN (
+                                       SELECT  packageID
+                                       FROM    wcf".WCF_N."_package
+                                       WHERE   package = ?
+                               )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->getPackage()->packageID,
+                       $this->getArchive()->getPackageInfo('plugin')
+               ));
+               $row = $statement->fetchArray();
+               if (!$row || empty($row['requirement'])) {
+                       throw new SystemException("can not find any available installations of required parent package '".$this->getArchive()->getPackageInfo('plugin')."'", 13012);
+               }
+               
+               // save parent package
+               $packageEditor = new PackageEditor($this->getPackage());
+               $packageEditor->update(array(
+                       'parentPackageID' => $row['requirement']
+               ));
+               
+               // rebuild parent package dependencies                                                          
+               Package::rebuildParentPackageDependencies($this->getPackage()->packageID);
+               
+               // rebuild parent's parent package dependencies
+               Package::rebuildParentPackageDependencies($row['requirement']);
+               
+               // reload package object on next request
+               $this->package = null;
+       }
+       
+       /**
+        * Executes a package installation plugin.
+        *
+        * @param       array           $nodeData
+        * @return      boolean
+        */
+       protected function executePIP(array $nodeData) {
+               $installationStep = new PackageInstallationStep();
+               
+               // fetch all pips associated with current PACKAGE_ID and include pips
+               // previously installed by current installation queue
+               $sql = "SELECT          pip.className, package.packageDir
+                       FROM            wcf".WCF_N."_package_installation_plugin pip
+                       LEFT JOIN       wcf".WCF_N."_package_dependency package_dependency
+                       ON              (package_dependency.packageID = pip.packageID)
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.packageID = pip.packageID)
+                       WHERE           pip.pluginName = ?
+                                       AND (
+                                               package_dependency.dependency = ?
+                                               OR pip.packageID = ?
+                                               OR pip.packageID IS NULL
+                                       )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $nodeData['pip'],
+                       PACKAGE_ID,
+                       $this->queue->packageID
+               ));
+               $row = $statement->fetchArray();
+               
+               // PIP is unknown, ignore
+               if (!$row) {
+                       return $installationStep;
+               }
+               
+               // valdidate class definition
+               $className = $row['className'];
+               if (!class_exists($className)) {
+                       throw new SystemException("unable to find class '".$className."'", 11001);
+               }
+               
+               $plugin = new $className($this, $nodeData);
+               
+               if (!($plugin instanceof \wcf\system\package\plugin\PackageInstallationPlugin)) {
+                       throw new SystemException("class '".$className."' does not implement the interface 'PackageInstallationPlugin'", 11010);
+               }
+               
+               // execute PIP
+               try {
+                       $plugin->{$this->action}();
+               }
+               catch (SplitNodeException $e) {
+                       $installationStep->setSplitNode();
+               }
+               
+               return $installationStep;
+       }
+       
+       /**
+        * Extracts files from .tar (or .tar.gz) archive and installs them
+        *
+        * @param       string                  $targetDir
+        * @param       string                  $sourceArchive
+        * @param       FileHandler             $fileHandler
+        * @return      Installer
+        */
+       public function extractFiles($targetDir, $sourceArchive, $fileHandler = null) {
+               return new \wcf\system\setup\Installer($targetDir, $sourceArchive, $fileHandler);
+       }
+       
+       /**
+        * Returns current package.
+        *
+        * @return      Package
+        */
+       public function getPackage() {
+               if ($this->package === null) {
+                       $this->package = new Package($this->queue->packageID);
+               }
+               
+               return $this->package;
+       }
+       
+       /**
+        * Prompts for a text input for package directory (applies for standalone-applications only)
+        *
+        * @return      FormDocument
+        */
+       protected function promptPackageDir() {
+               if (!PackageInstallationFormManager::findForm($this->queue, 'packageDir')) {
+                       $container = new container\GroupFormElementContainer();
+                       $packageDir = new element\TextInputFormElement($container);
+                       $packageDir->setName('packageDir');
+                       $packageDir->setLabel(WCF::getLanguage()->get('wcf.acp.package.packageDir.input'));
+                       
+                       $defaultPath = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator($_SERVER['DOCUMENT_ROOT']));
+                       $packageDir->setValue($defaultPath);
+                       $container->appendChild($packageDir);
+                       
+                       $document = new form\FormDocument('packageDir');
+                       $document->appendContainer($container);
+                       
+                       PackageInstallationFormManager::registerForm($this->queue, $document);
+                       return $document;
+               }
+               else {
+                       $document = PackageInstallationFormManager::getForm($this->queue, 'packageDir');
+                       $document->handleRequest();
+                       $packageDir = $document->getValue('packageDir');
+                       
+                       if ($packageDir !== null) {
+                               $packageEditor = new PackageEditor($this->getPackage());
+                               $packageEditor->update(array(
+                                       'packageDir' => FileUtil::getRelativePath(WCF_DIR, $packageDir)
+                               ));
+                               
+                               // create directory and set permissions
+                               @mkdir($packageDir, 0777, true);
+                               @chmod($packageDir, 0777);
+                       }
+                       
+                       return null;
+               }
+       }
+       
+       /**
+        * Returns current package id.
+        *
+        * @return      integer
+        */
+       public function getPackageID() {
+               return $this->queue->packageID;
+       }
+       
+       /**
+        * Returns current package installation type.
+        *
+        * @return      string
+        */
+       public function getAction() {
+               return $this->action;
+       }
+       
+       /**
+        * Opens the package installation queue and
+        * starts the installation, update or uninstallation of the first entry.
+        *
+        * @param       integer         $parentQueueID
+        * @param       integer         $processNo
+        */
+       public static function openQueue($parentQueueID = 0, $processNo = 0) {
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("userID = ?", array(WCF::getUser()->userID));
+               $conditions->add("parentQueueID = ?", array($parentQueueID));
+               if ($processNo != 0) $conditions->add("processNo = ?", array($processNo));
+               $conditions->add("done = ?", array(0));
+               
+               $sql = "SELECT          *
+                       FROM            wcf".WCF_N."_package_installation_queue
+                       ".$conditions."
+                       ORDER BY        queueID ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               $packageInstallation = $statement->fetchArray();
+               
+               if (!isset($packageInstallation['queueID'])) {
+                       HeaderUtil::redirect('index.php?page=PackageList'.SID_ARG_2ND_NOT_ENCODED);
+                       exit;
+               }
+               else {
+                       HeaderUtil::redirect('index.php?page=Package&action='.$packageInstallation['action'].'&queueID='.$packageInstallation['queueID'].''.SID_ARG_2ND_NOT_ENCODED);
+                       exit;
+               }
+       }
+       
+       /**
+        * Displays last confirmation before plugin installation.
+        */
+       public function beginInstallation() {
+               // get requirements
+               $requirements = $this->getArchive()->getRequirements();
+               $openRequirements = $this->getArchive()->getOpenRequirements();
+               
+               $updatableInstances = array();
+               $missingPackages = 0;
+               foreach ($requirements as $key => $requirement) {
+                       if (isset($openRequirements[$requirement['name']])) {
+                               $requirements[$key]['open'] = 1;
+                               $requirements[$key]['action'] = $openRequirements[$requirement['name']]['action'];
+                               if (!isset($requirements[$key]['file'])) $missingPackages++;
+                       }
+                       else {
+                               $requirements[$key]['open'] = 0;
+                       }
+               }
+               
+               // get other instances
+               if ($this->action == 'install') {
+                       $updatableInstances = $this->getArchive()->getUpdatableInstances();
+               }
+               
+               ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.package');
+               WCF::getTPL()->assign(array(
+                       'archive' => $this->getArchive(),
+                       'requiredPackages' => $requirements,
+                       'missingPackages' => $missingPackages,
+                       'updatableInstances' => $updatableInstances,
+                       'excludingPackages' => $this->getArchive()->getConflictedExcludingPackages(),
+                       'excludedPackages' => $this->getArchive()->getConflictedExcludedPackages(),
+                       'queueID' => $this->queue->queueID
+               ));
+               WCF::getTPL()->display('packageInstallationConfirm');
+               exit;
+       }
+       
+       /**
+        * Checks the package installation queue for outstanding entries.
+        *
+        * @return      integer
+        */
+       public static function checkPackageInstallationQueue() {
+               $sql = "SELECT          queueID
+                       FROM            wcf".WCF_N."_package_installation_queue
+                       WHERE           userID = ?
+                                       AND parentQueueID = 0
+                                       AND done = 0
+                       ORDER BY        queueID ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(WCF::getUser()->userID));
+               $row = $statement->fetchArray();
+               
+               if (!$row) {
+                       return 0;
+               }
+               
+               return $row['queueID'];
+       }
+       
+       /**
+        * Returns next queue within an installation process.
+        *
+        * @return      integer
+        */
+       protected function getNextQueue() {
+               $sql = "SELECT          queueID
+                       FROM            wcf".WCF_N."_package_installation_queue
+                       WHERE           userID = ?
+                                       AND processNo = ?
+                                       AND done = 0
+                       ORDER BY        queueID ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       WCF::getUser()->userID,
+                       $this->queue->processNo
+               ));
+               $row = $statement->fetchArray();
+               
+               if (!$row) {
+                       return 0;
+               }
+               
+               return $row['queueID'];
+       }
+       
+       /**
+        * Executes post-setup actions.
+        */
+       public function completeSetup() {
+               // rebuild dependencies
+               Package::rebuildPackageDependencies($this->queue->packageID);
+               
+               // mark queue as done
+               $queueEditor = new PackageInstallationQueueEditor($this->queue);
+               $queueEditor->update(array(
+                       'done' => 1
+               ));
+               
+               // remove node data
+               $this->nodeBuilder->purgeNodes();
+               
+               // return next queue within the same process no
+               $queueID = $this->getNextQueue();
+               
+               if (!$queueID) {
+                       // clear language files once whole installation is completed
+                       LanguageEditor::deleteLanguageFiles();
+                       
+                       // reset all caches
+                       CacheHandler::getInstance()->clear(WCF_DIR.'cache/', '*');
+               }
+               
+               return $queueID;
+       }
+       
+       /**
+        * Updates queue information.
+        */
+       public function updatePackage() {
+               if (empty($this->queue->packageName)) {
+                       $queueEditor = new PackageInstallationQueueEditor($this->queue);
+                       $queueEditor->update(array(
+                               'packageName' => $this->getArchive()->getPackageInfo('packageName')
+                       ));
+                       
+                       // reload queue
+                       $this->queue = new PackageInstallationQueue($this->queue->queueID);
+               }
+       }
+       
+       /**
+        * Validates specific php requirements.
+        * 
+        * @param       array           $requirements
+        * @return      array<array>
+        */
+       public static function validatePHPRequirements(array $requirements) {
+               $errors = array();
+               
+               // validate php version
+               if (isset($requirements['version'])) {
+                       $passed = false;
+                       if (version_compare(PHP_VERSION, $requirements['version'], '>=')) {
+                               $passed = true;
+                       }
+                       
+                       if (!$passed) {
+                               $errors['version'] = array(
+                                       'required' => $requirements['version'],
+                                       'installed' => PHP_VERSION
+                               );
+                       }
+               }
+               
+               // validate extensions
+               if (isset($requirements['extensions'])) {
+                       foreach ($requirements['extensions'] as $extension) {
+                               $passed = (extension_loaded($extension)) ? true : false;
+                               
+                               if (!$passed) {
+                                       $errors['extension'][] = array(
+                                               'extension' => $extension
+                                       );
+                               }
+                       }
+               }
+               
+               // validate settings
+               if (isset($requirements['settings'])) {
+                       foreach ($requirements['settings'] as $setting => $value) {
+                               $iniValue = ini_get($setting);
+                               
+                               $passed = self::compareSetting($setting, $value, $iniValue);
+                               if (!$passed) {
+                                       $errors['setting'][] = array(
+                                               'setting' => $setting,
+                                               'required' => $value,
+                                               'installed' => ($iniValue === false) ? '(unknown)' : $iniValue
+                                       );
+                               }
+                       }
+               }
+               
+               // validate functions
+               if (isset($requirements['functions'])) {
+                       foreach ($requirements['functions'] as $function) {
+                               $function = StringUtil::toLowerCase($function);
+                               
+                               $passed = self::functionExists($function);
+                               if (!$passed) {
+                                       $errors['function'][] = array(
+                                               'function' => $function
+                                       );
+                               }
+                       }
+               }
+               
+               // validate classes
+               if (isset($requirements['classes'])) {
+                       foreach ($requirements['classes'] as $class) {
+                               $passed = false;
+                               
+                               // see: http://de.php.net/manual/en/language.oop5.basic.php
+                               if (preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.~', $class)) {
+                                       $globalClass = '\\'.$class;
+                                       
+                                       if (class_exists($globalClass, false)) {
+                                               $passed = true;
+                                       }
+                               }
+                               
+                               if (!$passed) {
+                                       $errors['class'][] = array(
+                                               'class' => $class
+                                       );
+                               }
+                       }
+                               
+               }
+               
+               return $errors;
+       }
+       
+       /**
+        * Validates if an function exists and is not blacklisted by suhosin extension.
+        * 
+        * @param       string          $function
+        * @return      boolean
+        * @see         http://de.php.net/manual/en/function.function-exists.php#77980
+        */     
+       protected static function functionExists($function) {
+               if (extension_loaded('suhosin')) {
+                       $blacklist = @ini_get('suhosin.executor.func.blacklist');
+                       if (!empty($blacklist)) {
+                               $blacklist = explode(',', $blacklist);
+                               foreach ($blacklist as $disabledFunction) {
+                                       $disabledFunction = StringUtil::toLowerCase(StringUtil::trim($disabledFunction));
+                                       
+                                       if ($function == $disabledFunction) {
+                                               return false;
+                                       }
+                               }
+                       }
+               }
+               
+               return function_exists($function);
+       }
+       
+       /**
+        * Compares settings, converting values into compareable ones.
+        * 
+        * @param       string          $setting
+        * @param       string          $value
+        * @param       mixed           $compareValue
+        * @return      boolean
+        */
+       protected static function compareSetting($setting, $value, $compareValue) {
+               if ($compareValue === false) return false;
+               
+               $value = StringUtil::toLowerCase($value);
+               $trueValues = array('1', 'on', 'true');
+               $falseValues = array('0', 'off', 'false');
+               
+               // handle values considered as 'true'
+               if (in_array($value, $trueValues)) {
+                       return ($compareValue) ? true : false;
+               }
+               // handle values considered as 'false'
+               else if (in_array($value, $falseValues)) {
+                       return (!$compareValue) ? true : false;
+               }
+               else if (!is_numeric($value)) {
+                       $compareValue = self::convertShorthandByteValue($compareValue);
+                       $value = self::convertShorthandByteValue($value);
+               }
+               
+               return ($compareValue >= $value) ? true : false;
+       }
+       
+       /**
+        * Converts shorthand byte values into an integer representing bytes.
+        * 
+        * @param       string          $value
+        * @return      integer
+        * @see         http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+        */
+       protected static function convertShorthandByteValue($value) {
+               // convert into bytes
+               $lastCharacter = StringUtil::substring($value, -1);
+               switch ($lastCharacter) {
+                       // gigabytes
+                       case 'g':
+                               return (int)$value * 1073741824;
+                       break;
+                       
+                       // megabytes
+                       case 'm':
+                               return (int)$value * 1048576;
+                       break;
+                       
+                       // kilobytes
+                       case 'k':
+                               return (int)$value * 1024;
+                       break;
+                       
+                       default:
+                               return $value;
+                       break;
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationFileHandler.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationFileHandler.class.php
new file mode 100644 (file)
index 0000000..9335465
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+namespace wcf\system\package;
+use wcf\system\setup\FileHandler;
+
+/**
+ * PackageInstallationFileHandler is the abstract FileHandler implementation for all file installations during the package installation.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+abstract class PackageInstallationFileHandler implements FileHandler {
+       protected $packageInstallation;
+       
+       /**
+        * Creates a new PackageInstallationFileHandler object.
+        * 
+        * @param       PackageInstallationDispatcher   $packageInstallation
+        */
+       public function __construct(PackageInstallationDispatcher $packageInstallation) {
+               $this->packageInstallation = $packageInstallation;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationFormManager.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationFormManager.class.php
new file mode 100644 (file)
index 0000000..d9dd8df
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+namespace wcf\system\Package;
+use wcf\data\package\installation\queue\PackageInstallationQueue;
+use wcf\system\form\FormDocument;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * PackageInstallationFormManager handels form documents associated with a queue.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.form
+ * @category   Community Framework
+ */
+abstract class PackageInstallationFormManager {
+       /**
+        * Handles a POST or GET request.
+        *
+        * @param       PackageInstallationQueue        $queue
+        */
+       public static function handleRequest(PackageInstallationQueue $queue) {
+               $formName = (isset($_REQUEST['formName'])) ? StringUtil::trim($_REQUEST['formName']) : '';
+               
+               // ignore request
+               if (empty($formName) || !self::findForm($queue, $formName)) return;
+               
+               // get document
+               $document = self::getForm($queue, $formName);
+               $document->handleRequest();
+               
+               self::updateForm($queue, $document);
+       }
+       
+       /**
+        * Registers a form document.
+        *
+        * @param       PackageInstallationQueue        $queue
+        * @param       FormDocument                    $document
+        */
+       public static function registerForm(PackageInstallationQueue $queue, FormDocument $document) {
+               if (self::findForm($queue, $document->getName())) {
+                       self::updateForm($queue, $document);
+               }
+               else {
+                       self::insertForm($queue, $document);
+               }
+       }
+       
+       /**
+        * Searches for an existing form document associated with given queue.
+        *
+        * @param       PackageInstallationQueue        $queue
+        * @param       string                          $formName
+        * @return      boolean
+        */
+       public static function findForm(PackageInstallationQueue $queue, $formName) {
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_package_installation_form
+                       WHERE   queueID = ?
+                               AND formName = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $queue->queueID,
+                       $formName
+               ));
+               $row = $statement->fetchArray();
+               
+               return (bool)$row['count'];
+       }
+       
+       /**
+        * Inserts a form document into database.
+        *
+        * @param       PackageInstallationQueue        $queue
+        * @param       FormDocument                    $document
+        */
+       private static function insertForm(PackageInstallationQueue $queue, FormDocument $document) {
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_form
+                                       (queueID, formName, document)
+                       VALUES          (?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $queue->queueID,
+                       $document->getName(),
+                       serialize($document)
+               ));
+       }
+       
+       /**
+        * Updates a form document database entry.
+        *
+        * @param       PackageInstallationQueue        $queue
+        * @param       FormDocument                    $document
+        */
+       private static function updateForm(PackageInstallationQueue $queue, FormDocument $document) {
+               $sql = "UPDATE  wcf".WCF_N."_package_installation_form
+                       SET     document = ?
+                       WHERE   queueID = ?
+                               AND formName = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       serialize($document),
+                       $queue->queueID,
+                       $document->formName
+               ));
+       }
+       
+       /**
+        * Deletes form documents associated with given queue.
+        *
+        * @param       PackageInstallationQueue        $queue
+        */
+       public static function deleteForms(PackageInstallationQueue $queue) {
+               $sql = "DELETE FROM     wcf".WCF_N."_package_installation_form
+                       WHERE           queueID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($queue->queueID));
+       }
+       
+       /**
+        * Returns a form document from database.
+        *
+        * @param       PackageInstallationQueue        $queue
+        * @param       string                          $formName
+        * @return      FormDocument
+        */
+       public static function getForm(PackageInstallationQueue $queue, $formName) {
+               $sql = "SELECT  document
+                       FROM    wcf".WCF_N."_package_installation_form
+                       WHERE   queueID = ?
+                               AND formName = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $queue->queueID,
+                       $formName
+               ));
+               $row = $statement->fetchArray();
+               
+               if ($row) {
+                       $document = unserialize($row['document']);
+                       return $document;
+               }
+               
+               return null;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationNodeBuilder.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationNodeBuilder.class.php
new file mode 100644 (file)
index 0000000..e1a8883
--- /dev/null
@@ -0,0 +1,490 @@
+<?php
+namespace wcf\system\package;
+use wcf\data\package\installation\queue\PackageInstallationQueue;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * PackageInstallationNodeBuilder creates a logical node-based installation tree.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageInstallationNodeBuilder {
+       /**
+        * instance of PackageInstallationDispatcher
+        *
+        * @var PackageInstallationDispatcher
+        */
+       public $installation = null;
+       
+       /**
+        * current node
+        *
+        * @var string
+        */
+       public $node = '';
+       
+       /**
+        * current parent node
+        *
+        * @var string
+        */
+       public $parentNode = '';
+       
+       /**
+        * current sequence number within one node
+        *
+        * @var integer
+        */
+       public $sequenceNo = 0;
+       
+       /**
+        * Creates a new instance of PackageInstallationNodeBuilder
+        *
+        * @param       PackageInstallationDispatcher   $installation
+        */
+       public function __construct(PackageInstallationDispatcher $installation) {
+               $this->installation = $installation;
+       }
+       
+       /**
+        * Builds nodes for current installation queue.
+        */
+       public function buildNodes() {
+               // required packages
+               $this->buildRequirementNodes();
+               
+               // install package itself
+               $this->buildPackageNode();
+               
+               // package installation plugins
+               $this->buildPluginNodes();
+               
+               // optional packages
+               $this->buildOptionalNodes();
+       }
+       
+       /**
+        * Returns the succeeding node.
+        *
+        * @param       string          $parentNode
+        * @return      string
+        */
+       public function getNextNode($parentNode = '') {
+               $sql = "SELECT  node
+                       FROM    wcf".WCF_N."_package_installation_node
+                       WHERE   queueID = ?
+                               AND processNo = ?
+                               AND parentNode = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       $parentNode
+               ));
+               $row = $statement->fetchArray();
+               
+               if (!$row) {
+                       return '';
+               }
+               
+               return $row['node'];
+       }
+       
+       /**
+        * Returns data for current node.
+        *
+        * @param       string          $node
+        * @return      array
+        */
+       public function getNodeData($node) {
+               $sql = "SELECT          nodeType, nodeData, sequenceNo
+                       FROM            wcf".WCF_N."_package_installation_node
+                       WHERE           queueID = ?
+                                       AND processNo = ?
+                                       AND node = ?
+                       ORDER BY        sequenceNo ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       $node
+               ));
+               $data = array();
+               while ($row = $statement->fetchArray()) {
+                       $data[] = $row;
+               }
+               
+               return $data;
+       }
+       
+       /**
+        * Marks a node as completed.
+        *
+        * @param       string          $node
+        */
+       public function completeNode($node) {
+               $sql = "UPDATE  wcf".WCF_N."_package_installation_node
+                       SET     done = 1
+                       WHERE   queueID = ?
+                               AND processNo = ?
+                               AND node = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       $node
+               ));
+       }
+       
+       /**
+        * Removes all nodes associated with queue's process no.
+        *
+        * CAUTION: This method SHOULD NOT be called within the installation process!
+        */
+       public function purgeNodes() {
+               $sql = "DELETE FROM     wcf".WCF_N."_package_installation_node
+                       WHERE           processNo = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->processNo
+               ));
+               
+               $sql = "DELETE FROM     wcf".WCF_N."_package_installation_form
+                       WHERE           queueID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID
+               ));
+       }
+       
+       /**
+        * Calculates current setup process.
+        *
+        * @param       string          $node
+        * @return      integer
+        */
+       public function calculateProgress($node) {
+               $progress = array(
+                       'done' => 0,
+                       'outstanding' => 0
+               );
+               
+               $sql = "SELECT  done
+                       FROM    wcf".WCF_N."_package_installation_node
+                       WHERE   queueID = ?
+                               AND processNo = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo
+               ));
+               while ($row = $statement->fetchArray()) {
+                       if ($row['done']) {
+                               $progress['done']++;
+                       }
+                       else {
+                               $progress['outstanding']++;
+                       }
+               }
+               
+               if (!$progress['done']) {
+                       return 0;
+               }
+               else if ($progress['done'] == $progress['outstanding']) {
+                       return 100;
+               }
+               else {
+                       $total = $progress['done'] + $progress['outstanding'];
+                       return round(($progress['done'] / $total) * 100);
+               }
+       }
+       
+       /**
+        * Duplicates a node by re-inserting it and moving all descendants into a new tree.
+        *
+        * @param       string          $node
+        * @param       integer         $sequenceNo
+        */
+       public function insertNode($node, $sequenceNo) {
+               $newNode = $this->getToken();
+               
+               // update descendants
+               $sql = "UPDATE  wcf".WCF_N."_package_installation_node
+                       SET     parentNode = ?
+                       WHERE   parentNode = ?
+                               AND queueID = ?
+                               AND processNo = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $newNode,
+                       $node,
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo
+               ));
+               
+               // create a copy of current node (prevents empty nodes)
+               $sql = "SELECT  nodeType, nodeData, done
+                       FROM    wcf".WCF_N."_package_installation_node
+                       WHERE   node = ?
+                               AND queueID = ?
+                               AND processNo = ?
+                               AND sequenceNo = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $node,
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       $sequenceNo
+               ));
+               $row = $statement->fetchArray();
+               
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                       (queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData, done)
+                       VALUES          (?, ?, ?, ?, ?, ?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       0,
+                       $newNode,
+                       $node,
+                       $row['nodeType'],
+                       $row['nodeData'],
+                       $row['done']
+               ));
+               
+               // move other child-nodes greater than $sequenceNo into new node
+               $sql = "UPDATE  wcf".WCF_N."_package_installation_node
+                       SET     parentNode = ?,
+                               node = ?,
+                               sequenceNo = (sequenceNo - ?)
+                       WHERE   node = ?
+                               AND queueID = ?
+                               AND processNo = ?
+                               AND sequenceNo > ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $node,
+                       $newNode,
+                       $sequenceNo,
+                       $node,
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       $sequenceNo
+               ));
+       }
+       
+       /**
+        * Builds package node used to install the package itself.
+        */
+       protected function buildPackageNode() {
+               if (!empty($this->node)) {
+                       $this->parentNode = $this->node;
+                       $this->sequenceNo = 0;
+               }
+               
+               $this->node = $this->getToken();
+                                       
+               // calculate the number of instances of this package
+               $instanceNo = 1;
+               $sql = "SELECT  COUNT(*) AS count, MAX(instanceNo) AS instanceNo
+                       FROM    wcf".WCF_N."_package
+                       WHERE   package = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->getArchive()->getPackageInfo('name')
+               ));
+               $row = $statement->fetchArray();
+               
+               if ($row['count'] > 0) $instanceNo = $row['instanceNo'] + 1;
+               
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                       (queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData)
+                       VALUES          (?, ?, ?, ?, ?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       $this->sequenceNo,
+                       $this->node,
+                       $this->parentNode,
+                       'package',
+                       serialize(array(
+                               'package' => $this->installation->getArchive()->getPackageInfo('name'),
+                               'packageName' => $this->installation->getArchive()->getPackageInfo('packageName'),
+                               'instanceNo' => $instanceNo,
+                               'packageDescription' => $this->installation->getArchive()->getPackageInfo('packageDescription'),
+                               'packageVersion' => $this->installation->getArchive()->getPackageInfo('version'),
+                               'packageDate' => $this->installation->getArchive()->getPackageInfo('date'),
+                               'packageURL' => $this->installation->getArchive()->getPackageInfo('packageURL'),
+                               'standalone' => $this->installation->getArchive()->getPackageInfo('standalone'),
+                               'author' => $this->installation->getArchive()->getAuthorInfo('author'),
+                               'authorURL' => $this->installation->getArchive()->getAuthorInfo('authorURL'),
+                               'installDate' => TIME_NOW,
+                               'updateDate' => TIME_NOW
+                       ))
+               ));
+       }
+       
+       /**
+        * Builds nodes for required packages, whereas each has it own node.
+        *
+        * @return      string
+        */
+       protected function buildRequirementNodes() {
+               $packageNodes = array();
+               
+               $requiredPackages = $this->installation->getArchive()->getRequirements();
+               foreach ($requiredPackages as $packageName => $package) {
+                       if (!isset($package['file'])) {
+                               // ignore requirements which are not to be installed
+                               continue;
+                       }
+                       
+                       $this->parentNode = $this->node;
+                       $this->node = $this->getToken();
+                       $this->sequenceNo = 0;
+                       
+                       $packageNodes[] = array(
+                               'data' => array(
+                                       'file' => $package['file'],
+                                       'packageName' => $packageName
+                               ),
+                               'node' => $this->node,
+                               'parentNode' => $this->parentNode,
+                               'sequenceNo' => $this->sequenceNo
+                       );
+               }
+               
+               if (!empty($packageNodes)) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                               (queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData)
+                               VALUES          (?, ?, ?, ?, ?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($packageNodes as $nodeData) {
+                               $statement->execute(array(
+                                       $this->installation->queue->queueID,
+                                       $this->installation->queue->processNo,
+                                       $nodeData['sequenceNo'],
+                                       $nodeData['node'],
+                                       $nodeData['parentNode'],
+                                       'requiredPackage',
+                                       serialize($nodeData['data'])
+                               ));
+                       }
+               }
+       }
+       
+       /**
+        * Builds package installation plugin nodes, whereas pips could be grouped within
+        * one node, differ from each by nothing but the sequence number.
+        *
+        * @return      string
+        */
+       protected function buildPluginNodes() {
+               $pluginNodes = array();
+               
+               $instructions = ($this->installation->getAction() == 'install') ? $this->installation->getArchive()->getInstallInstructions() : $this->installation->getArchive()->getUpdateInstructions();
+               foreach ($instructions as $pip) {
+                       if (isset($pip['attributes']['run']) && ($pip['attributes']['run'] == 'standalone')) {
+                               $this->parentNode = $this->node;
+                               $this->node = $this->getToken();
+                               $this->sequenceNo = 0;
+                               
+                               $pluginNodes[] = array(
+                                       'data' => $pip,
+                                       'node' => $this->node,
+                                       'parentNode' => $this->parentNode,
+                                       'sequenceNo' => $this->sequenceNo
+                               );
+                       }
+                       else {
+                               $this->sequenceNo++;
+                               
+                               $pluginNodes[] = array(
+                                       'data' => $pip,
+                                       'node' => $this->node,
+                                       'parentNode' => $this->parentNode,
+                                       'sequenceNo' => $this->sequenceNo
+                               );
+                       }
+               }
+               
+               // insert nodes
+               if (count($pluginNodes) > 0) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                               (queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData)
+                               VALUES          (?, ?, ?, ?, ?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($pluginNodes as $index => $nodeData) {
+                               $statement->execute(array(
+                                       $this->installation->queue->queueID,
+                                       $this->installation->queue->processNo,
+                                       $nodeData['sequenceNo'],
+                                       $nodeData['node'],
+                                       $nodeData['parentNode'],
+                                       'pip',
+                                       serialize($nodeData['data'])
+                               ));
+                       }
+               }
+       }
+       
+       /**
+        * Builds nodes for optional packages, whereas each package exists within
+        * one node with the same parent node, seperated by sequence no (which does
+        * not really matter at this point).
+        */
+       protected function buildOptionalNodes() {
+               $packageNodes = array();
+               
+               $optionalPackages = $this->installation->getArchive()->getOptionals();
+               foreach ($optionalPackages as $package) {
+                       $packageNodes[] = array(
+                               'data' => $package
+                       );
+                       
+                       $lastNode = $newNode;
+               }
+               
+               if (!empty($packageNodes)) {
+                       $this->parentNode = $this->node;
+                       $this->node = $this->getToken();
+                       $this->sequenceNo = -1;
+                       
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                               (queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData)
+                               VALUES          (?, ?, ?, ?, ?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($packageNodes as $nodeData) {
+                               $this->sequenceNo = 0;
+                               
+                               $statement->execute(array(
+                                       $this->installation->queue->queueID,
+                                       $this->installation->queue->processNo,
+                                       $this->sequenceNo,
+                                       $this->node,
+                                       $this->parentNode,
+                                       'optionalPackage',
+                                       serialize($nodeData['data'])
+                               ));
+                       }
+               }
+       }
+       
+       /**
+        * Returns a short SHA1-hash.
+        *
+        * @return      string
+        */
+       protected function getToken() {
+               return StringUtil::substring(StringUtil::getRandomID(), 0, 8);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php
new file mode 100644 (file)
index 0000000..4a807c4
--- /dev/null
@@ -0,0 +1,461 @@
+<?php
+namespace wcf\system\package;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\data\package\Package;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Contains business logic related to preparation of package installations.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageInstallationScheduler {
+       /**
+        * list of packages to update or install
+        * 
+        * @var array
+        */
+       protected $selectedPackages = array();
+       
+       /**
+        * list of package update server ids
+        * 
+        * @var array
+        */
+       protected $packageUpdateServerIDs;
+       
+       /**
+        * enables downloading of updates
+        * 
+        * @var boolean
+        */
+       protected $download;
+       
+       /**
+        * virtual package versions
+        * 
+        * @var array
+        */
+       protected $virtualPackageVersions = array();
+       
+       /**
+        * stack of package installations / updates
+        * 
+        * @var array
+        */
+       protected $packageInstallationStack = array();
+       
+       /**
+        * Creates a new instance of PackageInstallationScheduler
+        * 
+        * @param       array           $selectedPackages
+        * @param       array           $packageUpdateServerIDs
+        * @param       boolean         $download
+        */
+       public function __construct(array $selectedPackages, array $packageUpdateServerIDs = array(), $download = true) {
+               $this->selectedPackages = $selectedPackages;
+               $this->packageUpdateServerIDs = $packageUpdateServerIDs;
+               $this->download = $download;
+       }
+       
+       /**
+        * Builds the stack of package installations / updates.
+        */
+       public function buildPackageInstallationStack() {
+               foreach ($this->selectedPackages as $package => $version) {
+                       if (is_numeric($package)) {
+                               $this->updatePackage($package, $version);
+                       }
+                       else {
+                               $this->tryToInstallPackage($package, $version, true);
+                       }
+               }
+       }
+       
+       /**
+        * Trys to install a new package. Checks the virtual package version list.
+        * 
+        * @param       string          $package                package identifier
+        * @param       string          $minversion             preferred package version
+        * @param       boolean         $installOldVersion      true, if you want to install the package in the given minversion and not in the newest version
+        */
+       protected function tryToInstallPackage($package, $minversion = '', $installOldVersion = false) {
+               // check virtual package version
+               if (isset($this->virtualPackageVersions[$package])) {
+                       if (!empty($minversion) && Package::compareVersion($this->virtualPackageVersions[$package], $minversion, '<')) {
+                               $stackPosition = -1;
+                               // remove installation of older version
+                               foreach ($this->packageInstallationStack as $key => $value) {
+                                       if ($value['package'] == $package) {
+                                               $stackPosition = $key;
+                                               break;
+                                       }
+                               }
+                               
+                               // install newer version
+                               $this->installPackage($package, ($installOldVersion ? $minversion : ''), $stackPosition);
+                       }
+               }
+               else {
+                       // package is missing -> install
+                       $this->installPackage($package, ($installOldVersion ? $minversion : ''));
+               }
+       }
+       
+       /**
+        * Installs a new package.
+        * 
+        * @param       string          $package        package identifier
+        * @param       string          $version        package version
+        * @param       integer         $stackPosition
+        */
+       protected function installPackage($package, $version = '', $stackPosition = -1) {
+               // get package update versions
+               $packageUpdateVersions = PackageUpdateDispatcher::getPackageUpdateVersions($package, $version);
+
+               // resolve requirements
+               $this->resolveRequirements($packageUpdateVersions[0]['packageUpdateVersionID']);
+               
+               // download package
+               $download = '';
+               if ($this->download) {
+                       $download = $this->downloadPackage($package, $packageUpdateVersions);
+               }
+                       
+               // add to stack
+               $data = array(
+                       'packageName' => $packageUpdateVersions[0]['packageName'],
+                       'packageVersion' => $packageUpdateVersions[0]['packageVersion'],
+                       'package' => $package,
+                       'packageID' => 0,
+                       'archive' => $download,
+                       'action' => 'install'
+               );
+               if ($stackPosition == -1) $this->packageInstallationStack[] = $data;
+               else $this->packageInstallationStack[$stackPosition] = $data;
+               
+               // update virtual versions
+               $this->virtualPackageVersions[$package] = $packageUpdateVersions[0]['packageVersion'];
+       }
+       
+       /**
+        * Resolves the package requirements of an package uppdate.
+        * Starts the installation or update to higher version of required packages.
+        * 
+        * @param       integer         $packageUpdateVersionID
+        */
+       protected function resolveRequirements($packageUpdateVersionID) {
+               // resolve requirements
+               $requiredPackages = array();
+               $requirementsCache = array();
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_package_update_requirement
+                       WHERE   packageUpdateVersionID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageUpdateVersionID));
+               while ($row = $statement->fetchArray()) {
+                       $requiredPackages[] = $row['package'];
+                       $requirementsCache[] = $row;
+               }
+               
+               if (!empty($requiredPackages)) {
+                       // find installed packages
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("package IN (?)", array($requiredPackages));
+                       
+                       $installedPackages = array();
+                       $sql = "SELECT  packageID, package, packageVersion
+                               FROM    wcf".WCF_N."_package
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               if (!isset($installedPackages[$row2['package']])) $installedPackages[$row2['package']] = array();
+                               $installedPackages[$row2['package']][$row2['packageID']] = (isset($this->virtualPackageVersions[$row2['packageID']]) ? $this->virtualPackageVersions[$row2['packageID']] : $row2['packageVersion']);
+                       }
+                       
+                       // check installed / missing packages
+                       foreach ($requirementsCache as $row) {
+                               if (isset($installedPackages[$row['package']])) {
+                                       // package already installed -> check version
+                                       // sort multiple instances by version number
+                                       uasort($installedPackages[$row['package']], array('Package', 'compareVersion'));
+                                       
+                                       foreach ($installedPackages[$row['package']] as $packageID => $packageVersion) {
+                                               if (empty($row['minversion']) || Package::compareVersion($row['minversion'], $packageVersion, '<=')) {
+                                                       continue 2;
+                                               }
+                                       }
+                                       
+                                       // package version too low -> update necessary
+                                       $this->updatePackage($packageID, $row['minversion']);
+                               }
+                               else {
+                                       $this->tryToInstallPackage($row['package'], $row['minversion']);
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Tries to download a package from available update servers.
+        * 
+        * @param       string          $package                package identifier
+        * @param       array           $packageUpdateVersions  package update versions
+        * @return      string          tmp filename of a downloaded package
+        */
+       protected function downloadPackage($package, $packageUpdateVersions) {
+               // get download from cache
+               if ($filename = $this->getCachedDownload($package, $packageUpdateVersions[0]['package'])) {
+                       return $filename;
+               }
+
+               // download file
+               $authorizationRequiredException = array();
+               $systemExceptions = array();
+               foreach ($packageUpdateVersions as $packageUpdateVersion) {
+                       try {
+                               // get auth data
+                               $authData = $this->getAuthData($packageUpdateVersion);          
+                       
+                               // send request
+                               if (!empty($packageUpdateVersion['file'])) {
+                                       $response = PackageUpdateDispatcher::sendRequest($packageUpdateVersion['file'], array(), $authData);
+                               }
+                               else {
+                                       $response = PackageUpdateDispatcher::sendRequest($packageUpdateVersion['server'], array('packageName' => $packageUpdateVersion['package'], 'packageVersion' => $packageUpdateVersion['packageVersion']), $authData);
+                               }
+                       
+                               // check response
+                               // check http code
+                               if ($response['httpStatusCode'] == 401) {
+                                       throw new PackageUpdateAuthorizationRequiredException($packageUpdateVersion['packageUpdateServerID'], (!empty($packageUpdateVersion['file']) ? $packageUpdateVersion['file'] : $packageUpdateVersion['server']), $response);
+                               }
+                               
+                               if ($response['httpStatusCode'] != 200) {
+                                       throw new SystemException(WCF::getLanguage()->get('wcf.acp.packageUpdate.error.downloadFailed', array('$package' => $package)) . ' ('.$response['httpStatusLine'].')', 18009);
+                               }
+                               
+                               // write content to tmp file
+                               $filename = FileUtil::getTemporaryFilename('package_');
+                               $file = new File($filename);
+                               $file->write($response['content']);
+                               $file->close();
+                               unset($response['content']);
+                               
+                               // test package
+                               $archive = new PackageArchive($filename);
+                               $archive->openArchive();
+                               $archive->getTar()->close();
+                               
+                               // cache download in session
+                               PackageUpdateDispatcher::cacheDownload($package, $packageUpdateVersion['packageVersion'], $filename);
+                               
+                               return $filename;
+                       }
+                       catch (PackageUpdateAuthorizationRequiredException $e) {
+                               $authorizationRequiredException[] = $e;
+                       }
+                       catch (SystemException $e) {
+                               $systemExceptions[] = $e;
+                       }
+               }
+               
+               if (count($authorizationRequiredException)) {
+                       throw array_shift($authorizationRequiredException);
+               }
+               
+               if (count($systemExceptions)) {
+                       throw array_shift($systemExceptions);
+               }
+               
+               return false;
+       }
+       
+       /**
+        * Returns a list of excluded packages.
+        * 
+        * @return      array
+        */
+       public function getExcludedPackages() {
+               $excludedPackages = array();
+               
+               if (count($this->packageInstallationStack)) {
+                       $packageInstallations = array();
+                       $packageIdentifier = array();
+                       foreach ($this->packageInstallationStack as $packageInstallation) {
+                               $packageInstallation['newVersion'] = ($packageInstallation['action'] == 'update' ? $packageInstallation['toVersion'] : $packageInstallation['packageVersion']);
+                               $packageInstallations[] = $packageInstallation;
+                               $packageIdentifier[] = $packageInstallation['package'];
+                       }
+
+                       // check exclusions of the new packages
+                       // get package update ids
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("package IN (?)", array($packageIdentifier));
+                       
+                       $sql = "SELECT  packageUpdateID, package
+                               FROM    wcf".WCF_N."_package_update
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               foreach ($packageInstallations as $key => $packageInstallation) {
+                                       if ($packageInstallation['package'] == $row['package']) {
+                                               $packageInstallations[$key]['packageUpdateID'] = $row['packageUpdateID'];
+                                       }
+                               }
+                       }
+                       
+                       // get exclusions of the new packages
+                       // build conditions
+                       $conditions = '';
+                       $statementParameters = array();
+                       foreach ($packageInstallations as $packageInstallation) {
+                               if (!empty($conditions)) $conditions .= ' OR ';
+                               $conditions .= "(packageUpdateID = ? AND packageVersion = ?)";
+                               $statementParameters[] = $packageInstallation['packageUpdateID'];
+                               $statementParameters[] = $packageInstallation['newVersion'];
+                       }
+                       
+                       $sql = "SELECT          package.*, package_update_exclusion.*,
+                                               package_update.packageUpdateID,
+                                               package_update.package
+                               FROM            wcf".WCF_N."_package_update_exclusion package_update_exclusion
+                               LEFT JOIN       wcf".WCF_N."_package_update_version package_update_version
+                               ON              (package_update_version.packageUpdateVersionID = package_update_exclusion.packageUpdateVersionID)
+                               LEFT JOIN       wcf".WCF_N."_package_update package_update
+                               ON              (package_update.packageUpdateID = package_update_version.packageUpdateID)
+                               LEFT JOIN       wcf".WCF_N."_package package
+                               ON              (package.package = package_update_exclusion.excludedPackage)
+                               WHERE           package_update_exclusion.packageUpdateVersionID IN (
+                                                       SELECT  packageUpdateVersionID
+                                                       FROM    wcf".WCF_N."_package_update_version
+                                                       WHERE   ".$conditions."
+                                               )
+                                               AND package.package IS NOT NULL";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($statementParameters);
+                       while ($row = $statement->fetchArray()) {
+                               foreach ($packageInstallations as $key => $packageInstallation) {
+                                       if ($packageInstallation['package'] == $row['package']) {
+                                               if (!isset($packageInstallations[$key]['excludedPackages'])) {
+                                                       $packageInstallations[$key]['excludedPackages'] = array();
+                                               }
+                                               $packageInstallations[$key]['excludedPackages'][$row['excludedPackage']] = array('package' => $row['excludedPackage'], 'version' => $row['excludedPackageVersion']);
+                                               
+                                               // check version
+                                               if (!empty($row['excludedPackageVersion'])) {
+                                                       if (Package::compareVersion($row['packageVersion'], $row['excludedPackageVersion'], '<')) {
+                                                               continue;
+                                                       }
+                                               }
+                                               
+                                               $excludedPackages[] = array(
+                                                       'package' => $row['package'],
+                                                       'packageName' => $packageInstallations[$key]['packageName'],
+                                                       'packageVersion' => $packageInstallations[$key]['newVersion'],
+                                                       'action' => $packageInstallations[$key]['action'],
+                                                       'conflict' => 'newPackageExcludesExistingPackage',
+                                                       'existingPackage' => $row['excludedPackage'],
+                                                       'existingPackageName' => $row['packageName'],
+                                                       'existingPackageVersion' => $row['packageVersion']
+                                               );
+                                       }
+                               }
+                       }
+                       
+                       // check excluded packages of the existing packages
+                       $conditions = new PreparedStatementConditionBuilder();
+                       $conditions->add("excludePackage IN (?)", array($packageIdentifier));
+                       
+                       $sql = "SELECT          package.*, package_exclusion.*
+                               FROM            wcf".WCF_N."_package_exclusion package_exclusion
+                               LEFT JOIN       wcf".WCF_N."_package package
+                               ON              (package.packageID = package_exclusion.packageID)
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       while ($row = $statement->fetchArray()) {
+                               foreach ($packageInstallations as $key => $packageInstallation) {
+                                       if ($packageInstallation['package'] == $row['excludedPackage']) {
+                                               if (!empty($row['excludedPackageVersion'])) {
+                                                       // check version
+                                                       if (Package::compareVersion($packageInstallation['newVersion'], $row['excludedPackageVersion'], '<')) {
+                                                               continue;
+                                                       }
+                                                       
+                                                       // search exclusing package in stack
+                                                       foreach ($packageInstallations as $packageUpdate) {
+                                                               if ($packageUpdate['packageID'] == $row['packageID']) {
+                                                                       // check new exclusions
+                                                                       if (!isset($packageUpdate['excludedPackages']) || !isset($packageUpdate['excludedPackages'][$row['excludedPackage']]) || (!empty($packageUpdate['excludedPackages'][$row['excludedPackage']]['version']) && Package::compareVersion($packageInstallation['newVersion'], $packageUpdate['excludedPackages'][$row['excludedPackage']]['version'], '<'))) {
+                                                                               continue 2;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+
+                                               $excludedPackages[] = array(
+                                                       'package' => $row['excludedPackage'],
+                                                       'packageName' => $packageInstallation['packageName'],
+                                                       'packageVersion' => $packageInstallation['newVersion'],
+                                                       'action' => $packageInstallation['action'],
+                                                       'conflict' => 'existingPackageExcludesNewPackage',
+                                                       'existingPackage' => $row['package'],
+                                                       'existingPackageName' => $row['packageName'],
+                                                       'existingPackageVersion' => $row['packageVersion']
+                                               );
+                                       }
+                               }
+                       }
+               }
+
+               return $excludedPackages;
+       }
+       
+       /**
+        * Returns the stack of package installations.
+        * 
+        * @return      array
+        */
+       public function getPackageInstallationStack() {
+               return $this->packageInstallationStack;
+       }
+       
+       /**
+        * Gets the filename of in session stored donwloads.
+        * 
+        * @param       string          $package        package identifier
+        * @param       string          $version        package version
+        * @return      string          $filename
+        */
+       protected function getCachedDownload($package, $version) {
+               $cachedDownloads = WCF::getSession()->getVar('cachedPackageUpdateDownloads');
+               if (isset($cachedDownloads[$package.'@'.$version]) && @file_exists($cachedDownloads[$package.'@'.$version])) {
+                       return $cachedDownloads[$package.'@'.$version];
+               }
+               
+               return false;
+       }
+       
+       /**
+        * Gets stored auth data of given update server.
+        *
+        * @param       array           $updateServer
+        * @return      array           $authData
+        */
+       protected function getAuthData(array $data) {
+               $updateServer = new PackageUpdateServer(null, $data);
+               return $updateServer->getAuthData();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationStep.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationStep.class.php
new file mode 100644 (file)
index 0000000..11ac2a1
--- /dev/null
@@ -0,0 +1,98 @@
+<?php\r
+namespace wcf\system\package;\r
+use wcf\system\form\FormDocument;\r
+\r
+/**\r
+ * Represents step information within an installation node.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.package\r
+ * @category   Community Framework\r
+ */\r
+class PackageInstallationStep {\r
+       /**\r
+        * form document object\r
+        *\r
+        * @var FormDocument\r
+        */\r
+       protected $document = null;\r
+       \r
+       /**\r
+        * next installation node\r
+        *\r
+        * @var string\r
+        */\r
+       protected $node = '';\r
+       \r
+       /**\r
+        * split current node\r
+        *\r
+        * @var boolean\r
+        */\r
+       protected $splitNode = false;\r
+       \r
+       /**\r
+        * Sets next installation node.\r
+        *\r
+        * @param       string          $node\r
+        */\r
+       public function setNode($node) {\r
+               $this->node = $node;\r
+       }\r
+       \r
+       /**\r
+        * Returns next installation node.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getNode() {\r
+               return $this->node;\r
+       }\r
+       \r
+       /**\r
+        * Sets form document object.\r
+        *\r
+        * @param       FormDocument    $document\r
+        */\r
+       public function setDocument(FormDocument $document) {\r
+               $this->document = $document;\r
+       }\r
+       \r
+       /**\r
+        * Returns HTML-representation of form document object.\r
+        *\r
+        * @return      string\r
+        */\r
+       public function getTemplate() {\r
+               return $this->document->getHTML();\r
+       }\r
+       \r
+       /**\r
+        * Returns true if current step holds a form document object.\r
+        *\r
+        * @return      boolean\r
+        */\r
+       public function hasDocument() {\r
+               return ($this->document !== null);\r
+       }\r
+       \r
+       /**\r
+        * Enforces node splitting.\r
+        */\r
+       public function setSplitNode() {\r
+               $this->splitNode = true;\r
+       }\r
+       \r
+       /**\r
+        * Returns true if node should be splitted.\r
+        *\r
+        * @return      boolean\r
+        */\r
+       public function splitNode() {\r
+               return $this->splitNode;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php
new file mode 100644 (file)
index 0000000..178a682
--- /dev/null
@@ -0,0 +1,231 @@
+<?php
+namespace wcf\system\package;
+use wcf\system\menu\acp\ACPMenu;
+use wcf\data\package\Package;
+use wcf\data\package\PackageEditor;
+use wcf\data\package\installation\queue\PackageInstallationQueue;
+use wcf\data\package\installation\queue\PackageInstallationQueueEditor;
+use wcf\system\cache\CacheHandler;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\SystemException;
+use wcf\system\setup\Uninstaller;
+use wcf\system\WCF;
+use wcf\util\HeaderUtil;
+
+/**
+ * PackageUninstallationDispatcher handles the whole uninstallation process.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageUninstallationDispatcher extends PackageInstallationDispatcher {
+       /**
+        * Creates a new instance of PackageUninstallationDispatcher.
+        *
+        * @param       PackageInstallationQueue        $queue
+        */
+       public function __construct(PackageInstallationQueue $queue) {
+               $this->queue = $queue;
+               $this->nodeBuilder = new PackageUninstallationNodeBuilder($this);
+               
+               $this->action = $this->queue->installationType;
+       }
+       
+       /**
+        * Uninstalls node components and returns next node.
+        *
+        * @param       string          $node
+        * @return      string
+        */
+       public function uninstall($node) {
+               $nodes = $this->nodeBuilder->getNodeData($node);
+               
+               // invoke node-specific actions
+               foreach ($nodes as $data) {
+                       $nodeData = unserialize($data['nodeData']);
+                       
+                       switch ($data['nodeType']) {
+                               case 'package':
+                                       $this->uninstallPackage($nodeData);
+                               break;
+                               
+                               case 'pip':
+                                       $this->executePIP($nodeData);
+                               break;
+                       }
+               }
+               
+               // mark node as completed
+               $this->nodeBuilder->completeNode($node);
+               
+               // return next node
+               return $this->nodeBuilder->getNextNode($node);
+       }
+       
+       /**
+        * @see PackageInstallationDispatcher::executePIP()
+        */
+       protected function executePIP(array $nodeData) {
+               $pip = new $nodeData['className']($this);
+               $pip->uninstall();
+       }
+       
+       /**
+        * Uninstalls current package.
+        *
+        * @param       array           $nodeData
+        */
+       protected function uninstallPackage(array $nodeData) {
+               PackageEditor::deleteAll(array($this->queue->packageID));
+               
+               // reset package cache
+               CacheHandler::getInstance()->clearResource('packages');
+               
+               // rebuild package dependencies
+               Package::rebuildParentPackageDependencies($this->queue->packageID);
+       }
+       
+       /**
+        * Deletes the given list of files from the target dir.
+        *
+        * @param       string          $targetDir
+        * @param       string          $files
+        * @param       boolean         $deleteEmptyDirectories
+        * @param       booelan         $deleteEmptyTargetDir
+        */
+       public function deleteFiles($targetDir, $files, $deleteEmptyTargetDir = false, $deleteEmptyDirectories = true) {
+               new Uninstaller($targetDir, $files, $deleteEmptyTargetDir, $deleteEmptyDirectories);
+       }
+       
+       /**
+        * Checks whether this package is required by other packages.
+        * If so than a template will be displayed to warn the user that
+        * a further uninstallation will uninstall also the dependent packages
+        */
+       public static function checkDependencies() {
+               $packageID = 0;
+               if (isset($_REQUEST['activePackageID'])) {
+                       $packageID = intval($_REQUEST['activePackageID']);
+               }
+               
+               // get packages info
+               try {
+                       // create object of uninstalling package
+                       $package = new Package($packageID);
+               }
+               catch (SystemException $e) {
+                       throw new IllegalLinkException();
+               }
+               
+               // can not uninstall wcf package.
+               if ($package->package == 'com.woltlab.wcf') {
+                       throw new IllegalLinkException();
+               }
+               
+               $dependentPackages = array();
+               $uninstallAvailable = true;
+               if ($package->isRequired()) {
+                       // get packages that requires this package
+                       $dependentPackages = self::getPackageDependencies($package->packageID);
+                       foreach ($dependentPackages as $dependentPackage) {
+                               if ($dependentPackage['packageID'] == PACKAGE_ID) {
+                                       $uninstallAvailable = false;
+                                       break;
+                               }
+                       }
+               }
+               
+               // add this package to queue
+               self::addQueueEntries($package, $dependentPackages);
+       }
+       
+       /**
+        * Get all packages which require this package.
+        *
+        * @param       integer         $packageID
+        * @return      array
+        */
+       public static function getPackageDependencies($packageID) {
+               $sql = "SELECT          *
+                       FROM            wcf".WCF_N."_package
+                       WHERE           packageID IN (
+                                               SELECT  packageID
+                                               FROM    wcf".WCF_N."_package_requirement_map
+                                               WHERE   requirement = ?
+                                       )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               $packages = array();
+               while ($row = $statement->fetchArray()) {
+                       $packages[] = $row;
+               }
+               
+               return $packages;
+       }
+       
+       /**
+        * Returns true if package has dependencies
+        *
+        * @param       integer         $packageID
+        * @return      boolean
+        */
+       public static function hasDependencies($packageID) {
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_package_requirement
+                       WHERE   requirement = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageID));
+               $row = $statement->fetchArray();
+               
+               return ($row['count'] > 0);
+       }
+       
+       /**
+        * Adds an uninstall entry to the package installation queue.
+        *
+        * @param       Package         $package
+        * @param       array           $packages
+        */
+       public static function addQueueEntries(Package $package, $packages = array()) {
+               // get new process no
+               $processNo = PackageInstallationQueue::getNewProcessNo();
+               
+               // add dependent packages to queue
+               $statementParameters = array();
+               foreach ($packages as $dependentPackage) {
+                       $statementParameters[] = array(
+                               'packageName' => $dependentPackage['packageName'],
+                               'packageID' => $dependentPackage['packageID']
+                       );
+               }
+               
+               // add uninstalling package to queue
+               $statementParameters[] = array(
+                       'packageName' => $package->getName(),
+                       'packageID' => $package->packageID
+               );
+               
+               // insert queue entry (entries)
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_queue
+                                       (processNo, userID, package, packageID, action)
+                       VALUES          (?, ?, ?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($statementParameters as $parameter) {
+                       $statement->execute(array(
+                               $processNo,
+                               WCF::getUser()->userID,
+                               $parameter['packageName'],
+                               $parameter['packageID'],
+                               'uninstall'
+                       ));
+               }
+               
+               HeaderUtil::redirect('index.php?page=Package&action=openQueue&processNo='.$processNo.''.SID_ARG_2ND_NOT_ENCODED);
+               exit;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php b/wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php
new file mode 100644 (file)
index 0000000..83479cf
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+namespace wcf\system\package;
+use wcf\system\WCF;
+
+/**
+ * PackageUninstallationNodeBuilder creates a logical node-based uninstallation tree.
+ *
+ * @todo       Change to use Prepared Statements, see line 42
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageUninstallationNodeBuilder extends PackageInstallationNodeBuilder {
+       /**
+        * Builds node for current uninstallation queue.
+        */
+       public function buildNodes() {
+               // build pip nodes
+               $this->buildPluginNodes();
+               
+               // remove package
+               $this->buildPackageNode();
+       }
+       
+       /**
+        * Creates a node-tree for package installation plugins, whereas the PIP- and files-plugin
+        * will be executed last.
+        */
+       protected function buildPluginNodes() {
+               $this->node = $this->getToken();
+               
+               // fetch ordered pips
+               $pips = array();
+               $sql = "SELECT          pluginName, className,
+                                       CASE pluginName WHEN 'packageinstallationplugins' THEN 1 WHEN 'files' THEN 2 ELSE 0 END 'pluginOrder'
+                       FROM            wcf".WCF_N."_package_installation_plugin
+                       WHERE           packageID IN (
+                                               1 /* TESTING ONLY */
+                                               /*
+                                               SELECT  dependency
+                                               FROM    wcf".WCF_N."_package_dependency
+                                               WHERE   packageID = ".$this->installation->queue->packageID."
+                                               */
+                                       )
+                       ORDER BY        pluginOrder ASC, priority DESC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $pips[] = $row;
+               }
+               
+               // insert pips
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                       (queueID, processNo, sequenceNo, node, nodeType, nodeData)
+                       VALUES          (?, ?, ?, ?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $sequenceNo = 0;
+               
+               foreach ($pips as $pip) {
+                       $statement->execute(array(
+                               $this->installation->queue->queueID,
+                               $this->installation->queue->processNo,
+                               $sequenceNo,
+                               $this->node,
+                               'pip',
+                               serialize(array(
+                                       'pluginName' => $pip['pluginName'],
+                                       'className' => $pip['className']
+                               ))
+                       ));
+                       
+                       $sequenceNo++;
+               }
+       }
+       
+       /**
+        * Builds node for package removal
+        */
+       protected function buildPackageNode() {
+               $this->parentNode = $this->node;
+               $this->node = $this->getToken();
+               
+               $sql = "INSERT INTO     wcf".WCF_N."_package_installation_node
+                                       (queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData)
+                       VALUES          (?, ?, ?, ?, ?, ?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $this->installation->queue->queueID,
+                       $this->installation->queue->processNo,
+                       0,
+                       $this->node,
+                       $this->parentNode,
+                       'package',
+                       'a:0:{}'
+               ));
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageUpdateAuthorizationRequiredException.class.php b/wcfsetup/install/files/lib/system/package/PackageUpdateAuthorizationRequiredException.class.php
new file mode 100644 (file)
index 0000000..13c72c7
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+namespace wcf\system\package;
+use wcf\acp\form\PackageUpdateAuthForm;
+
+/**
+ * A PackageUpdateAuthorizationRequiredException is thrown when a package update server requires a user authorization.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class PackageUpdateAuthorizationRequiredException extends UserException {
+       protected $packageUpdateServerID = 0;
+       protected $url = '';
+       protected $response = array();
+       
+       /**
+        * Creates a new PackageUpdateAuthorizationRequiredException object.
+        *
+        * @param       integer         $packageUpdateServerID
+        * @param       string          $url
+        * @param       array           $response
+        */
+       public function __construct($packageUpdateServerID, $url, array $response) {
+               $this->packageUpdateServerID = $packageUpdateServerID;
+               $this->url = $url;
+               $this->response = $response;
+       }
+       
+       /**
+        * Shows the package update authentification form.
+        */
+       public function show() {
+               new PackageUpdateAuthForm($this);
+               exit;
+       }
+       
+       /**
+        * Returns the package update server id.
+        *
+        * @return      integer
+        */
+       public function getPackageUpdateServerID() {
+               return $this->packageUpdateServerID;
+       }
+       
+       /**
+        * Returns the server url.
+        *
+        * @return      string
+        */
+       public function getURL() {
+               return $this->url;
+       }
+       
+       /**
+        * Returns the response header.
+        *
+        * @return      string
+        */
+       public function getResponseHeader() {
+               return $this->response['header'];
+       }
+       
+       /**
+        * Returns the response content.
+        *
+        * @return      string
+        */
+       public function getResponseContent() {
+               return $this->response['content'];
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php
new file mode 100644 (file)
index 0000000..09e6030
--- /dev/null
@@ -0,0 +1,771 @@
+<?php
+namespace wcf\system\package;
+use wcf\data\package\Package;
+use wcf\data\package\update\PackageUpdateEditor;
+use wcf\data\package\update\PackageUpdateList;
+use wcf\data\package\update\server\PackageUpdateServer;
+use wcf\data\package\update\server\PackageUpdateServerEditor;
+use wcf\data\package\update\version\PackageUpdateVersionEditor;
+use wcf\data\package\update\version\PackageUpdateVersionList;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\io\RemoteFile;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+use wcf\util\XML;
+
+/**
+ * Provides functions to manage package updates.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+abstract class PackageUpdateDispatcher {
+       /**
+        * Refreshes the package database.
+        *
+        * @param       array           $packageUpdateServerIDs
+        */
+       public static function refreshPackageDatabase(array $packageUpdateServerIDs = array()) {
+               // get update server data
+               $updateServers = PackageUpdateServer::getActiveUpdateServers($packageUpdateServerIDs);
+               
+               // loop servers
+               foreach ($updateServers as $updateServer) {
+                       if ($updateServer->lastUpdateTime < TIME_NOW - 600) {
+                               try {
+                                       self::getPackageUpdateXML($updateServer);
+                               }
+                               catch (SystemException $e) {
+                                       // save error status
+                                       $updateServerEditor = new PackageUpdateServerEditor($updateServer);
+                                       $updateServerEditor->update(array(
+                                               'status' => 'offline',
+                                               'errorMessage' => $e->getMessage()
+                                       ));
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Gets the package_update.xml from an update server.
+        * 
+        * @param       wcf\data\package\update\server\PackageUpdateServer      $updateServer
+        */
+       protected static function getPackageUpdateXML(PackageUpdateServer $updateServer) {
+               // send request
+               $response = self::sendRequest($updateServer->serverURL, array('lastUpdateTime' => $updateServer->lastUpdateTime), $updateServer->getAuthData());
+               
+               // check response
+               // check http code
+               if ($response['httpStatusCode'] == 401) {
+                       throw new PackageUpdateAuthorizationRequiredException($updateServer['packageUpdateServerID'], $updateServer['server'], $response);
+               }
+               
+               if ($response['httpStatusCode'] != 200) {
+                       throw new SystemException(WCF::getLanguage()->get('wcf.acp.packageUpdate.error.listNotFound') . ' ('.$response['httpStatusLine'].')', 18009);
+               }
+               
+               // parse given package update xml
+               $allNewPackages = self::parsePackageUpdateXML($response['content']);
+               unset($response);
+               
+               // save packages
+               if (count($allNewPackages)) {
+                       self::savePackageUpdates($allNewPackages, $updateServer->packageUpdateServerID);
+               }
+               unset($allNewPackages);
+               
+               // update server status
+               $updateServerEditor = new PackageUpdateServerEditor($updateServer);
+               $updateServerEditor->update(array(
+                       'lastUpdateTime' => TIME_NOW,
+                       'status' => 'online',
+                       'errorMessage' => ''
+               ));
+       }
+       
+       /**
+        * Sends a request to a remote (update) server.
+        * 
+        * @param       string          $url
+        * @param       array           $values
+        * @param       array           $authData
+        * @return      array           $response
+        */
+       public static function sendRequest($url, array $values = array(), array $authData = array()) {
+               // default values
+               $host = '';
+               $path = '/';
+               $port = 80;
+               $postString = '';
+               
+               // parse url
+               $parsedURL = parse_url($url);
+               if (!empty($parsedURL['host'])) $host = $parsedURL['host'];
+               if (!empty($parsedURL['path'])) $path = $parsedURL['path'];
+               if (!empty($parsedURL['query'])) $postString = $parsedURL['query'];
+               if (!empty($parsedURL['port'])) $port = $parsedURL['port'];
+               
+               // connect to server
+               if (PROXY_SERVER_HTTP) {
+                       $parsedProxyURL = parse_url(PROXY_SERVER_HTTP);
+                       $remoteFile = new RemoteFile($parsedProxyURL['host'], $parsedProxyURL['port'], 30);
+                       $path = $url;
+                       $host = $parsedProxyURL['host'];
+               }
+               else {
+                       $remoteFile = new RemoteFile($host, $port, 30);
+               }
+               
+               // Build and send the http request
+               $request = "POST ".$path." HTTP/1.0\r\n";
+               if (isset($authData['authType'])) {
+                       $request .= "Authorization: Basic ".base64_encode($authData['loginUsername'].":".$authData['loginPassword'])."\r\n";
+               }
+               
+               $request .= "User-Agent: HTTP.PHP (PackageUpdateDispatcher.class.php; WoltLab Community Framework/".WCF_VERSION."; ".WCF::getLanguage()->languageCode.")\r\n";
+               $request .= "Accept: */*\r\n";
+               $request .= "Accept-Language: ".WCF::getLanguage()->languageCode."\r\n";
+               $request .= "Host: ".$host."\r\n";
+               
+               // build post string
+               foreach ($values as $name => $value) {
+                       if (!empty($postString)) $postString .= '&';
+                       $postString .= $name.'='.$value;
+               }
+               
+               // send content type and length
+               $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
+               $request .= "Content-Length: ".strlen($postString)."\r\n";
+               // if it is a POST request, there MUST be a blank line before the POST data, but there MUST NOT be 
+               // another blank line before, and of course there must be another blank line at the end of the request!
+               $request .= "\r\n";
+               if (!empty($postString)) $request .= $postString."\r\n";
+               // send close
+               $request .= "Connection: Close\r\n\r\n";
+
+               // send request
+               $remoteFile->puts($request);
+               unset($request, $postString);
+               
+               // define response vars
+               $header = $content = '';
+               
+               // fetch the response.
+               while (!$remoteFile->eof()) {
+                       $line = $remoteFile->gets();
+                       if (rtrim($line) != '') {
+                               $header .= $line;
+                       } else {
+                               break;
+                       }
+               }
+               while (!$remoteFile->eof()) {
+                       $content .= $remoteFile->gets();
+               }
+               
+               // clean up and return the server's response.
+               $remoteFile->close();
+               
+               // get http status code / line
+               $httpStatusCode = 0;
+               $httpStatusLine = '';
+               if (preg_match('%http/\d\.\d (\d{3})[^\n]*%i', $header, $match)) {
+                       $httpStatusLine = trim($match[0]);
+                       $httpStatusCode = $match[1];
+               }
+               
+               // catch http 301 Moved Permanently
+               // catch http 302 Found
+               // catch http 303 See Other
+               if ($httpStatusCode == 301 || $httpStatusCode == 302 || $httpStatusCode == 303) {
+                       // find location
+                       if (preg_match('/location:([^\n]*)/i', $header, $match)) {
+                               $location = trim($match[1]);
+                               if ($location != $url) {
+                                       return self::sendRequest($location, $values, $authData);
+                               }
+                       }
+               }
+               // catch other http codes here
+               
+               return array(
+                       'httpStatusLine' => $httpStatusLine,
+                       'httpStatusCode' => $httpStatusCode,
+                       'header' => $header,
+                       'content' => $content
+               );
+       }
+       
+       /**
+        * Parses a stream containing info from a packages_update.xml.
+        *
+        * @param       string          $content
+        * @return      array           $allNewPackages
+        */
+       protected static function parsePackageUpdateXML($content) {
+               // load xml document
+               $xml = new XML();
+               $xml->loadXML('packageUpdateServer.xml', $content);
+               $xpath = $xml->xpath();
+               
+               // loop through <package> tags inside the <section> tag.
+               $allNewPackages = array();
+               $packages = $xpath->query('/ns:section[@name=\'packages\']/ns:package');
+               foreach ($packages as $package) {
+                       if (!Package::isValidPackageName($package->getAttribute('name'))) {
+                               throw new SystemException("'".$package->getAttribute('name')."' is not a valid package name.", 18004);
+                       }
+                       
+                       $allNewPackages[$package->getAttribute('name')] = self::parsePackageUpdateXMLBlock($xpath, $package);
+               }
+               
+               return $allNewPackages;
+       }
+       
+       /**
+        * Parses the xml stucture from a packages_update.xml.
+        *
+        * @param       \DOMXPath       $xpath
+        * @param       \DOMNode        $package
+        */
+       protected static function parsePackageUpdateXMLBlock(\DOMXPath $xpath, \DOMNode $package) {
+               // define default values
+               $packageInfo = array(
+                       'packageDescription' => '',
+                       'standalone' => 0,
+                       'plugin' => '',
+                       'author' => '',
+                       'authorURL' => '',
+                       'versions' => array()
+               );
+               
+               // parse package information
+               $elements = $xpath->query('./ns:packageinformation/*', $package);
+               foreach ($elements as $element) {
+                       switch ($element->tagName) {
+                               case 'packagename':
+                                       $packageInfo['packageName'] = $element->nodeValue;
+                               break;
+                               
+                               case 'packagedescription':
+                                       $packageInfo['packageDescription'] = $element->nodeValue;
+                               break;
+                               
+                               case 'standalone':
+                                       $packageInfo['standalone'] = intval($element->nodeValue);
+                               break;
+                               
+                               case 'plugin':
+                                       $packageInfo['plugin'] = $element->nodeValue;
+                               break;
+                       }
+               }
+               
+               // parse author information
+               $elements = $xpath->query('./ns:authorinformation/*', $package);
+               foreach ($elements as $element) {
+                       switch ($element->tagName) {
+                               case 'author':
+                                       $packageInfo['author'] = $element->nodeValue;
+                               break;
+                               
+                               case 'authorurl':
+                                       $packageInfo['authorURL'] = $element->nodeValue;
+                               break;
+                       }
+               }
+               
+               // parse versions
+               $elements = $xpath->query('./ns:versions/ns:version', $package);
+               foreach ($elements as $element) {
+                       $versionNo = $element->getAttribute('name');
+                       
+                       $children = $xpath->query('child::*', $element);
+                       foreach ($children as $child) {
+                               switch ($child->tagName) {
+                                       case 'fromversions':
+                                               $fromversions = $xpath->query('child::*', $child);
+                                               foreach ($fromversions as $fromversion) {
+                                                       $packageInfo['versions'][$versionNo]['fromversions'][] = $fromversion->nodeValue;
+                                               }
+                                       break;
+                                       
+                                       case 'updatetype':
+                                               $packageInfo['versions'][$versionNo]['updateType'] = $child->nodeValue;
+                                       break;
+                                       
+                                       case 'timestamp':
+                                               $packageInfo['versions'][$versionNo]['packageDate'] = $child->nodeValue;
+                                       break;
+                                       
+                                       case 'file':
+                                               $packageInfo['versions'][$versionNo]['file'] = $child->nodeValue;
+                                       break;
+                                       
+                                       case 'requiredpackages':
+                                               $requiredPackages = $xpath->query('child::*', $child);
+                                               foreach ($requiredPackages as $requiredPackage) {
+                                                       $minVersion = $requiredPackage->getAttribute('minversion');
+                                                       $required = $requiredPackage->nodeValue;
+                                                       
+                                                       $packageInfo['versions'][$versionNo]['requiredPackages'][$required] = array();
+                                                       if (!empty($minVersion)) {
+                                                               $packageInfo['versions'][$versionNo]['requiredPackages'][$required]['minversion'] = $minVersion;
+                                                       }
+                                               }
+                                       break;
+                                       
+                                       case 'excludedpackages':
+                                               $excludedpackages = $xpath->query('child::*', $child);
+                                               foreach ($excludedpackages as $excludedpackage) {
+                                                       $exclusion = $excludedpackage->nodeValue;
+                                                       $version = $excludedpackage->getAttribute('version');
+                                                       
+                                                       $packageInfo['versions'][$versionNo]['excludedPackages'][$exclusion] = array();
+                                                       if (!empty($version)) {
+                                                               $packageInfo['versions'][$versionNo]['excludedPackages'][$exclusion]['version'] = $version;
+                                                       }
+                                               }
+                                       break;
+                               }
+                       }
+               }
+               
+               return $packageInfo;
+       }
+       
+       /**
+        * Updates information parsed from a packages_update.xml into the database.
+        * 
+        * @param       array           $allNewPackages
+        * @param       integer         $packageUpdateServerID
+        */
+       protected static function savePackageUpdates(array &$allNewPackages, $packageUpdateServerID) {
+               // find existing packages and delete them
+               // get existing packages
+               $existingPackages = array();
+               $packageUpdateList = new PackageUpdateList();
+               $packageUpdateList->getConditionBuilder()->add("package_update.packageUpdateServerID = ? AND package_update.package IN (?)", array($packageUpdateServerID, array_keys($allNewPackages)));
+               $packageUpdateList->sqlLimit = 0;
+               $packageUpdateList->readObjects();
+               $tmp = $packageUpdateList->getObjects();
+               
+               foreach ($tmp as $packageUpdate) {
+                       $existingPackages[$packageUpdate->package] = $packageUpdate;
+               }
+               
+               // get existing versions
+               $existingPackageVersions = array();
+               if (count($existingPackages) > 0) {
+                       // get package update ids
+                       $packageUpdateIDs = array();
+                       foreach ($existingPackages as $packageUpdate) {
+                               $packageUpdateIDs[] = $packageUpdate->packageUpdateID;
+                       }
+                       
+                       // get version list
+                       $versionList = new PackageUpdateVersionList();
+                       $versionList->getConditionBuilder()->add("package_update_version.packageUpdateID IN (?)", array($packageUpdateIDs));
+                       $versionList->sqlLimit = 0;
+                       $versionList->readObjects();
+                       $tmp = $versionList->getObjects();
+                       
+                       foreach ($tmp as $version) {
+                               if (!isset($existingPackageVersions[$version->packageUpdateID])) $existingPackageVersions[$version->packageUpdateID] = array();
+                               $existingPackageVersions[$version->packageUpdateID][$version->packageVersion] = $version;
+                       }
+               }
+               
+               // insert updates
+               $excludedPackagesParameters = $fromversionParameters = $insertParameters = array();
+               foreach ($allNewPackages as $identifier => $packageData) {
+                       if (isset($existingPackages[$identifier])) {
+                               $packageUpdateID = $existingPackages[$identifier]->packageUpdateID;
+                               
+                               // update database entry
+                               $packageUpdateEditor = new PackageUpdateEditor($existingPackages[$identifier]);
+                               $packageUpdateEditor->update(array(
+                                       'packageName' => $packageData['packageName'],
+                                       'packageDescription' => $packageData['packageDescription'],
+                                       'author' => $packageData['author'],
+                                       'authorURL' => $packageData['authorURL'],
+                                       'standalone' => $packageData['standalone'],
+                                       'plugin' => $packageData['plugin']
+                               ));
+                       }
+                       else {
+                               // create new database entry
+                               $packageUpdate = PackageUpdateEditor::create(array(
+                                       'packageUpdateServerID' => $packageUpdateServerID,
+                                       'package' => $identifier,
+                                       'packageName' => $packageData['packageName'],
+                                       'packageDescription' => $packageData['packageDescription'],
+                                       'author' => $packageData['author'],
+                                       'authorURL' => $packageData['authorURL'],
+                                       'standalone' => $packageData['standalone'],
+                                       'plugin' => $packageData['plugin']
+                               ));
+                               
+                               $packageUpdateID = $packageUpdate->packageUpdateID;
+                       }
+                       
+                       // register version(s) of this update package.
+                       if (isset($packageData['versions'])) {
+                               foreach ($packageData['versions'] as $packageVersion => $versionData) {
+                                       if (isset($versionData['file'])) $packageFile = $versionData['file'];
+                                       else $packageFile = '';
+                                       
+                                       if (isset($existingPackageVersions[$packageUpdateID]) && isset($existingPackageVersions[$packageUpdateID][$packageVersion])) {
+                                               $packageUpdateVersionID = $existingPackageVersions[$packageUpdateID][$packageVersion]->packageUpdateVersionID;
+                                               
+                                               // update database entry
+                                               $versionEditor = new PackageUpdateVersionEditor($existingPackageVersions[$packageUpdateID][$packageVersion]);
+                                               $versionEditor->update(array(
+                                                       'updateType' => $versionData['updateType'],
+                                                       'packageDate' => $versionData['packageDate'],
+                                                       'filename' => $packageFile
+                                               ));
+                                       }
+                                       else {
+                                               // create new database entry
+                                               $version = PackageUpdateVersionEditor::create(array(
+                                                       'packageUpdateID' => $packageUpdateID,
+                                                       'packageVersion' => $packageVersion,
+                                                       'updateType' => $versionData['updateType'],
+                                                       'packageDate' => $versionData['packageDate'],
+                                                       'filename' => $packageFile
+                                               ));
+                                               
+                                               $packageUpdateVersionID = $version->packageUpdateVersionID;
+                                       }
+                                       
+                                       // register requirement(s) of this update package version.
+                                       if (isset($versionData['requiredPackages'])) {
+                                               foreach ($versionData['requiredPackages'] as $requiredIdentifier => $required) {
+                                                       $requirementInserts[] = array(
+                                                               'packageUpdateVersionID' => $packageUpdateVersionID,
+                                                               'package' => $requiredIdentifier,
+                                                               'minversion' => (isset($required['minversion']) ? $required['minversion'] : '')
+                                                       );
+                                               }
+                                       }
+                                       
+                                       // register excluded packages of this update package version.
+                                       if (isset($versionData['excludedPackages'])) {
+                                               foreach ($versionData['excludedPackages'] as $excludedIdentifier => $exclusion) {
+                                                       $excludedPackagesParameters[] = array(
+                                                               'packageUpdateVersionID' => $packageUpdateVersionID,
+                                                               'excludedPackage' => $excludedIdentifier,
+                                                               'excludedPackageVersion' => (isset($exclusion['version']) ? $exclusion['version'] : '')
+                                                       );
+                                               }
+                                       }
+                                       
+                                       // register fromversions of this update package version.
+                                       if (isset($versionData['fromversions'])) {
+                                               foreach ($versionData['fromversions'] as $fromversion) {
+                                                       $fromversionInserts[] = array(
+                                                               'packageUpdateVersionID' => $packageUpdateVersionID,
+                                                               'fromversion' => $fromversion
+                                                       );
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               // save requirements, excluded packages and fromversions
+               // use multiple inserts to save some queries
+               if (!empty($requirementInserts)) {
+                       // clear records
+                       $sql = "DELETE pur FROM wcf".WCF_N."_package_update_requirement pur
+                               LEFT JOIN       wcf".WCF_N."_package_update_version puv
+                               ON              (puv.packageUpdateVersionID = pur.packageUpdateVersionID)
+                               LEFT JOIN       wcf".WCF_N."_package_update pu
+                               ON              (pu.packageUpdateID = puv.packageUpdateID)
+                               WHERE           pu.packageUpdateServerID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($packageUpdateServerID));
+                       
+                       // insert requirements
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_update_requirement
+                                               (packageUpdateVersionID, package, minversion)
+                               VALUES          (?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($requirementInserts as $requirement) {
+                               $statement->execute(array(
+                                       $requirement['packageUpdateVersionID'],
+                                       $requirement['package'],
+                                       $requirement['minversion']
+                               ));
+                       }
+               }
+               
+               if (!empty($excludedPackagesInserts)) {
+                       // clear records
+                       $sql = "DELETE pue FROM wcf".WCF_N."_package_update_exclusion pue
+                               LEFT JOIN       wcf".WCF_N."_package_update_version puv
+                               ON              (puv.packageUpdateVersionID = pue.packageUpdateVersionID)
+                               LEFT JOIN       wcf".WCF_N."_package_update pu
+                               ON              (pu.packageUpdateID = puv.packageUpdateID)
+                               WHERE           pu.packageUpdateServerID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($packageUpdateServerID));
+                       
+                       // insert excludes
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_update_exclusion
+                                               (packageUpdateVersionID, excludedPackage, excludedPackageVersion)
+                               VALUES          (?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($excludedPackagesInserts as $excludedPackage) {
+                               $statement->execute(array(
+                                       $excludedPackage['packageUpdateVersionID'],
+                                       $excludedPackage['excludedPackage'],
+                                       $excludedPackage['excludedPackageVersion']
+                               ));
+                       }
+               }
+               
+               if (!empty($fromversionInserts)) {
+                       // clear records
+                       $sql = "DELETE puf FROM wcf".WCF_N."_package_update_fromversion puf
+                               LEFT JOIN       wcf".WCF_N."_package_update_version puv
+                               ON              (puv.packageUpdateVersionID = puf.packageUpdateVersionID)
+                               LEFT JOIN       wcf".WCF_N."_package_update pu
+                               ON              (pu.packageUpdateID = puv.packageUpdateID)
+                               WHERE           pu.packageUpdateServerID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($packageUpdateServerID));
+                       
+                       // insert excludes
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_update_fromversion
+                                               (packageUpdateVersionID, fromversion)
+                               VALUES          (?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($fromversionInserts as $fromversion) {
+                               $statement->execute(array(
+                                       $fromversion['packageUpdateVersionID'],
+                                       $fromversion['fromversion']
+                               ));
+                       }
+               }
+       }
+       
+       /**
+        * Returns a list of available updates for installed packages.
+        * 
+        * @param       boolean         $removeRequirements
+        * @return      array
+        */
+       public static function getAvailableUpdates($removeRequirements = true) {
+               $updates = array();
+               
+               // get update server data
+               $updateServers = PackageUpdateServer::getActiveUpdateServers();
+               $packageUpdateServerIDs = array_keys($updateServers);
+               if (empty($packageUpdateServerIDs)) return $updates;
+               
+               // get existing packages and their versions
+               $existingPackages = array();
+               $sql = "SELECT  packageID, package, instanceNo, packageDescription,
+                               packageVersion, packageDate, author, authorURL, standalone,
+                               CASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName
+                       FROM    wcf".WCF_N."_package";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $existingPackages[$row['package']][] = $row;
+               }
+               $existingPackageIdentifiers = implode("','", array_keys($existingPackages));
+               if (empty($existingPackageIdentifiers)) return $updates;
+               
+               // get all update versions
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("pu.packageUpdateServerID IN (?)", array($packageUpdateServerIDs));
+               $conditions->add("package IN (SELECT DISTINCT package FROM wcf".WCF_N."_package)");
+               
+               $sql = "SELECT          pu.packageUpdateID, pu.packageUpdateServerID, pu.package,
+                                       puv.packageUpdateVersionID, puv.updateType, puv.packageDate, puv.filename, puv.packageVersion
+                       FROM            wcf".WCF_N."_package_update pu
+                       LEFT JOIN       wcf".WCF_N."_package_update_version puv
+                       ON              (puv.packageUpdateID = pu.packageUpdateID)
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       // test version
+                       foreach ($existingPackages[$row['package']] as $existingVersion) {
+                               if (Package::compareVersion($existingVersion['packageVersion'], $row['packageVersion'], '<')) {
+                                       // package data
+                                       if (!isset($updates[$existingVersion['packageID']])) {
+                                               $existingVersion['versions'] = array();
+                                               $updates[$existingVersion['packageID']] = $existingVersion;
+                                       }
+                                       
+                                       // version data
+                                       if (!isset($updates[$existingVersion['packageID']]['versions'][$row['packageVersion']])) {
+                                               $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']] = array(
+                                                       'updateType' => $row['updateType'],
+                                                       'packageDate' => $row['packageDate'],
+                                                       'packageVersion' => $row['packageVersion'],
+                                                       'servers' => array()
+                                               );
+                                       }
+                                       
+                                       // server data
+                                       $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']]['servers'][] = array(
+                                               'packageUpdateID' => $row['packageUpdateID'],
+                                               'packageUpdateServerID' => $row['packageUpdateServerID'],
+                                               'packageUpdateVersionID' => $row['packageUpdateVersionID'],
+                                               'filename' => $row['filename']
+                                       );
+                               }
+                       }
+               }
+               
+               // sort package versions
+               // and remove old versions
+               foreach ($updates as $packageID => $data) {
+                       uksort($updates[$packageID]['versions'], array('Package', 'compareVersion'));
+                       $updates[$packageID]['version'] = end($updates[$packageID]['versions']);
+               }
+               
+               // remove requirements of standalone packages
+               if ($removeRequirements) {
+                       foreach ($existingPackages as $identifier => $instances) {
+                               foreach ($instances as $instance) {
+                                       if ($instance['standalone'] && isset($updates[$instance['packageID']])) {
+                                               $updates = self::removeUpdateRequirements($updates, $updates[$instance['packageID']]['version']['servers'][0]['packageUpdateVersionID']);
+                                       }
+                               }
+                       }
+               }
+               
+               return $updates;
+       }
+       
+       /**
+        * Removes unnecessary updates of requirements from the list of available updates.
+        * 
+        * @param       array           $updates
+        * @param       integer         $packageUpdateVersionID
+        * @return      array           $updates
+        */
+       protected static function removeUpdateRequirements(array $updates, $packageUpdateVersionID) {
+               $sql = "SELECT          pur.package, pur.minversion, p.packageID
+                       FROM            wcf".WCF_N."_package_update_requirement pur
+                       LEFT JOIN       wcf".WCF_N."_package p
+                       ON              (p.package = pur.package)
+                       WHERE           pur.packageUpdateVersionID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($packageUpdateVersionID));
+               while ($row = $statement->fetchArray()) {
+                       if (isset($updates[$row['packageID']])) {
+                               $updates = self::removeUpdateRequirements($updates, $updates[$row['packageID']]['version']['servers'][0]['packageUpdateVersionID']);
+                               if (Package::compareVersion($row['minversion'], $updates[$row['packageID']]['version']['packageVersion'], '>=')) {
+                                       unset($updates[$row['packageID']]);
+                               }
+                       }
+               }
+               
+               return $updates;
+       }
+       
+       public static function prepareInstallation(array $selectedPackages, array $packageUpdateServerIDs = array(), $download = true) {
+               return new PackageInstallationScheduler($selectedPackages, $packageUpdateServerIDs, $download);
+       }
+       
+       /**
+        * Gets package update versions of a package.
+        * 
+        * @param       string          $package        package identifier
+        * @param       string          $version        package version
+        * @return      array           package update versions
+        */
+       public static function getPackageUpdateVersions($package, $version = '') {
+               // get newest package version
+               if (empty($version)) {
+                       $version = self::getNewestPackageVersion($package);
+               }
+               
+               // get versions
+               $versions = array();
+               $sql = "SELECT          puv.*, pu.*
+                       FROM            wcf".WCF_N."_package_update_version puv
+                       LEFT JOIN       wcf".WCF_N."_package_update pu
+                       ON              (pu.packageUpdateID = puv.packageUpdateID)
+                       LEFT JOIN       wcf".WCF_N."_package_update_server pus
+                       ON              (pus.packageUpdateServerID = pu.packageUpdateServerID)
+                       WHERE           pu.package = ?
+                                       AND puv.packageVersion = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $package,
+                       $version
+               ));
+               while ($row = $statement->fetchArray()) {
+                       $versions[] = $row;
+               }
+               
+               if (!count($versions)) {
+                       throw new SystemException("Can not find package '".$package."' in version '".$version."'", 18101);
+               }
+               
+               return $versions;
+       }
+       
+       /**
+        * Returns the newest available version of a package.
+        * 
+        * @param       string          $package        package identifier
+        * @return      string          newest package version
+        */
+       public static function getNewestPackageVersion($package) {
+               // get all versions
+               $versions = array();
+               $sql = "SELECT  packageVersion
+                       FROM    wcf".WCF_N."_package_update_version
+                       WHERE   packageUpdateID IN (
+                                       SELECT  packageUpdateID
+                                       FROM    wcf".WCF_N."_package_update
+                                       WHERE   package = ?
+                               )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($package));
+               while ($row = $statement->fetchArray()) {
+                       $versions[$row['packageVersion']] = $row['packageVersion'];
+               }
+               
+               // sort by version number
+               usort($versions, array('Package', 'compareVersion'));
+               
+               // take newest (last)
+               return array_pop($versions);
+       }
+       
+       /**
+        * Stores the filename of a download in session.
+        * 
+        * @param       string          $package        package identifier
+        * @param       string          $version        package version
+        * @param       string          $filename
+        */
+       public static function cacheDownload($package, $version, $filename) {
+               $cachedDownloads = WCF::getSession()->getVar('cachedPackageUpdateDownloads');
+               if (!is_array($cachedDownloads)) {
+                       $cachedDownloads = array();
+               }
+               
+               // store in session
+               $cachedDownloads[$package.'@'.$version] = $filename;
+               WCF::getSession()->register('cachedPackageUpdateDownloads', $cachedDownloads);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/TemplatesFileHandler.class.php b/wcfsetup/install/files/lib/system/package/TemplatesFileHandler.class.php
new file mode 100644 (file)
index 0000000..0e16eeb
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+namespace wcf\system\package;
+
+/**
+ * TemplatesFileHandler is a FileHandler implementation for the installation of template files.
+ * 
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package
+ * @category   Community Framework
+ */
+class TemplatesFileHandler extends ACPTemplatesFileHandler {
+       protected $tableName = '_template';
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..40ca3a9
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+namespace wcf\system\package\plugin;
+
+/**
+ * This PIP installs, updates or deletes acp-menu items.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class ACPMenuPackageInstallationPlugin extends AbstractMenuPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\acp\menu\item\ACPMenuItemEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'acp_menu_item';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'acpmenuitem';
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/ACPTemplatesPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ACPTemplatesPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..9f91c1c
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\exception\SystemException;
+use wcf\system\io\Tar;
+use wcf\system\package\ACPTemplatesFileHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * This PIP installs, updates or deletes by a package delivered ACP-templates.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class ACPTemplatesPackageInstallationPlugin extends AbstractPackageInstallationPlugin {
+       public $tagName = 'acptemplates';
+       public $tableName = 'acp_template';
+       
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               parent::install();
+
+               // extract files.tar to temp folder
+               $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'acptemplates_');
+               
+               // create file handler
+               $fileHandler = new ACPTemplatesFileHandler($this->installation);
+               
+               // extract content of files.tar
+               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+               
+               try {
+                       $fileInstaller = $this->installation->extractFiles($packageDir.'acp/templates/', $sourceFile, $fileHandler);
+               }
+               catch (SystemException $e) {
+                       WCF::getTPL()->assign(array(
+                               'exception' => $e
+                       ));
+                       WCF::getTPL()->display('packageInstallationFileInstallationFailed');
+                       exit;
+               }
+               
+               // delete temporary sourceArchive
+               @unlink($sourceFile);
+       }
+       
+       /**
+        * @see PackageInstallationPlugin::uninstall()
+        */
+       public function uninstall() {
+               // create ACP-templates list
+               $templates = array();
+               
+               // get ACP-templates from log
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_acp_template
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               while ($row = $statement->fetchArray()) {
+                       // store acp template with suffix (_$packageID)
+                       $templates[] = 'acp/templates/'.$row['templateName'].'.tpl';
+               }
+               
+               if (count($templates) > 0) {
+                       // delete template files
+                       $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+                       $deleteEmptyDirectories = $this->installation->getPackage()->standalone;
+                       $this->installation->deleteFiles($packageDir, $templates, false, $deleteEmptyDirectories);
+                       
+                       // delete log entries
+                       parent::uninstall();
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..594dbe1
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Default implementation for menu item manipulations.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+abstract class AbstractMenuPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           menuItem = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $item['attributes']['name'],
+                               $this->installation->getPackageID()
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               // adjust show order
+               $showOrder = (isset($data['elements']['showorder'])) ? $data['elements']['showorder'] : null;
+               $parent = (isset($data['elements']['parent'])) ? $data['elements']['parent'] : '';
+               $showOrder = $this->getShowOrder($showOrder, $parent, 'parentMenuItem');
+               
+               // merge values and default values
+               return array(
+                       'menuItem' => $data['attributes']['name'],
+                       'menuItemLink' => (isset($data['elements']['link'])) ? $data['elements']['link'] : '',
+                       'options' => (isset($data['elements']['option'])) ? $data['elements']['options'] : '',
+                       'parentMenuItem' => (isset($data['elements']['parent'])) ? $data['elements']['parent'] : '',
+                       'permissions' => (isset($data['elements']['permissions'])) ? $data['elements']['permissions'] : '',
+                       'showOrder' => $showOrder
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::validateImport()
+        */
+       protected function validateImport(array $data) {
+               if (empty($data['parentMenuItem'])) {
+                       return;
+               }
+               
+               $sql = "SELECT  COUNT(menuItemID) AS count
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   menuItem = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($data['parentMenuItem']));
+               $row = $statement->fetchArray();
+               
+               if (!$row['count']) {
+                       throw new SystemException("Unable to find parent 'menu item' with name '".$data['parentMenuItem']."' for 'menu item' with name '".$data['menuItem']."'.", 13011);
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   menuItem = ?
+                               AND packageID = ?";
+               $parameters = array(
+                       $data['menuItem'],
+                       $this->installation->getPackageID()
+               );
+               
+               return array(
+                       'sql' => $sql,
+                       'parameters' => $parameters
+               );
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..1f1af72
--- /dev/null
@@ -0,0 +1,270 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Default implementation of some functions for PackageInstallationPlugin using options.
+ * 
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+abstract class AbstractOptionPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               AbstractPackageInstallationPlugin::install();
+               
+               $xml = $this->getXML($this->instruction['value']);
+               $xpath = $xml->xpath();
+               
+               
+               if ($this->installation->getAction() == 'update') {
+                       // handle delete first
+                       $this->deleteItems($xpath);
+               }
+               
+               // import or update categories
+               $this->importCategories($xpath);
+               
+               // import or update options
+               $this->importOptions($xpath);
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::deleteItems()
+        */     
+       protected function deleteItems(\DOMXPath $xpath) {
+               // delete options
+               $elements = $xpath->query('/ns:data/ns:delete/ns:option');
+               $options = array();
+               foreach ($elements as $element) {
+                       $options[] = $element->getAttribute('name');
+               }
+               
+               if (count($options)) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                               WHERE           optionName = ?
+                               AND packageID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($options as $option) {
+                               $statement->execute(array(
+                                       $option,
+                                       $this->installation->getPackageID()
+                               ));
+                       }
+               }
+               
+               // delete categories
+               $elements = $xpath->query('/ns:data/ns:delete/ns:optioncategory');
+               $categories = array();
+               foreach ($elements as $element) {
+                       $categories[] = $element->getAttribute('name');
+               }
+               
+               if (count($categories)) {
+                       // delete options for given categories
+                       $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                               WHERE           categoryName = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       foreach ($categories as $category) {
+                               $statement->execute(array($category));
+                       }
+                       
+                       // delete categories
+                       $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."_category
+                               WHERE           categoryName = ?
+                               AND packageID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($categories as $category) {
+                               $statement->execute(array(
+                                       $category,
+                                       $this->installation->getPackageID()
+                               ));
+                       }
+               }
+       }
+       
+       protected function importCategories(\DOMXPath $xpath) {
+               $elements = $xpath->query('/ns:data/ns:import/ns:categories/ns:category');
+               foreach ($elements as $element) {
+                       $data = array();
+                       
+                       // get child elements
+                       $children = $xpath->query('child::*', $element);
+                       foreach ($children as $child) {
+                               $data[$child->tagName] = $child->nodeValue;
+                       }
+                       
+                       // build data block with defaults
+                       $data = array(
+                               'categoryName' => $element->getAttribute('name'),
+                               'options' => (isset($data['options'])) ? $data['options'] : '',
+                               'parentCategoryName' => (isset($data['parent'])) ? $data['parent'] : '',
+                               'permissions' => (isset($data['permissions'])) ? $data['permissions'] : '',
+                               'showOrder' => (isset($data['showorder'])) ? intval($data['showorder']) : null
+                       );
+                       
+                       // adjust show order
+                       if ($data['showOrder'] !== null || $this->installation->getAction() != 'update') {
+                               $data['showOrder'] = $this->getShowOrder($data['showOrder'], $data['parentCategoryName'], 'parentCategoryName', '_category');
+                       }
+                       
+                       // validate parent
+                       if (!empty($data['parentCategoryName'])) {
+                               $sql = "SELECT  COUNT(categoryID) AS count
+                                       FROM    wcf".WCF_N."_".$this->tableName."_category
+                                       WHERE   categoryName = ?";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute(array($data['parentCategoryName']));
+                               $row = $statement->fetchArray();
+                               
+                               if (!$row['count']) {
+                                       throw new SystemException("Unable to find parent 'option category' with name '".$data['parentCategoryName']."' for category with name '".$data['categoryName']."'.", 13011);
+                               }
+                       }
+                       
+                       // save category
+                       $this->saveCategory($data);
+               }
+       }
+       
+       protected function importOptions(\DOMXPath $xpath) {
+               $elements = $xpath->query('/ns:data/ns:import/ns:options/ns:option');
+               foreach ($elements as $element) {
+                       $data = array();
+                       $children = $xpath->query('child::*', $element);
+                       foreach ($children as $child) {
+                               $data[$child->tagName] = $child->nodeValue;
+                       }
+                       
+                       $data['name'] = $element->getAttribute('name');
+                       
+                       if (!preg_match("/^[\w-\.]+$/", $data['name'])) {
+                               $matches = array();
+                               preg_match_all("/(\W)/", $data['name'], $matches);
+                               throw new SystemException("The user option '".$data['name']."' has at least one non-alphanumeric character (underscore is permitted): (".implode("), ( ", $matches[1]).").", 13024); 
+                       }
+                       
+                       $this->saveOption($data, $data['categoryname']);
+               }
+       }
+       
+       /**
+        * @see PackageInstallationPlugin::hasUninstall()
+        */
+       public function hasUninstall() {
+               $hasUninstallOptions = parent::hasUninstall();
+               $sql = "SELECT  COUNT(categoryID) AS count
+                       FROM    wcf".WCF_N."_".$this->tableName."_category
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $categoryCount = $statement->fetchArray();
+               return ($hasUninstallOptions || $categoryCount['count'] > 0);
+       }
+       
+       /**
+        * Uninstalls option categories and options.
+        */
+       public function uninstall() {
+               // delete options
+               parent::uninstall();
+               
+               // delete categories
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."_category
+                       WHERE           packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+       }
+
+       /**
+        * Installs option categories.
+        * 
+        * @param       array           $category
+        */
+       protected function saveCategory($category) {
+               // search existing category
+               $sql = "SELECT  categoryID
+                       FROM    wcf".WCF_N."_".$this->tableName."_category
+                       WHERE   categoryName = ?
+                               AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $category['categoryName'],
+                       $this->installation->getPackageID()
+               ));
+               $row = $statement->fetchArray();
+               if (empty($row['categoryID'])) {
+                       // insert new category
+                       $sql = "INSERT INTO     wcf".WCF_N."_".$this->tableName."_category
+                                               (packageID, categoryName, parentCategoryName, permissions,
+                                               options".($category['showOrder'] !== null ? ",showOrder" : "").")
+                               VALUES          (?, ?, ?, ?, ?".($category['showOrder'] !== null ? ", ?" : "").")";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       $data = array(
+                               $this->installation->getPackageID(),
+                               $category['categoryName'],
+                               $category['parentCategoryName'],
+                               $category['permissions'],
+                               $category['options']
+                       );
+                       if ($category['showOrder'] !== null) $data[] = $category['showOrder'];
+                       
+                       $statement->execute($data);
+               }
+               else {
+                       // update existing category
+                       $sql = "UPDATE  wcf".WCF_N."_".$this->tableName."_category
+                               SET     parentCategoryName = ?,
+                                       permissions = ?,
+                                       options = ?
+                                       ".($category['showOrder'] !== null ? ", showOrder = ?" : "")."
+                               WHERE   categoryID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       $data = array(
+                               $category['parentCategoryName'],
+                               $category['permissions'],
+                               $category['options']
+                       );
+                       if ($category['showOrder'] !== null) $data[] = $category['showOrder'];
+                       $data[] = $row['categoryID'];
+                       
+                       $statement->execute($data);
+               }
+       }
+       
+       /**
+        * Installs options.
+        * 
+        * @param       array           $option
+        * @param       string          $categoryName
+        * @param       integer         $existingOptionID
+        */
+       protected abstract function saveOption($option, $categoryName, $existingOptionID = 0);
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) { }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) { }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) { }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..a5f73a1
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\event\EventHandler;
+use wcf\system\package\PackageInstallationDispatcher;
+use wcf\system\WCF;
+
+/**
+ * Default implementation of some PackageInstallationPlugin functions.
+ * 
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+abstract class AbstractPackageInstallationPlugin implements PackageInstallationPlugin {
+       /**
+        * Database table name.
+        *
+        * @var string
+        */
+       public $tableName = '';
+       
+       /**
+        * Active instance of PackageInstallationQueue
+        *
+        * @var PackageInstallationQueue
+        */
+       public $installation = null;
+       
+       /**
+        * install/update instructions
+        *
+        * @var array
+        */
+       public $instruction = array();
+       
+       /**
+        * Creates a new AbstractPackageInstallationPlugin object.
+        * 
+        * @param       PackageInstallationDispatcher   $installation
+        * @param       array                           $instruction
+        */
+       public function __construct(PackageInstallationDispatcher $installation, $instruction = array()) {
+               $this->installation = $installation;
+               $this->instruction = $instruction;
+               
+               // call construct event
+               EventHandler::getInstance()->fireAction($this, 'construct');
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::install()
+        */
+       public function install() {
+               // call install event
+               EventHandler::getInstance()->fireAction($this, 'install');
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::update()
+        */
+       public function update() {
+                       // call update event
+               EventHandler::getInstance()->fireAction($this, 'update');
+                               
+               return $this->install();
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::hasUninstall()
+        */
+       public function hasUninstall() {
+               // call hasUninstall event
+               EventHandler::getInstance()->fireAction($this, 'hasUninstall');
+               
+               $sql = "SELECT  COUNT(*) AS count
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $installationCount = $statement->fetchArray();
+               return $installationCount['count'];
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::uninstall()
+        */
+       public function uninstall() {
+               // call uninstall event
+               EventHandler::getInstance()->fireAction($this, 'uninstall');
+               
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..2ae2300
--- /dev/null
@@ -0,0 +1,310 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\XML;
+
+/**
+ * Default implementation of some functions for a PackageInstallationPlugin using xml definitions.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+abstract class AbstractXMLPackageInstallationPlugin extends AbstractPackageInstallationPlugin {
+       /**
+        * object editor class name
+        * @var string
+        */
+       public $className = '';
+       
+       /**
+        * sql database table name
+        * @var string
+        */
+       public $tableName = '';
+       
+       /**
+        * xml tag name, e.g. 'acpmenuitem'
+        * @var string
+        */
+       public $tagName = '';
+       
+       /**
+        * @see  PackageInstallationPlugin::install()
+        */
+       public function install() {
+               parent::install();
+               
+               // get xml
+               $xml = $this->getXML($this->instruction['value']);
+               $xpath = $xml->xpath();
+               
+               // handle delete first
+               if ($this->installation->getAction() == 'update') {
+                       $this->deleteItems($xpath);
+               }
+               
+               // handle import
+               $this->importItems($xpath);
+               
+               // execute cleanup after successfull import/delete/update
+               $this->cleanup();
+       }
+       
+       /**
+        * Deletes items.
+        * 
+        * @param       DOMXPath $xpath
+        */
+       protected function deleteItems(\DOMXPath $xpath) {
+               $elements = $xpath->query('/ns:data/ns:delete/ns:'.$this->tagName);
+               $items = array();
+               foreach ($elements as $element) {
+                       $data = array(
+                               'attributes' => array(),
+                               'value' => $element->nodeValue
+                       );
+                       
+                       // get attributes
+                       $attributes = $xpath->query('attribute::*', $element);
+                       foreach ($attributes as $attribute) {
+                               $data['attributes'][$attribute->name] = $attribute->value;
+                       }
+                       
+                       $items[] = $data;
+               }
+               
+               // delete items
+               if (!empty($items)) {
+                       $this->handleDelete($items);
+               }
+       }
+       
+       /**
+        * Imports or updates items.
+        * 
+        * @param       DOMXPath        $xpath
+        */     
+       protected function importItems(\DOMXPath $xpath) {
+               $elements = $xpath->query('/ns:data/ns:import/ns:'.$this->tagName);
+               foreach ($elements as $element) {
+                       $data = array(
+                               'attributes' => array(),
+                               'elements' => array(),
+                               'nodeValue' => ''
+                       );
+                       
+                       // fetch attributes
+                       $attributes = $xpath->query('attribute::*', $element);
+                       foreach ($attributes as $attribute) {
+                               $data['attributes'][$attribute->name] = $attribute->value;
+                       }
+                       
+                       // fetch child elements
+                       $items = $xpath->query('child::*', $element);
+                       foreach ($items as $item) {
+                               $data['elements'][$item->tagName] = $item->nodeValue;
+                       }
+                       
+                       // include node value if item does not contain any child elements (eg. pip)
+                       if (empty($data['elements'])) {
+                               $data['nodeValue'] = $element->nodeValue;
+                       }
+                       
+                       // map element data to database fields
+                       $data = $this->prepareImport($data);
+                       
+                       // validate item data
+                       $this->validateImport($data);
+                       
+                       // try to find an existing item for updating
+                       $sqlData = $this->findExistingItem($data);
+                       
+                       // handle items which do not support updating (e.g. cronjobs)
+                       if ($sqlData === null) $row = false;
+                       else {
+                               $statement = WCF::getDB()->prepareStatement($sqlData['sql']);
+                               $statement->execute($sqlData['parameters']);
+                               $row = $statement->fetchArray();
+                       }
+                       
+                       // ensure a valid parameter for import()
+                       if ($row === false) $row = array();
+                       
+                       // import items
+                       $this->import($row, $data);
+               }
+               
+               // fire after import
+               $this->postImport();
+       }
+       
+       /**
+        * Inserts or updates new items.
+        * 
+        * @param       array           $row
+        * @param       array           $data
+        */     
+       protected function import(array $row, array $data) {
+               if (empty($row)) {
+                       // create new item
+                       $this->prepareCreate($data);
+                       
+                       call_user_func(array($this->className, 'create'), $data);
+               }
+               else {
+                       // update existing item
+                       $baseClass = call_user_func(array($this->className, 'getBaseClass'));
+                       
+                       $itemEditor = new $this->className(new $baseClass(null, $row));
+                       $itemEditor->update($data);
+               }
+       }
+       
+       /**
+        * Executed after all items would have been imported, use this hook if you've
+        * overwritten import() to disable insert/update.
+        */     
+       protected function postImport() { }
+       
+       /**
+        * Deletes items.
+        * 
+        * @param       array   $items
+        */     
+       abstract protected function handleDelete(array $items);
+       
+       /**
+        * Prepares import, use this to map xml tags and attributes
+        * to their corresponding database fields.
+        * 
+        * @param       array   $data
+        * @return      array
+        */
+       abstract protected function prepareImport(array $data);
+       
+       /**
+        * Validates given item, e.g. checking for invalid values. If validation
+        * fails you should throw an exception.
+        * 
+        * @param       array   $data
+        */
+       protected function validateImport(array $data) { }
+       
+       /**
+        * Find an existing item for updating, should return sql query.
+        * 
+        * @param       array   $data
+        * @return      array
+        */
+       abstract protected function findExistingItem(array $data);
+       
+       /**
+        * Append additional fields which are not to be updated if a corresponding
+        * item exists but are required for creation.
+        * 
+        * Attention: $data is passed by reference
+        * 
+        * @param       array   $data
+        */     
+       protected function prepareCreate(array &$data) {
+               $data['packageID'] = $this->installation->getPackageID();
+       }
+       
+       /**
+        * Triggered after executing all delete and/or import actions.
+        */     
+       protected function cleanup() { }
+       
+       /**
+        * Loads the xml file into a string and returns this string.
+        *
+        * @param       string          $filename
+        * @return      XML             $xml
+        */
+       protected function getXML($filename = '') {
+               if (empty($filename)) {
+                       $filename = $this->instruction['value'];
+               }
+
+               // Search the xml-file in the package archive.
+               // Abort installation in case no file was found.
+               if (($fileIndex = $this->installation->getArchive()->getTar()->getIndexByFilename($filename)) === false) {
+                       throw new SystemException("xml file '".$filename."' not found in '".$this->installation->getArchive()->getArchive()."'", 13008);
+               }
+
+               // Extract acpmenu file and parse with SimpleXML
+               $xml = new XML();
+               $tmpFile = FileUtil::getTemporaryFilename('xml_');
+               try {
+                       $this->installation->getArchive()->getTar()->extract($fileIndex, $tmpFile);
+                       $xml->load($tmpFile);
+               }
+               catch (Exception $e) { // bugfix to avoid file caching problems
+                       try {
+                               $this->installation->getArchive()->getTar()->extract($fileIndex, $tmpFile);
+                               $xml->load($tmpFile);
+                       }
+                       catch (Exception $e) {
+                               $this->installation->getArchive()->getTar()->extract($fileIndex, $tmpFile);
+                               $xml->load($tmpFile);
+                       }
+               }
+               
+               @unlink($tmpFile);
+               return $xml;
+       }
+       
+       /**
+        * Returns the show order value.
+        *
+        * @param       integer         $showOrder
+        * @param       string          $parentName
+        * @param       string          $columnName
+        * @param       string          $tableNameExtension
+        * @return      integer         new show order
+        */
+       protected function getShowOrder($showOrder, $parentName = null, $columnName = null, $tableNameExtension = '') {
+               if ($showOrder === null) {
+                        // get greatest showOrder value
+                       $conditions = new PreparedStatementConditionBuilder();
+                       if ($columnName !== null) $conditions->add($columnName." = ?", array($parentName));
+                       
+                       $sql = "SELECT  MAX(showOrder) AS showOrder
+                               FROM    wcf".WCF_N."_".$this->tableName.$tableNameExtension."
+                               ".$conditions;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditions->getParameters());
+                       $maxShowOrder = $statement->fetchArray();
+                       if (is_array($maxShowOrder) && isset($maxShowOrder['showOrder'])) {
+                               return $maxShowOrder['showOrder'] + 1;
+                       }
+                       else {
+                               return 1;
+                       }
+               }
+               else {
+                       // increase all showOrder values which are >= $showOrder
+                       $sql = "UPDATE  wcf".WCF_N."_".$this->tableName.$tableNameExtension."
+                               SET     showOrder = showOrder + 1
+                               WHERE   showOrder >= ?
+                               ".($columnName !== null ? "AND ".$columnName." = ?" : "");
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       $data = array($showOrder);
+                       if ($columnName !== null) $data[] = $parentName;
+                       
+                       $statement->execute($data);
+                       
+                       // return the wanted showOrder level
+                       return $showOrder;
+                       }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/CoreObjectPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/CoreObjectPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..ce6171f
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes core objects.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class CoreObjectPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\core\object\CoreObjectEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'core_object';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'coreobject';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           objectName = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $item['attributes']['name'],
+                               $this->installation->getPackageID()
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               return array(
+                       'objectName' => $data['elements']['objectname']
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   objectName = ?
+                               AND packageID = ?";
+               $parameters = array(
+                       $data['objectName'],
+                       $this->installation->getPackageID()
+               );
+               
+               return array(
+                       'sql' => $sql,
+                       'parameters' => $parameters
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::cleanup()
+        */     
+       protected function cleanup() {
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.coreObjects.php');
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::uninstall()
+        */
+       public function uninstall() {
+               parent::uninstall();
+               
+               // clear cache immediately
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.coreObjects.php');
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/CronjobsPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/CronjobsPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..5ccff06
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\WCF;
+use wcf\util\CronjobUtil;
+
+/**
+ * This PIP installs, updates or deletes cronjobs.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.package.plugin
+ * @category   Community Framework
+ */
+class CronjobsPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\cronjob\CronjobEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'cronjob';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'cronjobs';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           classPath = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $item['attributes']['classpath'],
+                               $this->installation->getPackageID()
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               return array(
+                       'active' => (isset($data['elements']['active'])) ? intval($data['elements']['active']) : 1,
+                       'canBeDisabled' => (isset($data['elements']['canbedisabled'])) ? intval($data['elements']['canbedisabled']) : 1,
+                       'canBeEdited' => (isset($data['elements']['canbeedited'])) ? intval($data['elements']['canbeedited']) : 1,
+                       'className' => (isset($data['elements']['classname'])) ? $data['elements']['classname'] : '',
+                       'description' => (isset($data['elements']['description'])) ? $data['elements']['description'] : '',
+                       'startDom' => $data['elements']['startdom'],
+                       'startDow' => $data['elements']['startdow'],
+                       'startHour' => $data['elements']['starthour'],
+                       'startMinute' => $data['elements']['startminute'],
+                       'startMonth' => $data['elements']['startmonth']
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::validateImport()
+        */
+       protected function validateImport(array $data) {
+               CronjobUtil::validate($startMinute, $startHour, $startDom, $startMonth, $startDow);
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               return null;
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareCreate()
+        */
+       protected function prepareCreate(array &$data) {
+               parent::prepareCreate($data);
+               
+               $data['nextExec'] = TIME_NOW;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..5988987
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes event listeners.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class EventListenerPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\event\listener\EventListenerEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'event_listener';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'eventlistener';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           packageID = ?
+                                       AND eventClassName = ?
+                                       AND eventName = ?,
+                                       AND inherit = ?
+                                       AND listenerClassName = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $this->installation->getPackageID(),
+                               $item['elements']['eventclassname'],
+                               $item['elements']['eventname'],
+                               $item['elements']['inherit'],
+                               $item['elements']['listenerclassname']
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               $nice = (isset($data['elements']['nice'])) ? intval($data['elements']['nice']) : 0;
+               if ($nice < -128) $nice = -128;
+               else if ($nice > 127) $nice = 127;
+               
+               return array(
+                       'eventClassName' => $data['elements']['eventclassname'],
+                       'eventName' => $data['elements']['eventname'],
+                       'inherit' => (isset($data['elements']['inherit'])) ? intval($data['elements']['inherit']) : 0,
+                       'listenerClassName' => $data['elements']['listenerclassname'],
+                       'niceValue' => $nice
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   eventClassName = ?
+                               AND eventName = ?
+                               AND listenerClassName = ?
+                               AND packageID = ?";
+               $parameters = array(
+                       $data['eventClassName'],
+                       $data['eventName'],
+                       $data['listenerClassName'],
+                       $this->installation->getPackageID()
+               );
+               
+               return array(
+                       'sql' => $sql,
+                       'parameters' => $parameters
+               );
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::uninstall()
+        */
+       public function uninstall() {
+               parent::uninstall();
+               
+               // clear cache immediately
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.eventListener-*.php');
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/FilesPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/FilesPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..9be6882
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\package\PackageInstallationDispatcher;
+
+use wcf\data\package\Package;
+use wcf\data\package\PackageEditor;
+use wcf\system\exception\SystemException;
+use wcf\system\package\FilesFileHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\StyleUtil;
+
+/**
+ * This PIP installs, updates or deletes by a package delivered files.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class FilesPackageInstallationPlugin extends AbstractPackageInstallationPlugin {
+       public $tableName = 'package_installation_file_log';
+       
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               parent::install();
+               
+               // get package installation dir
+               $dir = $this->installation->getPackage()->packageDir;
+               if (empty($dir)) {
+                       if ($this->installation->getPackage()->parentPackageID > 0) {
+                               // plugin
+                               // use parents package dir
+                               $dir = $this->installation->getPackage()->getParentPackage()->packageDir;
+                       }
+                       else if ($this->installation->getPackage()->standalone == 1 && $this->installation->getPackage()->package != 'com.woltlab.wcf' && $this->installation->getAction() == 'install') {
+                               // standalone package
+                               // prompt package dir
+                               $dir = $this->promptPackageDir();
+                       }
+                       
+                       // save package dir
+                       if (!empty($dir)) {
+                               $package = new Package($this->installation->getPackageID());
+                               $packageEditor = new PackageEditor($package);
+                               $packageEditor->update(array('packageDir' => $dir));
+                               
+                               $this->installation->getPackage()->packageDir = $dir;
+                       }
+               }
+               
+               // absolute path to package dir
+               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$dir));
+               
+               // extract files.tar to temp folder
+               $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'files_');
+               
+               // create file handler
+               $fileHandler = new FilesFileHandler($this->installation);
+               
+               // extract content of files.tar
+               $fileInstaller = $this->installation->extractFiles($packageDir, $sourceFile, $fileHandler);
+               
+               // if this a standalone package, write config.inc.php for this package
+               if ($this->installation->getPackage()->standalone == 1 && $this->installation->getPackage()->package != 'com.woltlab.wcf' && $this->installation->getAction() == 'install') {
+                       // touch file
+                       $fileInstaller->touchFile(PackageInstallationDispatcher::CONFIG_FILE);
+                       
+                       // create file
+                       Package::writeConfigFile($this->installation->getPackageID());
+                       
+                       // log file
+                       $sql = "INSERT INTO     wcf".WCF_N."_package_installation_file_log
+                                               (packageID, filename)
+                               VALUES          (?, 'config.inc.php')";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->installation->getPackageID()));
+               }
+               
+               // delete temporary sourceArchive
+               @unlink($sourceFile);
+               
+               // update acp style file
+               StyleUtil::updateStyleFile();
+       }
+       
+       /**
+        * Uninstalls the files of this package.
+        */
+       public function uninstall() {
+               // get absolute package dir
+               $packageDir = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator(realpath(WCF_DIR.$this->installation->getPackage()->packageDir)));
+               
+               // create file list
+               $files = array();
+               
+               // get files from log
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_package_installation_file_log
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               while ($row = $statement->fetchArray()) {
+                       $files[] = $row['filename'];
+               }
+               
+               if (count($files) > 0) {
+                       // delete files
+                       $this->installation->deleteFiles($packageDir, $files);
+                       
+                       // delete log entries
+                       parent::uninstall();
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/GroupOptionsPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/GroupOptionsPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..6fdfbec
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\data\user\group\option\UserGroupOption;
+use wcf\data\user\group\option\UserGroupOptionEditor;
+use wcf\data\user\group\UserGroup;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes user group permissions.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class GroupOptionsPackageInstallationPlugin extends AbstractOptionPackageInstallationPlugin {
+       public $tableName = 'user_group_option';
+       public static $reservedTags = array('name', 'optiontype', 'defaultvalue', 'admindefaultvalue', 'validationpattern', 'showorder', 'categoryname', 'selectoptions', 'enableoptions', 'permissions', 'options', 'attrs', 'cdata');
+       
+       /**
+        * Deletes group-option-categories and/or group-options which where installed by the package.
+        */
+       public function uninstall() {
+               // Delete value-entries using categories or options
+               // which will be deleted.
+               $sql = "DELETE FROM     wcf".WCF_N."_user_group_option_value
+                       WHERE           optionID IN (
+                                               SELECT  optionID
+                                               FROM    wcf".WCF_N."_user_group_option
+                                               WHERE   packageID = ?
+                                       )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+                       
+               parent::uninstall();
+       }
+       
+       /**
+        * @see  AbstractOptionPackageInstallationPlugin::saveOption()
+        */
+       protected function saveOption($option, $categoryName, $existingOptionID = 0) {
+               // default values
+               $optionName = $optionType = $defaultValue = $adminDefaultValue = $validationPattern = $enableOptions = $permissions = $options = '';
+               $showOrder = null;
+               
+               // get values
+               if (isset($option['name'])) $optionName = $option['name'];
+               if (isset($option['optiontype'])) $optionType = $option['optiontype'];
+               if (isset($option['defaultvalue'])) $defaultValue = $option['defaultvalue'];
+               if (isset($option['admindefaultvalue'])) $adminDefaultValue = $option['admindefaultvalue'];
+               if (isset($option['validationpattern'])) $validationPattern = $option['validationpattern'];
+               if (!empty($option['showorder'])) $showOrder = intval($option['showorder']);
+               $showOrder = $this->getShowOrder($showOrder, $categoryName, 'categoryName');
+               if (isset($option['enableoptions'])) $enableOptions = $option['enableoptions'];
+               if (isset($option['permissions'])) $permissions = $option['permissions'];
+               if (isset($option['options'])) $options = $option['options'];
+               
+               // check if optionType exists
+               $className = 'wcf\system\option\group\GroupOptionType'.ucfirst($optionType);
+               if (!class_exists($className)) {
+                       throw new SystemException("unable to find class '".$className."'", 11001);
+               }
+               
+               // collect additional tags and their values
+               $additionalData = array();
+               foreach ($option as $tag => $value) {
+                       if (!in_array($tag, self::$reservedTags)) $additionalData[$tag] = $value;
+               }
+               
+               // check if the otion exist already and was installed by this package
+               $sql = "SELECT  optionID
+                       FROM    wcf".WCF_N."_user_group_option
+                       WHERE   optionName = ?
+                       AND     packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $optionName,
+                       $this->installation->getPackageID()
+               ));
+               $row = $statement->fetchArray();
+               
+               $data = array(
+                       'categoryName' => $categoryName,
+                       'optionType' => $optionType,
+                       'defaultValue' => $defaultValue,
+                       'adminDefaultValue' => $adminDefaultValue,
+                       'validationPattern' => $validationPattern,
+                       'showOrder' => $showOrder,
+                       'enableOptions' => $enableOptions,
+                       'permissions' => $permissions,
+                       'options' => $options,
+                       'additionalData' => serialize($additionalData)
+               );
+               
+               if (!empty($row['optionID'])) {
+                       // update existing option
+                       $optionID = $row['optionID'];
+                       
+                       $groupOption = new UserGroupOption(null, $row);
+                       $groupOptionEditor = new UserGroupOptionEditor($groupOption);
+                       $groupOptionEditor->update($data);
+               }
+               else {
+                       // add new option
+                       $data['packageID'] = $this->installation->getPackageID();
+                       $data['optionName'] = $optionName;
+                       
+                       $groupOptionEditor = UserGroupOptionEditor::create($data);
+                       $optionID = $groupOptionEditor->optionID;
+                       
+                       // get default group ("everyone")
+                       $sql = "SELECT  groupID
+                               FROM    wcf".WCF_N."_user_group
+                               WHERE   groupType = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(UserGroup::EVERYONE));
+                       $row = $statement->fetchArray();
+                       
+                       // save default value
+                       $sql = "INSERT INTO     wcf".WCF_N."_user_group_option_value
+                                               (groupID, optionID, optionValue)
+                               VALUES          (?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($row['groupID'], $optionID, $defaultValue));
+                       
+                       if ($adminDefaultValue && $defaultValue != $adminDefaultValue) {
+                               $sql = "SELECT  groupID
+                                       FROM    wcf".WCF_N."_user_group_option_value
+                                       WHERE   optionID = (
+                                                       SELECT  optionID
+                                                       FROM    wcf".WCF_N."_user_group_option
+                                                       WHERE   optionName = ?
+                                               )
+                                               AND optionValue = '1'";
+                               $statement2 = WCF::getDB()->prepareStatement($sql);
+                               $statement2->execute(array('admin.general.canUseAcp'));
+                               
+                               $acpGroups = array();
+                               while ($row = $statement2->fetchArray()) {
+                                       $acpGroups[] = $row['groupID'];
+                               }
+                               
+                               $statement2->execute(array('admin.user.canEditGroup'));
+                               while ($row = $statement2->fetchArray()) {
+                                       if (!in_array($row['groupID'], $acpGroups)) {
+                                               continue;
+                                       }
+                                       
+                                       $statement->execute(array(
+                                               $row['groupID'],
+                                               $optionID,
+                                               $adminDefaultValue
+                                       ));
+                               }
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/LanguagesPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/LanguagesPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..34b956d
--- /dev/null
@@ -0,0 +1,300 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\data\language\LanguageEditor;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\language\LanguageFactory;
+use wcf\system\WCF;
+use wcf\util\XML;
+
+/**
+ * This PIP installs, updates or deletes language and their categories and items.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class LanguagesPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       public $tableName = 'language_item';
+       
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               AbstractPackageInstallationPlugin::install();
+               
+               // get language files
+               $languageFiles = array();
+               $multipleFiles = false;
+               $filename = $this->instruction['value'];
+               if (strpos($filename, '*') !== false) {
+                       // wildcard syntax; import multiple files
+                       $multipleFiles = true;
+                       $files = $this->installation->getArchive()->getTar()->getContentList();
+                       $pattern = str_replace("\*", ".*", preg_quote($filename));
+                       
+                       foreach ($files as $file) {
+                               if (preg_match('!'.$pattern.'!i', $file['filename'])) {
+                                       if (preg_match('~([a-z-]+)\.xml$~i', $file['filename'], $match)) {
+                                               $languageFiles[$match[1]] = $file['filename'];
+                                       }
+                                       else {
+                                               throw new SystemException("Can not determine language code of language file '".$file."'");
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if (!empty($this->instruction['attributes']['languagecode'])) {
+                               $languageCode = $this->instruction['attributes']['languagecode'];
+                       }
+                       else if (!empty($this->instruction['attributes']['language'])) {
+                               $languageCode = $this->instruction['attributes']['language'];
+                       }
+                       else if (preg_match('~([a-z-]+)\.xml$~i', $filename, $match)) {
+                               $languageCode = $match[1];
+                       }
+                       else {
+                               throw new SystemException("Can not determine language code of language file '".$filename."'");
+                       }
+                       
+                       $languageFiles[$languageCode] = $filename;
+               }
+               
+               // get installed languages
+               $installedLanguages = array();
+               $sql = "SELECT          *
+                       FROM            wcf".WCF_N."_language
+                       ORDER BY        isDefault DESC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               while ($row = $statement->fetchArray()) {
+                       $installedLanguages[] = $row;
+               }
+               
+               // install language
+               $addedLanguageIDArray = array();
+               foreach ($installedLanguages as $installedLanguage) {
+                       $languageFile = null;
+                       if (isset($languageFiles[$installedLanguage['languageCode']])) {
+                               $languageFile = $languageFiles[$installedLanguage['languageCode']];
+                       }
+                       else if ($multipleFiles) {
+                               // use default language
+                               if (isset($languageFiles[$installedLanguages[0]['languageCode']])) {
+                                       $languageFile = $languageFiles[$installedLanguages[0]['languageCode']];
+                               }
+
+                               // use english (if installed)
+                               else if (isset($languageFiles['en'])) {
+                                       foreach ($installedLanguages as $installedLanguage2) {
+                                               if ($installedLanguage2['languageCode'] == 'en') {
+                                                       $languageFile = $languageFiles['en'];
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               // use any installed language
+                               if ($languageFile === null) {
+                                       foreach ($installedLanguages as $installedLanguage2) {
+                                               if (isset($languageFiles[$installedLanguage2['languageCode']])) {
+                                                       $languageFile = $languageFiles[$installedLanguage2['languageCode']];
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               // use first delivered language
+                               if ($languageFile === null) {
+                                       foreach ($languageFiles as $languageFile) break;
+                               }
+                       }
+                       
+                       // save language
+                       if ($languageFile !== null) {
+                               if ($xml = $this->readLanguage($languageFile)) {
+                                       // get language object
+                                       $language = LanguageFactory::getLanguageByCode($installedLanguage['languageCode']);
+                                       $languageEditor = new LanguageEditor($language);
+                                       
+                                       // import xml
+                                       // don't update language files if package is standalone
+                                       $languageEditor->updateFromXML($xml, $this->installation->getPackageID(), !$this->installation->getPackage()->standalone);
+                                       
+                                       // add language to this package
+                                       $addedLanguageIDArray[] = $language->languageID;
+                               }
+                       }
+               }
+               
+               // save package to language
+               if (count($addedLanguageIDArray)) {
+                       $condition = '';
+                       $statementParameters = array($this->installation->getPackageID());
+                       foreach ($addedLanguageIDArray as $languageID) {
+                               if (!empty($condition)) $condition .= ',';
+                               $condition .= '?';
+                               $statementParameters[] = $languageID;
+                       }
+                       $statementParameters[] = $this->installation->getPackageID();
+                       
+                       $sql = "INSERT INTO     wcf".WCF_N."_language_to_package
+                                               (languageID, packageID)
+                               SELECT          languageID, ?
+                               FROM            wcf".WCF_N."_language
+                               WHERE           languageID IN (".$condition.")
+                                               AND languageID NOT IN (
+                                                       SELECT  languageID
+                                                       FROM    wcf".WCF_N."_language_to_package
+                                                       WHERE   packageID = ?
+                                               )";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($statementParameters);
+               }
+       }
+       
+       /**
+        * Returns true if the uninstalling package got to uninstall languages, categories or items.
+        *
+        * @return      boolean                         hasUnistall
+        */
+       public function hasUninstall() {
+               if (parent::hasUninstall()) return true;
+               
+               $sql = "SELECT  COUNT(languageID) AS count
+                       FROM    wcf".WCF_N."_language_to_package
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $languageCount = $statement->fetchArray();
+               return $languageCount['count'] > 0;
+       }
+       
+       /**
+        * Deletes languages, categories or items which where installed by the package.
+        */
+       public function uninstall() {
+               parent::uninstall();
+               
+               // delete language to package relation
+               $sql = "DELETE FROM     wcf".WCF_N."_language_to_package
+                       WHERE           packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               
+               // delete language items
+               // Get all items and their categories
+               // which where installed from this package.
+               $sql = "SELECT  languageItemID, languageCategoryID, languageID
+                       FROM    wcf".WCF_N."_language_item
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $itemIDs = array();
+               $categoryIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       $itemIDs[] = $row['languageItemID'];
+                       
+                       // Store categories
+                       $categoryIDs[$row['languageCategoryID']] = true;
+               }
+               
+               if (count($itemIDs) > 0) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                               WHERE           languageItemID = ?
+                                               AND packageID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($itemIDs as $itemID) {
+                               $statement->execute(array(
+                                       $itemID,
+                                       $this->installation->getPackageID()
+                               ));
+                       }
+                       
+                       $this->deleteEmptyCategories(array_keys($categoryIDs), $this->installation->getPackageID());
+               }
+       }
+       
+       /**
+        * Extracts the language file and parses it with
+        * SimpleXML. If the specified language file
+        * was not found, an error message is thrown.
+        *
+        * @param       string          $filename
+        * @return      wcf\util\XML    xml
+        */
+       protected function readLanguage($filename) {
+               // search language files in package archive
+               // throw error message if not found
+               if (($fileIndex = $this->installation->getArchive()->getTar()->getIndexByFilename($filename)) === false) {
+                       throw new SystemException("language file '".$filename."' not found.", 13025);
+               }
+               
+               // extract language file and parse with DOMDocument
+               $xml = new XML();
+               $xml->loadXML($filename, $this->installation->getArchive()->getTar()->extractToString($fileIndex));
+               return $xml;
+       }
+       
+       /**
+        * Deletes categories which where changed by an update or deinstallation in case they are now empty.
+        *
+        * @param       array           $categoryIDs
+        * @param       integer         $packageID
+        */
+       protected function deleteEmptyCategories(array $categoryIDs, $packageID) {
+               // Get empty categories which where changed by this package.
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("language_category.languageCategoryID IN (?)", array($categoryIDs));
+               
+               $sql = "SELECT          COUNT(item.languageItemID) AS count,
+                                       language_category.languageCategoryID,
+                                       language_category.languageCategory
+                       FROM            wcf".WCF_N."_language_category language_category
+                       LEFT JOIN       wcf".WCF_N."_language_item item
+                       ON              (item.languageCategoryID = language_category.languageCategoryID)
+                       ".$conditions."
+                       GROUP BY        language_category.languageCategoryID ASC,
+                                       language_category.languageCategory ASC";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               $categoriesToDelete = array();
+               while ($row = $statement->fetchArray()) {
+                       if ($row['count'] == 0) {
+                               $categoriesToDelete[$row['languageCategoryID']] = $row['languageCategory'];
+                       }
+               }
+               
+               // Delete categories from DB.
+               if (count($categoriesToDelete) > 0) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_language_category
+                               WHERE           languageCategory = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($categoriesToDelete as $category) {
+                               $statement->execute(array($category));
+                       }
+               }
+       }
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) { }
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) { }
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) { }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/OptionsPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/OptionsPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..d3f2533
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\data\option\Option;
+use wcf\data\option\OptionEditor;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes options.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class OptionsPackageInstallationPlugin extends AbstractOptionPackageInstallationPlugin {
+       public $tableName = 'option';
+       public static $reservedTags = array('name', 'optiontype', 'defaultvalue', 'validationpattern', 'enableoptions', 'showorder', 'hidden', 'selectoptions', 'categoryname', 'permissions', 'options', 'attrs', 'cdata');
+       
+       /**
+        * @see  AbstractOptionPackageInstallationPlugin::saveOption()
+        */
+       protected function saveOption($option, $categoryName, $existingOptionID = 0) {
+               // default values
+               $optionName = $optionType = $defaultValue = $validationPattern = $selectOptions = $enableOptions = $permissions = $options = '';
+               $showOrder = null;
+               $hidden = 0;
+               
+               // get values
+               if (isset($option['name'])) $optionName = $option['name'];
+               if (isset($option['optiontype'])) $optionType = $option['optiontype'];
+               if (isset($option['defaultvalue'])) $defaultValue = WCF::getLanguage()->get($option['defaultvalue']);
+               if (isset($option['validationpattern'])) $validationPattern = $option['validationpattern'];
+               if (isset($option['enableoptions'])) $enableOptions = $option['enableoptions'];
+               if (isset($option['showorder'])) $showOrder = intval($option['showorder']);
+               if (isset($option['hidden'])) $hidden = intval($option['hidden']);
+               $showOrder = $this->getShowOrder($showOrder, $categoryName, 'categoryName');
+               if (isset($option['selectoptions'])) $selectOptions = $option['selectoptions'];
+               if (isset($option['permissions'])) $permissions = $option['permissions'];
+               if (isset($option['options'])) $options = $option['options'];
+               
+               // check if optionType exists
+               $className = 'wcf\system\option\OptionType'.ucfirst($optionType);
+               if (!class_exists($className)) {
+                       throw new SystemException("unable to find class '".$className."'", 11001);
+               }
+               
+               // collect additional tags and their values
+               $additionalData = array();
+               foreach ($option as $tag => $value) {
+                       if (!in_array($tag, self::$reservedTags)) $additionalData[$tag] = $value;
+               }
+               
+               // build update or create data
+               $data = array(
+                       'categoryName' => $categoryName,
+                       'optionType' => $optionType,
+                       'validationPattern' => $validationPattern,
+                       'selectOptions' => $selectOptions,
+                       'showOrder' => $showOrder,
+                       'enableOptions' => $enableOptions,
+                       'hidden' => $hidden,
+                       'permissions' => $permissions,
+                       'options' => $options,
+                       'additionalData' => serialize($additionalData)
+               );
+               
+               // try to find an existing option for updating
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   optionName = ?
+                               AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $optionName,
+                       $this->installation->getPackageID()
+               ));
+               $row = $statement->fetchArray();
+               
+               // result was 'false' thus create a new item
+               if (!$row) {
+                       $data['optionName'] = $optionName;
+                       $data['packageID'] = $this->installation->getPackageID();
+                       $data['optionValue'] = $defaultValue;
+                       
+                       OptionEditor::create($data);
+               }
+               else {
+                       // update existing item
+                       $optionObj = new Option(null, $row);
+                       $optionEditor = new OptionEditor($optionObj);
+                       $optionEditor->update($data);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/PIPPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/PIPPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..25a978b
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes package installation plugins.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class PIPPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\package\installation\plugin\PackageInstallationPluginEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'package_installation_plugin';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */
+       public $tagName = 'pip';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           pluginName = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $item['attributes']['name'],
+                               $this->installation->getPackageID()
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               return array(
+                       'className' => $data['nodeValue'],
+                       'pluginName' => $data['attributes']['name'],
+                       'priority' => ($this->installation->getPackage()->package == 'com.woltlab.wcf' ? 1 : 0)
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               return null;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/PackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/PackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..b2e5b96
--- /dev/null
@@ -0,0 +1,37 @@
+<?php\r
+namespace wcf\system\package\plugin;\r
+\r
+/**\r
+ * Any PackageInstallationPlugin should implement this interface.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.package.plugin\r
+ * @category   Community Framework\r
+ */\r
+interface PackageInstallationPlugin {\r
+       /**\r
+        * Executes the installation of this plugin.\r
+        */\r
+       public function install();\r
+       \r
+       /**\r
+        * Executes the update of this plugin.\r
+        */\r
+       public function update();\r
+       \r
+       /**\r
+        * Returns true, if the uninstallation of the given package should execute this plugin.\r
+        * \r
+        * @return      boolean\r
+        */\r
+       public function hasUninstall();\r
+       \r
+       /**\r
+        * Executes the uninstallation of this plugin.\r
+        */\r
+       public function uninstall();\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/package/plugin/PageLocationPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/PageLocationPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..2927948
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes page locations.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf.page
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class PageLocationPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\page\location\PageLocationEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'page_location';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'pagelocation';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           locationName = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $item['attributes']['name'],
+                               $this->installation->getPackageID()
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               return array(
+                       'classPath' => (isset($data['elements']['classpath'])) ? $data['elements']['classpath'] : '',
+                       'locationName' => $data['attributes']['name'],
+                       'locationPattern' => $data['elements']['pattern']
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   locationName = ?
+                               AND packageID = ?";
+               $parameters = array(
+                       $data['locationName'],
+                       $this->installation->getPackageID()
+               );
+               
+               return array(
+                       'sql' => $sql,
+                       'parameters' => $parameters
+               );
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/PageMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/PageMenuPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..bac83e0
--- /dev/null
@@ -0,0 +1,56 @@
+<?php\r
+namespace wcf\system\package\plugin;\r
+use wcf\system\exception\SystemException;\r
+use wcf\util\ClassUtil;\r
+\r
+/**\r
+ * This PIP installs, updates or deletes page page menu items.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.package.plugin\r
+ * @category   Community Framework\r
+ */\r
+class PageMenuPackageInstallationPlugin extends AbstractMenuPackageInstallationPlugin {\r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$className\r
+        */\r
+       public $className = 'wcf\data\page\menu\item\PageMenuItemEditor';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$tableName\r
+        */\r
+       public $tableName = 'page_menu_item';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$tagName\r
+        */     \r
+       public $tagName = 'pagemenuitem';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()\r
+        */\r
+       protected function prepareImport(array $data) {\r
+               $result = parent::prepareImport($data);\r
+               \r
+               // position\r
+               $result['menuPosition'] = (!empty($data['elements']['position']) && $data['elements']['position'] == 'footer') ? 'footer' : 'header';\r
+               // class name\r
+               if (!empty($data['elements']['classname'])) {\r
+                       /*if (!class_exists($data['elements']['classname'])) {\r
+                               throw new SystemException("Unable to find class '".$data['elements']['classname']."'");\r
+                       }\r
+                       \r
+                       if (!ClassUtil::isInstanceOf($data['elements']['classname'], 'wcf\system\menu\page\PageMenuItemProvider')) {\r
+                               throw new SystemException($data['elements']['classname']." should implement wcf\system\menu\page\PageMenuItemProvider");\r
+                       }*/\r
+                       \r
+                       $result['className'] = $data['elements']['classname'];\r
+               }\r
+               \r
+               return $result;\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/package/plugin/ScriptPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ScriptPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..6051363
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * This PIP executes an individual php script.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class ScriptPackageInstallationPlugin extends AbstractPackageInstallationPlugin {
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               parent::install();
+
+               // get installation path of package
+               $sql = "SELECT  packageDir
+                       FROM    wcf".WCF_N."_package
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $packageDir = $statement->fetchArray();
+               $packageDir = $packageDir['packageDir'];
+               
+               // get relative path of script
+               $path = FileUtil::getRealPath(WCF_DIR.$packageDir);
+               
+               // run script
+               $this->run($path.$this->instruction['value']);
+               
+               // delete script
+               if (@unlink($path.$this->instruction['value'])) {
+                       // delete file log entry
+                       $sql = "DELETE FROM     wcf".WCF_N."_package_installation_file_log
+                               WHERE           packageID = ?
+                                               AND filename = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(
+                               $this->installation->getPackageID(),
+                               $this->instruction['value']
+                       ));
+               }
+       }
+       
+       private function run($scriptPath) {
+               include($scriptPath);
+       }
+       
+       /**
+        * Returns false. Scripts can't be uninstalled.
+        *
+        * @return      boolean         false
+        */
+       public function hasUninstall() {
+               return false;
+       }
+       
+       /**
+        * Does nothing.
+        */
+       public function uninstall() {}
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/SqlPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/SqlPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..4e1dc69
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * This PIP executes the delivered sql file.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class SqlPackageInstallationPlugin extends AbstractPackageInstallationPlugin {
+       public $tableName = 'package_installation_sql_log';
+       
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               parent::install();
+
+               // extract sql file from archive
+               if ($queries = $this->getSQL($this->instruction['value'])) {
+                       $package = $this->installation->getPackage();
+                       if ($package->parentPackageID) {
+                               // package is a plugin; get parent package
+                               $package = $package->getParentPackage();
+                       }
+                       
+                       if ($package->standalone == 1) {
+                               // package is standalone
+                               $packageAbbr = $package->getAbbreviation();
+                               $tablePrefix = WCF_N.'_'.$package->instanceNo.'_';
+                               
+                               // Replace the variable xyz1_1 with $tablePrefix in the table names.
+                               $queries = StringUtil::replace($packageAbbr.'1_1_', $packageAbbr.$tablePrefix, $queries);
+                       }
+                       
+                       // replace wcf1_  with the actual WCF_N value
+                       $queries = str_replace("wcf1_", "wcf".WCF_N."_", $queries);
+                       
+                       // check queries
+                       $parser = new PackageInstallationSQLParser($queries, $package, $this->installation->getAction());
+                       $conflicts = $parser->test();
+                       if (count($conflicts)) {
+                               // ask user here
+                               // search default value in session
+                               if (!WCF::getSession()->getVar('overrideAndDontAskAgain')) {
+                                       // show page
+                                       if (!empty($_POST['override']) || !empty($_POST['overrideAndDontAskAgain'])) {
+                                               if (!empty($_POST['overrideAndDontAskAgain'])) {
+                                                       WCF::getSession()->register('overrideAndDontAskAgain', true);
+                                                       WCF::getSession()->update();
+                                               }
+                                       }
+                                       else {
+                                               WCF::getTPL()->assign('conflicts', $conflicts);
+                                               WCF::getTPL()->display('packageInstallationCheckOverrideTables');
+                                               exit;
+                                       }
+                               }
+                       }
+                       
+                       // execute queries
+                       $parser->execute();
+                       
+                       // log changes
+                       $parser->log();
+               }
+       }
+       
+       /**
+        * Deletes the sql tables or columns which where installed by the package.
+        */
+       public function uninstall() {
+               // get logged sql tables/columns
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_package_installation_sql_log
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $entries = array();
+               while ($row = $statement->fetchArray()) {
+                       $entries[] = $row;
+               }
+               
+               // get all tablenames from database
+               $existingTableNames = WCF::getDB()->getEditor()->getTablenames();
+               
+               // delete or alter tables
+               foreach ($entries as $entry) {
+                       // don't alter table if it should be dropped
+                       if (!empty($entry['sqlColumn']) || !empty($entry['sqlIndex'])) {
+                               $isDropped = false;
+                               foreach ($entries as $entry2) {
+                                       if ($entry['sqlTable'] == $entry2['sqlTable'] && empty($entry2['sqlColumn']) && empty($entry2['sqlIndex'])) {
+                                               $isDropped = true;
+                                       }
+                               }
+                               if ($isDropped) continue;
+                       }
+                       // drop table
+                       if (!empty($entry['sqlTable']) && empty($entry['sqlColumn']) && empty($entry['sqlIndex'])) {
+                               WCF::getDB()->getEditor()->dropTable($entry['sqlTable']);
+                       }
+                       // drop column
+                       else if (in_array($entry['sqlTable'], $existingTableNames) && !empty($entry['sqlColumn'])) {
+                               WCF::getDB()->getEditor()->dropColumn($entry['sqlTable'], $entry['sqlColumn']);
+                       }
+                       // drop index
+                       else if (in_array($entry['sqlTable'], $existingTableNames) && !empty($entry['sqlIndex'])) {
+                               WCF::getDB()->getEditor()->dropIndex($entry['sqlTable'], $entry['sqlIndex']);
+                       }
+               }
+               // delete from log table
+               parent::uninstall();
+       }
+       
+       /**
+        * Extracts and returns the sql file.
+        * If the specified sql file was not found, an error message is thrown.
+        *
+        * @param       string          $filename
+        * @return      string
+        */
+       protected function getSQL($filename) {
+               // search sql files in package archive
+               if (($fileindex = $this->installation->getArchive()->getTar()->getIndexByFilename($filename)) === false) {
+                       throw new SystemException("SQL file '".$filename."' not found.", 13016);
+               }
+
+               // extract sql file to string
+               return $this->installation->getArchive()->getTar()->extractToString($fileindex);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/StyleAttributesPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/StyleAttributesPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..b329f7b
--- /dev/null
@@ -0,0 +1,145 @@
+<?php\r
+namespace wcf\system\package\plugin;\r
+use wcf\data\style\StyleEditor;\r
+use wcf\data\style\StyleList;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * This PIP installs, updates or deletes style attributes.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.package.plugin\r
+ * @category   Community Framework\r
+ */\r
+class StyleAttributesPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {\r
+       /**\r
+        * list of updated or new style variables\r
+        * @var array\r
+        */     \r
+       protected $styleVariables = array();\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$tableName\r
+        */\r
+       public $tableName = 'style_variable_to_attribute';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$tagName\r
+        */\r
+       public $tagName = 'styleattribute';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()\r
+        */\r
+       protected function handleDelete(array $items) {\r
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."\r
+                       WHERE           packageID = ?\r
+                                       AND cssSelector = ?\r
+                                       AND attributeName = ?\r
+                                       AND variableName = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               \r
+               foreach ($items as $item) {\r
+                       $statement->execute(array(\r
+                               $this->installation->getPackageID(),\r
+                               $item['elements']['selector'],\r
+                               $item['elements']['name'],\r
+                               $item['elements']['value']\r
+                       ));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()\r
+        */\r
+       protected function prepareImport(array $data) {\r
+               return array(\r
+                       'cssSelector' => $data['elements']['selector'],\r
+                       'attributeName' => $data['elements']['name'],\r
+                       'variableName' => $data['elements']['value']\r
+               );\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()\r
+        */\r
+       protected function findExistingItem(array $data) {\r
+               return null;\r
+       }\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::import()\r
+        */     \r
+       protected function import(array $row, array $data) {\r
+               $this->styleVariables[] = $data;\r
+       }\r
+       \r
+       /**\r
+        * It is not possible to properly update and insert values without\r
+        * spamming loads of queries for each import, thus delete all\r
+        * matching variables first and insert them afterwards.\r
+        * \r
+        * @see AbstractXMLPackageInstallationPlugin::postImport()\r
+        */\r
+       protected function postImport() {\r
+               if (!count($this->styleVariables)) return;\r
+               \r
+               // delete items first\r
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."\r
+                       WHERE           packageID = ?\r
+                                       AND cssSelector = ?\r
+                                       AND attributeName = ?\r
+                                       AND variableName = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               foreach ($this->styleVariables as $variable) {\r
+                       $statement->execute(array(\r
+                               $this->installation->getPackageID(),\r
+                               $variable['cssSelector'],\r
+                               $variable['attributeName'],\r
+                               $variable['variableName']\r
+                       ));\r
+               }\r
+               \r
+               // insert items\r
+               $sql = "INSERT INTO     wcf".WCF_N."_".$this->tableName."\r
+                                       (packageID, cssSelector, attributeName, variableName)\r
+                       VALUES          (?, ?, ?, ?)";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               foreach ($this->styleVariables as $variable) {\r
+                       $statement->execute(array(\r
+                               $this->installation->getPackageID(),\r
+                               $variable['cssSelector'],\r
+                               $variable['attributeName'],\r
+                               $variable['variableName']\r
+                       ));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see  PackageInstallationPlugin::uninstall()\r
+        */\r
+       public function uninstall() {\r
+               parent::uninstall();\r
+               \r
+               $this->cleanup();\r
+       }\r
+       \r
+       /**\r
+        * Updates styles files of all styles.\r
+        */\r
+       protected function cleanup() {\r
+               // get all styles\r
+               $styleList = new StyleList();\r
+               $styleList->sqlLimit = 0;\r
+               $styleList->readObjects();\r
+               \r
+               foreach ($styleList->getObjects() as $style) {\r
+                       $styleEditor = new StyleEditor($style);\r
+                       $style->writeStyleFile();\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/package/plugin/StylePackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/StylePackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..037d851
--- /dev/null
@@ -0,0 +1,90 @@
+<?php\r
+namespace wcf\system\package\plugin;\r
+use wcf\data\style\StyleEditor;\r
+use wcf\data\style\StyleList;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * This PIP installs, updates or deletes styles.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.package.plugin\r
+ * @category   Community Framework\r
+ */\r
+class StylePackageInstallationPlugin extends AbstractPackageInstallationPlugin {\r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$className\r
+        */\r
+       public $className = 'wcf\data\style\StyleEditor';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$tableName\r
+        */\r
+       public $tableName = 'style';\r
+       \r
+       /**\r
+        * @see AbstractXMLPackageInstallationPlugin::$tagName\r
+        */     \r
+       public $tagName = 'style';\r
+       \r
+       /** \r
+        * @see PackageInstallationPlugin::install()\r
+        */\r
+       public function install() {\r
+               parent::install();\r
+               \r
+               // extract style tar\r
+               $filename = $this->installation->getArchive()->extractTar($this->instructions['value'], 'style_');\r
+               \r
+               // import style\r
+               $style = StyleEditor::import($filename, $this->installation->getPackageID());\r
+               \r
+               // set style as default\r
+               if (isset($this->instruction['attributes']['default'])) {\r
+                       $style->setAsDefault();\r
+               }\r
+               \r
+               // remove tmp file\r
+               @unlink($filename);\r
+       }\r
+       \r
+       /** \r
+        * @see PackageInstallationPlugin::uninstall()\r
+        */\r
+       public function uninstall() {\r
+               // call uninstall event\r
+               EventHandler::fireAction($this, 'uninstall');\r
+               \r
+               // get all style of this package\r
+               $isDefault = false;\r
+               $styleList = new StyleList();\r
+               $styleList->getConditionBuilder()->add("packageID = ?", array($this->installation->getPackageID()));\r
+               $styleList->sqlLimit = 0;\r
+               $styleList->readObjects();\r
+               \r
+               foreach ($styleList->getObjects() as $style) {\r
+                       $styleEditor = new StyleEditor($style);\r
+                       $styleEditor->delete();\r
+                       \r
+                       $isDefault = $isDefault || $style->isDefault;\r
+               }\r
+               \r
+               // default style deleted\r
+               if ($isDefault) {\r
+                       $styleList = new StyleList();\r
+                       $styleList->sqlOrderBy = 'style.styleID ASC';\r
+                       $styleList->sqlLimit = 1;\r
+                       $styleList->readObjects();\r
+                       $styles = $styleList->getObjects();\r
+                       \r
+                       if (count($styles)) {\r
+                               $styleEditor = new StyleEditor($styles[0]);\r
+                               $styleEditor->setAsDefault();\r
+                       }\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..d5af0b2
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes template listeners.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\template\listener\TemplateListenerEditor';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'template_listener';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'templatelistener';
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           packageID = ?
+                                       AND environment = ?
+                                       AND eventName = ?
+                                       AND name = ?
+                                       AND templateName = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $this->installation->getPackageID(),
+                               $item['elements']['environment'],
+                               $item['elements']['eventname'],
+                               $item['attributes']['name'],
+                               $item['elements']['templatename']
+                       ));
+               }
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               return array(
+                       'environment' => $data['elements']['environment'],
+                       'eventName' => $data['elements']['eventname'],
+                       'name' => $data['attributes']['name'],
+                       'templateCode' => $data['elements']['templatecode'],
+                       'templateName' => $data['elements']['templatename']
+               );
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   packageID = ?
+                               AND name = ?
+                               AND templateName = ?
+                               AND eventName = ?
+                               AND environment = ?";
+               $parameters = array(
+                       $this->installation->getPackageID(),
+                       $data['name'],
+                       $data['templateName'],
+                       $data['eventName'],
+                       $data['environment']
+               );
+               
+               return array(
+                       'sql' => $sql,
+                       'parameters' => $parameters
+               );
+       }
+       
+       /**
+        * @see  PackageInstallationPlugin::uninstall()
+        */
+       public function uninstall() {
+               parent::uninstall();
+               
+               $this->cleanup();
+       }
+       
+       /**
+        * @see AbstractXMLPackageInstallationPlugin::cleanup()
+        */     
+       protected function cleanup() {
+               // clear cache immediately
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.templateListener-*.php');
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache/templateListener', '*.php');
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/TemplatesPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/TemplatesPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..1c7010a
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\exception\SystemException;
+use wcf\system\io\Tar;
+use wcf\system\package\TemplatesFileHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * This PIP installs, updates or deletes by a package delivered templates.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class TemplatesPackageInstallationPlugin extends AbstractPackageInstallationPlugin {
+       public $tableName = 'template';
+       
+       /**
+        * @see PackageInstallationPlugin::install()
+        */
+       public function install() {
+               parent::install();
+
+               // extract files.tar to temp folder
+               $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'templates_');
+               
+               // create file handler
+               $fileHandler = new TemplatesFileHandler($this->installation);
+               
+               // extract content of files.tar
+               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+               
+               $fileInstaller = $this->installation->extractFiles($packageDir.'templates/', $sourceFile, $fileHandler);
+               
+               // delete temporary sourceArchive
+               @unlink($sourceFile);
+       }
+       
+       /**
+        * Uninstalls the templates of this package.
+        */
+       public function uninstall() {
+               // create templates list
+               $templates = array();
+               
+               // get templates from log
+               $sql = "SELECT  templateName
+                       FROM    wcf".WCF_N."_template
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               while ($row = $statement->fetchArray()) {
+                       $templates[] = 'templates/'.$row['templateName'].'.tpl';
+               }
+               
+               if (count($templates) > 0) {
+                       // delete template files
+                       $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+                       $deleteEmptyDirectories = $this->installation->getPackage()->standalone;
+                       $this->installation->deleteFiles($packageDir, $templates, false, $deleteEmptyDirectories);
+                       
+                       // delete log entries
+                       parent::uninstall();
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/package/plugin/UserOptionsPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/UserOptionsPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..dff5ff2
--- /dev/null
@@ -0,0 +1,169 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\data\user\option\category\UserOptionCategory;
+use wcf\data\user\option\category\UserOptionCategoryEditor;
+use wcf\data\user\option\UserOption;
+use wcf\data\user\option\UserOptionEditor;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes user fields.
+ *
+ * @author     Benjamin Kunz
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class UserOptionsPackageInstallationPlugin extends AbstractOptionPackageInstallationPlugin {
+       public $tableName = 'user_option';
+       public static $reservedTags = array('name', 'optiontype', 'defaultvalue', 'validationpattern', 'required', 'editable', 'visible', 'searchable', 'showorder', 'outputclass', 'selectoptions', 'enableoptions', 'disabled', 'categoryname', 'permissions', 'options', 'attrs', 'cdata');
+       
+       /**
+        * Installs user option categories.
+        *
+        * @param       array           $category
+        * @param       array           $categoryXML
+        */
+       protected function saveCategory($category, $categoryXML = null) {
+               $icon = $menuIcon = '';
+               if (isset($categoryXML['icon'])) $icon = $categoryXML['icon'];
+               if (isset($categoryXML['menuicon'])) $menuIcon = $categoryXML['menuicon'];
+               
+               // use for create and update
+               $data = array(
+                       'parentCategoryName' => $category['parentCategoryName'],
+                       'categoryIconS' => $menuIcon,
+                       'categoryIconM' => $icon,
+                       'permissions' => $category['permissions'],
+                       'options' => $category['options']
+               );
+               // append show order if explicitly stated
+               if ($category['showOrder'] !== null) $data['showOrder'] = $category['showOrder'];
+               
+               $userOptionCategory = UserOptionCategory::getCategoryByName($category['categoryName'], $this->installation->getPackageID());
+               if ($userOptionCategory->categoryID) {
+                       $categoryEditor = new UserOptionCategoryEditor($userOptionCategory);
+                       $categoryEditor->update($data);
+               }
+               else {
+                       // append data fields for create
+                       $data['packageID'] = $this->installation->getPackageID();
+                       $data['categoryName'] = $category['categoryName'];
+                       
+                       UserOptionCategoryEditor::create($data);
+               }
+       }
+       
+       /**
+        * @see  AbstractOptionPackageInstallationPlugin::saveOption()
+        */
+       protected function saveOption($option, $categoryName, $existingOptionID = 0) {
+               // default values
+               $optionName = $optionType = $defaultValue = $validationPattern = $outputClass = $selectOptions = $enableOptions = $permissions = $options = '';
+               $required = $editable = $visible = $searchable = $disabled = $askDuringRegistration = 0;
+               $showOrder = null;
+               
+               // get values
+               if (isset($option['name'])) $optionName                         = $option['name'];
+               if (isset($option['optiontype'])) $optionType                   = $option['optiontype'];
+               if (isset($option['defaultvalue'])) $defaultValue               = $option['defaultvalue'];
+               if (isset($option['validationpattern'])) $validationPattern     = $option['validationpattern'];
+               if (isset($option['required'])) $required                       = intval($option['required']);
+               if (isset($option['askduringregistration'])) $askDuringRegistration = intval($option['askduringregistration']);
+               if (isset($option['editable'])) $editable                       = intval($option['editable']);
+               if (isset($option['visible'])) $visible                         = intval($option['visible']);
+               if (isset($option['searchable'])) $searchable                   = intval($option['searchable']);
+               if (isset($option['showorder'])) $showOrder                     = intval($option['showorder']);
+               if (isset($option['outputclass'])) $outputClass                 = $option['outputclass'];
+               if (isset($option['selectoptions'])) $selectOptions             = $option['selectoptions'];
+               if (isset($option['enableoptions'])) $enableOptions             = $option['enableoptions'];
+               if (isset($option['disabled'])) $disabled                       = intval($option['disabled']);
+               $showOrder = $this->getShowOrder($showOrder, $categoryName, 'categoryName');
+               if (isset($option['permissions'])) $permissions                 = $option['permissions'];
+               if (isset($option['options'])) $options                         = $option['options'];
+               
+               
+               // check if optionType exists
+               $className = 'wcf\system\option\OptionType'.ucfirst($optionType);
+               if (!class_exists($className)) {
+                       throw new SystemException("unable to find class '".$className."'", 11001);
+               }
+               
+               // collect additional tags and their values
+               $additionalData = array();
+               foreach ($option as $tag => $value) {
+                       if (!in_array($tag, self::$reservedTags)) $additionalData[$tag] = $value;
+               }
+               
+               // get optionID if it was installed by this package already
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   optionName = ?
+                       AND     packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $optionName,
+                       $this->installation->getPackageID()
+               ));
+               $result = $statement->fetchArray();
+               
+               // build data array
+               $data = array(
+                       'categoryName' => $categoryName,
+                       'optionType' => $optionType,
+                       'defaultValue' => $defaultValue,
+                       'validationPattern' => $validationPattern,
+                       'selectOptions' => $selectOptions,
+                       'enableOptions' => $enableOptions,
+                       'required' => $required,
+                       'askDuringRegistration' => $askDuringRegistration,
+                       'editable' => $editable,
+                       'visible' => $visible,
+                       'outputClass' => $outputClass,
+                       'searchable' => $searchable,
+                       'showOrder' => $showOrder,
+                       'disabled' => $disabled,
+                       'permissions' => $permissions,
+                       'options' => $options,
+                       'additionalData' => serialize($additionalData)
+               );
+               
+               // update option
+               if (!empty($result['optionID']) && $this->installation->getAction() == 'update') {
+                       $userOption = new UserOption(null, $result);
+                       $userOptionEditor = new UserOptionEditor($userOption);
+                       $userOptionEditor->update($data);
+               }
+               // insert new option
+               else {
+                       // append option name
+                       $data['optionName'] = $optionName;
+                       $data['packageID'] = $this->installation->getPackageID();
+                       UserOptionEditor::create($data);
+               }
+        }
+       
+       /**
+        * Drops the columns from user option value table from options
+        * installed by this package.
+        */
+       public function uninstall() {
+               // get optionsIDs from package
+               $sql = "SELECT  optionID
+                       FROM    wcf".WCF_N."_user_option
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array($this->installation->getPackageID()));
+               $optionIDs = array();
+               while ($row = $statement->fetchArray()) {
+                       WCF::getDB()->getEditor()->dropColumn('wcf'.WCF_N.'_user_option_value', 'userOption'.$row['optionID']);
+               }
+               
+               // uninstall options and categories
+               parent::uninstall();
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/request/LinkHandler.class.php b/wcfsetup/install/files/lib/system/request/LinkHandler.class.php
new file mode 100644 (file)
index 0000000..ec8ae45
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+namespace wcf\system\request;
+use wcf\system\application\ApplicationHandler;
+use wcf\system\SingletonFactory;
+
+/**
+ * Handles relative links within the wcf.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.request
+ * @category   Community Framework
+ */
+class LinkHandler extends SingletonFactory {
+       /**
+        * Returns a relative link.
+        * 
+        * @param       string          $url
+        * @param       string          $abbreviation
+        * @return      string
+        */
+       public function getLink($url, $abbreviation = 'wcf') {
+               $applicationGroup = ApplicationHandler::getInstance()->getActiveGroup();
+               
+               // not within an application group, return unmodified url
+               if ($applicationGroup === null) {
+                       return $url . (strstr($url, '?') === false ? SID_ARG_1ST : SID_ARG_2ND_NOT_ENCODED);
+               }
+               
+               // try to resolve abbreviation
+               $application = null;
+               if ($abbreviation != 'wcf') {
+                       $application = ApplicationHandler::getInstance()->getApplication($abbreviation);
+               }
+               
+               // fallback to primary application if abbreviation is 'wcf' or unknown
+               if ($application === null) {
+                       $application = ApplicationHandler::getInstance()->getPrimaryApplication();
+               }
+               
+               return $application->domainName . $application->domainPath . $url . (strstr($url, '?') === false ? SID_ARG_1ST : SID_ARG_2ND_NOT_ENCODED);
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/request/Request.class.php b/wcfsetup/install/files/lib/system/request/Request.class.php
new file mode 100644 (file)
index 0000000..4d0433d
--- /dev/null
@@ -0,0 +1,97 @@
+<?php\r
+namespace wcf\system\request;\r
+\r
+/**\r
+ * Represents a page request.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.request\r
+ * @category   Community Framework\r
+ */\r
+class Request {\r
+       /**\r
+        * page class name\r
+        * @var string\r
+        */\r
+       protected $className = '';\r
+       \r
+       /**\r
+        * page name\r
+        * @var string\r
+        */\r
+       protected $pageName = '';\r
+       \r
+       /**\r
+        * page type\r
+        * @var string\r
+        */\r
+       protected $pageType = '';\r
+       \r
+       /**\r
+        * true, if this request was executed already.\r
+        * @var boolean\r
+        */\r
+       protected $executed = false;\r
+       \r
+       /**\r
+        * Creates a new request object.\r
+        * \r
+        * @param       string          $className\r
+        * @param       string          $pageName\r
+        * @param       string          $pageType\r
+        */\r
+       public function __construct($className, $pageName, $pageType) {\r
+               $this->className = $className;\r
+               $this->pageName = $pageName;\r
+               $this->pageType = $pageType;\r
+       }\r
+       \r
+       /**\r
+        * Executes this request.\r
+        */\r
+       public function execute() {\r
+               if (!$this->executed) {\r
+                       $this->executed = true;\r
+                       new $this->className();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if this request was executed already.\r
+        * \r
+        * @return boolean\r
+        */\r
+       public function isExecuted() {\r
+               return $this->executed;\r
+       }\r
+       \r
+       /**\r
+        * Returns the page class name of this request.\r
+        * \r
+        * @return string\r
+        */\r
+       public function getClassName() {\r
+               return $this->className; \r
+       }\r
+       \r
+       /**\r
+        * Returns the page name of this request.\r
+        * \r
+        * @return string\r
+        */\r
+       public function getPageName() {\r
+               return $this->pageName;\r
+       }\r
+       \r
+       /**\r
+        * Returns the page type of this request.\r
+        * \r
+        * @return string\r
+        */\r
+       public function getPageType() {\r
+               return $this->pageType;\r
+       }\r
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php
new file mode 100644 (file)
index 0000000..8a805c1
--- /dev/null
@@ -0,0 +1,93 @@
+<?php\r
+namespace wcf\system\request;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\exception\IllegalLinkException;\r
+use wcf\system\SingletonFactory;\r
+\r
+/**\r
+ * Handles http requests.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.request\r
+ * @category   Community Framework\r
+ */\r
+class RequestHandler extends SingletonFactory {\r
+       /**\r
+        * active request object\r
+        * @var Request\r
+        */\r
+       protected $activeRequest = null;\r
+       \r
+       /**\r
+        * Handles a http request\r
+        *\r
+        * @param       string          $application\r
+        */\r
+       public function handle($application = 'wcf', $isACP = false) {\r
+               // default values\r
+               $pageName = 'Index';\r
+               $pageType = 'page';\r
+               \r
+               if (!empty($_GET['page']) || !empty($_POST['page'])) {\r
+                       $pageName = (!empty($_GET['page']) ? $_GET['page'] : $_POST['page']);\r
+                       $pageType = 'page';\r
+               }\r
+               else if (!empty($_GET['form']) || !empty($_POST['form'])) {\r
+                       $pageName = (!empty($_GET['form']) ? $_GET['form'] : $_POST['form']);\r
+                       $pageType = 'form';\r
+               }\r
+               else if (!empty($_GET['action']) || !empty($_POST['action'])) {\r
+                       $pageName = (!empty($_GET['action']) ? $_GET['action'] : $_POST['action']);\r
+                       $pageType = 'action';\r
+               }\r
+               \r
+               // build request\r
+               $this->buildRequest($pageName, $pageType, $application, $isACP);\r
+               // start request\r
+               $this->activeRequest->execute();\r
+       }\r
+       \r
+       /**\r
+        * Builds a new request.\r
+        *\r
+        * @param       string          $pageName\r
+        * @param       string          $application\r
+        * @param       string          $pageType\r
+        * @param       boolean         $isACP\r
+        */\r
+       protected function buildRequest($pageName, $pageType, $application, $isACP) {\r
+               try {\r
+                       // validate class name\r
+                       if (!preg_match('~^[a-z0-9_]+$~i', $pageName)) {\r
+                               throw new SystemException("Illegal class name '".$pageName."'", 11009);\r
+                       }\r
+                       \r
+                       // find class\r
+                       $className = $application.'\\'.($isACP ? 'acp\\' : '').$pageType.'\\'.ucfirst($pageName).ucfirst($pageType);\r
+                       if ($application != 'wcf' && !class_exists($className)) {\r
+                               $className = 'wcf\\'.($isACP ? 'acp\\' : '').$pageType.'\\'.ucfirst($pageName).ucfirst($pageType);\r
+                       }\r
+                       if (!class_exists($className)) {\r
+                               throw new SystemException("unable to find class '".$className."'", 11000);\r
+                       }\r
+                       \r
+                       $this->activeRequest = new Request($className, $pageName, $pageType);\r
+               }\r
+               catch (SystemException $e) {\r
+                       throw new IllegalLinkException();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns the active request object.\r
+        *\r
+        * @return Request\r
+        */\r
+       public function getActiveRequest() {\r
+               return $this->activeRequest;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/session/ACPSessionFactory.class.php b/wcfsetup/install/files/lib/system/session/ACPSessionFactory.class.php
new file mode 100644 (file)
index 0000000..9f7309c
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+namespace wcf\system\session;
+use wcf\system\event\EventHandler;
+
+/**
+ * ACPSessionFactory handles session for active user.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.session
+ * @category   Community Framework
+ */
+class ACPSessionFactory {
+       /**
+        * session editor class name
+        *
+        * @var string
+        */     
+       protected $sessionEditor = 'wcf\data\acp\session\ACPSessionEditor';
+       
+       /**
+        * session data editor class name
+        * 
+        * @var string
+        */
+       protected $sessionDataEditor = 'wcf\data\acp\session\data\ACPSessionDataEditor';
+       
+       /**
+        * Returns the object of the active session.
+        */     
+       public function load() {
+               // get session
+               $sessionID = $this->readSessionID();
+               SessionHandler::getInstance()->load($this->sessionEditor, $this->sessionDataEditor, $sessionID);
+               
+               // call shouldInit event
+               if (!defined('NO_IMPORTS')) EventHandler::getInstance()->fireAction($this, 'shouldInit');
+               
+               $this->init();
+               
+               // call didInit event
+               if (!defined('NO_IMPORTS')) EventHandler::getInstance()->fireAction($this, 'didInit');
+       }
+       
+       /**
+        * Initializes the session system.
+        */
+       protected function init() {
+               SessionHandler::getInstance()->initSession();
+       }
+       
+       /**
+        * Gets the sessionID from request (GET/POST). Returns an empty string,
+        * if no sessionID was given.
+        *
+        * @return      string
+        *
+        */     
+       protected function readSessionID() {
+               if (isset($_GET['s'])) return $_GET['s'];
+               else if (isset($_POST['s'])) return $_POST['s'];
+               
+               return '';
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/session/AbstractSessionHandler.class.php b/wcfsetup/install/files/lib/system/session/AbstractSessionHandler.class.php
new file mode 100644 (file)
index 0000000..1f2698a
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+namespace wcf\system\session;
+use wcf\system\SingletonFactory;
+
+/**
+ * Abstract implementation for application-specific session handlers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.session
+ * @category   Community Framework
+ */
+abstract class AbstractSessionHandler extends SingletonFactory {
+       /**
+        * SessionHandler object
+        * 
+        * @var SessionHandler
+        */
+       protected $sessionHandler = null;
+       
+       /**
+        * Initializes session class.
+        */     
+       protected final function init() {
+               $this->sessionHandler = SessionHandler::getInstance();
+               
+               // initialize session
+               $this->initSession();
+       }
+       
+       /**
+        * Forwards calls on unknown properties to stored SessionHandler
+        * 
+        * @param       string          $key
+        * @return      mixed
+        */
+       public function __get($key) {
+               return $this->sessionHandler->{$key};
+       }
+       
+       /**
+        * Initializes this session.
+        */
+       abstract protected function initSession();
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/session/SessionFactory.class.php b/wcfsetup/install/files/lib/system/session/SessionFactory.class.php
new file mode 100644 (file)
index 0000000..4bc5050
--- /dev/null
@@ -0,0 +1,67 @@
+<?php\r
+namespace wcf\system\session;\r
+use wcf\util\HeaderUtil;\r
+\r
+/**\r
+ * SessionFactory handles session for active user.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.session\r
+ * @category   Community Framework\r
+ */\r
+class SessionFactory extends ACPSessionFactory {\r
+       /**\r
+        * @see ACPSessionFactory::$sessionEditor\r
+        */     \r
+       protected $sessionEditor = 'wcf\data\session\SessionEditor';\r
+       \r
+       /**\r
+        * @see ACPSessionFactory::$sessionDataEditor\r
+        */\r
+       protected $sessionDataEditor = 'wcf\data\session\data\SessionDataEditor';\r
+       \r
+       /**\r
+        * @see ACPSessionFactory::readSessionID()\r
+        */     \r
+       protected function readSessionID() {\r
+               $sessionID = parent::readSessionID();\r
+               \r
+               // get sessionID from cookie\r
+               if (empty($sessionID) && isset($_COOKIE[COOKIE_PREFIX.'cookieHash'])) {\r
+                       $sessionID = $_COOKIE[COOKIE_PREFIX . 'cookieHash'];\r
+               }\r
+               \r
+               return $sessionID;\r
+       }\r
+       \r
+       /**\r
+        * @see ACPSessionFactory::init()\r
+        */     \r
+       protected function init() {\r
+               $usesCookies = true;\r
+               \r
+               if (isset($_COOKIE[COOKIE_PREFIX.'cookieHash'])) {\r
+                       if ($_COOKIE[COOKIE_PREFIX.'cookieHash'] != SessionHandler::getInstance()->sessionID) {\r
+                               $usesCookies = false;\r
+                       }\r
+               }\r
+               else {\r
+                       $usesCookies = false;\r
+               }\r
+               \r
+               if (!$usesCookies) {\r
+                       // cookie support will be enabled upon next request\r
+                       HeaderUtil::setCookie('cookieHash', SessionHandler::getInstance()->sessionID);\r
+               }\r
+               else {\r
+                       // enable cookie support\r
+                       SessionHandler::getInstance()->enableCookies();\r
+               }\r
+               \r
+               parent::init();\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/session/SessionHandler.class.php b/wcfsetup/install/files/lib/system/session/SessionHandler.class.php
new file mode 100644 (file)
index 0000000..79b65cf
--- /dev/null
@@ -0,0 +1,614 @@
+<?php
+namespace wcf\system\session;
+use wcf\data\user\group\UserGroup;
+use wcf\data\user\User;
+use wcf\system\auth\UserAuth;
+use wcf\system\cache\CacheHandler;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\storage\StorageHandler;
+use wcf\system\SingletonFactory;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+use wcf\util\UserUtil;
+
+/**
+ * SessionHandler provides an abstract implementation for session handling.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.session
+ * @category   Community Framework
+ */
+class SessionHandler extends SingletonFactory {
+       /**
+        * prevents update on shutdown
+        *
+        * @var boolean
+        */     
+       protected $doNotUpdate = false;
+       
+       /**
+        * various environment variables
+        *
+        * @var array
+        */     
+       protected $environment = array();
+       
+       /**
+        * group data and permissions
+        *
+        * @var array<array>
+        */     
+       protected $groupData = null;
+       
+       /**
+        * language if for active user
+        *
+        * @var integer
+        */     
+       protected $languageID = 0;
+       
+       /**
+        * language ids for active user
+        *
+        * @var array<integer>
+        */     
+       protected $languageIDs = null;
+       
+       /**
+        * session object
+        *
+        * @var ACPSession
+        */     
+       protected $session = null;
+       
+       /**
+        * session data object
+        * 
+        * @var ACPSessionData
+        */
+       protected $sessionData = null;
+       
+       /**
+        * session data class name
+        * 
+        * @var string
+        */
+       protected $sessionDataClassName = '';
+       
+       /**
+        * session data editor class name
+        * 
+        * @var string
+        */
+       protected $sessionDataEditorClassName = '';
+       
+       /**
+        * session class name
+        *
+        * @var string
+        */     
+       protected $sessionClassName = '';
+       
+       /**
+        * session editor class name
+        * 
+        * @var string
+        */
+       protected $sessionEditorClassName = '';
+       
+       /**
+        * enable cookie support
+        * 
+        * @var boolean
+        */
+       protected $useCookies = false;
+       
+       /**
+        * user object
+        *
+        * @var User
+        */     
+       protected $user = null;
+       
+       /**
+        * session variables
+        * 
+        * @var array
+        */     
+       protected $variables = null;
+       
+       /**
+        * indicates if session variables changed and must be saved upon shutdown
+        * 
+        * @var boolean
+        */     
+       protected $variablesChanged = false;
+       
+       /**
+        * Provides access to session data.
+        * 
+        * @param       string          $key
+        * @return      mixed
+        */     
+       public function __get($key) {
+               if (isset($this->environment[$key])) {
+                       return $this->environment[$key];
+               }
+               
+               return $this->session->{$key};
+       }
+       
+       /**
+        * Loads an existing session or creates a new one.
+        *
+        * @param       string          $sessionEditorClassName
+        * @param       string          $sessionEditorDataClassName
+        * @param       string          $sessionID
+        */     
+       public function load($sessionEditorClassName, $sessionEditorDataClassName, $sessionID) {
+               $this->sessionEditorClassName = $sessionEditorClassName;
+               $this->sessionClassName = call_user_func(array($sessionEditorClassName, 'getBaseClass'));
+               $this->sessionDataEditorClassName = $sessionEditorDataClassName;
+               $this->sessionDataClassName = call_user_func(array($sessionEditorDataClassName, 'getBaseClass'));
+               
+               // try to get existing session
+               if (!empty($sessionID)) {
+                       $this->getExistingSession($sessionID);
+               }
+               
+               // create new session
+               if ($this->session === null) {
+                       $this->create();
+               }
+       }
+       
+       /**
+        * Initializes session system.
+        */     
+       public function initSession() {
+               // init session environment
+               $this->loadVariables();
+               $this->initSecurityToken();
+               $this->defineConstants();
+               
+               // assign language id
+               $this->languageID = $this->user->languageID;
+               
+               // init environment variables
+               $this->initEnvironment();
+       }
+       
+       /**
+        * Enables cookie support.
+        */     
+       public function enableCookies() {
+               $this->useCookies = true;
+       }
+       
+       /**
+        * Initializes environment variables.
+        */
+       protected function initEnvironment() {
+               $this->environment = array(
+                       'lastRequestURI' => $this->session->requestURI,
+                       'lastRequestMethod' => $this->session->requestMethod,
+                       'ipAddress' => UserUtil::getIpAddress(),
+                       'userAgent' => UserUtil::getUserAgent(),
+                       'requestURI' => UserUtil::getRequestURI(),
+                       'requestMethod' => (!empty($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '')
+               );
+       }
+       
+       /**
+        * Disables update on shutdown.
+        */
+       public function disableUpdate() {
+               $this->doNotUpdate = true;
+       }
+       
+       /**
+        * Defines WCF-global constants related to session.
+        */
+       protected function defineConstants() {
+               if ($this->useCookies) {
+                       if (!defined('SID_ARG_1ST')) define('SID_ARG_1ST', '');
+                       if (!defined('SID_ARG_2ND')) define('SID_ARG_2ND', '');
+                       if (!defined('SID_ARG_2ND_NOT_ENCODED')) define('SID_ARG_2ND_NOT_ENCODED', '');
+                       if (!defined('SID')) define('SID', '');
+                       if (!defined('SID_INPUT_TAG')) define('SID_INPUT_TAG', '');
+               }
+               else {
+                       if (!defined('SID_ARG_1ST')) define('SID_ARG_1ST', '?s='.$this->sessionID);
+                       if (!defined('SID_ARG_2ND')) define('SID_ARG_2ND', '&amp;s='.$this->sessionID);
+                       if (!defined('SID_ARG_2ND_NOT_ENCODED')) define('SID_ARG_2ND_NOT_ENCODED', '&s='.$this->sessionID);
+                       if (!defined('SID')) define('SID', $this->sessionID);
+                       if (!defined('SID_INPUT_TAG')) define('SID_INPUT_TAG', '<input type="hidden" name="s" value="'.$this->sessionID.'" />');
+               }
+               
+               // security token
+               if (!defined('SECURITY_TOKEN')) define('SECURITY_TOKEN', $this->getSecurityToken());
+               if (!defined('SECURITY_TOKEN_INPUT_TAG')) define('SECURITY_TOKEN_INPUT_TAG', '<input type="hidden" name="t" value="'.$this->getSecurityToken().'" />');
+       }
+       
+       /**
+        * Initializes security token.
+        */     
+       protected function initSecurityToken() {
+               if ($this->getVar('__SECURITY_TOKEN') === null) {
+                       $this->register('__SECURITY_TOKEN', StringUtil::getRandomID());
+               }
+       }
+       
+       /**
+        * Returns security token.
+        * 
+        * @return      string
+        */
+       public function getSecurityToken() {
+               return $this->getVar('__SECURITY_TOKEN');
+       }
+       
+       /**
+        * Validates the given security token, returns false if
+        * given token is invalid.
+        * 
+        * @param       string          $token
+        * @return      boolean
+        */
+       public function checkSecurityToken($token) {
+               return ($this->getSecurityToken() === $token);
+       }
+       
+       /**
+        * Registers a session variable.
+        *
+        * @param       string          $key
+        * @param       string          $value
+        */     
+       public function register($key, $value) {
+               $this->variables[$key] = $value;
+               $this->variablesChanged = true;
+       }
+       
+       /**
+        * Unsets a session variable.
+        * 
+        * @param       string          $key
+        */     
+       public function unregister($key) {
+               unset($this->variables[$key]);
+               $this->variablesChanged = true;
+       }
+       
+       /**
+        * Returns the value of a session variable.
+        * 
+        * @param       string          $key
+        */
+       public function getVar($key) {
+               if (isset($this->variables[$key])) {
+                       return $this->variables[$key];
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Initializes session variables.
+        */     
+       protected function loadVariables() {
+               @$this->variables = unserialize($this->sessionData->sessionVariables);
+               if (!is_array($this->variables)) {
+                       $this->variables = array();
+               }
+       }
+       
+       /**
+        * Returns the user object of this session.
+        *
+        * @return      User    $user
+        */
+       public function getUser() {
+               return $this->user;
+       }
+       
+       /**
+        * Tries to read existing session identified by $sessionID.
+        *
+        * @param       string          $sessionID 
+        * @return      UserSession
+        */     
+       protected function getExistingSession($sessionID) {
+               $this->session = new $this->sessionClassName($sessionID);
+               if (!$this->session->sessionID || !$this->validate()) {
+                       $this->session = $this->sessionData = null;
+                       return;
+               }
+               
+               // load session data
+               $this->sessionData = new $this->sessionDataClassName($this->session->sessionID);
+               
+               // load user
+               $this->user = new User($this->session->userID);
+       }
+       
+       /**
+        * Validates the ip address of this session.
+        * 
+        * @return      boolean
+        * 
+        * @todo        Needs to be implemented, keep proper IPv6 support in mind!
+        */
+       protected function validate() {
+               return true;
+       }
+       
+       /**
+        * Creates a new session.
+        */     
+       protected function create() {
+               // create new session hash
+               $sessionID = StringUtil::getRandomID();
+               
+               // get user automatically
+               $this->user = UserAuth::getInstance()->loginAutomatically();
+               
+               // create user
+               if ($this->user === null) {
+                       // no valid user found
+                       // create guest user
+                       $this->user = new User(null);
+               }
+               
+               // insert session into database
+               $requestMethod = (!empty($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '');
+               
+               // save session
+               $this->session = call_user_func(array($this->sessionEditorClassName, 'create'), array(
+                       'sessionID' => $sessionID,
+                       'packageID' => PACKAGE_ID,
+                       'userID' => $this->user->userID,
+                       'ipAddress' => UserUtil::getIpAddress(),
+                       'userAgent' => UserUtil::getUserAgent(),
+                       'lastActivityTime' => TIME_NOW,
+                       'requestURI' => UserUtil::getRequestURI(),
+                       'requestMethod' => $requestMethod
+               ));
+               
+               // creaty entry in session data
+               $this->sessionData = call_user_func(array($this->sessionDataEditorClassName, 'create'), array(
+                       'sessionID' => $this->session->sessionID
+               ));
+       }
+       
+       /**
+        * Returns the value of the permission with the given name.
+        *
+        * @param       string          $permission
+        * @return      mixed           permission value
+        */
+       public function getPermission($permission) {
+               $this->loadGroupData();
+               
+               if (!isset($this->groupData[$permission])) return false;
+               return $this->groupData[$permission];
+       }
+       
+       /**
+        * Checks the requested permission, throws a PermissionDeniedException
+        * if the permission is false.
+        * @see SessionHandler::getPermission()
+        */
+       public function checkPermission(array $permissions) {
+               foreach ($permissions as $permission) {
+                       if (!$this->getPermission($permission)) {
+                               throw new PermissionDeniedException();
+                       }
+               }
+       }
+       
+       /**
+        * Loads group data from cache.
+        */     
+       protected function loadGroupData() {
+               if ($this->groupData !== null) return;
+               
+               // work-around for setup process (package wcf does not exist yet)
+               if (!PACKAGE_ID) {
+                       $groupIDs = array();
+                       $sql = "SELECT  groupID
+                               FROM    wcf".WCF_N."_user_to_group
+                               WHERE   userID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->user->userID));
+                       while ($row = $statement->fetchArray()) {
+                               $groupIDs[] = $row['groupID'];
+                       }
+               }
+               else {
+                       $groupIDs = $this->user->getGroupIDs();
+               }
+               
+               $groups = implode(',', $groupIDs);
+               $groupsFileName = StringUtil::getHash($groups);
+               
+               // register cache resource
+               CacheHandler::getInstance()->addResource(
+                       'groups-'.PACKAGE_ID.'-'.$groups,
+                       WCF_DIR.'cache/cache.groups-'.PACKAGE_ID.'-'.$groupsFileName.'.php',
+                       'wcf\system\cache\CacheBuilderUserGroupPermission'
+               );
+               
+               // get group data from cache
+               $this->groupData = CacheHandler::getInstance()->get('groups-'.PACKAGE_ID.'-'.$groups);
+               if (isset($this->groupData['groupIDs']) && $this->groupData['groupIDs'] != $groups) {
+                       $this->groupData = array();
+               }
+       }
+       
+       /**
+        * Returns language ids for active user.
+        *
+        * @return      array<integer>
+        */     
+       public function getLanguageIDs() {
+               $this->loadLanguageIDs();
+               
+               return $this->languageIDs;
+       }
+       
+       /**
+        * Loads language ids for active user.
+        */     
+       protected function loadLanguageIDs() {
+               if ($this->languageIDs !== null) return;
+               
+               $this->languageIDs = array();
+               
+               if (!$this->user->userID) {
+                       return;
+               }
+               
+               // work-around for setup process (package wcf does not exist yet)
+               if (!PACKAGE_ID) {
+                       $sql = "SELECT  languageID
+                               FROM    wcf".WCF_N."_user_to_language
+                               WHERE   userID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->user->userID));
+                       while ($row = $statement->fetchArray()) {
+                               $this->languageIDs[] = $row['languageID'];
+                       }
+               }
+               else {
+                       $this->languageIDs = $this->user->getLanguageIDs();
+               }
+       }
+       
+       /**
+        * Stores a new user object in this session, e.g. a user was guest because not
+        * logged in, after the login his old session is used to store his full data.
+        *
+        * @param       User            $user
+        */     
+       public function changeUser(User $user) {
+               $sessionTable = call_user_func(array($this->sessionClassName, 'getDatabaseTableName'));
+               $sessionDataTable = call_user_func(array($this->sessionDataClassName, 'getDatabaseTableName'));
+               
+               if ($user->userID) {
+                       // user is not a gest, delete all other sessions of this user
+                       $sql = "SELECT          sessionID
+                               FROM            ".$sessionTable."
+                               WHERE           sessionID <> ?
+                                               AND userID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->sessionID, $this->userID));
+                       $row = $statement->fetchArray();
+                       
+                       if ($row) {
+                               $sql = "DELETE FROM     ".$sessionTable."
+                                       WHERE           sessionID = ?";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute(array(
+                                       $row['sessionID']
+                               ));
+                               
+                               // delete session data
+                               $sql = "DELETE FROM     ".$sessionDataTable."
+                                       WHERE           sessionID = ?";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute(array(
+                                       $row['sessionID']
+                               ));
+                       }
+               }
+               
+               // update user reference
+               $this->user = $user;
+               
+               // update session
+               $sessionEditor = new $this->sessionEditorClassName($this->session);
+               $sessionEditor->update(array(
+                       'userID' => $this->user->userID,
+                       'username' => $this->user->username
+               ));
+               
+               // truncate session variables
+       }
+       
+       /**
+        * Updates user session on shutdown.
+        */     
+       public function update() {
+               if ($this->doNotUpdate) return;
+               
+               // update session
+               $sessionEditor = new $this->sessionEditorClassName($this->session);
+               $sessionEditor->update(array(
+                       'ipAddress' => $this->ipAddress,
+                       'userAgent' => $this->userAgent,
+                       'requestURI' => $this->requestURI,
+                       'requestMethod' => $this->requestMethod,
+                       'lastActivityTime' => TIME_NOW,
+                       'packageID' => PACKAGE_ID
+               ));
+               
+               // update session variables
+               if ($this->variablesChanged) {
+                       $sessionDataEditor = new $this->sessionDataEditorClassName($this->sessionData);
+                       $sessionDataEditor->update(array(
+                               'sessionVariables' => serialize($this->variables)
+                       ));
+               }
+       }
+       
+       /**
+        * Deletes this session and it's related data.
+        */     
+       public function delete() {
+               // remove session data
+               $sessionDataEditor = new $this->sessionDataEditorClassName($this->sessionData);
+               $sessionDataEditor->delete();
+               
+               // remove session
+               $sessionEditor = new $this->sessionEditorClassName($this->session);
+               $sessionEditor->delete();
+               
+               // clear storage
+               if ($this->user->userID) {
+                       self::resetSessions(array($this->user->userID));
+               }
+               
+               // disable update
+               $this->disableUpdate();
+       }
+       
+       /**
+        * Returns currently active language id
+        *
+        * @return      integer
+        */     
+       public function getLanguageID() {
+               return $this->languageID;
+       }
+       
+       /**
+        * Resets session-specific storage data.
+        *
+        * @param       array           $userIDs
+        */     
+       public static function resetSessions(array $userIDs = array()) {
+               if (count($userIDs)) {
+                       StorageHandler::getInstance()->reset($userIDs, 'groupIDs', 1);
+                       StorageHandler::getInstance()->reset($userIDs, 'languageIDs', 1);
+               }
+               else {
+                       StorageHandler::getInstance()->resetAll('groupIDs', 1);
+                       StorageHandler::getInstance()->resetAll('languageIDs', 1);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/setup/FileHandler.class.php b/wcfsetup/install/files/lib/system/setup/FileHandler.class.php
new file mode 100644 (file)
index 0000000..c06a530
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+namespace wcf\system\setup;\r
+\r
+/**\r
+ * A FileHandler class logs files and checks their overwriting rights.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.setup\r
+ * @category   Community Framework\r
+ */\r
+interface FileHandler {\r
+       /**\r
+        * Checks the overwriting rights of the given files.\r
+        * \r
+        * @param       array           $files\r
+        */\r
+       public function checkFiles(array $files);\r
+       \r
+       /**\r
+        * Logs the given list of files.\r
+        * \r
+        * @param       array           $files\r
+        */\r
+       public function logFiles(array $files);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/setup/Installer.class.php b/wcfsetup/install/files/lib/system/setup/Installer.class.php
new file mode 100644 (file)
index 0000000..5153206
--- /dev/null
@@ -0,0 +1,190 @@
+<?php\r
+namespace wcf\system\setup;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\io\Tar;\r
+use wcf\util\FileUtil;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * Installer extracts folders and files from a tar archive.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.setup\r
+ * @category   Community Framework\r
+ */\r
+class Installer {\r
+       protected $targetDir, $source, $folder, $fileHandler;\r
+       \r
+       /**\r
+        * Creates a new Installer object.\r
+        *\r
+        * @param       string          $targetDir      extract the files in this dir\r
+        * @param       string          $source         name of the source tar archive\r
+        * @param       FileHandler     $fileHandler\r
+        * @param       string          $folder         extract only the files from this subfolder\r
+        */\r
+       public function __construct($targetDir, $source, $fileHandler = null, $folder = '') {\r
+               $this->targetDir = FileUtil::addTrailingSlash($targetDir);\r
+               $this->source = $source;\r
+               $this->folder = $folder;\r
+               $this->fileHandler = $fileHandler;\r
+               $this->install();\r
+       }\r
+       \r
+       /**\r
+        * Creates the target directory if necessary.\r
+        */\r
+       protected function createTargetDir() {\r
+               if (!@is_dir($this->targetDir)) {\r
+                       if (!FileUtil::makePath($this->targetDir, (FileUtil::isApacheModule() ? 0777 : 0755))) {\r
+                               throw new SystemException("Could not create dir '".$this->targetDir."'", 11011);\r
+                       }\r
+               }\r
+               if (FileUtil::isApacheModule() || !is_writeable($this->targetDir)) {\r
+                       $this->makeWriteable($this->targetDir);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Creates a directory in the target directory.\r
+        *\r
+        * @param       string          $dir\r
+        */\r
+       protected function createDir($dir) {\r
+               if (!@is_dir($this->targetDir.$dir)) {\r
+                       $oldumask = umask(0);\r
+                       if (!@mkdir($this->targetDir.$dir, 0755, true)) {\r
+                               throw new SystemException("Could not create dir '".$this->targetDir.$dir."'", 11011);\r
+                       }\r
+                       umask($oldumask);\r
+               }\r
+               if (FileUtil::isApacheModule() || !is_writeable($this->targetDir.$dir)) {\r
+                       $this->makeWriteable($this->targetDir.$dir);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Touches a file in the target directory.\r
+        *\r
+        * @param       string          $file\r
+        */\r
+       public function touchFile($file) {\r
+               @touch($this->targetDir.$file);\r
+               $this->makeWriteable($this->targetDir.$file);\r
+       }\r
+       \r
+       /**\r
+        * Creates a file in the target directory.\r
+        *\r
+        * @param       string          $file\r
+        * @param       integer         $index\r
+        * @param       Tar             $tar\r
+        */\r
+       protected function createFile($file, $index, Tar $tar) {\r
+               $tar->extract($index, $this->targetDir.$file);\r
+               if (FileUtil::isApacheModule() || !is_writeable($this->targetDir.$file)) {\r
+                       $this->makeWriteable($this->targetDir.$file);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Starts the extracting of the files.\r
+        */\r
+       protected function install() {\r
+               $this->createTargetDir();\r
+               \r
+               // open source archive\r
+               $tar = new Tar($this->source);\r
+               \r
+               // distinct directories and files\r
+               $directories = array();\r
+               $files = array();\r
+               foreach ($tar->getContentList() as $index => $file) {\r
+                       if (empty($this->folder) || StringUtil::indexOf($file['filename'], $this->folder) === 0) {\r
+                               if (!empty($this->folder)) {\r
+                                       $file['filename'] = StringUtil::replace($this->folder, '', $file['filename']);\r
+                               }\r
+                               \r
+                               // remove leading slash\r
+                               $file['filename'] = FileUtil::removeLeadingSlash($file['filename']);\r
+                               if ($file['type'] == 'folder') {\r
+                                       // remove trailing slash\r
+                                       $directories[] = FileUtil::removeTrailingSlash($file['filename']);\r
+                               }\r
+                               else {\r
+                                       $files[$index] = $file['filename'];\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               $this->checkFiles($files);\r
+\r
+               // now create the directories\r
+               $errors = array();\r
+               foreach ($directories as $dir) {\r
+                       try {\r
+                               $this->createDir($dir);\r
+                       }\r
+                       catch (SystemException $e) {\r
+                               $errors[] = array('file' => $dir, 'code' => $e->getCode(), 'message' => $e->getMessage());\r
+                       }\r
+               }\r
+\r
+               // now untar all files\r
+               foreach ($files as $index => $file) {\r
+                       try {\r
+                               $this->createFile($file, $index, $tar);\r
+                       }\r
+                       catch (SystemException $e) {\r
+                               $errors[] = array('file' => $file, 'code' => $e->getCode(), 'message' => $e->getMessage());\r
+                       }\r
+               }\r
+               if (count($errors) > 0) {\r
+                       throw new SystemException('error(s) during the installation of the files.', 11111, $errors);\r
+               }\r
+               \r
+               $this->logFiles($files);\r
+\r
+               // close tar\r
+               $tar->close();\r
+       }\r
+       \r
+       /**\r
+        * Checkes whether the given files overwriting locked existing files.\r
+        *\r
+        * @param       array           $files          list of files\r
+        */\r
+       protected function checkFiles(&$files) {\r
+               if ($this->fileHandler != null && $this->fileHandler instanceof FileHandler) {\r
+                       $this->fileHandler->checkFiles($files);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Logs the extracted files.\r
+        *\r
+        * @param       array           $files          list of files\r
+        */\r
+       protected function logFiles(&$files) {\r
+               if ($this->fileHandler != null && $this->fileHandler instanceof FileHandler) {\r
+                       $this->fileHandler->logFiles($files);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Makes a file or directory writeable.\r
+        *\r
+        * @param       string          $target\r
+        */\r
+       protected function makeWriteable($target) {\r
+               if (!preg_match('/^WIN/i', PHP_OS)) {\r
+                       if (!@chmod($target, 0777)) {\r
+                               //throw new SystemException("Could not chmod file '".$target."'", 11005);\r
+                       }\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/setup/Uninstaller.class.php b/wcfsetup/install/files/lib/system/setup/Uninstaller.class.php
new file mode 100644 (file)
index 0000000..b867dac
--- /dev/null
@@ -0,0 +1,126 @@
+<?php\r
+namespace wcf\system\setup;\r
+\r
+/**\r
+ * Uninstaller deletes files and directories.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.setup\r
+ * @category   Community Framework\r
+ */\r
+class Uninstaller {\r
+       protected $targetDir, $files, $deleteEmptyTargetDir, $deleteEmptyDirectories;\r
+       \r
+       /**\r
+        * Creates a new Uninstaller object.\r
+        *\r
+        * @param       string          $targetDir\r
+        * @param       array           $files                  delete the files\r
+        * @param       boolean         $deleteEmptyTargetDir   delete target dir if empty\r
+        * @param       boolean         $deleteEmptyDirectories delete sub-directories if empty\r
+        */\r
+       public function __construct($targetDir, $files, $deleteEmptyTargetDir, $deleteEmptyDirectories) {\r
+               $this->targetDir = $targetDir;\r
+               $this->files = $files;\r
+               $this->deleteEmptyTargetDir = $deleteEmptyTargetDir;\r
+               $this->deleteEmptyDirectories = $deleteEmptyDirectories;\r
+               $this->uninstall();\r
+       }\r
+       \r
+       /**\r
+        * Checks if the target directory is a valid directory.\r
+        */\r
+       protected function checkTargetDir() {\r
+               return is_dir($this->targetDir);\r
+       }\r
+       \r
+       /**\r
+        * Returns true if a directory is emtpy.\r
+        *\r
+        * @param       string          $dir\r
+        * @return      boolean                         true if dir is empty\r
+        */\r
+       protected function isEmpty($dir) {\r
+               if (is_dir($dir)) {\r
+                       // subtract default directories . and ..\r
+                       return count(scandir($dir)) - 2 == 0;\r
+               }\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Deletes a file.\r
+        *\r
+        * @param       string          $file\r
+        */\r
+       protected function deleteFile($file) {\r
+               @unlink($file);\r
+       }\r
+       \r
+       /**\r
+        * Deletes a directory.\r
+        *\r
+        * @param       string          $dir\r
+        */\r
+       protected function deleteDir($dir) {\r
+               @rmdir($dir);\r
+       }\r
+       \r
+       /**\r
+        * Starts the deletion of the files.\r
+        */\r
+       protected function uninstall() {\r
+               if ($this->checkTargetDir()) {\r
+                       \r
+                       // delete all files\r
+                       $directories = array();\r
+                       foreach ($this->files as $file) {\r
+                               $this->deleteFile($this->targetDir.$file);\r
+\r
+                               // store directory if this file is not direct in the targetdirectory\r
+                               $dirname = dirname($file);\r
+                               if ($dirname != '.') {\r
+                                       // split the directory\r
+                                       $path = explode("/", $dirname);\r
+                               \r
+                                       // store the directory in a key which is the representation\r
+                                       // for the depth of this directory.\r
+                                       // use dirname as key to store each dir only once\r
+                                       $directories[count($path)][$dirname] = $dirname;\r
+                                       \r
+                                       // store the parent directories\r
+                                       while (array_pop($path)) {\r
+                                               $dirname = implode("/", $path);\r
+                                               if (!empty($dirname)) {\r
+                                                       $directories[count($path)][$dirname] = $dirname;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       // delete direcotries\r
+                       if ($this->deleteEmptyDirectories) {\r
+                               // the deepest diretories first\r
+                               krsort($directories, SORT_NUMERIC);\r
+                               foreach ($directories as $depth) {\r
+                                       foreach ($depth as $dir) {\r
+                                               if ($this->isEmpty($this->targetDir.$dir)) {\r
+                                                       $this->deleteDir($this->targetDir.$dir);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       // delete target directory\r
+                       if ($this->deleteEmptyTargetDir && $this->isEmpty($this->targetDir)) {\r
+                               $this->deleteDir($this->targetDir);\r
+                       }\r
+               }\r
+               // TODO: else throw SystemException ?\r
+       }\r
+       \r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/lib/system/storage/StorageHandler.class.php b/wcfsetup/install/files/lib/system/storage/StorageHandler.class.php
new file mode 100644 (file)
index 0000000..de0e47c
--- /dev/null
@@ -0,0 +1,200 @@
+<?php
+namespace wcf\system\storage;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\SingletonFactory;
+use wcf\system\WCF;
+
+/**
+ * Handles the persistent data storage.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.storage
+ * @category   Community Framework
+ */
+class StorageHandler extends SingletonFactory {
+       /**
+        * Data cache
+        * 
+        * @var array<array>
+        */
+       protected $cache = array();
+       
+       /**
+        * List of outdated data records
+        * 
+        * @var array<array>
+        */
+       protected $resetFields = array();
+       
+       /**
+        * List of updated or new data records
+        * 
+        * @var array<array>
+        */
+       protected $updateFields = array();
+       
+       /**
+        * Loads storage for a given set of users.
+        * 
+        * @param       array           $userIDs
+        * @param       integer         $packageID
+        */
+       public function loadStorage(array $userIDs, $packageID = PACKAGE_ID) {
+               $tmp = array();
+               foreach ($userIDs as $userID) {
+                       if (!isset($this->cache[$userID])) $tmp[] = $userID;
+               }
+               
+               // ignore users whose storage data is already loaded
+               if (empty($tmp)) return;
+               
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("userID IN (?)", array($tmp));
+               $conditions->add("packageID = ?", array(PACKAGE_ID));
+               
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_storage
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               while ($row = $statement->fetchArray()) {
+                       if (!isset($this->cache[$row['userID']])) {
+                               $this->cache[$row['userID']] = array();
+                       }
+                       
+                       if (!isset($this->cache[$row['userID']][$row['packageID']])) {
+                               $this->cache[$row['userID']][$row['packageID']] = array();
+                       }
+                       
+                       $this->cache[$row['userID']][$row['packageID']][$row['field']] = $row['fieldValue'];
+               }
+       }
+       
+       /**
+        * Returns stored data for given users.
+        * 
+        * @param       array           $userIDs
+        * @param       string          $field
+        * @param       integer         $packageID
+        * @return      array<array>
+        */
+       public function getStorage(array $userIDs, $field, $packageID = PACKAGE_ID) {
+               $data = array();
+               
+               foreach ($userIDs as $userID) {
+                       if (isset($this->cache[$userID][$packageID][$field])) {
+                               $data[$userID] = $this->cache[$userID][$packageID][$field];
+                       }
+                       else {
+                               $data[$userID] = null;
+                       }
+               }
+               
+               return $data;
+       }
+       
+       /**
+        * Inserts new data records into database.
+        * 
+        * @param       integer         $userID
+        * @param       string          $field
+        * @param       string          $fieldValue
+        * @param       integer         $packageID
+        */
+       public function update($userID, $field, $fieldValue, $packageID = PACKAGE_ID) {
+               $this->updateFields[$userID][$packageID][$field] = $fieldValue;
+               
+               // update data cache for given user
+               if (!isset($this->cache[$userID])) {
+                       $this->cache[$userID] = array();
+               }
+               
+               if (!isset($this->cache[$userID][$packageID])) {
+                       $this->cache[$userID][$packageID] = array();
+               }
+               
+               $this->cache[$userID][$packageID][$field] = $fieldValue;
+               
+               // flag key as outdated
+               self::reset($userID, $field, $packageID);
+       }
+       
+       /**
+        * Removes a data record from database.
+        * 
+        * @param       integer         $userID
+        * @param       string          $field
+        * @param       integer         $packageID
+        */
+       public function reset($userID, $field, $packageID = PACKAGE_ID) {
+               $this->resetFields[$userID][$packageID][] = $field;
+       }
+       
+       /**
+        * Removes a specific data record for all users.
+        * 
+        * @param       string          $field
+        * @param       integer         $packageID
+        */     
+       public function resetAll($field, $packageID = PACKAGE_ID) {
+               $sql = "DELETE FROM     wcf".WCF_N."_storage
+                       WHERE           field = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(
+                       $field,
+                       $packageID
+               ));
+       }
+       
+       /**
+        * Removes and inserts data records on shutdown.
+        */
+       public function shutdown() {
+               // remove outdated entries
+               if (count($this->resetFields)) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_storage
+                               WHERE           userID = ?
+                                               AND field = ?
+                                               AND packageID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($this->resetFields as $userID => $data) {
+                               foreach ($data as $packageID => $fields) {
+                                       foreach ($fields as $field) {
+                                               $statement->execute(array(
+                                                       $userID,
+                                                       $field,
+                                                       $packageID
+                                               ));
+                                       }
+                               }
+                       }
+               }
+               
+               // insert data
+               if (count($this->updateFields)) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_storage
+                                               (userID, field, fieldValue, packageID)
+                               VALUES          (?, ?, ?, ?)";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       
+                       foreach ($this->updateFields as $userID => $data) {
+                               foreach ($data as $packageID => $fieldValues) {
+                                       foreach ($fieldValues as $field => $fieldValue) {
+                                               $statement->execute(array(
+                                                       $userID,
+                                                       $field,
+                                                       $fieldValue,
+                                                       $packageID
+                                               ));
+                                       }
+                               }
+                       }
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/style/StyleHandler.class.php b/wcfsetup/install/files/lib/system/style/StyleHandler.class.php
new file mode 100644 (file)
index 0000000..4a7e427
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+namespace wcf\system\style;
+use wcf\data\style\ActiveStyle;
+use wcf\system\cache\CacheHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+use wcf\system\WCF;
+
+/**
+ * Handles style-related actions.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.style
+ * @category   Community Framework
+ */
+class StyleHandler extends SingletonFactory {
+       /**
+        * style information cache
+        * @var array
+        */
+       protected $cache = array();
+       
+       /**
+        * active style object
+        * @var ActiveStyle
+        */
+       protected $style = null;
+       
+       /**
+        * Creates a new StyleHandler object.
+        */
+       protected function init() {
+               // load cache
+               CacheHandler::getInstance()->addResource('styles', WCF_DIR.'cache/cache.styles.php', 'wcf\system\cache\CacheBuilderStyle');
+               $this->cache = CacheHandler::getInstance()->get('styles');
+       }
+       
+       /**
+        * Returns a list of all for the current user available styles.
+        * 
+        * @return      array<Style>
+        */
+       public function getAvailableStyles() {
+               $styles = array();
+               
+               foreach ($this->cache['styles'] as $styleID => $style) {
+                       if ((!$style->disabled && empty($this->cache['packages'][PACKAGE_ID]['disabled'][$styleID])) || WCF::getSession()->getPermission('admin.style.canUseDisabledStyle')) {
+                               $styles[$styleID] = $style;
+                       }
+               }
+               
+               return $styles;
+       }
+       
+       /**
+        * Returns the active style.
+        * 
+        * @return      ActiveStyle
+        */
+       public function getStyle() {
+               return $this->style;
+       }
+       
+       /**
+        * Changes the active style.
+        * 
+        * @param       integer         $styleID
+        */
+       public function changeStyle($styleID, $ignorePermissions = false) {
+               // check permission
+               if (!$ignorePermissions) {
+                       if (isset($this->cache['styles'][$styleID])) {
+                               if (($this->cache['styles'][$styleID]->disabled || !empty($this->cache['packages'][PACKAGE_ID]['disabled'][$styleID])) && !WCF::getSession()->getPermission('admin.style.canUseDisabledStyle')) {
+                                       $styleID = 0;
+                               }
+                       }
+               }
+               
+               // fallback to default style
+               if (!isset($this->cache['styles'][$styleID])) {
+                       // get package default style
+                       if (!empty($this->cache['packages'][PACKAGE_ID]['default'])) {
+                               $styleID = $this->cache['packages'][PACKAGE_ID]['default'];
+                       }
+                       // get global default style
+                       else {
+                               $styleID = $this->cache['default'];
+                       }
+                       
+                       if (!isset($this->cache['styles'][$styleID])) {
+                               throw new SystemException('no default style defined', 100000);
+                       }
+               }
+
+               // init style
+               $this->style = new ActiveStyle($this->cache['styles'][$styleID]);
+               
+               // set template group id
+               if (WCF::getTPL()) {
+                       WCF::getTPL()->setTemplateGroupID($this->style->templateGroupID);
+               }
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/template/ACPTemplateEngine.class.php b/wcfsetup/install/files/lib/system/template/ACPTemplateEngine.class.php
new file mode 100644 (file)
index 0000000..86efdfd
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+namespace wcf\system\template;
+
+/**
+ * ACPTemplate loads and displays template in the admin control panel of the wcf.
+ * ACPTemplate does not support template groups.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template
+ * @category   Community Framework
+ */
+class ACPTemplateEngine extends TemplateEngine {
+       /**
+        * @see TemplateEngine::$environment
+        */
+       protected $environment = 'admin';
+       
+       /**
+        * @see TemplateEngine::__construct()
+        */
+       protected function init() {
+               parent::init();
+               
+               $this->templatePaths = array(1 => WCF_DIR.'acp/templates/');
+               $this->compileDir = WCF_DIR.'acp/templates/compiled/';
+               
+               if (!defined('NO_IMPORTS')) {
+                       $this->loadTemplateListeners();
+               }
+       }
+       
+       /**
+        * Deletes all compiled acp templates.
+        * 
+        * @param       string          $compileDir
+        */
+       public static function deleteCompiledACPTemplates($compileDir = '') {
+               if (empty($compileDir)) $compileDir = WCF_DIR.'acp/templates/compiled/';
+               
+               self::deleteCompiledTemplates($compileDir);
+       }
+       
+       /**
+        * Template groups are not supported by acp template engine.
+        * 
+        * @see TemplateEngine::setTemplateGroupID()
+        */
+       public final function setTemplateGroupID($templateGroupID) {
+               $this->templateGroupID = 0;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/template/SetupTemplate.class.php b/wcfsetup/install/files/lib/system/template/SetupTemplate.class.php
new file mode 100644 (file)
index 0000000..da1163b
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+namespace wcf\system\template;\r
+\r
+/**\r
+ * SetupTemplate loads and displays template in the setup process.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+class SetupTemplate extends Template {\r
+       protected $templatePath = '';\r
+       \r
+       /**\r
+        * @see Template::setTemplatePaths()\r
+        */\r
+       public function setTemplatePaths($templatePaths) {\r
+               if (is_array($templatePaths)) $this->templatePath = array_shift($templatePaths);\r
+               else $this->templatePath = $templatePaths;\r
+       }\r
+       \r
+       /**\r
+        * @see Template::loadTemplateStructure()\r
+        */\r
+       protected function loadTemplateStructure() {}\r
+       \r
+       /**\r
+        * @see Template::getSourceFilename()\r
+        */\r
+       public function getSourceFilename($templateName, $packageID = 0) {\r
+               return $this->templatePath.TMP_FILE_PREFIX.$templateName.'.tpl';\r
+       }\r
+       \r
+       /**\r
+        * @see Template::getCompiledFilename()\r
+        */\r
+       public function getCompiledFilename($templateName, $packageID = 0) {\r
+               return $this->compileDir.TMP_FILE_PREFIX.$this->languageID.'_'.$templateName.'.php';\r
+       }\r
+       \r
+       /**\r
+        * @see Template::getPluginFilename()\r
+        */\r
+       public function getPluginFilename($type, $tag) {\r
+               return $this->pluginDir.TMP_FILE_PREFIX.'TemplatePlugin'.StringUtil::firstCharToUpperCase(StringUtil::toLowerCase($type)).StringUtil::firstCharToUpperCase(StringUtil::toLowerCase($tag)).'.class.php';\r
+       }\r
+       \r
+       /**\r
+        * @see Template::getCompiler()\r
+        */\r
+       protected function getCompiler() {\r
+               return new TemplateCompiler($this);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/SetupTemplateEngine.class.php b/wcfsetup/install/files/lib/system/template/SetupTemplateEngine.class.php
new file mode 100644 (file)
index 0000000..65d7524
--- /dev/null
@@ -0,0 +1,59 @@
+<?php\r
+namespace wcf\system\template;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * SetupTemplateEngine loads and displays template in the setup process.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+class SetupTemplateEngine extends TemplateEngine {\r
+       /**\r
+        * @see TemplateEngine::loadTemplateGroupCache()\r
+        */\r
+       protected function loadTemplateGroupCache() {}\r
+       \r
+       /**\r
+        * @see TemplateEngine::getSourceFilename()\r
+        */\r
+       public function getSourceFilename($templateName, $packageID) {\r
+               return $this->templatePaths[PACKAGE_ID].'setup/template/'.$templateName.'.tpl';\r
+       }\r
+       \r
+       /**\r
+        * @see TemplateEngine::getCompiledFilename()\r
+        */\r
+       public function getCompiledFilename($templateName, $packageID) {\r
+               return $this->compileDir.'setup/template/compiled/'.$this->languageID.'_'.$templateName.'.php';\r
+       }\r
+       \r
+       /**\r
+        * @see TemplateEngine::getPackageID()\r
+        */\r
+       public function getPackageID($templateName, $packageID) {\r
+               $path = $this->templatePaths[PACKAGE_ID].'setup/template/'.$templateName.'.tpl';\r
+               if (file_exists($path)) {\r
+                       return PACKAGE_ID;\r
+               }\r
+               \r
+               throw new SystemException("Unable to find template '$templateName'", 12005);\r
+       }\r
+       \r
+       /**\r
+        * @see TemplateEngine::getCompiler()\r
+        */\r
+       protected function getCompiler() {\r
+               return new TemplateCompiler($this);\r
+       }\r
+       \r
+       /**\r
+        * Template Listener are not available during setup.\r
+        */\r
+       protected function loadTemplateListeners() {}\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplateCompiler.class.php b/wcfsetup/install/files/lib/system/template/TemplateCompiler.class.php
new file mode 100644 (file)
index 0000000..c071a61
--- /dev/null
@@ -0,0 +1,45 @@
+<?php\r
+namespace wcf\system\template;\r
+use wcf\system\io\File;\r
+\r
+/**\r
+ * TemplateCompiler compiles template source in valid php code.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+class TemplateCompiler extends TemplateScriptingCompiler {\r
+       /**\r
+        * Compiles the source of a template.\r
+        * \r
+        * @param       string          $templateName\r
+        * @param       string          $sourceContent\r
+        * @param       string          $compiledFilename\r
+        */\r
+       public function compile($templateName, $sourceContent, $compiledFilename) {\r
+               // build fileheader\r
+               $compiledHeader = "<?php\n/**\n* WoltLab Community Framework\n* Template: ".$templateName."\n* Compiled at: ".gmdate('r')."\n* \n* DO NOT EDIT THIS FILE\n*/\n\$this->v['tpl']['template'] = '".addcslashes($templateName, "'\\")."';\n?>\n";\r
+               \r
+               // include Plugins\r
+               $compiledContent = $this->compileString($templateName, $sourceContent);\r
+               \r
+               // write compiled to file\r
+               $file = new File($compiledFilename);\r
+               $file->write($compiledHeader.$compiledContent);\r
+               $file->close();\r
+       }\r
+       \r
+       /**\r
+        * Returns the name of the current template.\r
+        * \r
+        * @return      string\r
+        */\r
+       public function getCurrentTemplate() {\r
+               return $this->getCurrentIdentifier();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplateEngine.class.php b/wcfsetup/install/files/lib/system/template/TemplateEngine.class.php
new file mode 100644 (file)
index 0000000..89ee37a
--- /dev/null
@@ -0,0 +1,702 @@
+<?php
+namespace wcf\system\template;
+use wcf\system\cache\CacheHandler;
+use wcf\system\event\EventHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+use wcf\util\HeaderUtil;
+use wcf\util\StringUtil;
+
+/**
+ * TemplateEngine loads and displays template.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template
+ * @category   Community Framework
+ */
+class TemplateEngine extends SingletonFactory {
+       /**
+        * Directory used to cache previously compiled templates
+        * 
+        * @var string
+        */
+       public $compileDir = '';
+       
+       /**
+        * Active language id used to identify specific language versions of compiled templates
+        * 
+        * @var integer
+        */
+       public $languageID = 0;
+       
+       /**
+        * Directories used as template source
+        * 
+        * @var array
+        */
+       public $templatePaths = array();
+       
+       /**
+        * Namespace containing template modifiers and plugins
+        * 
+        * @var string
+        */
+       public $pluginNamespace = '';
+       
+       /**
+        * Active template compiler.
+        * 
+        * @var TemplateCompiler
+        */
+       protected $compilerObj = null;
+       
+       /**
+        * forces the template engine to recompile all included templates
+        * 
+        * @var boolean
+        */
+       protected $forceCompile = false;
+       
+       /**
+        * list of registered prefilters
+        * 
+        * @var array
+        */
+       protected $prefilters = array();
+       
+       /**
+        * Cached list of known template groups.
+        * 
+        * @var array
+        */
+       protected $templateGroupCache = array();
+       
+       /**
+        * Active template group id.
+        * 
+        * @var integer
+        */
+       protected $templateGroupID = 0;
+       
+       /**
+        * Contains all available template variables and those assigned during runtime
+        * 
+        * @var array<array>
+        */
+       protected $v = array();
+       
+       /**
+        * Contains all templates with assigned template listeners
+        * 
+        * @var array<array>
+        */
+       protected $templateListeners = array();
+       
+       /**
+        * Current environment
+        * 
+        * @var string
+        */
+       protected $environment = 'user';
+       
+       /**
+        * Creates a new instance of TemplateEngine.
+        * 
+        * @see TemplateEngine::getInstance()
+        */
+       protected function init() {
+               $this->templatePaths = array(1 => WCF_DIR.'templates/');
+               $this->pluginNamespace = 'wcf\system\template\plugin\\';
+               $this->compileDir = WCF_DIR.'templates/compiled/';
+               
+               $this->loadTemplateGroupCache();
+               $this->assignSystemVariables();
+               $this->loadTemplateListeners();
+       }
+       
+       /**
+        * Adds a new template path for given package id.
+        * 
+        * @param       integer         $packageID
+        * @param       string          $templatePath
+        */
+       public function addTemplatePath($packageID, $templatePath) {
+               $this->templatePaths[$packageID] = $templatePath;
+       }
+       
+       /**
+        * Sets active language id.
+        * 
+        * @param       integer         $languageID
+        */
+       public function setLanguageID($languageID) {
+               $this->languageID = $languageID;
+       }
+       
+       /**
+        * Assigns some system variables.
+        */
+       protected function assignSystemVariables() {
+               $this->v['tpl'] = array();
+               
+               // assign super globals
+               $this->v['tpl']['get'] =& $_GET;
+               $this->v['tpl']['post'] =& $_POST;
+               $this->v['tpl']['cookie'] =& $_COOKIE;
+               $this->v['tpl']['server'] =& $_SERVER;
+               $this->v['tpl']['env'] =& $_ENV;
+               
+               // system info
+               $this->v['tpl']['now'] = TIME_NOW;
+               $this->v['tpl']['template'] = '';
+               $this->v['tpl']['includedTemplates'] = array();
+               
+               // section / foreach / capture arrays
+               $this->v['tpl']['section'] = $this->v['tpl']['foreach'] = $this->v['tpl']['capture'] = array();
+       }
+       
+       /**
+        * Assigns a template variable.
+        *
+        * @param       mixed   $variable
+        * @param       mixed   $value
+        */
+       public function assign($variable, $value = '') {
+               if (is_array($variable)) {
+                       foreach ($variable as $key => $value) {
+                               if (empty($key)) continue;
+                               
+                               $this->assign($key, $value);
+                       }
+               }
+               else {
+                       $this->v[$variable] = $value;
+               }
+       }
+       
+       /**
+        * Appends content to an existing template variable.
+        *
+        * @param       mixed           $variable
+        * @param       mixed           $value
+        */
+       public function append($variable, $value = '') {
+               if (is_array($variable)) {
+                       foreach ($variable as $key => $val) {
+                               if ($key != '') {
+                                       $this->append($key, $val);
+                               }
+                       }
+               }
+               else {
+                       if (!empty($variable)) {
+                               if (isset($this->v[$variable])) {
+                                       if (is_array($this->v[$variable]) && is_array($value)) {
+                                               $keys = array_keys($value);
+                                               foreach ($keys as $key) {
+                                                       if (isset($this->v[$variable][$key])) {
+                                                               $this->v[$variable][$key] .= $value[$key];
+                                                       }
+                                                       else { 
+                                                               $this->v[$variable][$key] = $value[$key];
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               $this->v[$variable] .= $value;
+                                       }
+                               }
+                               else {
+                                       $this->v[$variable] = $value;
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Prepends content to an existing template variable.
+        *
+        * @param       mixed           $variable
+        * @param       mixed           $value
+        */
+       public function prepend($variable, $value = '') {
+               if (is_array($variable)) {
+                       foreach ($variable as $key => $val) {
+                               if ($key != '') {
+                                       $this->prepend($key, $val);
+                               }
+                       }
+               }
+               else {
+                       if (!empty($variable)) {
+                               if (isset($this->v[$variable])) {
+                                       if (is_array($this->v[$variable]) && is_array($value)) {
+                                               $keys = array_keys($value);
+                                               foreach ($keys as $key) {
+                                                       if (isset($this->v[$variable][$key])) {
+                                                               $this->v[$variable][$key] = $value[$key] . $this->v[$variable][$key];
+                                                       }
+                                                       else { 
+                                                               $this->v[$variable][$key] = $value[$key];
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               $this->v[$variable] = $value . $this->v[$variable];
+                                       }
+                               }
+                               else {
+                                       $this->v[$variable] = $value;
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Assigns a template variable by reference.
+        *
+        * @param       string          $variable
+        * @param       mixed           $value
+        */
+       public function assignByRef($variable, &$value) {
+               if (!empty($variable)) {
+                       $this->v[$variable] = &$value;
+               }
+       }
+       
+       /**
+        * Clears an assignment of template variables.
+        *
+        * @param       mixed           $variables
+        */
+       public function clearAssign(array $variables) {
+               foreach ($variables as $key) {
+                       unset($this->v[$key]);
+               }
+       }
+       
+       /**
+        * Clears assignment of all template variables. This should not be called
+        * during runtime as it could leed to an unexpected behaviour.
+        */
+       public function clearAllAssign() {
+               $this->v = array();
+       }
+       
+       /**
+        * Outputs a template.
+        *
+        * @param       string          $templateName
+        * @param       integer         $packageID
+        * @param       boolean         $sendHeaders
+        */
+       public function display($templateName, $packageID = PACKAGE_ID, $sendHeaders = true) {
+               if ($sendHeaders) {
+                       HeaderUtil::sendHeaders();
+                       
+                       // call shouldDisplay event
+                       if (!defined('NO_IMPORTS')) EventHandler::getInstance()->fireAction($this, 'shouldDisplay');
+               }
+               
+               $tplPackageID = $this->getPackageID($templateName, $packageID);
+               $compiledFilename = $this->getCompiledFilename($templateName, $tplPackageID);
+               $sourceFilename = $this->getSourceFilename($templateName, $tplPackageID);
+               
+               // check if compilation is necessary
+               if (!$this->isCompiled($templateName, $sourceFilename, $compiledFilename)) {
+                       // compile
+                       $this->compileTemplate($templateName, $sourceFilename, $compiledFilename);
+               }
+               
+               // assign current package id
+               $this->assign('__PACKAGE_ID', $packageID);
+               
+               include($compiledFilename);
+               
+               if ($sendHeaders) {
+                       // call didDisplay event
+                       if (!defined('NO_IMPORTS')) EventHandler::getInstance()->fireAction($this, 'didDisplay');
+               }
+       }
+       
+       /**
+        * Returns path and corresponding file path.
+        * 
+        * @param       string          $templateName
+        * @param       integer         $packageID
+        * @return      integer
+        */
+       protected function getPackageID($templateName, $packageID) {
+               if ($packageID != 1 && isset($this->templatePaths[$packageID])) {
+                       $path = $this->getPath($this->templatePaths[$packageID], $templateName);
+                       
+                       if (!empty($path)) {
+                               return $packageID;
+                       }
+               }
+               
+               $path = $this->getPath($this->templatePaths[1], $templateName);
+               if (!empty($path)) {
+                       return 1;
+               }
+               
+               
+               throw new SystemException("Unable to find template '$templateName'", 12005);
+       }
+       
+       /**
+        * Returns the absolute filename of a template source.
+        *
+        * @param       string          $templateName
+        * @param       integer         $packageID
+        * @return      string          $path
+        */
+       public function getSourceFilename($templateName, $packageID) {
+               return $this->getPath($this->templatePaths[$packageID], $templateName);
+       }
+       
+       /**
+        * Returns path if template was found.
+        * 
+        * @param       string          $templatePath
+        * @param       string          $templateName
+        * @return      string
+        */
+       protected function getPath($templatePath, $templateName) {
+               $templateGroupID = $this->templateGroupID;
+               
+               while ($templateGroupID != 0) {
+                       $templateGroup = $this->templateGroupCache[$templateGroupID];
+                       
+                       $path = $templatePath.$templateGroup['templateGroupFolderName'].$templateName.'.tpl';
+                       if (file_exists($path)) {
+                               return $path;
+                       }
+                       
+                       $templateGroupID = $templateGroup['parentTemplateGroupID'];
+               }
+               
+               // use default template
+               $path = $templatePath.$templateName.'.tpl';
+               
+               if (file_exists($path)) {
+                       return $path;
+               }
+               
+               return '';
+       }
+       
+       /**
+        * Returns the absolute filename of a compiled template.
+        *
+        * @param       string          $templateName
+        * @return      string          $path
+        */
+       public function getCompiledFilename($templateName, $packageID) {
+               return $this->compileDir.$packageID.'_'.$this->templateGroupID.'_'.$this->languageID.'_'.$templateName.'.php';
+       }
+       
+       /**
+        * Checks wheater a template is already compiled or not.
+        *
+        * @param       string          $templateName
+        * @param       string          $sourceFilename
+        * @param       string          $compiledFilename
+        * @return      boolean         $isCompiled
+        */
+       protected function isCompiled($templateName, $sourceFilename, $compiledFilename) {
+               if ($this->forceCompile || !file_exists($compiledFilename)) {
+                       return false;
+               }
+               else {
+                       $sourceMTime = @filemtime($sourceFilename);
+                       $compileMTime = @filemtime($compiledFilename);
+                       
+                       if ($sourceMTime >= $compileMTime) {
+                               return false;
+                       }
+                       else {
+                               // check for template listeners
+                               if ($this->hasTemplateListeners($templateName)) {
+                                       $this->loadTemplateListenerCode($templateName);
+                                       
+                                       $templateListenerCache = WCF_DIR.'cache/templateListener/'.PACKAGE_ID.'-'.$this->environment.'-'.$templateName.'.php';
+                                       $templateListenerCacheMTime = @filemtime($templateListenerCache);
+                                       
+                                       return !($sourceMTime >= $templateListenerCacheMTime);
+                               }
+                               
+                               return true;
+                       }
+               }
+       }
+       
+       /**
+        * Compiles a template.
+        *
+        * @param       string          $templateName
+        * @param       string          $sourceFilename
+        * @param       string          $compiledFilename
+        */
+       protected function compileTemplate($templateName, $sourceFilename, $compiledFilename) {
+               // get compiler
+               if (!($this->compilerObj instanceof TemplateCompiler)) {
+                       $this->compilerObj = $this->getCompiler();
+               }
+               
+               // get source
+               $sourceContent = $this->getSourceContent($sourceFilename);
+               
+               // compile template
+               $this->compilerObj->compile($templateName, $sourceContent, $compiledFilename);
+       }
+       
+       /**
+        * Returns a new template compiler object.
+        * 
+        * @return      TemplateCompiler
+        */
+       protected function getCompiler() {
+               return new TemplateCompiler($this);
+       }
+       
+       /**
+        * Reads the content of a template file.
+        *
+        * @param       string          $sourceFilename
+        * @return      string          $sourceContent
+        */
+       public function getSourceContent($sourceFilename) {
+               $sourceContent = '';
+               if (!file_exists($sourceFilename) || (($sourceContent = @file_get_contents($sourceFilename)) === false)) {
+                       throw new SystemException("Could not open template '$sourceFilename' for reading", 12005);
+               }
+               else {
+                       return $sourceContent;
+               }
+       }
+       
+       /**
+        * Returns the class name of a plugin.
+        *
+        * @param       string          $type
+        * @param       string          $tag
+        * @return      string                          class name
+        */
+       public function getPluginClassName($type, $tag) {
+               return $this->pluginNamespace.'TemplatePlugin'.StringUtil::firstCharToUpperCase(StringUtil::toLowerCase($type)).StringUtil::firstCharToUpperCase(StringUtil::toLowerCase($tag));
+       }
+       
+       /**
+        * Returns the output of a template.
+        *
+        * @param       string          $templateName
+        * @param       integer         $packageID
+        * @return      string          output
+        */
+       public function fetch($templateName, $packageID = PACKAGE_ID) {
+               ob_start();
+               $this->display($templateName, $packageID, false);
+               $output = ob_get_contents();
+               ob_end_clean();
+
+               return $output;
+       }
+       
+       /**
+        * Executes a compiled template scripting source and returns the result.
+        *
+        * @param       string          $compiledSource
+        * @return      string          result
+        */
+       public function fetchString($compiledSource) {
+               ob_start();
+               eval('?>'.$compiledSource);
+               $output = ob_get_contents();
+               ob_end_clean();
+
+               return $output;
+       }
+       
+       /**
+        * Deletes all compiled templates.
+        * 
+        * @param       string          $compileDir
+        */
+       public static function deleteCompiledTemplates($compileDir = '') {
+               if (empty($compileDir)) $compileDir = WCF_DIR.'templates/compiled/';
+               
+               // delete compiled templates
+               $matches = glob($compileDir . '*_*_*.php');
+               if (is_array($matches)) {
+                       foreach ($matches as $match) @unlink($match);
+               }
+       }
+       
+       /**
+        * Returns an array with all prefilters.
+        *
+        * @return      array
+        */
+       public function getPrefilters() {
+               return $this->prefilters;
+       }
+       
+       /**
+        * Returns the active template group id.
+        * 
+        * @return      integer
+        */
+       public function getTemplateGroupID() {
+               return $this->templateGroupID;
+       }
+       
+       /**
+        * Sets the active template group id.
+        * 
+        * @param       integer         $templateGroupID
+        */
+       public function setTemplateGroupID($templateGroupID) {
+               if ($templateGroupID && !isset($this->templateGroupCache[$templateGroupID])) {
+                       $templateGroupID = 0;
+               }
+               
+               $this->templateGroupID = $templateGroupID;
+       }
+       
+       /**
+        * Loads cached template group information.
+        */
+       protected function loadTemplateGroupCache() {
+               CacheHandler::getInstance()->addResource('templateGroups', WCF_DIR.'cache/cache.templateGroups.php', 'wcf\system\cache\CacheBuilderTemplateGroup');
+               $this->templateGroupCache = CacheHandler::getInstance()->get('templateGroups');
+       }
+       
+       /**
+        * Registers prefilters.
+        *
+        * @param       array           $prefilters
+        */
+       public function registerPrefilter(array $prefilters) {
+               foreach ($prefilters as $name) {
+                       $this->prefilters[$name] = $name;
+               }
+       }
+       
+       /**
+        * Sets the dir for the compiled templates.
+        *
+        * @param       string          $compileDir
+        */
+       public function setCompileDir($compileDir) {
+               if (!is_dir($compileDir)) {
+                       throw new SystemException("'".$compileDir."' is not a valid dir", 11014);
+               }
+               
+               $this->compileDir = $compileDir;
+       }
+       
+       /**
+        * Includes a template.
+        *
+        * @param       string          $templateName
+        * @param       array           $variables
+        * @param       boolean         $sandbox        enables execution in sandbox
+        */
+       protected function includeTemplate($templateName, array $variables = array(), $sandbox = true, $packageID = PACKAGE_ID) {
+               // add new template variables
+               if ($sandbox) {
+                       $templateVars = $this->v;
+               }
+
+               if (count($variables)) {
+                       $this->v = array_merge($this->v, $variables);
+               }
+               
+               $this->display($templateName, $packageID, false);
+               
+               if ($sandbox) {
+                       $this->v = $templateVars;
+               }
+       }
+       
+       /**
+        * Returns the value of a template variable.
+        * 
+        * @param       string          $varname
+        * @return      mixed
+        */
+       public function get($varname) {
+               if (isset($this->v[$varname])) {
+                       return $this->v[$varname];
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Loads all available template listeners.
+        */
+       protected function loadTemplateListeners() {
+               $cacheName = 'templateListener-'.PACKAGE_ID.'-'.$this->environment;
+               CacheHandler::getInstance()->addResource(
+                       $cacheName,
+                       WCF_DIR.'cache/cache.'.$cacheName.'.php',
+                       'wcf\system\cache\CacheBuilderTemplateListener'
+               );
+               
+               $this->templateListeners = CacheHandler::getInstance()->get($cacheName);
+       }
+       
+       /**
+        * Returns true if requested template has assigned template listeners.
+        * 
+        * @param       string          $templateName
+        * @return      boolean
+        */
+       public function hasTemplateListeners($templateName) {
+               if (isset($this->templateListeners[$templateName])) {
+                       return true;
+               }
+               
+               return false;
+       }
+       
+       /**
+        * Loads template code for specified template.
+        * 
+        * @param       string          $templateName
+        */
+       protected function loadTemplateListenerCode($templateName) {
+               // cache was already loaded
+               if (count($this->templateListeners[$templateName])) return;
+               
+               $cacheName = PACKAGE_ID.'-'.$this->environment.'-'.$templateName;
+               CacheHandler::getInstance()->addResource(
+                       $cacheName,
+                       WCF_DIR.'cache/templateListener/'.$cacheName.'.php',
+                       'wcf\system\cache\CacheBuilderTemplateListenerCode'
+               );
+               
+               $this->templateListeners[$templateName] = CacheHandler::getInstance()->get($cacheName);
+       }
+       
+       /**
+        * Returns template listener's code.
+        * 
+        * @param       string          $templateName
+        * @param       string          $eventName
+        * @return      string
+        */
+       public function getTemplateListenerCode($templateName, $eventName) {
+               if (isset($this->templateListeners[$templateName][$eventName])) {
+                       return implode("\n", $this->templateListeners[$templateName][$eventName]);
+               }
+               
+               return '';
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/template/TemplatePluginBlock.class.php b/wcfsetup/install/files/lib/system/template/TemplatePluginBlock.class.php
new file mode 100644 (file)
index 0000000..2b2f157
--- /dev/null
@@ -0,0 +1,41 @@
+<?php\r
+namespace wcf\system\template;\r
+\r
+/**\r
+ * Block functions encloses a template block and operate on the contents of this block.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+interface TemplatePluginBlock {\r
+       /**\r
+        * Executes this template block.\r
+        * \r
+        * @param       array                   $tagArgs\r
+        * @param       string                  $blockContent\r
+        * @param       TemplateEngine          $tplObj\r
+        * @return      string                  output\r
+        */\r
+       public function execute($tagArgs, $blockContent, TemplateEngine $tplObj);\r
+       \r
+       /**\r
+        * Initialises this template block.\r
+        * \r
+        * @param       array                   $tagArgs\r
+        * @param       TemplateEngine          $tplObj\r
+        */\r
+       public function init($tagArgs, TemplateEngine $tplObj);\r
+       \r
+       /**\r
+        * This function is called before every execution of this block function.\r
+        * \r
+        * @param       TemplateEngine          $tplObj\r
+        * @return      boolean\r
+        */\r
+       public function next(TemplateEngine $tplObj);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplatePluginCompiler.class.php b/wcfsetup/install/files/lib/system/template/TemplatePluginCompiler.class.php
new file mode 100644 (file)
index 0000000..2611a5d
--- /dev/null
@@ -0,0 +1,32 @@
+<?php\r
+namespace wcf\system\template;\r
+\r
+/**\r
+ * Compiler functions are called during the compilation of a template.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+interface TemplatePluginCompiler {\r
+       /**\r
+        * Executes the start tag of this compiler function.\r
+        * \r
+        * @param       array                           $tagArgs                \r
+        * @param       TemplateScriptingCompiler       $compiler\r
+        * @return      string                                          php code        \r
+        */\r
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler);\r
+       \r
+       /**\r
+        * Executes the end tag of this compiler function.\r
+        * \r
+        * @param       TemplateScriptingCompiler       $compiler       \r
+        * @return      string                                          php code        \r
+        */\r
+       public function executeEnd(TemplateScriptingCompiler $tplObj);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplatePluginFunction.class.php b/wcfsetup/install/files/lib/system/template/TemplatePluginFunction.class.php
new file mode 100644 (file)
index 0000000..8180f18
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+namespace wcf\system\template;\r
+\r
+/**\r
+ * Template functions are identical to template blocks, but they have no closing tag.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+interface TemplatePluginFunction {\r
+       /**\r
+        * Executes this template function.\r
+        * \r
+        * @param       array                   $tagArgs\r
+        * @param       TemplateEngine          $tplObj\r
+        * @return      string                          output\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplatePluginModifier.class.php b/wcfsetup/install/files/lib/system/template/TemplatePluginModifier.class.php
new file mode 100644 (file)
index 0000000..82069ac
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+namespace wcf\system\template;\r
+\r
+/**\r
+ * Modifiers are functions that are applied to a variable in the template \r
+ * before it is displayed or used in some other context.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+interface TemplatePluginModifier {\r
+       /**\r
+        * Executes this modifier.\r
+        * \r
+        * @param       array                   $tagArgs                \r
+        * @param       TemplateEngine          $tplObj\r
+        * @return      string                  output          \r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplatePluginPrefilter.class.php b/wcfsetup/install/files/lib/system/template/TemplatePluginPrefilter.class.php
new file mode 100644 (file)
index 0000000..08dce30
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+namespace wcf\system\template;\r
+\r
+/**\r
+ * Prefilters are used to process the source of the template immediately before compilation.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template\r
+ * @category   Community Framework\r
+ */\r
+interface TemplatePluginPrefilter {\r
+       /**\r
+        * Executes this prefilter.\r
+        * \r
+        * @param       string                          $templateName\r
+        * @param       string                          $sourceContent  \r
+        * @param       TemplateScriptingCompiler       $compiler       \r
+        * @return      string                          $sourceContent\r
+        */\r
+       public function execute($templateName, $sourceContent, TemplateScriptingCompiler $compiler);\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/TemplateScriptingCompiler.class.php b/wcfsetup/install/files/lib/system/template/TemplateScriptingCompiler.class.php
new file mode 100644 (file)
index 0000000..97f9b3a
--- /dev/null
@@ -0,0 +1,1422 @@
+<?php
+namespace wcf\system\template;
+use wcf\system\exception\SystemException;
+use wcf\util\StringStack;
+use wcf\util\StringUtil;
+
+/**
+ * TemplateScriptingCompiler compiles template source in valid php code.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template
+ * @category   Community Framework
+ */
+class TemplateScriptingCompiler {
+       /**
+        * template object
+        * 
+        * @var         TemplateEngine
+        */
+       protected       $template;
+       
+       /**
+        * PHP functions that can be used in the modifier syntax and are unknown to the function_exists PHP method.
+        * 
+        * @var array
+        */
+       protected       $unknownPHPFunctions = array('isset', 'unset', 'empty');
+       
+       /**
+        * PHP functions that can not be used in the modifier syntax.
+        * 
+        * @var array
+        */
+       protected       $disabledPHPFunctions = array(
+                               'system', 'exec', 'passthru', 'shell_exec', // command line execution
+                               'include', 'require', 'include_once', 'require_once', // includes
+                               'eval', 'virtual', 'call_user_func_array', 'call_user_func', 'assert' // code execution
+                       );
+       
+       protected       $variableOperatorPattern, $conditionOperatorPattern, $escapedPattern, $validVarnamePattern,
+                       $constantPattern, $doubleQuotePattern, $singleQuotePattern, $quotePattern, $numericPattern,
+                       $simpleVarPattern, $outputPattern;
+       
+       protected       $currentIdentifier, $currentLineNo;
+       
+       protected       $modifiers = array(), $autoloadPlugins = array(), $tagStack = array(),
+                       $compilerPlugins = array(), $captureStack = array();
+       
+       protected       $leftDelimiter = '{', $rightDelimiter = '}';
+       protected       $ldq, $rdq;
+       
+       /**
+        * Creates a new TemplateScriptingCompiler.
+        * 
+        * @param       TemplateEngine          $template
+        */
+       public function __construct(TemplateEngine $template) {
+               $this->template = $template;
+               
+               // quote left and right delimiter for use in regular expressions
+               $this->ldq = preg_quote($this->leftDelimiter, '~').'(?=\S)';
+               $this->rdq = '(?<=\S)'.preg_quote($this->rightDelimiter, '~');
+               
+               // build regular expressions
+               $this->buildPattern();
+       }
+       
+       /**
+        * Compiles the source of a template.
+        * 
+        * @param       string          $identifier
+        * @param       string          $sourceContent
+        * @return      string
+        */
+       public function compileString($identifier, $sourceContent) {
+               // reset vars
+               $this->autoloadPlugins = $this->tagStack = $this->stringStack = $this->literalStack = array();
+               $this->currentIdentifier = $identifier;
+               $this->currentLineNo = 1;
+               
+               // apply prefilters
+               $sourceContent = $this->applyPrefilters($identifier, $sourceContent);
+               
+               // replace all {literal} Tags with unique hash values
+               $sourceContent = $this->replaceLiterals($sourceContent);
+               
+               // handle <?php tags
+               $sourceContent = $this->replacePHPTags($sourceContent);
+               
+               // remove comments
+               $sourceContent = $this->removeComments($sourceContent);
+               
+               // match all template tags
+               $matches = array();
+               preg_match_all("~".$this->ldq."(.*?)".$this->rdq."~s", $sourceContent, $matches);
+               $templateTags = $matches[1];
+               
+               // Split content by template tags to obtain non-template content
+               $textBlocks = preg_split("~".$this->ldq.".*?".$this->rdq."~s", $sourceContent);
+               
+               // compile the template tags into php-code
+               $compiledTags = array();
+               for ($i = 0, $j = count($templateTags); $i < $j; $i++) {
+                       $this->currentLineNo += StringUtil::countSubstring($textBlocks[$i], "\n");
+                       $compiledTags[] = $this->compileTag($templateTags[$i]);
+                       $this->currentLineNo += StringUtil::countSubstring($templateTags[$i], "\n");
+               }
+               
+               // throw error messages for unclosed tags
+               if (count($this->tagStack) > 0) {
+                       foreach ($this->tagStack as $tagStack) {
+                               throw new SystemException($this->formatSyntaxError('unclosed tag {'.$tagStack[0].'}', $this->currentIdentifier, $tagStack[1]), 12002);
+                       }
+                       return false;
+               }
+               
+               $compiledContent = '';
+               // Interleave the compiled contents and text blocks to get the final result.
+               for ($i = 0, $j = count($compiledTags); $i < $j; $i++) {
+                       if ($compiledTags[$i] == '') {
+                               // tag result empty, remove first newline from following text block
+                               $textBlocks[$i + 1] = preg_replace('%^(\r\n|\r|\n)%', '', $textBlocks[$i + 1]);
+                       }
+                       $compiledContent .= $textBlocks[$i].$compiledTags[$i];
+               }
+               $compiledContent .= $textBlocks[$i];
+               $compiledContent = chop($compiledContent);
+               
+               // INSERT POSTFILTERS HERE!
+               
+               // reinsert {literal} Tags
+               $compiledContent = $this->reinsertLiterals($compiledContent);
+               
+               // include Plugins
+               $compiledAutoloadPlugins = '';
+               if (count($this->autoloadPlugins) > 0) {
+                       $compiledAutoloadPlugins = "<?php\n";
+                       foreach ($this->autoloadPlugins as $className/* => $fileName*/) {
+                               $compiledAutoloadPlugins .= "use ".$className.";\n";
+                               $compiledAutoloadPlugins .= "if (!isset(\$this->pluginObjects['$className'])) {\n";
+                               /*
+                               if (WCF_DIR != '' && strpos($fileName, WCF_DIR) === 0) {
+                                       $compiledAutoloadPlugins .= "require_once(WCF_DIR.'".StringUtil::replace(WCF_DIR, '', $fileName)."');\n";
+                               }
+                               else {
+                                       $compiledAutoloadPlugins .= "require_once('".$fileName."');\n";
+                               }
+                               */
+                               $compiledAutoloadPlugins .= "\$this->pluginObjects['$className'] = new $className;\n";
+                               $compiledAutoloadPlugins .= "}\n";
+                       }
+                       $compiledAutoloadPlugins .= "?>";
+               }
+               
+               return $compiledAutoloadPlugins.$compiledContent;
+       }
+       
+       /**
+        * Compiles a template tag.
+        * 
+        * @param       string          $tag
+        */
+       protected function compileTag($tag) {
+               if (preg_match('~^'.$this->outputPattern.'~s', $tag)) {
+                       // variable output
+                       return $this->compileOutputTag($tag);
+               }
+               
+               $match = array();
+               // replace 'else if' with 'elseif'
+               $tag = preg_replace('~^else\s+if(?=\s)~i', 'elseif', $tag);
+               
+               if (preg_match('~^(/?\w+)~', $tag, $match)) {
+                       // build in function or plugin
+                       $tagCommand = $match[1];
+                       $tagArgs = StringUtil::substring($tag, StringUtil::length($tagCommand));
+                       
+                       switch ($tagCommand) {
+                               case 'if':
+                                       $this->pushTag('if');
+                                       return $this->compileIfTag($tagArgs);
+                                       
+                               case 'elseif':
+                                       list($openTag) = end($this->tagStack);
+                                       if ($openTag != 'if' && $openTag != 'elseif') {
+                                               throw new SystemException($this->formatSyntaxError('unxepected {elseif}', $this->currentIdentifier, $this->currentLineNo));
+                                       }
+                                       else if ($openTag == 'if') {
+                                               $this->pushTag('elseif');
+                                       }
+                                       return $this->compileIfTag($tagArgs, true);
+                                       
+                               case 'else':
+                                       list($openTag) = end($this->tagStack);
+                                       if ($openTag != 'if' && $openTag != 'elseif') {
+                                               throw new SystemException($this->formatSyntaxError('unexpected {else}', $this->currentIdentifier, $this->currentLineNo));
+                                       }
+                                       else {
+                                               $this->pushTag('else');
+                                               return '<?php } else { ?>';
+                                       }
+                                       
+                               case '/if':
+                                       list($openTag) = end($this->tagStack);
+                                       if ($openTag != 'if' && $openTag != 'elseif' && $openTag != 'else') {
+                                               throw new SystemException($this->formatSyntaxError('unexpected {/if}', $this->currentIdentifier, $this->currentLineNo));
+                                       }
+                                       else {
+                                               $this->popTag('if');
+                                       }
+                                       return '<?php } ?>';
+                               
+                               case 'include':
+                                       return $this->compileIncludeTag($tagArgs);
+                                       
+                               case 'foreach':
+                                       $this->pushTag('foreach');
+                                       return $this->compileForeachTag($tagArgs);
+
+                               case 'foreachelse':
+                                       list($openTag) = end($this->tagStack);
+                                       if ($openTag != 'foreach') {
+                                               throw new SystemException($this->formatSyntaxError('unexpected {foreachelse}', $this->currentIdentifier, $this->currentLineNo));
+                                       }
+                                       else {
+                                               $this->pushTag('foreachelse');
+                                               return '<?php } } else { { ?>';
+                                       }
+                                       
+                               case '/foreach':
+                                       $this->popTag('foreach');
+                                       return "<?php } } ?>";
+                                       
+                               case 'section':
+                                       $this->pushTag('section');
+                                       return $this->compileSectionTag($tagArgs);
+                       
+                               case 'sectionelse':
+                                       list($openTag) = end($this->tagStack);
+                                       if ($openTag != 'section') {
+                                               throw new SystemException($this->formatSyntaxError('unexpected {sectionelse}', $this->currentIdentifier, $this->currentLineNo));
+                                       }
+                                       else {
+                                               $this->pushTag('sectionelse');
+                                               return '<?php } } else { { ?>';
+                                       }
+                                       
+                               case '/section':
+                                       $this->popTag('section');
+                                       return "<?php } } ?>";
+                                       
+                               case 'capture':
+                                       $this->pushTag('capture');
+                                       return $this->compileCaptureTag(true, $tagArgs);
+                       
+                               case '/capture':
+                                       $this->popTag('capture');
+                                       return $this->compileCaptureTag(false);
+                                       
+                               case 'ldelim':
+                                       return $this->leftDelimiter;
+                                       
+                               case 'rdelim':
+                                       return $this->rightDelimiter;
+                               
+                               default:
+                                       // 1) compiler functions first
+                                       if ($phpCode = $this->compileCompilerPlugin($tagCommand, $tagArgs)) {
+                                               return $phpCode;
+                                       }
+                                       // 2) block functions
+                                       if ($phpCode = $this->compileBlockPlugin($tagCommand, $tagArgs)) {
+                                               return $phpCode;
+                                       }
+                                       // 3) functions
+                                       if ($phpCode = $this->compileFunctionPlugin($tagCommand, $tagArgs)) {
+                                               return $phpCode;
+                                       }
+                       }
+               }
+               
+               throw new SystemException($this->formatSyntaxError('unknown tag {'.$tag.'}', $this->currentIdentifier, $this->currentLineNo), 12003);
+       }
+       
+       /**
+        * Compiles a function plugin.
+        *
+        * @param       string          $tagCommand
+        * @param       string          $tagArgs
+        * @return      mixed                           false, if the plugin does not exist
+        *                                              otherwise the php output of the plugin
+        */
+       protected function compileFunctionPlugin($tagCommand, $tagArgs) {
+               $className = $this->template->getPluginClassName('function', $tagCommand);
+               if (!class_exists($className)) {
+                       return false;
+               }
+               $this->autoloadPlugins[$className] = $className;
+               
+               $tagArgs = $this->makeArgString($this->parseTagArgs($tagArgs, $tagCommand));
+
+               return "<?php echo \$this->pluginObjects['".$className."']->execute(array(".$tagArgs."), \$this); ?>";
+       }
+       
+       /**
+        * Compiles a block plugin.
+        *
+        * @param       string          $tagCommand
+        * @param       string          $tagArgs
+        * @return      mixed                           false, if the plugin does not exist
+        *                                              otherwise the php output of the plugin
+        */
+       protected function compileBlockPlugin($tagCommand, $tagArgs) {
+               // check wheater this is the start ({block}) or the
+               // end tag ({/block})
+               if (substr($tagCommand, 0, 1) == '/') {
+                       $tagCommand = substr($tagCommand, 1);
+                       $startTag = false;
+               }
+               else {
+                       $startTag = true;
+               }
+
+               $className = $this->template->getPluginClassName('block', $tagCommand);
+               if (!class_exists($className)) {
+                       return false;
+               }
+               $this->autoloadPlugins[$className] = $className;
+               
+               if ($startTag) {
+                       $this->pushTag($tagCommand);
+
+                       $tagArgs = $this->makeArgString($this->parseTagArgs($tagArgs, $tagCommand));
+
+                       $phpCode = "<?php \$this->tagStack[] = array('".$tagCommand."', array(".$tagArgs."));\n";
+                       $phpCode .= "\$this->pluginObjects['".$className."']->init(\$this->tagStack[count(\$this->tagStack) - 1][1], \$this);\n";
+                       $phpCode .= "while (\$this->pluginObjects['".$className."']->next(\$this)) { ob_start(); ?>";
+               }
+               else {
+                       $this->popTag($tagCommand);
+                       $phpCode = "<?php \$blockContent = ob_get_contents();\n";
+                       $phpCode .= "ob_end_clean();\n";
+                       $phpCode .= "echo \$this->pluginObjects['".$className."']->execute(\$this->tagStack[count(\$this->tagStack) - 1][1], \$blockContent, \$this); }\n";
+                       $phpCode .= "array_pop(\$this->tagStack);\n";
+                       $phpCode .= "unset(\$blockContent, \$blockRepeat); ?>";
+               }
+               
+               return $phpCode;
+       }
+       
+       
+       /**
+        * Compiles a compiler function/block.
+        *
+        * @param       string          $tagCommand
+        * @param       string          $tagArgs
+        * @return      mixed                           false, if the plugin does not exist
+        *                                              otherwise the php output of the plugin
+        */
+       protected function compileCompilerPlugin($tagCommand, $tagArgs) {
+               // check wheater this is the start ({block}) or the
+               // end tag ({/block})
+               if (substr($tagCommand, 0, 1) == '/') {
+                       $tagCommand = substr($tagCommand, 1);
+                       $startTag = false;
+               }
+               else {
+                       $startTag = true;
+               }
+
+               $className = $this->template->getPluginClassName('compiler', $tagCommand);
+               // if necessary load plugin from plugin-dir
+               if (!isset($this->compilerPlugins[$className])) {
+                       if (!class_exists($className)) {
+                               return false;
+                       }
+                       
+                       $this->compilerPlugins[$className] = new $className();
+                       
+                       if (!($this->compilerPlugins[$className] instanceof TemplatePluginCompiler)) {
+                               throw new SystemException($this->formatSyntaxError("Compiler plugin '".$tagCommand."' does not implement the interface 'TemplatePluginCompiler'", $this->currentIdentifier), 11010);
+                       }
+               }
+               
+               // execute plugin
+               if ($startTag) {
+                       $tagArgs = $this->parseTagArgs($tagArgs, $tagCommand);
+                       $phpCode = $this->compilerPlugins[$className]->executeStart($tagArgs, $this);
+               }
+               else {
+                       $phpCode = $this->compilerPlugins[$className]->executeEnd($this);
+               }
+               
+               return $phpCode;
+       }
+
+       /**
+        * Compiles a capture tag.
+        *
+        * @param       boolean         $startTag
+        * @param       string          $captureTag
+        * @return      string                          phpCode
+        */
+       protected function compileCaptureTag($startTag, $captureTag = null) {
+               if ($startTag) {
+                       $append = false;
+                       $args = $this->parseTagArgs($captureTag, 'capture');
+                       
+                       if (!isset($args['name'])) {
+                               $args['name'] = "'default'";
+                       }
+                       
+                       if (!isset($args['assign'])) {
+                               if (isset($args['append'])) {
+                                       $args['assign'] = $args['append'];
+                                       $append = true;
+                               }
+                               else {
+                                       $args['assign'] = '';
+                               }
+                       }
+                       
+                       $this->captureStack[] = array('name' => $args['name'], 'variable' => $args['assign'], 'append' => $append);
+                       return '<?php ob_start(); ?>';
+               }
+               else {
+                       $capture = array_pop($this->captureStack);
+                       $phpCode = "<?php\n";
+                       $phpCode .= "\$this->v['tpl']['capture'][".$capture['name']."] = ob_get_contents();\nob_end_clean();\n";
+                       if (!empty($capture['variable'])) $phpCode .= "\$this->".($capture['append'] ? 'append' : 'assign')."(".$capture['variable'].", \$this->v['tpl']['capture'][".$capture['name']."]);\n";
+                       $phpCode .= "?>";
+                       return $phpCode;
+               }
+       }
+       
+       /**
+        * Compiles a section tag.
+        *
+        * @param       string          $sectionTag
+        * @return      string                          phpCode
+        */
+       protected function compileSectionTag($sectionTag) {
+               $args = $this->parseTagArgs($sectionTag, 'section');
+
+               // check arguments
+               if (!isset($args['loop'])) {
+                       throw new SystemException($this->formatSyntaxError("missing 'loop' attribute in section tag", $this->currentIdentifier, $this->currentLineNo), 12001);
+               }
+               if (!isset($args['name'])) {
+                       throw new SystemException($this->formatSyntaxError("missing 'name' attribute in section tag", $this->currentIdentifier, $this->currentLineNo), 12001);
+               }
+               if (!isset($args['show'])) {
+                       $args['show'] = true;
+               }
+               
+               $sectionProp = "\$this->v['tpl']['section'][".$args['name']."]";
+
+               $phpCode = "<?php\n";
+               $phpCode .= "if (".$args['loop'].") {\n";
+               $phpCode .= $sectionProp." = array();\n";
+               $phpCode .= $sectionProp."['loop'] = (is_array(".$args['loop'].") ? count(".$args['loop'].") : max(0, (int)".$args['loop']."));\n";
+               $phpCode .= $sectionProp."['show'] = ".$args['show'].";\n";
+               if (!isset($args['step'])) {
+                       $phpCode .= $sectionProp."['step'] = 1;\n";
+               }
+               else {
+                       $phpCode .= $sectionProp."['step'] = ".$args['step'].";\n";
+               }
+               if (!isset($args['max'])) {
+                       $phpCode .= $sectionProp."['max'] = ".$sectionProp."['loop'];\n";
+               }
+               else {
+                       $phpCode .= $sectionProp."['max'] = (".$args['max']." < 0 ? ".$sectionProp."['loop'] : ".$args['max'].");\n";
+               }
+               if (!isset($args['start'])) {
+                       $phpCode .= $sectionProp."['start'] = (".$sectionProp."['step'] > 0 ? 0 : ".$sectionProp."['loop'] - 1);\n";
+               }
+               else {
+                       $phpCode .= $sectionProp."['start'] = ".$args['start'].";\n";
+                       $phpCode .= "if (".$sectionProp."['start'] < 0) {\n";
+                       $phpCode .= $sectionProp."['start'] = max(".$sectionProp."['step'] > 0 ? 0 : -1, ".$sectionProp."['loop'] + ".$sectionProp."['start']);\n}\n";
+                       $phpCode .= "else {\n";
+                       $phpCode .= $sectionProp."['start'] = min(".$sectionProp."['start'], ".$sectionProp."['step'] > 0 ? ".$sectionProp."['loop'] : ".$sectionProp."['loop'] - 1);\n}\n";
+               }
+               
+               if (!isset($args['start']) && !isset($args['step']) && !isset($args['max'])) {
+                       $phpCode .= $sectionProp."['total'] = ".$sectionProp."['loop'];\n";
+               } else {
+                       $phpCode .= $sectionProp."['total'] = min(ceil((".$sectionProp."['step'] > 0 ? ".$sectionProp."['loop'] - ".$sectionProp."['start'] : ".$sectionProp."['start'] + 1) / abs(".$sectionProp."['step'])), ".$sectionProp."['max']);\n";
+               }
+               $phpCode .= "if (".$sectionProp."['total'] == 0) ".$sectionProp."['show'] = false;\n";
+               $phpCode .= "} else {\n";
+               $phpCode .= "".$sectionProp."['total'] = 0;\n";
+               $phpCode .= "".$sectionProp."['show'] = false;}\n";
+
+               $phpCode .= "if (".$sectionProp."['show']) {\n";
+               $phpCode .= "for (".$sectionProp."['index'] = ".$sectionProp."['start'], ".$sectionProp."['rowNumber'] = 1;\n";
+               $phpCode .= $sectionProp."['rowNumber'] <= ".$sectionProp."['total'];\n";
+               $phpCode .= $sectionProp."['index'] += ".$sectionProp."['step'], ".$sectionProp."['rowNumber']++) {\n";
+               $phpCode .= "\$this->v[".$args['name']."] = ".$sectionProp."['index'];\n";
+               $phpCode .= $sectionProp."['previousIndex'] = ".$sectionProp."['index'] - ".$sectionProp."['step'];\n";
+               $phpCode .= $sectionProp."['nextIndex'] = ".$sectionProp."['index'] + ".$sectionProp."['step'];\n";
+               $phpCode .= $sectionProp."['first']      = (".$sectionProp."['rowNumber'] == 1);\n";
+               $phpCode .= $sectionProp."['last']       = (".$sectionProp."['rowNumber'] == ".$sectionProp."['total']);\n";
+               $phpCode .= "?>";
+
+               return $phpCode;
+       }
+       
+       /**
+        * Compiles a foreach tag.
+        *
+        * @param       string          $foreachTag
+        * @return      string                          phpCode
+        */
+       protected function compileForeachTag($foreachTag) {
+               $args = $this->parseTagArgs($foreachTag, 'foreach');
+
+               // check arguments
+               if (!isset($args['from'])) {
+                       throw new SystemException($this->formatSyntaxError("missing 'from' attribute in foreach tag", $this->currentIdentifier, $this->currentLineNo), 12001);
+               }
+               if (!isset($args['item'])) {
+                       throw new SystemException($this->formatSyntaxError("missing 'item' attribute in foreach tag", $this->currentIdentifier, $this->currentLineNo), 12001);
+               }
+
+               $foreachProp = '';
+               if (isset($args['name'])) {
+                       $foreachProp = "\$this->v['tpl']['foreach'][".$args['name']."]";
+               }
+               
+               $phpCode = "<?php\n";
+               if (!empty($foreachProp)) {
+                       $phpCode .= $foreachProp."['total'] = count(".$args['from'].");\n";
+                       $phpCode .= $foreachProp."['show'] = (".$foreachProp."['total'] > 0 ? true : false);\n";
+                       $phpCode .= $foreachProp."['iteration'] = 0;\n";
+               }
+               $phpCode .= "if (count(".$args['from'].") > 0) {\n";
+               
+               if (isset($args['key'])) {
+                       $phpCode .= "foreach (".$args['from']." as ".(StringUtil::substring($args['key'], 0, 1) != '$' ? "\$this->v[".$args['key']."]" : $args['key'])." => ".(StringUtil::substring($args['item'], 0, 1) != '$' ? "\$this->v[".$args['item']."]" : $args['item']).") {\n";
+               }
+               else {
+                       $phpCode .= "foreach (".$args['from']." as ".(StringUtil::substring($args['item'], 0, 1) != '$' ? "\$this->v[".$args['item']."]" : $args['item']).") {\n";
+               }
+               
+               if (!empty($foreachProp)) {
+                       $phpCode .= $foreachProp."['first'] = (".$foreachProp."['iteration'] == 0 ? true : false);\n";
+                       $phpCode .= $foreachProp."['last'] = ((".$foreachProp."['iteration'] == ".$foreachProp."['total'] - 1) ? true : false);\n";
+                       $phpCode .= $foreachProp."['iteration']++;\n";
+               }
+               
+               $phpCode .= "?>";
+               return $phpCode;
+       }
+       
+       /**
+        * Compiles an include tag.
+        *
+        * @param       string          $includeTag
+        * @return      string                          phpCode
+        */
+       protected function compileIncludeTag($includeTag) {
+               $args = $this->parseTagArgs($includeTag, 'include');
+               $append = false;
+               
+               // check arguments
+               if (!isset($args['file'])) {
+                       throw new SystemException($this->formatSyntaxError("missing 'file' attribute in include tag", $this->currentIdentifier, $this->currentLineNo), 12001);
+               }
+
+               // get filename
+               $file = $args['file'];
+               unset($args['file']);
+
+               // special parameters
+               $assignVar = false;
+               if (isset($args['assign'])) {
+                       $assignVar = $args['assign'];
+                       unset($args['assign']);
+               }
+               
+               if (isset($args['append'])) {
+                       $assignVar = $args['append'];
+                       $append = true;
+                       unset($args['append']);
+               }
+               
+               $sandbox = true;
+               if (isset($args['sandbox'])) {
+                       $sandbox = $args['sandbox'];
+                       unset($args['sandbox']);
+               }
+               
+               $once = false;
+               if (isset($args['once'])) {
+                       $once = $args['once'];
+                       unset($args['once']);
+               }
+               
+               // make argument string
+               $argString = $this->makeArgString($args);
+               
+               // build phpCode
+               $phpCode = "<?php\n";
+               if ($once) $phpCode .= "if (!isset(\$this->v['tpl']['includedTemplates'][".$file."])) {\n";
+               $hash = StringUtil::getRandomID();
+               $phpCode .= "\$outerTemplateName".$hash." = \$this->v['tpl']['template'];\n";
+               
+               if ($assignVar !== false) {
+                       $phpCode .= "ob_start();\n";
+               }
+               
+               $phpCode .= '$this->includeTemplate('.$file.', array('.$argString.'), ('.$sandbox.' ? 1 : 0), $this->v[\'__PACKAGE_ID\']);'."\n";
+               
+               if ($assignVar !== false) {
+                       $phpCode .= '$this->'.($append ? 'append' : 'assign').'('.$assignVar.', ob_get_contents()); ob_end_clean();'."\n";
+               }
+               
+               $phpCode .= "\$this->v['tpl']['template'] = \$outerTemplateName".$hash.";\n";
+               $phpCode .= "\$this->v['tpl']['includedTemplates'][".$file."] = 1;\n";
+               if ($once) $phpCode .= "}\n";
+               $phpCode .= '?>';
+               
+               return $phpCode;
+       }
+       
+       /**
+        * Parses an argument list and returns
+        * the keys and values in an associative array.
+        *
+        * @param       string          $tagArgs
+        * @param       string          $tag
+        * @return      array           $tagArgs
+        */
+       public function parseTagArgs($tagArgs, $tag) {
+               // replace strings
+               $tagArgs = $this->replaceQuotes($tagArgs);
+               
+               // validate tag arguments
+               if (!preg_match('~^(?:\s+\w+\s*=\s*[^=]*(?=\s|$))*$~s', $tagArgs)) {
+                       throw new SystemException($this->formatSyntaxError('syntax error in tag {'.$tag.'}', $this->currentIdentifier, $this->currentLineNo), 12000);
+               }
+
+               // parse tag arguments
+               $matches = array();
+               // find all variables
+               preg_match_all('~\s+(\w+)\s*=\s*([^=]*)(?=\s|$)~s', $tagArgs, $matches);
+               $args = array();
+               for ($i = 0, $j = count($matches[1]); $i < $j; $i++) {
+                       $name = $matches[1][$i];
+                       $string = $this->compileVariableTag($matches[2][$i], false);
+                       
+                       // reinserts strings
+                       foreach (StringStack::getStack('singleQuote') as $hash => $value) {
+                               if (StringUtil::indexOf($string, $hash) !== false) {
+                                       $string = StringUtil::replace($hash, $value, $string);
+                               }
+                       }
+                       foreach (StringStack::getStack('doubleQuote') as $hash => $value) {
+                               if (StringUtil::indexOf($string, $hash) !== false) {
+                                       $string = StringUtil::replace($hash, $value, $string);
+                               }
+                       }
+                       
+                       $args[$name] = $string;
+               }
+               
+               // clear stack
+               $this->reinsertQuotes('');
+               
+               return $args;
+       }
+       
+       /**
+        * Takes an array created by TemplateCompiler::parseTagArgs()
+        * and creates a string.
+        *
+        * @param       array           $args
+        * @return      string          $args
+        */
+       public static function makeArgString($args) {
+               $argString = '';
+               foreach ($args as $key => $val) {
+                       if ($argString != '') {
+                               $argString .= ', ';
+                       }
+                       $argString .= "'$key' => $val";
+               }
+               return $argString;
+       }
+       
+       /**
+        * Formats a syntax error message.
+        * 
+        * @param       string          $errorMsg
+        * @param       string          $file
+        * @param       integer         $line
+        * @return      string                          formatted error message
+        */
+       public static function formatSyntaxError($errorMsg, $file = null, $line = null) {
+               $errorMsg = 'Template compilation failed: '.$errorMsg;
+               if ($file && $line) {
+                       $errorMsg .= " in template '$file' on line $line";
+               }
+               elseif ($file && !$line) {
+                       $errorMsg .= " in template '$file'";
+               }
+               return $errorMsg;
+       }
+       
+       /**
+        * Compiles an {if} Tag
+        *
+        * @param       string          $tagArgs
+        * @param       boolean         $elseif         true, if this tag is an else tag
+        * @return      string                          php code of this tag
+        */
+       protected function compileIfTag($tagArgs, $elseif = false) {
+               $tagArgs = $this->replaceQuotes($tagArgs);
+               $tagArgs = str_replace(' ', '', $tagArgs);
+               
+               // split tags
+               preg_match_all('~('.$this->conditionOperatorPattern.')~', $tagArgs, $matches);
+               $operators = $matches[1];
+               $values = preg_split('~(?:'.$this->conditionOperatorPattern.')~', $tagArgs);
+               $leftParentheses = 0;
+               $result = '';
+               
+               for ($i = 0, $j = count($values); $i < $j; $i++) {
+                       $operator = (isset($operators[$i]) ? $operators[$i] : null);
+                       
+                       if ($operator !== '!' && $values[$i] == '') {
+                               throw new SystemException($this->formatSyntaxError('syntax error in tag {'.($elseif ? 'elseif' : 'if').'}', $this->currentIdentifier, $this->currentLineNo), 12000);
+                       }
+                       
+                       $leftParenthesis = StringUtil::countSubstring($values[$i], '(');
+                       $rightParenthesis = StringUtil::countSubstring($values[$i], ')');
+                       if ($leftParenthesis > $rightParenthesis) {
+                               $leftParentheses += $leftParenthesis - $rightParenthesis;
+                               $value = StringUtil::substring($values[$i], $leftParenthesis - $rightParenthesis);
+                               $result .= str_repeat('(', $leftParenthesis - $rightParenthesis);
+                               
+                               if (str_replace('(', '', StringUtil::substring($values[$i], 0, $leftParenthesis - $rightParenthesis)) != '') {
+                                       throw new SystemException($this->formatSyntaxError('syntax error in tag {'.($elseif ? 'elseif' : 'if').'}', $this->currentIdentifier, $this->currentLineNo), 12000);
+                               }
+                       }
+                       else if ($leftParenthesis < $rightParenthesis) {
+                               $leftParentheses += $leftParenthesis - $rightParenthesis;
+                               $value = StringUtil::substring($values[$i], 0, $leftParenthesis - $rightParenthesis);
+                               
+                               if ($leftParentheses < 0 || str_replace(')', '', StringUtil::substring($values[$i], $leftParenthesis - $rightParenthesis)) != '') {
+                                       throw new SystemException($this->formatSyntaxError('syntax error in tag {'.($elseif ? 'elseif' : 'if').'}', $this->currentIdentifier, $this->currentLineNo), 12000);
+                               }
+                       }
+                       else $value = $values[$i];
+                       
+                       try {
+                               $result .= $this->compileVariableTag($value, false);
+                       }
+                       catch (SystemException $e) {
+                               throw new SystemException($this->formatSyntaxError('syntax error in tag {'.($elseif ? 'elseif' : 'if').'}', $this->currentIdentifier, $this->currentLineNo), 12000);
+                       }
+                       
+                       if ($leftParenthesis < $rightParenthesis) {
+                               $result .= str_repeat(')', $rightParenthesis - $leftParenthesis);
+                       }
+                       
+                       if ($operator) $result .= ' '.$operator.' ';
+               }
+               
+               return '<?php '.($elseif ? '} elseif' : 'if').' ('.$result.') { ?>';
+       }
+       
+       /**
+        * Adds a tag to the tag stack.
+        *
+        * @param       string          $tag
+        */
+       public function pushTag($tag) {
+               $this->tagStack[] = array($tag, $this->currentLineNo);
+       }
+       
+       /**
+        * Deletes a tag from the tag stack.
+        *
+        * @param       string          $tag
+        * @return      string          $tag
+        */
+       public function popTag($tag) {
+               list($openTag, $lineNo) = array_pop($this->tagStack);
+               if ($tag == $openTag) {
+                       return $openTag;
+               }
+               if ($tag == 'if' && ($openTag == 'else' || $openTag == 'elseif')) {
+                       return $this->popTag($tag);
+               }
+               if ($tag == 'foreach' && $openTag == 'foreachelse') {
+                       return $this->popTag($tag);
+               }
+               if ($tag == 'section' && $openTag == 'sectionelse') {
+                       return $this->popTag($tag);
+               }
+       }
+       
+       /**
+        * Compiles an output tag.
+        * 
+        * @param       string          $tag
+        * @return      string                  php code of this tag
+        */
+       protected function compileOutputTag($tag) {
+               $encodeHTML = false;
+               $formatNumeric = false;
+               if ($tag[0] == '@') {
+                       $tag = StringUtil::substring($tag, 1);
+               }
+               else if ($tag[0] == '#') {
+                       $tag = StringUtil::substring($tag, 1);
+                       $formatNumeric = true;
+               }
+               else {
+                       $encodeHTML = true;
+               }
+               
+               $parsedTag = $this->compileVariableTag($tag);
+               
+               // the @ operator at the beginning of an output avoids
+               // the default call of StringUtil::encodeHTML()
+               if ($encodeHTML) {
+                       $parsedTag = 'wcf\util\StringUtil::encodeHTML('.$parsedTag.')';
+               }
+               // the # operator at the beginning of an output instructs
+               // the complier to call the StringUtil::formatNumeric() method
+               else if ($formatNumeric) {
+                       $parsedTag = 'wcf\util\StringUtil::formatNumeric('.$parsedTag.')';
+               }
+               
+               return '<?php echo '.$parsedTag.'; ?>';
+       }
+       
+       /**
+        * Compiles a variable tag.
+        * 
+        * @param       string          $variable
+        * @param       string          $type
+        * @param       boolean         $allowConstants
+        * @return      string
+        */
+       protected function compileSimpleVariable($variable, $type = '', $allowConstants = true) {
+               if ($type == '') $type = $this->getVariableType($variable);
+               
+               if ($type == 'variable') return '$this->v[\''.substr($variable, 1).'\']';
+               else if ($type == 'string') return $variable;
+               else if ($allowConstants && ($variable == 'true' || $variable == 'false' || $variable == 'null' || preg_match('/^[A-Z0-9_]*$/', $variable))) return $variable;
+               else return "'".$variable."'";
+       }
+       
+       /**
+        * Compiles a modifier tag.
+        * 
+        * @param       array           $data
+        * @return      string
+        */
+       protected function compileModifier($data) {
+               if (isset($data['className'])) {
+                       return "\$this->pluginObjects['".$data['className']."']->execute(array(".implode(',', $data['parameter'])."), \$this)";
+               }
+               else {
+                       return $data['name'].'('.implode(',', $data['parameter']).')';
+               }
+       }
+       
+       /**
+        * Returns type of the given variable
+        * 
+        * @param       string          $variable
+        * @return      string
+        */
+       protected function getVariableType($variable) {
+               if (substr($variable, 0, 1) == '$') return 'variable';
+               else if (substr($variable, 0, 2) == '@@') return 'string';
+               else return 'constant';
+       }
+       
+       /**
+        * Compiles a variable tag.
+        * 
+        * @param       string          $tag
+        * @return      string
+        */
+       public function compileVariableTag($tag, $replaceQuotes = true) {
+               // replace all quotes with unique hash values
+               $compiledTag = $tag;
+               if ($replaceQuotes) $compiledTag = $this->replaceQuotes($compiledTag);
+               // replace numbers and special constants
+               $compiledTag = $this->replaceConstants($compiledTag);
+               
+               // split tags
+               preg_match_all('~('.$this->variableOperatorPattern.')~', $compiledTag, $matches);
+               $operators = $matches[1];
+               $values = preg_split('~(?:'.$this->variableOperatorPattern.')~', $compiledTag);
+               
+               // parse tags
+               $statusStack = array(0 => 'start');
+               $result = '';
+               $modifierData = null;
+               for ($i = 0, $j = count($values); $i < $j; $i++) {
+                       // check value
+                       $status = end($statusStack);
+                       $operator = (isset($operators[$i]) ? $operators[$i] : null);
+                       $values[$i] = trim($values[$i]);
+                       
+                       if ($values[$i] !== '') {
+                               $variableType = $this->getVariableType($values[$i]);
+                               
+                               switch ($status) {
+                                       case 'start': 
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType);
+                                               $statusStack[0] = $status = $variableType;
+                                               break;
+                                               
+                                       case 'object access':
+                                               if (/*strpos($values[$i], '$') !== false || */strpos($values[$i], '@@') !== false) {
+                                                       throw new SystemException($this->formatSyntaxError("unexpected '->".$values[$i]."' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12003);
+                                               }
+                                               if (strpos($values[$i], '$') !== false) $result .= '{'.$this->compileSimpleVariable($values[$i], $variableType).'}';
+                                               else $result .= $values[$i];
+                                               $statusStack[count($statusStack) - 1] = $status = 'object';
+                                               break;
+                                       
+                                       case 'object method start':
+                                               $statusStack[count($statusStack) - 1] = 'object method';
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType);
+                                               $statusStack[] = $status = $variableType;
+                                               break;
+                                               
+                                       case 'object method parameter separator':
+                                               array_pop($statusStack);
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType);
+                                               $statusStack[] = $status = $variableType;
+                                               break;
+
+                                       case 'dot access':
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType, false);
+                                               $result .= ']';
+                                               $statusStack[count($statusStack) - 1] = $status = 'variable';
+                                               break;
+                                               
+                                       case 'object method':
+                                       case 'left parenthesis':        
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType);
+                                               $statusStack[] = $status = $variableType;
+                                               break;
+                                               
+                                       case 'bracket open':
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType, false);
+                                               $statusStack[] = $status = $variableType;
+                                               break;
+
+                                       case 'math':
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType);
+                                               $statusStack[count($statusStack) - 1] = $status = $variableType;
+                                               break;
+                                               
+                                       case 'modifier end':
+                                               $result .= $this->compileSimpleVariable($values[$i], $variableType);
+                                               $statusStack[] = $status = $variableType;
+                                               break;
+                                       
+                                       case 'modifier':
+                                               if (strpos($values[$i], '$') !== false || strpos($values[$i], '@@') !== false) {
+                                                       throw new SystemException($this->formatSyntaxError("unknown modifier '".$values[$i]."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               }
+                                               
+                                               // handle modifier name
+                                               $modifierData['name'] = StringUtil::toLowerCase($values[$i]);
+                                               $className = $this->template->getPluginClassName('modifier', $modifierData['name']);
+                                               if (class_exists($className)) {
+                                                       $modifierData['className'] = $className;
+                                                       $this->autoloadPlugins[$modifierData['className']] = $modifierData['className'];        
+                                               }
+                                               else if ((!function_exists($modifierData['name']) && !in_array($modifierData['name'], $this->unknownPHPFunctions)) || in_array($modifierData['name'], $this->disabledPHPFunctions)) {
+                                                       throw new SystemException($this->formatSyntaxError("unknown modifier '".$values[$i]."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               }
+                                               
+                                               $statusStack[count($statusStack) - 1] = $status = 'modifier end';
+                                               break;
+                                               
+                                       case 'object':
+                                       case 'constant': 
+                                       case 'variable':
+                                       case 'string': 
+                                               throw new SystemException($this->formatSyntaxError('unknown tag {'.$tag.'}', $this->currentIdentifier, $this->currentLineNo), 12003);
+                                               break;
+                               }
+                       }
+
+                       // check operator
+                       if ($operator !== null) {
+                               switch ($operator) {
+                                       case '.': 
+                                               if ($status == 'variable' || $status == 'object') {
+                                                       if ($status == 'object') $statusStack[count($statusStack) - 1] = 'variable';
+                                                       $result .= '[';
+                                                       $statusStack[] = 'dot access';
+                                                       break;
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected '.' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                       
+                                       // object access
+                                       case '->':
+                                               if ($status == 'variable' || $status == 'object') {
+                                                       $result .= $operator;
+                                                       $statusStack[count($statusStack) - 1] = 'object access';
+                                                       break;
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected '->' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                       
+                                       // left parenthesis
+                                       case '(':
+                                               if ($status == 'object') {
+                                                       $statusStack[count($statusStack) - 1] = 'variable';
+                                                       $statusStack[] = 'object method start';
+                                                       $result .= $operator;
+                                                       break;
+                                               }
+                                               else if ($status == 'math' || $status == 'start' || $status == 'left parenthesis' || $status == 'bracket open' || $status == 'modifier end') {
+                                                       if ($status == 'start') $statusStack[count($statusStack) - 1] = 'constant';
+                                                       $statusStack[] = 'left parenthesis';
+                                                       $result .= $operator;
+                                                       break;
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected '(' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                       
+                                       // right parenthesis
+                                       case ')': 
+                                               while ($oldStatus = array_pop($statusStack)) {
+                                                       if ($oldStatus != 'variable' && $oldStatus != 'object' && $oldStatus != 'constant' && $oldStatus != 'string') {
+                                                               if ($oldStatus == 'object method start' || $oldStatus == 'object method' || $oldStatus == 'left parenthesis') {
+                                                                       $result .= $operator;
+                                                                       break 2;
+                                                               }
+                                                               else break;
+                                                       }
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected ')' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                       
+                                       // bracket open
+                                       case '[': 
+                                               if ($status == 'variable' || $status == 'object') {
+                                                       if ($status == 'object') $statusStack[count($statusStack) - 1] = 'variable';
+                                                       $statusStack[] = 'bracket open';
+                                                       $result .= $operator;
+                                                       break;
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected '[' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                       
+                                       // bracket close
+                                       case ']':
+                                               while ($oldStatus = array_pop($statusStack)) {
+                                                       if ($oldStatus != 'variable' && $oldStatus != 'object' && $oldStatus != 'constant' && $oldStatus != 'string') {
+                                                               if ($oldStatus == 'bracket open') {
+                                                                       $result .= $operator;
+                                                                       break 2;
+                                                               }
+                                                               else break;
+                                                       }
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected ']' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+
+                                       // modifier
+                                       case '|': 
+                                               // handle previous modifier
+                                               if ($modifierData !== null) {
+                                                       if ($result !== '') $modifierData['parameter'][] = $result;
+                                                       $result = $this->compileModifier($modifierData);
+                                               }
+                                               
+                                               // clear status stack
+                                               while ($oldStatus = array_pop($statusStack)) {
+                                                       if ($oldStatus != 'variable' && $oldStatus != 'object' && $oldStatus != 'constant' && $oldStatus != 'string' && $oldStatus != 'modifier end') {
+                                                               throw new SystemException($this->formatSyntaxError("unexpected '|' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                                       }
+                                               }
+                                               
+                                               $statusStack = array(0 => 'modifier');
+                                               $modifierData = array('name' => '', 'parameter' => array(0 => $result));
+                                               $result = '';
+                                               break;
+
+                                       // modifier parameter
+                                       case ':': 
+                                               while ($oldStatus = array_pop($statusStack)) {
+                                                       if ($oldStatus != 'variable' && $oldStatus != 'object' && $oldStatus != 'constant' && $oldStatus != 'string') {
+                                                               if ($oldStatus == 'modifier end') {
+                                                                       $statusStack[] = 'modifier end';
+                                                                       if ($result !== '') $modifierData['parameter'][] = $result;
+                                                                       $result = '';
+                                                                       break 2;
+                                                               }
+                                                               else break;
+                                                       }
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected ':' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                               
+                                       case ',':
+                                               while ($oldStatus = array_pop($statusStack)) {
+                                                       if ($oldStatus != 'variable' && $oldStatus != 'object' && $oldStatus != 'constant' && $oldStatus != 'string') {
+                                                               if ($oldStatus == 'object method') {
+                                                                       $result .= $operator;
+                                                                       $statusStack[] = 'object method';
+                                                                       $statusStack[] = 'object method parameter separator';
+                                                                       break 2;
+                                                               }
+                                                               else break;
+                                                       }
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected ',' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                                       
+                                       // math operators       
+                                       case '+':
+                                       case '-':
+                                       case '*':
+                                       case '/':
+                                       case '%':
+                                       case '^':
+                                               if ($status == 'variable' || $status == 'object' || $status == 'constant' ||  $status == 'string' || $status == 'modifier end') {
+                                                       $result .= $operator;
+                                                       $statusStack[count($statusStack) - 1] = 'math';
+                                                       break;
+                                               }
+                                               
+                                               throw new SystemException($this->formatSyntaxError("unexpected '".$operator."' in tag '".$tag."'", $this->currentIdentifier, $this->currentLineNo), 12004);
+                                               break;
+                               }
+                       }
+               }
+               
+               // handle open modifier
+               if ($modifierData !== null) {
+                       if ($result !== '') $modifierData['parameter'][] = $result;
+                       $result = $this->compileModifier($modifierData);
+               }
+               
+               // reinserts strings
+               $result = $this->reinsertQuotes($result);
+               $result = $this->reinsertConstants($result);
+               
+               return $result;
+       }
+       
+       /**
+        * Generates the regexp pattern.
+        */
+       protected function buildPattern() {
+               // operator pattern
+               $this->variableOperatorPattern = '\-\>|\.|\(|\)|\[|\]|\||\:|\+|\-|\*|\/|\%|\^|\,';
+               $this->conditionOperatorPattern = '===|!==|==|!=|<=|<|>=|(?<!-)>|\|\||&&|!|=';
+
+               // negative lookbehind for a backslash
+               $this->escapedPattern = '(?<!\\\\)';
+               
+               // valid variable name pattern
+               $this->validVarnamePattern = '(?:[a-zA-Z_][a-zA-Z_0-9]*)';
+               
+               // matches constants
+               // CONSTANT
+               // __CONSTANT2
+               $this->constantPattern = '(?:[A-Z_][A-Z_0-9]*)';
+               
+               // matches double quoted strings
+               // "blah"
+               // "quote: \"blah\""
+               //$this->doubleQuotePattern = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
+               $this->doubleQuotePattern = '"(?:[^"\\\\]+|\\\\.)*"';
+               
+               // matches single quoted strings
+               // 'blah'
+               // 'don\'t'
+               //$this->singleQuotePattern = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
+               $this->singleQuotePattern = '\'(?:[^\'\\\\]+|\\\\.)*\'';
+               
+               // matches single or double quoted strings
+               $this->quotePattern = '(?:' . $this->doubleQuotePattern . '|' . $this->singleQuotePattern . ')';
+               
+               // matches numericals and boolean constants
+               // 234
+               // -12
+               // 23.92
+               // true
+               // false
+               $this->numericPattern = '(?i)(?:(?:\-?\d+(?:\.\d+)?)|true|false|null)';
+               
+               // matches simple variables
+               // $foo
+               $this->simpleVarPattern = '(?:\$('.$this->validVarnamePattern.'))';
+               
+               // matches variable outputs
+               // @$oo
+               $this->outputPattern = '(?:(?:@|#)?(?:'.$this->constantPattern.'|'.$this->quotePattern.'|'.$this->numericPattern.'|'.$this->simpleVarPattern.'|\())';
+       }
+       
+       /**
+        * Returns the instance of the template engine class.
+        * 
+        * @return       TemplateEngine
+        */
+       public function getTemplate() {
+               return $this->template;
+       }
+       
+       /**
+        * Returns the left delimiter for template tags.
+        * 
+        * @return      string
+        */
+       public function getLeftDelimiter() {
+               return $this->leftDelimiter;
+       }
+       
+       /**
+        * Returns the right delimiter for template tags.
+        * 
+        * @return      string
+        */
+       public function getRightDelimiter() {
+               return $this->rightDelimiter;
+       }
+       
+       /**
+        * Returns the name of the current template.
+        * 
+        * @return      string
+        */
+       public function getCurrentIdentifier() {
+               return $this->currentIdentifier;
+       }
+       
+       /**
+        * Returns the current line number.
+        * 
+        * @return      integer
+        */
+       public function getCurrentLineNo() {
+               return $this->currentLineNo;
+       }
+       
+       /**
+        * Applies the prefilters to the given string.
+        * 
+        * @param       string          $templateName
+        * @param       string          $string
+        * @return      string
+        */
+       public function applyPrefilters($templateName, $string) {
+               foreach ($this->template->getPrefilters() as $prefilter) {
+                       if (!is_object($prefilter)) {
+                               $className = $this->template->getPluginClassName('prefilter', $prefilter);
+                               if (!class_exists($className)) {
+                                       throw new SystemException($this->formatSyntaxError('unable to find prefilter class '.$className, $this->currentIdentifier), 11001);
+                               }
+                               $prefilter = new $className();
+                       }
+                       
+                       if ($prefilter instanceof TemplatePluginPrefilter) {
+                               $string = $prefilter->execute($templateName, $string, $this);
+                       }
+                       else {
+                               throw new SystemException($this->formatSyntaxError("Prefilter '".$prefilter."' does not implement the interface 'TemplatePluginPrefilter'", $this->currentIdentifier), 11010);
+                       }
+               }
+               
+               return $string;
+       }
+       
+       /**
+        * Replaces all {literal} Tags with unique hash values.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function replaceLiterals($string) {
+               return preg_replace_callback("~".$this->ldq."literal".$this->rdq."(.*?)".$this->ldq."/literal".$this->rdq."~s", array($this, 'replaceLiteralsCallback'), $string);
+       }
+       
+       /**
+        * Reinserts the literal tags.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function reinsertLiterals($string) {
+               return StringStack::reinsertStrings($string, 'literal');
+       }
+       
+       /**
+        * Callback function used in replaceLiterals()
+        */
+       private function replaceLiteralsCallback($matches) {
+               return StringStack::pushToStringStack($matches[1], 'literal');
+       }
+       
+       /**
+        * Removes template comments
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function removeComments($string) {
+               return preg_replace("~".$this->ldq."\*.*?\*".$this->rdq."~s", '', $string);
+       }
+       
+       /**
+        * Replaces all quotes with unique hash values.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function replaceQuotes($string) {
+               $string = preg_replace_callback('~\'([^\'\\\\]+|\\\\.)*\'~', array($this, 'replaceSingleQuotesCallback'), $string);
+               $string = preg_replace_callback('~"([^"\\\\]+|\\\\.)*"~', array($this, 'replaceDoubleQuotesCallback'), $string);
+               
+               return $string;
+       }
+       
+       /**
+        * Callback function used in replaceQuotes()
+        */
+       private function replaceSingleQuotesCallback($matches) {
+               return StringStack::pushToStringStack($matches[0], 'singleQuote');
+       }
+       
+       /**
+        * Callback function used in replaceQuotes()
+        */
+       private function replaceDoubleQuotesCallback($matches) {
+               // parse unescaped simple vars in double quotes
+               // replace $foo with {$this->v['foo']}
+               $matches[0] = preg_replace('~'.$this->escapedPattern.$this->simpleVarPattern.'~', '{$this->v[\'\\1\']}', $matches[0]);
+               return StringStack::pushToStringStack($matches[0], 'doubleQuote');
+       }
+       
+       /**
+        * Reinserts the quotes.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function reinsertQuotes($string) {
+               $string = StringStack::reinsertStrings($string, 'singleQuote');
+               $string = StringStack::reinsertStrings($string, 'doubleQuote');
+               
+               return $string;
+       }
+       
+       /**
+        * Replaces all constants with unique hash values.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function replaceConstants($string) {
+               return preg_replace_callback('~(?<=^|'.$this->variableOperatorPattern.')(?i)((?:\-?\d+(?:\.\d+)?)|true|false|null)(?=$|'.$this->variableOperatorPattern.')~', array($this, 'replaceConstantsCallback'), $string);
+       }
+       
+       /**
+        * Callback function used in replaceConstants()
+        */
+       private function replaceConstantsCallback($matches) {
+               return StringStack::pushToStringStack($matches[1], 'constants');
+       }
+       
+       /**
+        * Reinserts the constants.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function reinsertConstants($string) {
+               return StringStack::reinsertStrings($string, 'constants');
+       }
+       
+       /**
+        * Replaces all php tags.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public function replacePHPTags($string) {
+               if (StringUtil::indexOf($string, '<?') !== false) {
+                       $string = StringUtil::replace('<?php', '@@PHP_START_TAG@@', $string);
+                       $string = StringUtil::replace('<?', '@@PHP_SHORT_START_TAG@@', $string);
+                       $string = StringUtil::replace('?>', '@@PHP_END_TAG@@', $string);
+                       $string = StringUtil::replace('@@PHP_END_TAG@@', "<?php echo '?>'; ?>\n", $string);
+                       $string = StringUtil::replace('@@PHP_SHORT_START_TAG@@', "<?php echo '<?'; ?>\n", $string);
+                       $string = StringUtil::replace('@@PHP_START_TAG@@', "<?php echo '<?php'; ?>\n", $string);
+               }
+               
+               return $string;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginBlockLink.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginBlockLink.class.php
new file mode 100644 (file)
index 0000000..cc7301a
--- /dev/null
@@ -0,0 +1,58 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\request\LinkHandler;\r
+use wcf\system\template\TemplatePluginBlock;\r
+use wcf\system\template\TemplateEngine;\r
+\r
+/**\r
+ * Shortcut for usage of LinkHandler::getInstance()->getLink() in template scripting.\r
+ * \r
+ * Usage:\r
+ * {link application='wcf'}index.php{/link}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginBlockLink implements TemplatePluginBlock {\r
+       /**\r
+        * internal loop counter\r
+        * @var integer\r
+        */\r
+       protected $counter = 0;\r
+       \r
+       /**\r
+        * @see TemplatePluginBlock::execute()\r
+        */\r
+       public function execute($tagArgs, $blockContent, TemplateEngine $tplObj) {\r
+               $application = 'wcf';\r
+               if (!empty($tagArgs['application'])) {\r
+                       $application = $tagArgs['application'];\r
+               }\r
+               \r
+               return LinkHandler::getInstance()->getLink($blockContent, $application);\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginBlock::init()\r
+        */\r
+       public function init($tagArgs, TemplateEngine $tplObj) {\r
+               $this->counter = 0;\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginBlock::next()\r
+        */\r
+       public function next(TemplateEngine $tplObj) {\r
+               if ($this->counter == 0) {\r
+                       $this->counter++;\r
+                       return true;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerAppend.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerAppend.class.php
new file mode 100644 (file)
index 0000000..6d3221a
--- /dev/null
@@ -0,0 +1,42 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginCompiler;\r
+use wcf\system\template\TemplateScriptingCompiler;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The 'append' compiler function calls the append function on the template object.\r
+ * \r
+ * Usage:\r
+ * {append var=name value="foo"}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginCompilerAppend implements TemplatePluginCompiler {\r
+       /**\r
+        * @see TemplatePluginCompiler::executeStart()\r
+        */\r
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {\r
+               if (!isset($tagArgs['var'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'var' argument in append tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+               if (!isset($tagArgs['value'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'value' argument in append tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+                               \r
+               return "<?php \$this->append(".$tagArgs['var'].", ".$tagArgs['value']."); ?>";\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginCompiler::executeEnd()\r
+        */\r
+       public function executeEnd(TemplateScriptingCompiler $compiler) {\r
+               throw new SystemException($compiler->formatSyntaxError("unknown tag {/append}", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12003);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerAssign.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerAssign.class.php
new file mode 100644 (file)
index 0000000..8e5d871
--- /dev/null
@@ -0,0 +1,42 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginCompiler;\r
+use wcf\system\template\TemplateScriptingCompiler;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The 'assign' compiler function calls the assign function on the template object.\r
+ * \r
+ * Usage:\r
+ * {assign var=name value="foo"}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginCompilerAssign implements TemplatePluginCompiler {\r
+       /**\r
+        * @see TemplatePluginCompiler::executeStart()\r
+        */\r
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {\r
+               if (!isset($tagArgs['var'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'var' argument in assign tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+               if (!isset($tagArgs['value'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'value' argument in assign tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+                               \r
+               return "<?php \$this->assign(".$tagArgs['var'].", ".$tagArgs['value']."); ?>";\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginCompiler::executeEnd()\r
+        */\r
+       public function executeEnd(TemplateScriptingCompiler $compiler) {\r
+               throw new SystemException($compiler->formatSyntaxError("unknown tag {/assign}", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12003);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerFetch.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerFetch.class.php
new file mode 100644 (file)
index 0000000..20efe59
--- /dev/null
@@ -0,0 +1,45 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginCompiler;\r
+use wcf\system\template\TemplateScriptingCompiler;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * The 'fetch' compiler function fetches files from the local file system, http, or ftp and displays the content.\r
+ * \r
+ * Usage:\r
+ * {fetch file='x.html'}\r
+ * {fetch file='x.html' assign=var}\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginCompilerFetch implements TemplatePluginCompiler {\r
+       /**\r
+        * @see TemplatePluginCompiler::executeStart()\r
+        */\r
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {\r
+               if (!isset($tagArgs['file'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'file' argument in fetch tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+               \r
+               if (isset($tagArgs['assign'])) {\r
+                       return "<?php \$this->assign(".$tagArgs['assign'].", @file_get_contents(".$tagArgs['file'].")); ?>";\r
+               }\r
+               else {\r
+                       return "<?php echo @file_get_contents(".$tagArgs['file']."); ?>";\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginCompiler::executeEnd()\r
+        */\r
+       public function executeEnd(TemplateScriptingCompiler $compiler) {\r
+               throw new SystemException($compiler->formatSyntaxError("unknown tag {/fetch}", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12003);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerIcon.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerIcon.class.php
new file mode 100644 (file)
index 0000000..f1b9de8
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplatePluginCompiler;
+use wcf\system\template\TemplateScriptingCompiler;
+use wcf\util\StringUtil;
+
+/**
+ * The 'icon' compiler function compiles dynamic icon paths.
+ *
+ * Usage:
+ * {icon}{$foo}{/icon}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginCompilerIcon implements TemplatePluginCompiler {
+       /**
+        * @see TemplatePluginCompiler::executeStart()
+        */
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {
+               $compiler->pushTag('icon');
+               return "<?php ob_start(); ?>";
+       }
+       
+       /**
+        * @see TemplatePluginCompiler::executeEnd()
+        */
+       public function executeEnd(TemplateScriptingCompiler $compiler) {
+               $compiler->popTag('icon');
+               $hash = StringUtil::getRandomID();
+               return "<?php \$_icon".$hash." = ob_get_contents(); ob_end_clean(); echo wcf\system\style\StyleHandler::getInstance()->getStyle()->getIconPath(\$_icon".$hash."); ?>";
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerImplode.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerImplode.class.php
new file mode 100644 (file)
index 0000000..00e76b7
--- /dev/null
@@ -0,0 +1,62 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginCompiler;\r
+use wcf\system\template\TemplateScriptingCompiler;\r
+use wcf\system\exception\SystemException;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'implode' compiler function joins array elements with a string.\r
+ * \r
+ * Usage:\r
+ * {implode from=$array key=bar item=foo glue=";"}{$foo}{/implode}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginCompilerImplode implements TemplatePluginCompiler {\r
+       protected $tagStack = array();\r
+       \r
+       /**\r
+        * @see TemplatePluginCompiler::executeStart()\r
+        */\r
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {\r
+               $compiler->pushTag('implode');\r
+               \r
+               if (!isset($tagArgs['from'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'from' argument in implode tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+               if (!isset($tagArgs['item'])) {\r
+                       throw new SystemException($compiler->formatSyntaxError("missing 'item' argument in implode tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);\r
+               }\r
+               \r
+               $hash = StringUtil::getRandomID();\r
+               $glue = isset($tagArgs['glue']) ? $tagArgs['glue'] : "', '";\r
+               $this->tagStack[] = array('hash' => $hash, 'glue' => $glue);\r
+               \r
+               $phpCode = "<?php\n";\r
+               $phpCode .= "\$_length".$hash." = count(".$tagArgs['from'].");\n";\r
+               $phpCode .= "\$_i".$hash." = 0;\n";\r
+               $phpCode .= "foreach (".$tagArgs['from']." as ".(isset($tagArgs['key']) ? (StringUtil::substring($tagArgs['key'], 0, 1) != '$' ? "\$this->v[".$tagArgs['key']."]" : $tagArgs['key'])." => " : '').(StringUtil::substring($tagArgs['item'], 0, 1) != '$' ? "\$this->v[".$tagArgs['item']."]" : $tagArgs['item']).") { ?>";\r
+               return $phpCode;\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginCompiler::executeEnd()\r
+        */\r
+       public function executeEnd(TemplateScriptingCompiler $compiler) {\r
+               $compiler->popTag('implode');\r
+               $tagArgs = array_pop($this->tagStack);\r
+               \r
+               $phpCode = "<?php\n";\r
+               $phpCode .= "if (++\$_i".$tagArgs['hash']." < \$_length".$tagArgs['hash'].") { echo ".$tagArgs['glue']."; }\n";\r
+               $phpCode .= "} ?>";\r
+               \r
+               return $phpCode;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerLang.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerLang.class.php
new file mode 100644 (file)
index 0000000..f575e44
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginCompiler;\r
+use wcf\system\template\TemplateScriptingCompiler;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'lang' compiler function compiles dynamic language variables.\r
+ * \r
+ * Usage:\r
+ * {lang}$blah{/lang}\r
+ * {lang var=$x}foo{/lang}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginCompilerLang implements TemplatePluginCompiler {\r
+       /**\r
+        * @see TemplatePluginCompiler::executeStart()\r
+        */\r
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {\r
+               $compiler->pushTag('lang');\r
+               \r
+               $newTagArgs = array();\r
+               foreach ($tagArgs as $key => $arg) {\r
+                       $newTagArgs[$key] = 'wcf\util\StringUtil::encodeHTML('.$arg.')';\r
+               }\r
+               \r
+               $tagArgs = $compiler->makeArgString($newTagArgs);\r
+               return "<?php \$this->tagStack[] = array('lang', array($tagArgs)); ob_start(); ?>";\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginCompiler::executeEnd()\r
+        */\r
+       public function executeEnd(TemplateScriptingCompiler $compiler) {\r
+               $compiler->popTag('lang');\r
+               $hash = StringUtil::getRandomID();\r
+               return "<?php \$_lang".$hash." = ob_get_contents(); ob_end_clean(); echo wcf\system\WCF::getLanguage()->getDynamicVariable(\$_lang".$hash.", \$this->tagStack[count(\$this->tagStack) - 1][1]); array_pop(\$this->tagStack); ?>";\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerPrepend.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerPrepend.class.php
new file mode 100644 (file)
index 0000000..f524782
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplatePluginCompiler;
+use wcf\system\template\TemplateScriptingCompiler;
+use wcf\util\StringUtil;
+
+/**
+ * The 'prepend' compiler function calls the prepend function on the template object.
+ * 
+ * Usage:
+ * {prepend var=name value="foo"}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginCompilerPrepend implements TemplatePluginCompiler {
+       /**
+        * @see TemplatePluginCompiler::executeStart()
+        */
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {
+               if (!isset($tagArgs['var'])) {
+                       throw new SystemException($compiler->formatSyntaxError("missing 'var' argument in prepend tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);
+               }
+               if (!isset($tagArgs['value'])) {
+                       throw new SystemException($compiler->formatSyntaxError("missing 'value' argument in prepend tag", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12001);
+               }
+                               
+               return "<?php \$this->prepend(".$tagArgs['var'].", ".$tagArgs['value']."); ?>";
+       }
+       
+       /**
+        * @see TemplatePluginCompiler::executeEnd()
+        */
+       public function executeEnd(TemplateScriptingCompiler $compiler) {
+               throw new SystemException($compiler->formatSyntaxError("unknown tag {/prepend}", $compiler->getCurrentIdentifier(), $compiler->getCurrentLineNo()), 12003);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerStaticlang.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginCompilerStaticlang.class.php
new file mode 100644 (file)
index 0000000..129aac2
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplatePluginCompiler;
+use wcf\system\template\TemplateScriptingCompiler;
+use wcf\util\StringUtil;
+
+/**
+ * The 'staticlang' compiler function gets the source of a language variables.
+ * 
+ * Usage:
+ * {staticlang}$blah{/staticlang}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginCompilerStaticlang implements TemplatePluginCompiler {
+       /**
+        * @see TemplatePluginCompiler::executeStart()
+        */
+       public function executeStart($tagArgs, TemplateScriptingCompiler $compiler) {
+               $compiler->pushTag('staticlang');
+               
+               return "<?php ob_start(); ?>";
+       }
+       
+       /**
+        * @see TemplatePluginCompiler::executeEnd()
+        */
+       public function executeEnd(TemplateScriptingCompiler $compiler) {
+               $compiler->popTag('staticlang');
+               $hash = StringUtil::getRandomID();
+               return "<?php \$_lang".$hash." = ob_get_contents(); ob_end_clean(); echo WCF::getLanguage()->get(\$_lang".$hash."); ?>";
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionCounter.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionCounter.class.php
new file mode 100644 (file)
index 0000000..7faa0de
--- /dev/null
@@ -0,0 +1,78 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginFunction;\r
+use wcf\system\template\TemplateEngine;\r
+\r
+/**\r
+ * The 'counter' template function is used to print out a count.\r
+ * \r
+ * Usage:\r
+ * {counter assign=i}\r
+ * {counter start=10 skip=2}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginFunctionCounter implements TemplatePluginFunction {\r
+       protected $counters = array();\r
+       \r
+       /**\r
+        * @see TemplatePluginFunction::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               if (!isset($tagArgs['name'])) {\r
+                       $tagArgs['name'] = 'default';\r
+               }\r
+\r
+               if (!isset($this->counters[$tagArgs['name']])) {\r
+                       $this->counters[$tagArgs['name']] = array(\r
+                               'start' => 1,\r
+                               'skip' => 1,\r
+                               'direction' => 'up',\r
+                               'count' => 1\r
+                       );\r
+               }\r
+\r
+               $counter =& $this->counters[$tagArgs['name']];\r
+\r
+               if (isset($tagArgs['start'])) {\r
+                       $counter['start'] = $counter['count'] = intval($tagArgs['start']);\r
+               }\r
+\r
+               if (isset($tagArgs['assign']) && !empty($tagArgs['assign'])) {\r
+                       $counter['assign'] = $tagArgs['assign'];\r
+               }\r
+\r
+               if (isset($counter['assign'])) {\r
+                       $tplObj->assign($counter['assign'], $counter['count']);\r
+               }\r
+\r
+               $result = null;\r
+               if (!isset($tagArgs['print']) || $tagArgs['print']) {\r
+                       $result = $counter['count'];\r
+               } \r
+               \r
+               if (isset($tagArgs['skip'])) {\r
+                       $counter['skip'] = intval($tagArgs['skip']);\r
+               }\r
+\r
+               // get direction\r
+               if (isset($tagArgs['direction'])) {\r
+                       $counter['direction'] = $tagArgs['direction'];\r
+               }\r
+\r
+               if ($counter['direction'] == 'down') {\r
+                       $counter['count'] -= $counter['skip'];\r
+               }\r
+               else {\r
+                       $counter['count'] += $counter['skip'];\r
+               }\r
+\r
+               return $result;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionCycle.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionCycle.class.php
new file mode 100644 (file)
index 0000000..8dc44e9
--- /dev/null
@@ -0,0 +1,93 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\template\TemplatePluginFunction;\r
+use wcf\system\template\TemplateEngine;\r
+\r
+/**\r
+ * The 'cycle' template function cycles through given values.\r
+ * \r
+ * Usage:\r
+ * {cycle values="#eee,#fff"}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginFunctionCycle implements TemplatePluginFunction {\r
+       protected $cycles = array();\r
+       \r
+       /**\r
+        * @see TemplatePluginFunction::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               // get params\r
+               $name = isset($tagArgs['name']) ? $tagArgs['name'] : 'default';\r
+               $print = isset($tagArgs['print']) ? $tagArgs['print'] : 1;\r
+               $advance = isset($tagArgs['advance']) ? $tagArgs['advance'] : 1;\r
+               $reset = isset($tagArgs['reset']) ? $tagArgs['reset'] : 0;\r
+               \r
+               // get values\r
+               if (!isset($tagArgs['values']) ) {\r
+                       if (!isset($this->cycles[$name]['values'])) {\r
+                               throw new SystemException("missing 'values' argument in cycle tag", 12001);\r
+                       }\r
+               }\r
+               else {\r
+                       if (isset($this->cycles[$name]['values']) && $this->cycles[$name]['values'] != $tagArgs['values'] ) {\r
+                               $this->cycles[$name]['index'] = 0;\r
+                       }\r
+                       $this->cycles[$name]['values'] = $tagArgs['values'];\r
+               }\r
+               \r
+               // get delimiter\r
+               if (!isset($this->cycles[$name]['delimiter'])) {\r
+                       // set default delimiter\r
+                       $this->cycles[$name]['delimiter'] = ',';\r
+               }\r
+               if (isset($tagArgs['delimiter'])) {\r
+                       $this->cycles[$name]['delimiter'] = $tagArgs['delimiter'];\r
+               }\r
+               \r
+               // split values\r
+               if (is_array($this->cycles[$name]['values'])) {\r
+                       $cycleArray = $this->cycles[$name]['values'];\r
+               }\r
+               else {\r
+                       $cycleArray = explode($this->cycles[$name]['delimiter'], $this->cycles[$name]['values']);\r
+               }\r
+               \r
+               // set index\r
+               if (!isset($this->cycles[$name]['index']) || $reset) {\r
+                       $this->cycles[$name]['index'] = 0;\r
+               }\r
+               \r
+               // get result\r
+               $result = $cycleArray[$this->cycles[$name]['index']];\r
+               \r
+               // assign result to template var\r
+               if (isset($tagArgs['assign'])) {\r
+                       $print = false;\r
+                       $tplObj->assign($tagArgs['assign'], $result);\r
+               }\r
+               \r
+               // update index\r
+               if ($advance) {\r
+                       if ($this->cycles[$name]['index'] >= count($cycleArray) - 1) {\r
+                               $this->cycles[$name]['index'] = 0;\r
+                       }\r
+                       else {\r
+                               $this->cycles[$name]['index']++;\r
+                       }\r
+               }\r
+               \r
+               // print var\r
+               if ($print) {\r
+                       return $result;\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionHtmlcheckboxes.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionHtmlcheckboxes.class.php
new file mode 100644 (file)
index 0000000..7e41775
--- /dev/null
@@ -0,0 +1,89 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\template\TemplatePluginFunction;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'htmlcheckboxes' template function generates a list of html checkboxes.\r
+ * \r
+ * Usage:\r
+ * {htmlcheckboxes name="x" options=$array}\r
+ * {htmlcheckboxes name="x" options=$array selected=$foo}\r
+ * {htmlcheckboxes name="x" output=$outputArray}\r
+ * {htmlcheckboxes name="x" output=$outputArray values=$valueArray}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginFunctionHtmlcheckboxes implements TemplatePluginFunction {\r
+       protected $disableEncoding = false;\r
+       \r
+       /**\r
+        * @see TemplatePluginFunction::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               // get options\r
+               if (isset($tagArgs['output']) && is_array($tagArgs['output'])) {\r
+                       if (isset($tagArgs['values']) && is_array($tagArgs['values'])) {\r
+                               $tagArgs['options'] = array_combine($tagArgs['values'], $tagArgs['output']);\r
+                       }\r
+                       else {\r
+                               $tagArgs['options'] = array_combine($tagArgs['output'], $tagArgs['output']);\r
+                       }\r
+               }\r
+\r
+               if (!isset($tagArgs['options']) || !is_array($tagArgs['options'])) {\r
+                       throw new SystemException("missing 'options' argument in htmlCheckboxes tag", 12001);\r
+               }\r
+               \r
+               if (!isset($tagArgs['name'])) {\r
+                       throw new SystemException("missing 'name' argument in htmlCheckboxes tag", 12001);\r
+               }\r
+               \r
+               if (isset($tagArgs['disableEncoding']) && $tagArgs['disableEncoding']) {\r
+                       $this->disableEncoding = true;\r
+               }\r
+               else {\r
+                       $this->disableEncoding = false;\r
+               }\r
+               \r
+               // get selected values\r
+               if (isset($tagArgs['selected'])) {\r
+                       if (!is_array($tagArgs['selected'])) $tagArgs['selected'] = array($tagArgs['selected']);        \r
+               }\r
+               else {\r
+                       $tagArgs['selected'] = array();\r
+               }\r
+               if (!isset($tagArgs['separator'])) {\r
+                       $tagArgs['separator'] = '';\r
+               }\r
+               \r
+               // build html\r
+               $html = '';\r
+               foreach ($tagArgs['options'] as $key => $value) {\r
+                       if (!empty($html)) $html .= $tagArgs['separator'];\r
+                       $html .= '<label><input type="checkbox" name="'.$this->encodeHTML($tagArgs['name']).'[]" value="'.$this->encodeHTML($key).'"'.(in_array($key, $tagArgs['selected']) ? ' checked="checked"' : '').' /> '.$this->encodeHTML($value).'</label>';                   \r
+               }\r
+               \r
+               return $html;\r
+       }\r
+       \r
+       /**\r
+        * Executes StringUtil::encodeHTML on the given text if disableEncoding is false.\r
+        * @see StringUtil::encodeHTML()\r
+        */\r
+       protected function encodeHTML($text) {\r
+               if (!$this->disableEncoding) {\r
+                       $text = StringUtil::encodeHTML($text);\r
+               }\r
+               \r
+               return $text;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionHtmloptions.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionHtmloptions.class.php
new file mode 100644 (file)
index 0000000..9e2871f
--- /dev/null
@@ -0,0 +1,129 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'htmloptions' template function generates the options of an html select list.\r
+ * \r
+ * Usage:\r
+ * {htmloptions options=$array}\r
+ * {htmloptions options=$array selected=$foo}\r
+ * {htmloptions options=$array name="x"}\r
+ * {htmloptions output=$outputArray}\r
+ * {htmloptions output=$outputArray values=$valueArray}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginFunctionHtmloptions extends TemplatePluginFunctionHtmlcheckboxes {\r
+       protected $selected = array();\r
+       \r
+       /**\r
+        * @see TemplatePluginFunction::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               if (isset($tagArgs['output']) && is_array($tagArgs['output'])) {\r
+                       if (count($tagArgs['output'])) {\r
+                               if (isset($tagArgs['values']) && is_array($tagArgs['values'])) {\r
+                                       if (count($tagArgs['output']) == count($tagArgs['values'])) {\r
+                                               $tagArgs['options'] = array_combine($tagArgs['values'], $tagArgs['output']);\r
+                                       }\r
+                                       else {\r
+                                               $tagArgs['options'] = array();\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       $tagArgs['options'] = array_combine($tagArgs['output'], $tagArgs['output']);\r
+                               }\r
+                       }\r
+                       else {\r
+                               $tagArgs['options'] = array();\r
+                       }\r
+               }\r
+\r
+               if (!isset($tagArgs['options']) || !is_array($tagArgs['options'])) {\r
+                       throw new SystemException("missing 'options' argument in htmloptions tag", 12001);\r
+               }\r
+               \r
+               if (isset($tagArgs['disableEncoding']) && $tagArgs['disableEncoding']) {\r
+                       $this->disableEncoding = true;\r
+               }\r
+               else {\r
+                       $this->disableEncoding = false;\r
+               }\r
+               \r
+               // get selected values\r
+               $this->selected = array();\r
+               if (isset($tagArgs['selected'])) {\r
+                       $this->selected = $tagArgs['selected'];\r
+                       if (!is_array($this->selected)) $this->selected = array($this->selected);       \r
+               }\r
+               \r
+               // create option list\r
+               $htmloptions = $this->makeOptionGroup(null, $tagArgs['options']);\r
+               \r
+               // create also a 'select' tag\r
+               if (isset($tagArgs['name'])) {\r
+                       // unset all system vars\r
+                       unset($tagArgs['options'], $tagArgs['selected'], $tagArgs['output'], $tagArgs['values'], $tagArgs['disableEncoding']);\r
+                       \r
+                       // generate 'select' parameters\r
+                       $params = '';\r
+                       foreach ($tagArgs as $key => $value) {\r
+                               $params .= ' '.$key.'="'.$this->encodeHTML($value).'"';\r
+                       }\r
+                       \r
+                       $htmloptions = '<select'.$params.'>'."\n".$htmloptions."</select>\n";\r
+               }\r
+               \r
+               return $htmloptions;\r
+       }\r
+       \r
+       /**\r
+        * Makes the html for an option group.\r
+        * \r
+        * @param       string          $key\r
+        * @param       array           $values\r
+        * @return      string                          html code of an option group\r
+        */\r
+       protected function makeOptionGroup($key, $values) {\r
+               $html = '';\r
+               if ($key !== null) {\r
+                       $html = '<optgroup label="'.$this->encodeHTML($key).'">'."\n";\r
+               }\r
+               \r
+               foreach ($values as $childKey => $value) {\r
+                       if (is_array($value)) {\r
+                               $html .= $this->makeOptionGroup($childKey, $value);\r
+                       }\r
+                       else {\r
+                               $html .= $this->makeOption($childKey, $value);\r
+                       }\r
+               }\r
+               \r
+               if ($key !== null) {\r
+                       $html .= "</optgroup>\n";\r
+               }\r
+               \r
+               return $html;\r
+       }\r
+       \r
+       /**\r
+        * Makes the html for an option.\r
+        * \r
+        * @param       string          $key\r
+        * @param       string          $value\r
+        * @return      string                          html code of an option tag\r
+        */\r
+       protected function makeOption($key, $value) {\r
+               $value = $this->encodeHTML($value);\r
+               return '<option label="'.$value.'" value="'.$this->encodeHTML($key).'"'.(in_array($key, $this->selected) ? ' selected="selected"' : '').'>'.$value."</option>\n";\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionPages.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionPages.class.php
new file mode 100644 (file)
index 0000000..2c73a75
--- /dev/null
@@ -0,0 +1,221 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\WCF;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginFunction;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'pages' template function is used to generate sliding pagers.\r
+ * \r
+ * Usage:\r
+ * {pages pages=10 link='page-%d.html'}\r
+ * {pages page=8 pages=10 link='page-%d.html'}\r
+ * \r
+ * assign to variable 'output'; do not print: \r
+ * {pages page=8 pages=10 link='page-%d.html' assign='output'}\r
+ * \r
+ * assign to variable 'output' and do print also:\r
+ * {pages page=8 pages=10 link='page-%d.html' assign='output' print=true}\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginFunctionPages implements TemplatePluginFunction {\r
+       const SHOW_LINKS = 11;\r
+       const SHOW_SUB_LINKS = 20;\r
+       \r
+       /**\r
+        * Inserts the page number into the link.\r
+        * \r
+        * @param       string          $link\r
+        * @param       integer         $pageNo\r
+        * @return      string          final link\r
+        */\r
+       protected static function insertPageNumber($link, $pageNo) {\r
+               $startPos = StringUtil::indexOf($link, '%d');\r
+               if ($startPos !== null) $link = StringUtil::substring($link, 0, $startPos) . $pageNo . StringUtil::substring($link, $startPos + 2);\r
+               return $link;\r
+       }\r
+       \r
+       /**\r
+        * Generates html code of a link.\r
+        * \r
+        * @param       string          $link\r
+        * @param       integer         $pageNo\r
+        * @param       integer         $activePage\r
+        * @param       boolean         $break\r
+        * @return      string\r
+        */\r
+       protected function makeLink($link, $pageNo, $activePage, $break = false) {\r
+               // first page\r
+               if ($activePage != $pageNo) {\r
+                       return '<li'.($break ? ' class="break"' : '').'><a href="'.$this->insertPageNumber($link, $pageNo).'">'.StringUtil::formatInteger($pageNo).'</a></li>'."\n";\r
+               }\r
+               else {\r
+                       return '<li class="'.($break ? 'break ' : '').'active"><span>'.StringUtil::formatInteger($pageNo).'</span></li>'."\n";\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see TemplatePluginFunction::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               // needed params: link, page, pages\r
+               if (!isset($tagArgs['link'])) throw new SystemException("missing 'link' argument in pages tag", 12001);\r
+               if (!isset($tagArgs['pages'])) {\r
+                       if (($tagArgs['pages'] = $tplObj->get('pages')) === null) {\r
+                               throw new SystemException("missing 'pages' argument in pages tag", 12001);\r
+                       }\r
+               }\r
+               \r
+               $html = '';\r
+               \r
+               if ($tagArgs['pages'] > 1) {\r
+                       // define page link for js function\r
+                       $html .= "<script type=\"text/javascript\">\n//<![CDATA[\nmultiPagesLinks.setPageLink('".StringUtil::replace("'", "\'", $tagArgs['link'])."');\n//]]>\n</script>";\r
+                       \r
+                       // encode link\r
+                       $tagArgs['link'] = StringUtil::encodeHTML($tagArgs['link']);\r
+               \r
+                       if (!isset($tagArgs['page'])) {\r
+                               if (($tagArgs['page'] = $tplObj->get('pageNo')) === null) {\r
+                                       $tagArgs['page'] = 0;\r
+                               }\r
+                       }\r
+                       \r
+                       // open div and ul\r
+                       $html .= "<div class=\"pageNavigation\">\n<ul>\n";\r
+                       \r
+                       // previous page\r
+                       $previousTitle = WCF::getLanguage()->getDynamicVariable('wcf.global.page.previous');\r
+                       if ($tagArgs['page'] > 1) {\r
+                               $html .= '<li class="skip"><a href="'.$this->insertPageNumber($tagArgs['link'], $tagArgs['page'] - 1).'" title="'.$previousTitle.'"><img src="'.self::getIconPath('previousS.png').'" alt="" /></a></li>'."\n";\r
+                       }\r
+                       else {\r
+                               $html .= '<li class="skip"><img src="'.self::getIconPath('previousDisabledS.png').'" alt="" /></li>'."\n";\r
+                       }\r
+                       \r
+                       // first page\r
+                       $html .= $this->makeLink($tagArgs['link'], 1, $tagArgs['page']);\r
+                       \r
+                       // calculate page links\r
+                       $maxLinks = self::SHOW_LINKS - 4;\r
+                       $linksBeforePage = $tagArgs['page'] - 2;\r
+                       if ($linksBeforePage < 0) $linksBeforePage = 0; \r
+                       $linksAfterPage = $tagArgs['pages'] - ($tagArgs['page'] + 1);\r
+                       if ($linksAfterPage < 0) $linksAfterPage = 0; \r
+                       if ($tagArgs['page'] > 1 && $tagArgs['page'] < $tagArgs['pages']) {\r
+                               $maxLinks--;\r
+                       }\r
+                       \r
+                       $half = $maxLinks / 2;\r
+                       $left = $right = $tagArgs['page'];\r
+                       if ($left < 1) $left = 1;\r
+                       if ($right < 1) $right = 1;\r
+                       if ($right > $tagArgs['pages'] - 1) $right = $tagArgs['pages'] - 1;\r
+                       \r
+                       if ($linksBeforePage >= $half) {\r
+                               $left -= $half;\r
+                       }\r
+                       else {\r
+                               $left -= $linksBeforePage;\r
+                               $right += $half - $linksBeforePage;\r
+                       }\r
+                       \r
+                       if ($linksAfterPage >= $half) {\r
+                               $right += $half;\r
+                       }\r
+                       else {\r
+                               $right += $linksAfterPage;\r
+                               $left -= $half - $linksAfterPage;\r
+                       }\r
+                       \r
+                       $right = intval(ceil($right));\r
+                       $left = intval(ceil($left));\r
+                       if ($left < 1) $left = 1;\r
+                       if ($right > $tagArgs['pages']) $right = $tagArgs['pages'];\r
+                       \r
+                       // left ... links\r
+                       if ($left > 1) {\r
+                               if ($left - 1 < 2) {\r
+                                       $html .= $this->makeLink($tagArgs['link'], 2, $tagArgs['page']);\r
+                               }\r
+                               else {\r
+                                       $html .= '<li class="children"><a onclick="multiPagesLinks.startPageNumberInput(this)">&hellip;<img src="'.self::getIconPath('arrowDown.png').'" alt="" /></a><input type="text" class="inputText" name="pageNo" /><div><ul>'."\n";\r
+                                       \r
+                                       $k = 0;\r
+                                       $step = intval(ceil(($left - 2) / self::SHOW_SUB_LINKS));\r
+                                       for ($i = 2; $i <= $left; $i += $step) {\r
+                                               $html .= $this->makeLink($tagArgs['link'], $i, $tagArgs['page'], $k != 0 && $k % 4 == 0);\r
+                                               $k++;\r
+                                       }\r
+                                       \r
+                                       $html .= "</ul></div></li>\n";\r
+                               }\r
+                       }\r
+                       \r
+                       // visible links\r
+                       for ($i = $left + 1; $i < $right; $i++) {\r
+                               $html .= $this->makeLink($tagArgs['link'], $i, $tagArgs['page']);\r
+                       }\r
+                       \r
+                       // right ... links\r
+                       if ($right < $tagArgs['pages']) {\r
+                               if ($tagArgs['pages'] - $right < 2) {\r
+                                       $html .= $this->makeLink($tagArgs['link'], $tagArgs['pages'] - 1, $tagArgs['page']);\r
+                               }\r
+                               else {\r
+                                       $html .= '<li class="children"><a onclick="multiPagesLinks.startPageNumberInput(this)">&hellip;<img src="'.self::getIconPath('arrowDown.png').'" alt="" /></a><input type="text" class="inputText" name="page" /><div><ul>'."\n";\r
+                                       \r
+                                       $k = 0;\r
+                                       $step = intval(ceil(($tagArgs['pages'] - $right) / self::SHOW_SUB_LINKS));\r
+                                       for ($i = $right; $i < $tagArgs['pages']; $i += $step) {\r
+                                               $html .= $this->makeLink($tagArgs['link'], $i, $tagArgs['page'], $k != 0 && $k % 4 == 0);\r
+                                               $k++;\r
+                                       }\r
+                                       \r
+                                       $html .= "</ul></div></li>\n";\r
+                               }\r
+                       }\r
+                       \r
+                       // last page\r
+                       $html .= $this->makeLink($tagArgs['link'], $tagArgs['pages'], $tagArgs['page']);\r
+                       \r
+                       // next page\r
+                       $nextTitle = WCF::getLanguage()->getDynamicVariable('wcf.global.page.next');\r
+                       if ($tagArgs['page'] && $tagArgs['page'] < $tagArgs['pages']) {\r
+                               $html .= '<li class="skip"><a href="'.$this->insertPageNumber($tagArgs['link'], $tagArgs['page'] + 1).'" title="'.$nextTitle.'"><img src="'.self::getIconPath('nextS.png').'" alt="" /></a></li>'."\n";\r
+                       }\r
+                       else {\r
+                               $html .= '<li class="skip"><img src="'.self::getIconPath('nextDisabledS.png').'" alt="" /></li>'."\n";\r
+                       }\r
+                       \r
+                       // close div and ul\r
+                       $html .= "</ul></div>\n";\r
+               }\r
+               \r
+               // assign html output to template var\r
+               if (isset($tagArgs['assign'])) {\r
+                       $tplObj->assign($tagArgs['assign'], $html);\r
+                       if (!isset($tagArgs['print']) || !$tagArgs['print']) return '';\r
+               }\r
+               \r
+               return $html;\r
+       }\r
+       \r
+       private static function getIconPath($filename) {\r
+               if (class_exists('StyleManager')) {\r
+                       return StyleManager::getStyle()->getIconPath($filename);\r
+               }\r
+               else {\r
+                       return RELATIVE_WCF_DIR.'icon/'.$filename;\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionSmallpages.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginFunctionSmallpages.class.php
new file mode 100644 (file)
index 0000000..7729783
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\WCF;
+use wcf\system\exception\SystemException;
+use wcf\system\template\TemplateEngine;
+use wcf\system\template\TemplatePluginFunction;
+use wcf\util\StringUtil;
+
+/**
+ * The 'smallpages' template function is used to generate simple sliding pagers.
+ * 
+ * Usage:
+ * {smallpages pages=10 link='page-%d.html'}
+ * 
+ * assign to variable 'output'; do not print: 
+ * {smallpages pages=10 link='page-%d.html' assign='output'}
+ * 
+ * assign to variable 'output' and do print also:
+ * {smallpages pages=10 link='page-%d.html' assign='output' print=true}
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginFunctionSmallpages implements TemplatePluginFunction {
+       const SHOW_LINKS = 5;
+       
+       /**
+        * Inserts the page number into the link.
+        * 
+        * @param       string          $link
+        * @param       integer         $pageNo
+        * @return      string          final link
+        */
+       protected static function insertPageNumber($link, $pageNo) {
+               $startPos = StringUtil::indexOf($link, '%d');
+               if ($startPos !== null) $link = StringUtil::substring($link, 0, $startPos) . $pageNo . StringUtil::substring($link, $startPos + 2);
+               return $link;
+       }
+       
+       /**
+        * Generates html code of a link.
+        * 
+        * @param       string          $link
+        * @param       integer         $pageNo
+        * @return      string
+        */
+       protected function makeLink($link, $pageNo) {
+               return '<li><a href="'.$this->insertPageNumber($link, $pageNo).'" title="' . WCF::getLanguage()->getDynamicVariable('wcf.page.pageNo', array('pageNo' => $pageNo)) . '">'.StringUtil::formatInteger($pageNo).'</a></li>'."\n";
+       }
+       
+       /**
+        * @see TemplatePluginFunction::execute()
+        */
+       public function execute($tagArgs, TemplateEngine $tplObj) {
+               // needed params: link, pages
+               if (!isset($tagArgs['link'])) throw new SystemException("missing 'link' argument in pages tag", 12001);
+               if (!isset($tagArgs['pages'])) {
+                       if (($tagArgs['pages'] = $tplObj->get('pages')) === null) {
+                               throw new SystemException("missing 'pages' argument in pages tag", 12001);
+                       }
+               }
+               
+               $html = '';
+               if ($tagArgs['pages'] > 1) {
+                       // encode link
+                       $link = StringUtil::encodeHTML($tagArgs['link']);
+               
+                       // open div and ul
+                       $html .= "<div class=\"pageNavigation\">\n<ul>\n";
+                       
+                       // generate simple links
+                       $simpleLinks = $tagArgs['pages'];
+                       if ($simpleLinks > self::SHOW_LINKS) {
+                               $simpleLinks = self::SHOW_LINKS - 2;
+                       }
+                       
+                       for ($i = 1; $i <= $simpleLinks; $i++) {
+                               $html .= $this->makeLink($link, $i);
+                       }
+                       
+                       if ($tagArgs['pages'] > self::SHOW_LINKS) {
+                               // jumper
+                               $html .= '<li><a onclick="var result = prompt(\''.WCF::getLanguage()->get('wcf.global.page.input').'\', \''.$tagArgs['pages'].'\'); if (typeof(result) != \'object\' &amp;&amp; typeof(result) != \'undefined\') document.location.href = fixURL((\''.StringUtil::replace("'", "\'", $link).'\').replace(/%d/, result));">&hellip;</a></li>'."\n";
+
+                               // last page
+                               $html .= $this->makeLink($link, $tagArgs['pages']);
+                       }
+                       
+                       // close div and ul
+                       $html .= "</ul></div>\n";
+               }
+               
+               // assign html output to template var
+               if (isset($tagArgs['assign'])) {
+                       $tplObj->assign($tagArgs['assign'], $html);
+                       if (!isset($tagArgs['print']) || !$tagArgs['print']) return '';
+               }
+               
+               return $html;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierArrayfromlist.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierArrayfromlist.class.php
new file mode 100644 (file)
index 0000000..cecb1e0
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\data\option\Option;
+use wcf\system\template\TemplateEngine;
+use wcf\system\template\TemplatePluginModifier;
+
+/**
+ * The 'arrayfromlist' modifier generates an associative array out of a key-value list.
+ * The list has key-value pairs separated by : with each pair on an own line:
+ * 
+ * Example list:
+ * key1:value1
+ * key2:value2
+ * ...
+ * 
+ * Usage:
+ * {$list|arrayfromlist}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginModifierArrayfromlist implements TemplatePluginModifier {
+       /**
+        * @see TemplatePluginModifier::execute()
+        */
+       public function execute($tagArgs, TemplateEngine $tplObj) {
+               return Option::parseSelectOptions($tagArgs[0]);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierConcat.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierConcat.class.php
new file mode 100644 (file)
index 0000000..2d48bcf
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\exception\SystemException;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+\r
+/**\r
+ * The 'concat' modifier returns the string that results from concatenating the arguments.\r
+ * May have two or more arguments.\r
+ * \r
+ * Usage:\r
+ * {"left"|concat:$right}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierConcat implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               if (count($tagArgs) < 2) {\r
+                       throw new SystemException("concat modifier needs two or more arguments", 12001);\r
+               }\r
+               \r
+               $result = '';\r
+               foreach ($tagArgs as $arg) {\r
+                       $result .= $arg;\r
+               }\r
+       \r
+               return $result; \r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierDate.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierDate.class.php
new file mode 100644 (file)
index 0000000..2d07696
--- /dev/null
@@ -0,0 +1,30 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+use wcf\util\DateUtil;\r
+\r
+/**\r
+ * The 'date' modifier formats a unix timestamp.\r
+ * Default date format contains year, month and day.\r
+ * \r
+ * Usage:\r
+ * {$timestamp|date}\r
+ * {"132845333"|date:"Y-m-d"}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierDate implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               return DateUtil::format(DateUtil::getDateTimeByTimestamp($tagArgs[0]), (!empty($tagArgs[2]) ? $tagArgs[2] : DateUtil::DATE_FORMAT));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierDatediff.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierDatediff.class.php
new file mode 100644 (file)
index 0000000..57f0c71
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplateEngine;
+use wcf\system\template\TemplatePluginModifier;
+use wcf\util\DateUtil;
+
+/**
+ * The 'datediff' modifier calculates the difference between two unix timestamps.
+ * 
+ * Usage:
+ * {$timestamp|datediff}
+ * {"123456789"|datediff:$timestamp}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginModifierDatediff implements TemplatePluginModifier {
+       /**
+        * @see TemplatePluginModifier::execute()
+        */
+       public function execute($tagArgs, TemplateEngine $tplObj) {
+               // get timestamps
+               if (!isset($tagArgs[1])) $tagArgs[1] = TIME_NOW;
+               $start = min($tagArgs[0], $tagArgs[1]);
+               $end = max($tagArgs[0], $tagArgs[1]);
+               
+               return DateUtil::diff($start, $end, 'string');
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierEncodejs.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierEncodejs.class.php
new file mode 100644 (file)
index 0000000..9830e54
--- /dev/null
@@ -0,0 +1,42 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'encodejs' modifier formats a string for usage in a single quoted javascript string. \r
+ * Escapes single quotes and new lines.\r
+ * \r
+ * Usage:\r
+ * {$string|encodejs}\r
+ * {"bl''ah"|encodejs}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierEncodejs implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               // escape backslash\r
+               $tagArgs[0] = StringUtil::replace("\\", "\\\\", $tagArgs[0]);\r
+               \r
+               // escape singe quote\r
+               $tagArgs[0] = StringUtil::replace("'", "\'", $tagArgs[0]);\r
+               \r
+               // escape new lines\r
+               $tagArgs[0] = StringUtil::replace("\n", '\n', $tagArgs[0]);\r
+               \r
+               // escape slashes\r
+               $tagArgs[0] = StringUtil::replace("/", '\/', $tagArgs[0]);\r
+               \r
+               return $tagArgs[0];\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierFilesize.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierFilesize.class.php
new file mode 100644 (file)
index 0000000..bc65913
--- /dev/null
@@ -0,0 +1,29 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+use wcf\util\FileUtil;\r
+\r
+/**\r
+ * The 'filesize' modifier formats a filesize (given in bytes).\r
+ * \r
+ * Usage:\r
+ * {$string|filesize}\r
+ * {123456789|filesize}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierFilesize implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               return FileUtil::formatFilesize($tagArgs[0]);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierFilesizeBinary.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierFilesizeBinary.class.php
new file mode 100644 (file)
index 0000000..73e68aa
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplateEngine;
+use wcf\system\template\TemplatePluginModifier;
+use wcf\util\FileUtil;
+
+/**
+ * The 'filesize' modifier formats a filesize (binary) (given in bytes).
+ * 
+ * Usage:
+ * {$string|filesizeBinary}
+ * {123456789|filesizeBinary}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginModifierFilesizeBinary implements TemplatePluginModifier {
+       /**
+        * @see TemplatePluginModifier::execute()
+        */
+       public function execute($tagArgs, TemplateEngine $tplObj) {
+               return FileUtil::formatFilesizeBinary($tagArgs[0]);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierPlainTime.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierPlainTime.class.php
new file mode 100644 (file)
index 0000000..45f1800
--- /dev/null
@@ -0,0 +1,32 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+use wcf\system\WCF;\r
+use wcf\util\DateUtil;\r
+\r
+/**\r
+ * The 'plainTime' modifier formats a unix timestamp.\r
+ * Default date format contains year, month, day, hour and minute.\r
+ * \r
+ * Usage:\r
+ * {$timestamp|plainTime}\r
+ * {"132845333"|plainTime}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierPlainTime implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               $dateTime = DateUtil::getDateTimeByTimestamp($tagArgs[0]);\r
+               return str_replace('%time%', DateUtil::format($dateTime, DateUtil::TIME_FORMAT), str_replace('%date%', DateUtil::format($dateTime, DateUtil::DATE_FORMAT), WCF::getLanguage()->get('wcf.global.date.dateTimeFormat')));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierTime.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierTime.class.php
new file mode 100644 (file)
index 0000000..8646f0d
--- /dev/null
@@ -0,0 +1,37 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+use wcf\system\WCF;\r
+use wcf\util\DateUtil;\r
+\r
+/**\r
+ * The 'time' modifier formats a unix timestamp.\r
+ * Default date format contains year, month, day, hour and minute.\r
+ * \r
+ * Usage:\r
+ * {$timestamp|time}\r
+ * {"132845333"|time}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierTime implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               $timestamp = intval($tagArgs[0]);\r
+               $dateTimeObject = DateUtil::getDateTimeByTimestamp($timestamp);\r
+               $date = DateUtil::format($dateTimeObject, DateUtil::DATE_FORMAT);\r
+               $time = DateUtil::format($dateTimeObject, DateUtil::TIME_FORMAT);\r
+               $dateTime = str_replace('%time%', $time, str_replace('%date%', $date, WCF::getLanguage()->get('wcf.global.date.dateTimeFormat')));\r
+               \r
+               return '<time datetime="'.DateUtil::format($dateTimeObject, 'c').'" class="datetime" data-timestamp="'.$timestamp.'" data-date="'.$date.'" data-time="'.$time.'" data-offset="'.$dateTimeObject->getOffset().'">'.$dateTime.'</time>';\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierTruncate.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginModifierTruncate.class.php
new file mode 100644 (file)
index 0000000..e40fb50
--- /dev/null
@@ -0,0 +1,55 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplateEngine;\r
+use wcf\system\template\TemplatePluginModifier;\r
+use wcf\util\StringUtil;\r
+\r
+/**\r
+ * The 'truncate' modifier truncates a string.\r
+ * \r
+ * Usage:\r
+ * {$foo|truncate:35:'...'}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginModifierTruncate implements TemplatePluginModifier {\r
+       /**\r
+        * @see TemplatePluginModifier::execute()\r
+        */\r
+       public function execute($tagArgs, TemplateEngine $tplObj) {\r
+               // default values\r
+               $length = 80;\r
+               $etc = '...';\r
+               $breakWords = false;\r
+               \r
+               // get values\r
+               $string = $tagArgs[0];\r
+               if (isset($tagArgs[1])) $length = intval($tagArgs[1]);\r
+               if (isset($tagArgs[2])) $etc = $tagArgs[2];\r
+               if (isset($tagArgs[3])) $breakWords = $tagArgs[3];\r
+               \r
+               // execute plugin\r
+               if ($length == 0) {\r
+                       return '';\r
+               }\r
+\r
+               if (StringUtil::length($string) > $length) {\r
+                       $length -= StringUtil::length($etc);\r
+                       \r
+                       if (!$breakWords) {\r
+                               $string = preg_replace('/\s+?(\S+)?$/', '', StringUtil::substring($string, 0, $length + 1));\r
+                       }\r
+  \r
+                       return StringUtil::substring($string, 0, $length).$etc;\r
+               }\r
+               else {\r
+                       return $string;\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterEvent.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterEvent.class.php
new file mode 100644 (file)
index 0000000..e14853f
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplatePluginPrefilter;
+use wcf\system\template\TemplateScriptingCompiler;
+
+/**
+ * The 'event' prefilter inserts template listener's code before compilation.
+ * 
+ * Usage:
+ * {event name='foo'}
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginPrefilterEvent implements TemplatePluginPrefilter {
+       /**
+        * @see TemplatePluginPrefilter::execute()
+        */
+       public function execute($templateName, $sourceContent, TemplateScriptingCompiler $compiler) {
+               $ldq = preg_quote($compiler->getLeftDelimiter(), '~');
+               $rdq = preg_quote($compiler->getRightDelimiter(), '~');
+               $sourceContent = preg_replace("~{$ldq}event\ name\=\'([\w]+)\'{$rdq}~e", 'wcf\system\WCF::getTPL()->getTemplateListenerCode(\''.$templateName.'\', \'$1\')', $sourceContent);
+               
+               return $sourceContent;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterHascontent.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterHascontent.class.php
new file mode 100644 (file)
index 0000000..6aecd54
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplatePluginPrefilter;
+use wcf\system\template\TemplateScriptingCompiler;
+use wcf\util\StringUtil;
+
+/**
+ * The 'hascontent' prefilter inserts ability to insert code dynamically upon the contents of 'content'.
+ * 
+ * Usage:
+ * {hascontent}
+ * <ul>
+ *     {content}
+ *             {if $foo}<li>bar</li>{/if}
+ *     {/content}
+ * </ul>
+ * {hascontentelse}
+ *     <p>baz</p>
+ * {/hascontent}
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginPrefilterHascontent implements TemplatePluginPrefilter {
+       /**
+        * @see TemplatePluginPrefilter::execute()
+        */
+       public function execute($templateName, $sourceContent, TemplateScriptingCompiler $compiler) {
+               $ldq = preg_quote($compiler->getLeftDelimiter(), '~');
+               $rdq = preg_quote($compiler->getRightDelimiter(), '~');
+               
+               $sourceContent = preg_replace_callback("~{$ldq}hascontent{$rdq}(.*){$ldq}content{$rdq}(.*){$ldq}\/content{$rdq}(.*)({$ldq}hascontentelse{$rdq}(.*))?{$ldq}\/hascontent{$rdq}~sU", array('self', 'replaceContentCallback'), $sourceContent);
+               
+               return $sourceContent;
+       }
+       
+       /**
+        * Reorders content to provide a logical order. In fact the content of
+        * '{content}' is moved outside the if-condition in order to capture
+        * the content during runtime, safely determining wether content is empty
+        * or not.
+        * 
+        * @param       array           $matches
+        * @return      string
+        */
+       protected static function replaceContentCallback(array $matches) {
+               $beforeContent = $matches[1];
+               $content = $matches[2];
+               $afterContent = $matches[3];
+               $elseContent = (isset($matches[5])) ? $matches[5] : '';
+               
+               $variable = 'hascontent_' . StringUtil::getRandomID();
+               
+               $newContent = '{capture assign='.$variable.'}'.$content.'{/capture}'."\n";
+               $newContent .= '{assign var='.$variable.' value=$'.$variable.'|trim}'."\n";
+               $newContent .= '{if $'.$variable.'}'.$beforeContent.'{@$'.$variable.'}'."\n".$afterContent;
+               
+               if (!empty($elseContent)) {
+                       $newContent .= '{else}'.$elseContent."\n";
+               }
+               
+               $newContent .= '{/if}'."\n";
+               
+               return $newContent;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterIcon.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterIcon.class.php
new file mode 100644 (file)
index 0000000..71dcb2a
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+namespace wcf\system\template\plugin;
+use wcf\system\template\TemplatePluginPrefilter;
+use wcf\system\template\TemplateScriptingCompiler;
+
+/**
+ * The 'icon' prefilter compiles static icon paths.
+ * 
+ * Usage:
+ * {icon}iconS.png{/icon}
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.template.plugin
+ * @category   Community Framework
+ */
+class TemplatePluginPrefilterIcon implements TemplatePluginPrefilter {
+       /**
+        * @see TemplatePluginPrefilter::execute()
+        */
+       public function execute($sourceContent, TemplateScriptingCompiler $compiler) {
+               $ldq = preg_quote($compiler->getLeftDelimiter(), '~');
+               $rdq = preg_quote($compiler->getRightDelimiter(), '~');
+               $sourceContent = preg_replace("~{$ldq}icon{$rdq}([\w\.]+){$ldq}/icon{$rdq}~", '{literal}<?php echo wcf\system\style\StyleHandler::getInstance()->getStyle()->getIconPath(\'$1\'); ?>{/literal}', $sourceContent);
+
+               return $sourceContent;
+       }
+}
+?>
diff --git a/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterLang.class.php b/wcfsetup/install/files/lib/system/template/plugin/TemplatePluginPrefilterLang.class.php
new file mode 100644 (file)
index 0000000..c8dd0d0
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+namespace wcf\system\template\plugin;\r
+use wcf\system\template\TemplatePluginPrefilter;\r
+use wcf\system\template\TemplateScriptingCompiler;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * The 'lang' prefilter compiles static language variables.\r
+ * Dynamic language variables will catched by the 'lang' compiler function.\r
+ * It is recommended to use static language variables.\r
+ * \r
+ * Usage:\r
+ * {lang}foo{/lang}\r
+ * {lang}lang.foo.bar{/lang}\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage system.template.plugin\r
+ * @category   Community Framework\r
+ */\r
+class TemplatePluginPrefilterLang implements TemplatePluginPrefilter {\r
+       /**\r
+        * @see TemplatePluginPrefilter::execute()\r
+        */\r
+       public function execute($templateName, $sourceContent, TemplateScriptingCompiler $compiler) {\r
+               $ldq = preg_quote($compiler->getLeftDelimiter(), '~');\r
+               $rdq = preg_quote($compiler->getRightDelimiter(), '~');\r
+               $sourceContent = preg_replace("~{$ldq}lang{$rdq}([\w\.]+){$ldq}/lang{$rdq}~e", 'wcf\system\WCF::getLanguage()->get(\'$1\')', $sourceContent);\r
+\r
+               return $sourceContent;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/ArrayUtil.class.php b/wcfsetup/install/files/lib/util/ArrayUtil.class.php
new file mode 100644 (file)
index 0000000..3a0b708
--- /dev/null
@@ -0,0 +1,172 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Contains Array-related functions.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class ArrayUtil {\r
+       /**\r
+        * Applies StringUtil::trim() to all elements of an array.\r
+        *\r
+        * @param       array           $array\r
+        * @param       boolean         $removeEmptyElements\r
+        * @return      array           $array\r
+        */\r
+       public static function trim($array, $removeEmptyElements = true) {\r
+               if (!is_array($array)) {\r
+                       return StringUtil::trim($array);\r
+               }\r
+               else {\r
+                       foreach ($array as $key => $val) {\r
+                               $temp = self::trim($val, $removeEmptyElements);\r
+                               if ($removeEmptyElements && empty($temp)) unset($array[$key]);\r
+                               else $array[$key] = $temp;\r
+                       }\r
+                       return $array;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Applies intval() to all elements of an array.\r
+        *\r
+        * @param       array           $array\r
+        * @return      array           $array\r
+        */\r
+       public static function toIntegerArray($array) {\r
+               if (!is_array($array)) {\r
+                       return intval($array);\r
+               }\r
+               else {\r
+                       foreach ($array as $key => $val) {\r
+                               $array[$key] = self::toIntegerArray($val);\r
+                       }\r
+                       return $array;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Converts html special characters in arrays.\r
+        *\r
+        * @param       array           $array\r
+        * @return      array           $array\r
+        */\r
+       public static function encodeHTML($array) {\r
+               if (!is_array($array)) {\r
+                       return StringUtil::encodeHTML($array);\r
+               }\r
+               else {\r
+                       foreach ($array as $key => $val) {\r
+                               $array[$key] = self::encodeHTML($val);\r
+                       }\r
+                       return $array;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Applies stripslashes on all elements of an array.\r
+        *\r
+        * @param       array           $array\r
+        * @return      array           $array\r
+        */\r
+       public static function stripslashes($array) {\r
+               if (!is_array($array)) {\r
+                       return stripslashes($array);\r
+               }\r
+               else {\r
+                       foreach ($array as $key => $val) {\r
+                               $array[$key] = self::stripslashes($val);\r
+                       }\r
+                       return $array;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Appends a suffix to all elements of the given array.\r
+        *\r
+        * @param       array    $array\r
+        * @param       string   $suffix\r
+        * @return      array\r
+        */\r
+       public static function appendSuffix($array, $suffix) {\r
+               foreach ($array as $key => $value) {\r
+                       $array[$key] = $value . $suffix;\r
+               }\r
+               \r
+               return $array;\r
+       }\r
+       \r
+       /**\r
+        * Computes the intersection of arrays using keys for comparison\r
+        * Alias to php array_intersect_key() function\r
+        *\r
+        * @param       array   $array1         The array with master keys to check. \r
+        * @param       array   $array2         An array to compare keys against.\r
+        * @return                              Returns an associative array containing all the values of array1  which have matching keys that are present in all arguments. \r
+        * @see                                 array_intersect_key\r
+        */\r
+       public static function intersectKeys($array1, $array2) {\r
+               if (!function_exists('array_intersect_key')) {\r
+                       $numberOfArguments = func_num_args();\r
+                       for ($i = 1; !empty($array1) && $i < $numberOfArguments; $i++) {\r
+                               $currentArray = func_get_arg($i);\r
+                               foreach (array_keys($array1) as $key) {\r
+                                       if (!isset($currentArray[$key])) {\r
+                                               unset($array1[$key]);\r
+                                       }\r
+                               }\r
+                       }\r
+                       return $array1;\r
+               } \r
+               else {\r
+                       $parameters = func_get_args();\r
+                       return call_user_func_array('array_intersect_key', $parameters);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Converts dos to unix newlines.\r
+        *\r
+        * @param       array           $array\r
+        * @return      array           $array\r
+        */\r
+       public static function unifyNewlines($array) {\r
+               if (!is_array($array)) {\r
+                       return StringUtil::unifyNewlines($array);\r
+               }\r
+               else {\r
+                       foreach ($array as $key => $val) {\r
+                               $array[$key] = self::unifyNewlines($val);\r
+                       }\r
+                       return $array;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Converts a array of strings to requested character encoding.\r
+        * @see mb_convert_encoding()\r
+        * \r
+        * @param       string          $inCharset\r
+        * @param       string          $outCharset\r
+        * @param       string          $array\r
+        * @return      string          $array\r
+        */\r
+       public static function convertEncoding($inCharset, $outCharset, $array) {\r
+               if (!is_array($array)) {\r
+                       return StringUtil::convertEncoding($inCharset, $outCharset, $array);\r
+               }\r
+               else {\r
+                       foreach ($array as $key => $val) {\r
+                               $array[$key] = self::convertEncoding($inCharset, $outCharset, $val);\r
+                       }\r
+                       return $array;\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/BasicFileUtil.class.php b/wcfsetup/install/files/lib/util/BasicFileUtil.class.php
new file mode 100644 (file)
index 0000000..2895492
--- /dev/null
@@ -0,0 +1,70 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Contains file-related functions.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class BasicFileUtil {\r
+       /**\r
+        * Tries to find the temp folder.\r
+        * \r
+        * @return      string\r
+        */\r
+       public static function getTempFolder() {\r
+               // use tmp folder in document root by default\r
+               if (!empty($_SERVER['DOCUMENT_ROOT'])) {\r
+                       if (strpos($_SERVER['DOCUMENT_ROOT'], 'strato') !== false) {\r
+                               // strato bugfix\r
+                               // create tmp folder in document root automatically\r
+                               if (!@file_exists($_SERVER['DOCUMENT_ROOT'].'/tmp')) { \r
+                                       @mkdir($_SERVER['DOCUMENT_ROOT'].'/tmp/', 0777);\r
+                                       @chmod($_SERVER['DOCUMENT_ROOT'].'/tmp/', 0777);\r
+                               }\r
+                       }\r
+                       if (@file_exists($_SERVER['DOCUMENT_ROOT'].'/tmp') && @is_writable($_SERVER['DOCUMENT_ROOT'].'/tmp')) {\r
+                               return $_SERVER['DOCUMENT_ROOT'].'/tmp/';\r
+                       }\r
+               }\r
+               \r
+               if (isset($_ENV['TMP']) && @is_writable($_ENV['TMP'])) {\r
+                       return $_ENV['TMP'] . '/';\r
+               }\r
+               if (isset($_ENV['TEMP']) && @is_writable($_ENV['TEMP'])) {\r
+                       return $_ENV['TEMP'] . '/';\r
+               }\r
+               if (isset($_ENV['TMPDIR']) && @is_writable($_ENV['TMPDIR'])) {\r
+                       return $_ENV['TMPDIR'] . '/';\r
+               }\r
+               \r
+               // workaround for a bug in php 5.1.2 that returns true for is_writable('/tmp/') with safe_mode = on\r
+               if (!preg_match('/^5\.1\.2(?![.0-9])/', phpversion())) {\r
+                       if (($path = ini_get('upload_tmp_dir')) && @is_writable($path)) {\r
+                               return $path . '/';\r
+                       }\r
+                       if (@file_exists('/tmp/') && @is_writable('/tmp/')) {\r
+                               return '/tmp/';\r
+                       }\r
+                       if (function_exists('session_save_path') && ($path = session_save_path()) && @is_writable($path)) {\r
+                               return $path . '/';\r
+                       }\r
+               }\r
+               \r
+               $path = WCF_DIR.'tmp/';\r
+               if (@file_exists($path) && @is_writable($path)) {\r
+                       return $path;\r
+               }\r
+               else {\r
+                       if (ini_get('safe_mode')) $reason = "due to php safe_mode restrictions";\r
+                       else $reason = "due to an unknown reason";\r
+                       throw new SystemException('There is no access to the system temporary folder '.$reason.' and no user specific temporary folder exists in '.WCF_DIR.'! This is a misconfiguration of your webserver software! Please create a folder called '.$path.' using your favorite ftp program, make it writable and then retry this installation.', 10000);\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/ClassUtil.class.php b/wcfsetup/install/files/lib/util/ClassUtil.class.php
new file mode 100644 (file)
index 0000000..0dfdb59
--- /dev/null
@@ -0,0 +1,36 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Provides methods for class interactions.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class ClassUtil {\r
+       /**\r
+        * Checks wether given class extends or implements the target class or interface.\r
+        * You SHOULD NOT call this method if 'instanceof' satisfies your request!\r
+        *\r
+        * @param       string          $className\r
+        * @param       string          $targetClass\r
+        * @return      boolean\r
+        */\r
+       public static function isInstanceOf($className, $targetClass) {\r
+               if (!is_string($className)) return false;\r
+               \r
+               if (class_exists($targetClass)) {\r
+                       return is_subclass_of($className, $targetClass);\r
+               }\r
+               else if (interface_exists($targetClass)) {\r
+                       $reflectionClass = new \ReflectionClass($className);\r
+                       return $reflectionClass->implementsInterface($targetClass);\r
+               }\r
+               \r
+               return false;\r
+       }\r
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/CronjobUtil.class.php b/wcfsetup/install/files/lib/util/CronjobUtil.class.php
new file mode 100644 (file)
index 0000000..0245f69
--- /dev/null
@@ -0,0 +1,585 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Provides methods used for cron-like time calculations.\r
+ * As against the official cron-documentation, this implementation\r
+ * does not support using nicknames (prefixed by the '@' character).\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+abstract class CronjobUtil {\r
+       /**\r
+        * Set to true if day of month is '*'\r
+        * \r
+        * @var boolean\r
+        */\r
+       protected static $domRestricted = false;\r
+       \r
+       /**\r
+        * Set to true if day of week is '*'\r
+        * \r
+        * @var boolean\r
+        */\r
+       protected static $dowRestricted = false;\r
+       \r
+       /**\r
+        * Result date\r
+        * \r
+        * @var array<integer>\r
+        */\r
+       protected static $result = array();\r
+       \r
+       /**\r
+        * Time based used as reference for finding the next time of execution\r
+        * \r
+        * @var integer\r
+        */\r
+       protected static $timeBase = 0;\r
+       \r
+       /**\r
+        * Valid ranges for each known field. Note that the range for\r
+        * 'day of month' is missing, since it varies on each month.\r
+        * \r
+        * @var array<array>\r
+        */\r
+       public static $ranges = array(\r
+               'minute' => array(0, 59),\r
+               'hour' => array(0, 23),\r
+               'dom' => array(1, 31),\r
+               'month' => array(1, 12),\r
+               'dow' => array(0, 6)\r
+       );\r
+       \r
+       /**\r
+        * Calculates timestamp for next execution based on cron-like expressions and a given time base.\r
+        * \r
+        * @param       string          $minute\r
+        * @param       string          $hour\r
+        * @param       string          $dom\r
+        * @param       string          $month\r
+        * @param       string          $dow\r
+        * @param       integer         $timeBase\r
+        * @return      integer\r
+        */\r
+       public static function calculateNextExec($minute, $hour, $dom, $month, $dow, $timeBase = TIME_NOW) {\r
+               // initialize fields\r
+               self::$timeBase = $timeBase;\r
+               self::$result = array(\r
+                       'minute' => 0,\r
+                       'hour' => 0,\r
+                       'day' => 0,\r
+                       'month' => 0,\r
+                       'year' => 0\r
+               );\r
+               \r
+               $fields = array(\r
+                       'minute' => $minute,\r
+                       'hour' => $hour,\r
+                       'dom' => $dom,\r
+                       'month' => $month,\r
+                       'dow' => $dow\r
+               );\r
+               \r
+               self::$domRestricted = ($dom != '*') ? true : false;\r
+               self::$dowRestricted = ($dow != '*') ? true : false;\r
+               \r
+               // calculate values based upon each expression\r
+               foreach ($fields as $fieldName => $fieldValue) {\r
+                       $fieldValue = StringUtil::toLowerCase($fieldValue);\r
+                       \r
+                       // Names can also be used for the "month" and "day of week" fields.\r
+                       // Use the first three letters of the particular day or month (case\r
+                       // doesn't matter). Ranges or lists of names are not allowed.\r
+                       // -- crontab (5)\r
+                       \r
+                       switch ($fieldName) {\r
+                               case 'dow':\r
+                                       $dayNames = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');\r
+                                       \r
+                                       if (strlen($fieldValue) == 3 && in_array($fieldName, $dayNames)) {\r
+                                               $fieldValue = $monthNames[$fieldValue];\r
+                                       }\r
+                                       // When specifying day of week, both day 0 and day 7\r
+                                       // will be considered Sunday. -- crontab(5) \r
+                                       else if ($fieldValue == 7) {\r
+                                               $fieldValue = 0;\r
+                                       }\r
+                               break;\r
+                               \r
+                               case 'month':\r
+                                       $monthNames = array('jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec');\r
+                                       \r
+                                       if (strlen($fieldValue) == 3 && in_array($fieldValue, $monthNames)) {\r
+                                               $fieldValue = $monthNames[$fieldValue] + 1;\r
+                                       }\r
+                               break;\r
+                       }\r
+                       \r
+                       $values[$fieldName] = self::calculateValue($fieldName, $fieldValue);\r
+               }\r
+               \r
+               // calculate date of next execution\r
+               self::calculateTime($values);\r
+               \r
+               // return timestamp\r
+               return mktime(\r
+                       self::$result['hour'],\r
+                       self::$result['minute'],\r
+                       1,\r
+                       self::$result['month'],\r
+                       self::$result['day'],\r
+                       self::$result['year']\r
+               );\r
+       }\r
+       \r
+       /**\r
+        * Calculates the date of next execution.\r
+        * \r
+        * @param       array           $values\r
+        */\r
+       protected static function calculateTime(array &$values) {\r
+               $timestamp = false;\r
+               \r
+               // calculation starts with month, thus start with\r
+               // month of $time (if within values)\r
+               $currentMonth = date('n', self::$timeBase);\r
+               $currentYear = date('Y', self::$timeBase);\r
+               $index = self::findKey($currentMonth, $values['month']);\r
+               \r
+               self::calculateDay($values);\r
+       }\r
+       \r
+       /**\r
+        * Calculates the day while adjusting month and year to match given criteria.\r
+        * \r
+        * Note: The day of a command's execution can be specified by two fields - day\r
+        * of month, and day of week. If both fields are restricted (ie, aren't *), the\r
+        * command will be run when either field matches the current time. -- crontab(5)\r
+        * \r
+        * @param       array           $values\r
+        * @see         CronjobUtil::getDom()\r
+        */\r
+       protected static function calculateDay(array &$values) {\r
+               $addAnDay = self::calculateHour($values, self::$timeBase);\r
+               $timeBase = self::$timeBase;\r
+               \r
+               if ($addAnDay) {\r
+                       $date = getdate($timeBase);\r
+                       $timeBase = mktime(0, 0, 1, $date['mon'], $date['mday'] + 1, $date['year']);\r
+               }\r
+               \r
+               $day = date('j', $timeBase);\r
+               $month = date('n', $timeBase);\r
+               $year = date('Y', $timeBase);\r
+               \r
+               // calculate date of next execution based upon day of week\r
+               $dateDow = self::calculateDow($month, $year, $values, $day);\r
+               $dateDowTimestamp = mktime(0, 0, 1, $dateDow['month'], $dateDow['day'], $dateDow['year']);\r
+               \r
+               // calculate date of next execution based upon day of month\r
+               $dateDom = self::calculateDom($month, $year, $values, $day);\r
+               $dateDomTimestamp = mktime(0, 0, 1, $dateDom['month'], $dateDom['day'], $dateDom['year']);\r
+               \r
+               // pick the earlier date if both dom and dow are restricted\r
+               if (self::$domRestricted && self::$dowRestricted) {\r
+                       if ($dateDowTimestamp < $dateDomTimestamp) {\r
+                               self::$result['day'] = $dateDow['day'];\r
+                               self::$result['month'] = $dateDow['month'];\r
+                               self::$result['year'] = $dateDow['year'];\r
+                       }\r
+                       else {\r
+                               self::$result['day'] = $dateDom['day'];\r
+                               self::$result['month'] = $dateDom['month'];\r
+                               self::$result['year'] = $dateDom['year'];\r
+                       }\r
+               }\r
+               else {\r
+                       if (self::$domRestricted) {\r
+                               self::$result['day'] = $dateDom['day'];\r
+                               self::$result['month'] = $dateDom['month'];\r
+                               self::$result['year'] = $dateDom['year'];\r
+                       }\r
+                       else if (self::$dowRestricted) {\r
+                               self::$result['day'] = $dateDow['day'];\r
+                               self::$result['month'] = $dateDow['month'];\r
+                               self::$result['year'] = $dateDow['year'];\r
+                       }\r
+                       // neither dom nor dow are restricted, thus pick the date given by time base\r
+                       else {\r
+                               self::$result['day'] = $day;\r
+                               self::$result['month'] = $month;\r
+                               self::$result['year'] = $year;\r
+                       }\r
+                       \r
+               }\r
+               \r
+               // compare day, month and year wether we have to recalculate hour and minute\r
+               if (($day != self::$result['day']) || ($month != self::$result['month']) || ($year != self::$result['year'])) {\r
+                       // calculate new time base\r
+                       $timeBase = mktime(0, 0, 1, self::$result['month'], self::$result['day'], self::$result['year']);\r
+                       \r
+                       self::calculateHour($values, $timeBase);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Calculates the date of next execution based upon a given set for day of week.\r
+        * \r
+        * @param       integer         $month\r
+        * @param       integer         $year\r
+        * @param       array           $values\r
+        * @param       integer         $day\r
+        * @return      array\r
+        */\r
+       protected static function calculateDow($month, $year, array &$values, $day = 1) {\r
+               $days = date('t', mktime(0, 0, 1, $month, $day, $year));\r
+               \r
+               for ($i = $day; $i <= $days; $i++) {\r
+                       // get dow\r
+                       $dow = date('w', mktime(0, 0, 1, $month, $i, $year));\r
+                       \r
+                       if (in_array($dow, $values['dow'])) {\r
+                               return array(\r
+                                       'day' => $i,\r
+                                       'month' => $month,\r
+                                       'year' => $year\r
+                               );\r
+                       }\r
+               }\r
+               \r
+               // try next month\r
+               return self::calculateDow(++$month, $year, $values);\r
+       }\r
+       \r
+       /**\r
+        * Calculates the date of next execution based upon a given set for day of month.\r
+        * \r
+        * @param       integer         $month\r
+        * @param       integer         $year\r
+        * @param       array           $values\r
+        * @param       integer         $day\r
+        * @return      array\r
+        */\r
+       protected static function calculateDom($month, $year, array &$values, $day = 1) {\r
+               $days = date('t', mktime(0, 0, 1, $month, $day, $year));\r
+               \r
+               for ($i = $day; $i <= $days; $i++) {\r
+                       if (in_array($i, $values['dom'])) {\r
+                               return array(\r
+                                       'day' => $i,\r
+                                       'month' => $month,\r
+                                       'year' => $year\r
+                               );\r
+                       }\r
+               }\r
+               \r
+               // try next month\r
+               return self::calculateDom(++$month, $year, $values);\r
+       }\r
+       \r
+       /**\r
+        * Calculates hour of next execution. Returns number of days which\r
+        * had been added in order to match expression for hour and minutes.\r
+        * \r
+        * @param       array           $values\r
+        * @param       integer         $timeBase\r
+        * @return      integer\r
+        */\r
+       protected static function calculateHour(array &$values, &$timeBase) {\r
+               $addAnDay = false;\r
+               \r
+               // compare hour\r
+               $hour = intval(date('G', $timeBase));\r
+               $index = self::findKey($hour, $values['hour'], false);\r
+               if ($index === false) {\r
+                       $index = self::findKey($hour, $values['hour']);\r
+                       $addAnDay = true;\r
+               }\r
+               $hour = $values['hour'][$index];\r
+               \r
+               // calculate minutes\r
+               $addAnHour = self::calculateMinute($values, $timeBase, $addAnDay);\r
+               \r
+               if ($addAnHour) {\r
+                       $hour++;\r
+                       $index = self::findKey($hour, $values['hour'], false);\r
+                       \r
+                       if ($index === false) {\r
+                               if ($index === false) {\r
+                                       $index = self::findKey($hour, $values['hour']);\r
+                                       $addAnDay = true;\r
+                               }\r
+                               $hour = $values['hour'][$index];\r
+                       }\r
+               }\r
+               \r
+               self::$result['hour'] = $hour;\r
+               \r
+               return $addAnDay;\r
+       }\r
+       \r
+       /**\r
+        * Calculates minutes of next execution. Returns false if minute-declaration\r
+        * is past the current hour, thus requires to add at least one hour.\r
+        * \r
+        * @param       array           $values\r
+        * @param       integer         $timeBase\r
+        * @return      boolean\r
+        */\r
+       protected static function calculateMinute(array &$values, &$timeBase, $addAnDay) {\r
+               $returnValue = false;\r
+               \r
+               if ($addAnDay) {\r
+                       $minute = 0;\r
+               }\r
+               else {\r
+                       $minute = date('i', $timeBase);\r
+               }\r
+               \r
+               $index = self::findKey($minute, $values['minute'], false);\r
+               \r
+               // if index was out of bounds, pick the first item but\r
+               // notify calling method that we had to increase the hour\r
+               if ($index === false) {\r
+                       $index = self::findKey($minute, $values['minute']);\r
+                       $returnValue = true;\r
+               }\r
+               \r
+               self::$result['minute'] = $values['minute'][$index];\r
+               \r
+               return $returnValue;\r
+       }\r
+       \r
+       /**\r
+        * Tries to find index of an array element which is bigger or equal the current\r
+        * needle. If $continue is not set to false and foreach-loop is out of bounds,\r
+        * then the array-index '0' is returned, referring the first item.\r
+        * \r
+        * @param       integer         $needle\r
+        * @param       array           $haystack\r
+        * @param       boolean         $continue\r
+        * @return      mixed\r
+        */\r
+       protected static function findKey($needle, array &$haystack, $continue = true) {\r
+               $index = array_search($needle, $haystack);\r
+               \r
+               if ($index === false) {\r
+                       foreach ($haystack as $key => $value) {\r
+                               if ($needle < $value) {\r
+                                       $index = $key;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       if ($continue && $index === false) {\r
+                               $index = 0;\r
+                       }\r
+               }\r
+               \r
+               return $index;\r
+       }\r
+       \r
+       /**\r
+        * Calculates all values matching possible expressions.\r
+        * \r
+        * @param       string          $fieldName\r
+        * @param       string          $fieldValue\r
+        * @return      array\r
+        */\r
+       protected static function calculateValue($fieldName, $fieldValue) {\r
+               $values = array();\r
+               \r
+               // examinate first char\r
+               $char = StringUtil::substring($fieldValue, 0, 1);\r
+               \r
+               // could be a single value, range or list\r
+               if (is_numeric($char)) {\r
+                       $items = self::getListItems($fieldValue);\r
+                       \r
+                       foreach ($items as $item) {\r
+                               $values = array_merge($values, self::getRanges($item));\r
+                       }\r
+               }\r
+               // asterisk may be followed by a step value\r
+               else if ($char == '*') {\r
+                       $step = 1;\r
+                       \r
+                       if (StringUtil::indexOf($fieldValue, '/') !== false) {\r
+                               $rangeData = explode('/', $fieldValue);\r
+                               $step = $rangeData[1];\r
+                       }\r
+                       \r
+                       $values = self::calculateRange(self::$ranges[$fieldName][0], self::$ranges[$fieldName][1], $step);\r
+               }\r
+               \r
+               sort($values, SORT_NUMERIC);\r
+               \r
+               return $values;\r
+       }\r
+       \r
+       /**\r
+        * Tries to parse list items separated by a comma.\r
+        * \r
+        * @param       string          $fieldValue\r
+        * @return      array\r
+        */\r
+       protected static function getListItems($fieldValue) {\r
+               if (StringUtil::indexOf($fieldValue, ',') !== false) {\r
+                       return explode(',', $fieldValue);\r
+               }\r
+               \r
+               return array($fieldValue);\r
+       }\r
+       \r
+       /**\r
+        * Parses a possible range of values including a step value.\r
+        * \r
+        * @param       string          $value\r
+        * @return      array\r
+        */\r
+       protected static function getRanges($value) {\r
+               // this is a single value\r
+               if (StringUtil::indexOf($value, '-') === false) {\r
+                       return array($value);\r
+               }\r
+               \r
+               $step = 1;\r
+               if (StringUtil::indexOf($value, '/') !== false) {\r
+                       $data = explode('/', $value);\r
+                       $step = $data[1];\r
+                       $value = $data[0];\r
+               }\r
+               \r
+               $data = explode('-', $value);\r
+               \r
+               return self::calculateRange($data[0], $data[1], $step);\r
+       }\r
+       \r
+       /**\r
+        * Calculates all values for a given range.\r
+        * \r
+        * @param       integer         $startValue\r
+        * @param       integer         $endValue\r
+        * @param       integer         $step\r
+        * @return      array\r
+        */\r
+       protected static function calculateRange($startValue, $endValue, $step = 1) {\r
+               $values = array();\r
+               \r
+               for ($i = $startValue; $i <= $endValue; $i = $i + $step) {\r
+                       $values[] = $i;\r
+               }\r
+               \r
+               return $values;\r
+       }\r
+       \r
+       /**\r
+        * Validates all cronjob attributes.\r
+        * \r
+        * @param       string          $startMinute\r
+        * @param       string          $startHour\r
+        * @param       string          $startDom\r
+        * @param       string          $startMonth\r
+        * @param       string          $startDow\r
+        * \r
+        * @todo        Move code to seperate class, e.g. CronjobUtil\r
+        */\r
+       public static function validate($startMinute, $startHour, $startDom, $startMonth, $startDow) {\r
+               self::validateAttribute('startMinute', $startMinute);\r
+               self::validateAttribute('startHour', $startHour);\r
+               self::validateAttribute('startDom', $startDom);\r
+               self::validateAttribute('startMonth', $startMonth);\r
+               self::validateAttribute('startDow', $startDow);\r
+       }\r
+       \r
+       /**\r
+        * Validates a cronjob attribute.\r
+        * \r
+        * @param       string          $name\r
+        * @param       string          $value\r
+        * @todo        Move code to seperate class, e.g. CronjobUtil\r
+        */\r
+       protected static function validateAttribute($name, $value) {\r
+               if ($value === '') {\r
+                       throw new SystemException("invalid value '".$value."' given for cronjob attribute '".$name."'");\r
+               }\r
+               \r
+               $pattern = '';\r
+               $step = '[1-9]?[0-9]';\r
+               $months = 'jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec';\r
+               $days = 'mon|tue|wed|thu|fri|sat|sun';\r
+               $namesArr = array();\r
+               \r
+               switch ($name) {\r
+                       // check if startMinute is a valid minute or a list of valid minutes.\r
+                       case 'startMinute':\r
+                               $pattern = '[ ]*(\b[0-5]?[0-9]\b)[ ]*';\r
+                               break;\r
+                               \r
+                       // check if startHour is a valid hour or a list of valid hours.\r
+                       case 'startHour':\r
+                               $pattern = '[ ]*(\b[01]?[0-9]\b|\b2[0-3]\b)[ ]*';\r
+                               break;\r
+                               \r
+                       // check if startDom is a valid day of month or a list of valid days of month.\r
+                       case 'startDom':\r
+                               $pattern = '[ ]*(\b[01]?[1-9]\b|\b2[0-9]\b|\b3[01]\b)[ ]*';\r
+                               break;\r
+                               \r
+                       // check if startMonth is a valid month or a list of valid months.\r
+                       case 'startMonth':\r
+                               $digits = '[ ]*(\b[0-1]?[0-9]\b)[ ]*';\r
+                               $namesArr = explode('|', $months);\r
+                               $pattern = '('.$digits.')|([ ]*('.$months.')[ ]*)';\r
+                               break;\r
+                               \r
+                       // check if startDow is a valid day of week or a list of valid days of week.\r
+                       case 'startDow':\r
+                               $digits = '[ ]*(\b[0]?[0-7]\b)[ ]*';\r
+                               $namesArr = explode('|', $days);\r
+                               $pattern = '('.$digits.')|([ ]*('.$days.')[ ]*)';\r
+                               break;\r
+               }\r
+               \r
+               // perform the actual regex pattern matching.\r
+               $range = '((('.$pattern.')|(\*\/'.$step.')?)|((('.$pattern.')-('.$pattern.'))(\/'.$step.')?))';\r
+               \r
+               // $longPattern prototype: ^\d+(,\d)*$\r
+               // $longPattern = '/^(?<!,)'.$range.'+(,'.$range.')*$/i'; // with assertions?\r
+               // $longPattern = '/^'.$range.'+(,'.$range.')*$/i'; / does not work on some php installations\r
+               $longPattern = '/^'.$range.'(,'.$range.')*$/i';\r
+               \r
+               preg_match($longPattern, $value);\r
+               if ($value != '*' && !preg_match($longPattern, $value)) {\r
+                       throw new SystemException("invalid value '".$value."' given for cronjob attribute '".$name."'");\r
+               }\r
+               // test whether the user provided a meaningful order inside a range.\r
+               else {\r
+                       $testArr = explode(',', $value);\r
+                       foreach ($testArr as $testField) {\r
+                               if ($pattern && preg_match('/^((('.$pattern.')-('.$pattern.'))(\/'.$step.')?)+$/', $testField)) {\r
+                                       $compare = explode('-', $testField);\r
+                                       $compareSlash = explode('/', $compare['1']);\r
+                                       if (count($compareSlash) == 2) $compare['1'] = $compareSlash['0'];\r
+                                       \r
+                                       // see if digits or names are being given.\r
+                                       $left = array_search(StringUtil::toLowerCase($compare['0']), $namesArr);\r
+                                       $right = array_search(StringUtil::toLowerCase($compare['1']), $namesArr);\r
+                                       if (!$left) $left = $compare['0'];\r
+                                       if (!$right) $right = $compare['1'];\r
+                                       // now check the values.\r
+                                       if (intval($left) > intval($right)) {\r
+                                               throw new SystemException("invalid value '".$value."' given for cronjob attribute '".$name."'");\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/DateUtil.class.php b/wcfsetup/install/files/lib/util/DateUtil.class.php
new file mode 100644 (file)
index 0000000..a2ac641
--- /dev/null
@@ -0,0 +1,254 @@
+<?php
+namespace wcf\util;
+use wcf\system\WCF;
+use wcf\data\user\User;
+use wcf\data\language\Language;
+
+/**
+ * Contains date-related functions.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage util
+ * @category   Community Framework
+ */
+class DateUtil {
+       /**
+        * name of the default date format language variable
+        * @var string
+        */
+       const DATE_FORMAT = 'wcf.global.date.dateFormat';
+       
+       /**
+        * name of the default time format language variable
+        * @var string
+        */
+       const TIME_FORMAT = 'wcf.global.date.timeFormat';
+       
+       /**
+        * list of available time zones
+        * @var array<string>
+        */
+       protected static $availableTimezones = array(
+               'Pacific/Kwajalein', // (GMT-12:00) International Date Line West
+               'Pacific/Midway', // (GMT-11:00) Midway Island
+               'Pacific/Samoa', // (GMT-11:00) Samoa
+               'Pacific/Honolulu', // (GMT-10:00) Hawaii
+               'America/Anchorage', // (GMT-09:00) Alaska
+               'America/Tijuana', // (GMT-08:00) Tijuana, Baja California
+               'America/Los_Angeles', // (GMT-08:00) Pacific Time (US & Canada)
+               'America/Phoenix', // (GMT-07:00) Arizona
+               'America/Chihuahua', // (GMT-07:00) Chihuahua, Mazatlan
+               'America/Denver', // (GMT-07:00) Mountain Time (US & Canada)
+               'America/Chicago', // (GMT-06:00) Central Time (US & Canada)    
+               'America/Mexico_City', // (GMT-06:00) Mexico City, Monterrey
+               'America/Tegucigalpa', // (GMT-06:00) Central America
+               'America/Regina', // (GMT-06:00) Saskatchewan
+               'America/Bogota', // (GMT-05:00) Bogota, Lima
+               'America/New_York', // (GMT-05:00) Eastern Time (US & Canada)
+               'America/Indiana/Indianapolis', // (GMT-05:00) Indiana (East)
+               'America/Rio_Branco', // (GMT-05:00) Rio Branco
+               'America/Caracas', // (GMT-04:30) Caracas
+               'America/Asuncion', // UTC-04:00 Asuncion
+               'America/Halifax', // (GMT-04:00) Atlantic Time (Canada)
+               'America/Cuiaba', // UTC-04:00 Cuiaba
+               'America/La_Paz', // (GMT-04:00) Georgetown, La Paz, Manaus
+               'America/Santiago', // (GMT-04:00) Santiago
+               'America/St_Johns', // (GMT-03:30) Newfoundland
+               'America/Sao_Paulo', // (GMT-03:00) Brasilia
+               'America/Argentina/Buenos_Aires', // (GMT-03:00) Buenos Aires
+               'America/Cayenne', // UTC-03:00 Cayenne
+               'America/Godthab', // (GMT-03:00) Greenland
+               'America/Montevideo', // (GMT-03:00) Montevideo
+               'Atlantic/South_Georgia', // (GMT-02:00) Mid-Atlantic
+               'Atlantic/Azores', // (GMT-01:00) Azores
+               'Atlantic/Cape_Verde', // (GMT-01:00) Cape Verde Is.
+               'Africa/Casablanca', // (GMT) Casablanca
+               'Europe/London', // (GMT) Dublin, Lisbon, London
+               'Africa/Monrovia', // (GMT) Monrovia, Reykjavik
+               'Europe/Berlin', // (GMT+01:00) Amsterdam, Berlin, Rome, Stockholm, Vienna
+               'Europe/Belgrade', // (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
+               'Europe/Paris', // (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
+               'Europe/Sarajevo', // (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
+               'Africa/Algiers', // (GMT+01:00) West Central Africa
+               'Africa/Windhoek', // (GMT+01:00) Windhoek
+               'Asia/Amman', // (GMT+02:00) Amman
+               'Europe/Athens', // (GMT+02:00) Athens, Bucharest, Istanbul
+               'Asia/Beirut', // (GMT+02:00) Beirut
+               'Asia/Damascus', // (GMT+02:00) Damascus
+               'Africa/Harare', // (GMT+02:00) Harare
+               'Europe/Helsinki', // (GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius
+               'Asia/Jerusalem', // (GMT+02:00) Jerusalem
+               'Africa/Cairo', // (GMT+02:00) Cairo
+               'Europe/Minsk', // (GMT+02:00) Minsk
+               'Asia/Baghdad', // (GMT+03:00) Baghdad
+               'Asia/Kuwait', // (GMT+03:00) Kuwait, Riyadh
+               'Europe/Moscow', // (GMT+03:00) Moscow, Volgograd
+               'Africa/Nairobi', // (GMT+03:00) Nairobi
+               'Asia/Tehran', // (GMT+03:30) Tehran
+               'Asia/Muscat', // (GMT+04:00) Muscat
+               'Asia/Baku', // (GMT+04:00) Baku
+               'Asia/Yerevan', // (GMT+04:00) Yerevan
+               'Indian/Mauritius', // UTC+04:00 Port Loius
+               'Asia/Tbilisi', // UTC+04:00 Tbilisi
+               'Asia/Kabul', // UTCU+04:30 Kabul
+               'Asia/Karachi', // (GMT+05:00) Karachi
+               'Asia/Yekaterinburg', // (GMT+05:00) Ekaterinburg
+               'Asia/Tashkent', // (GMT+05:00) Tashkent
+               'Asia/Kolkata', // (GMT+05:30) Calcutta, New Dehli
+               'Asia/Colombo', // (GMT+05:30) Sri Jayawardenepura
+               'Asia/Katmandu', // (GMT+05:45) Kathmandu
+               'Asia/Almaty', // (GMT+06:00) Almaty
+               'Asia/Dhaka', // (GMT+06:00) Dhaka
+               'Asia/Novosibirsk', // (GMT+06:00) Novosibirsk
+               'Asia/Rangoon', // (GMT+06:30) Yangon (Rangoon)
+               'Asia/Bangkok', // (GMT+07:00) Bangkok, Jakarta
+               'Asia/Krasnoyarsk', // (GMT+07:00) Krasnoyarsk
+               'Asia/Irkutsk', // (GMT+08:00) Irkutsk
+               'Asia/Kuala_Lumpur', // (GMT+08:00) Kuala Lumpur, Singapore
+               'Asia/Chongqing', // (GMT+08:00) Beijing, Chongqing, Hong Kong
+               'Australia/Perth', // (GMT+08:00) Perth
+               'Asia/Taipei', // (GMT+08:00) Taipei
+               'Asia/Ulaanbaatar', // (GMT+08:00) Ulaan Bataar
+               'Asia/Yakutsk', // (GMT+09:00) Yakutsk
+               'Asia/Tokyo', // (GMT+09:00) Tokyo
+               'Asia/Seoul', // (GMT+09:00) Seoul
+               'Australia/Adelaide', // (GMT+09:30) Adelaide
+               'Australia/Darwin', // (GMT+09:30) Darwin
+               'Australia/Brisbane', // (GMT+10:00) Brisbane
+               'Australia/Sydney', // (GMT+10:00) Canberra, Melbourne, Sydney
+               'Pacific/Guam', // (GMT+10:00) Guam, Port Moresby
+               'Australia/Hobart', // (GMT+10:00) Hobart
+               'Asia/Vladivostok', // (GMT+10:00) Vladivostok
+               'Asia/Magadan', // (GMT+11:00) Magadan
+               'Pacific/Noumea', // UTC+11:00 New Caledonia
+               'Pacific/Auckland', // (GMT+12:00) Auckland
+               'Pacific/Fiji', // (GMT+12:00) Fiji
+               'Asia/Kamchatka', // (GMT+12:00) Kamchatka
+               'Pacific/Tongatapu', // (GMT+13:00) Nukualofa
+       );
+       
+       /**
+        * Returns a formatted date.
+        * 
+        * @param       DateTime                $time
+        * @param       string                  $format
+        * @param       Language                $language
+        * @param       User                    $user
+        */
+       public static function format(\DateTime $time = null, $format = null, Language $language = null, User $user = null) {
+               // get default values
+               if ($time === null) $time = new \DateTime();
+               if ($user === null) $user = WCF::getUser();
+               if ($language === null) $language = WCF::getLanguage();
+               if ($format === null) $format = self::DATE_FORMAT;
+               
+               // set time zone
+               $time->setTimezone($user->getTimeZone());
+               
+               // format date
+               $output = $time->format($language->get($format));
+               
+               // localize output
+               $output = self::localizeDate($output, $format, $language);
+               
+               return $output;
+       }
+       
+       /**
+        * Returns a localized date output.
+        * 
+        * @param       string          $date
+        * @param       string          $format
+        * @param       Language        $language
+        */
+       public static function localizeDate($date, $format, Language $language) {
+               if ($language->languageCode != 'en') {
+                       // full textual representation of the day of the week (l)
+                       if (stripos($format, 'l') !== false) {
+                               $date = str_replace(array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), array(
+                                       $language->get('wcf.global.date.day.sunday'),
+                                       $language->get('wcf.global.date.day.monday'),
+                                       $language->get('wcf.global.date.day.tuesday'),
+                                       $language->get('wcf.global.date.day.wednesday'),
+                                       $language->get('wcf.global.date.day.thursday'),
+                                       $language->get('wcf.global.date.day.friday'),
+                                       $language->get('wcf.global.date.day.saturday')
+                               ), $date);
+                       }
+                       
+                       // textual representation of a day, three letters (D)
+                       if (stripos($format, 'D') !== false) {
+                               $date = str_replace(array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'), array(
+                                       $language->get('wcf.global.date.day.sun'),
+                                       $language->get('wcf.global.date.day.mon'),
+                                       $language->get('wcf.global.date.day.tue'),
+                                       $language->get('wcf.global.date.day.wed'),
+                                       $language->get('wcf.global.date.day.thu'),
+                                       $language->get('wcf.global.date.day.fri'),
+                                       $language->get('wcf.global.date.day.sat')
+                               ), $date);
+                       }
+                       
+                       // full textual representation of a month (F)
+                       if (stripos($format, 'F') !== false) {
+                               $date = str_replace(array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'), array(
+                                       $language->get('wcf.global.date.month.january'),
+                                       $language->get('wcf.global.date.month.february'),
+                                       $language->get('wcf.global.date.month.march'),
+                                       $language->get('wcf.global.date.month.april'),
+                                       $language->get('wcf.global.date.month.may'),
+                                       $language->get('wcf.global.date.month.june'),
+                                       $language->get('wcf.global.date.month.july'),
+                                       $language->get('wcf.global.date.month.august'),
+                                       $language->get('wcf.global.date.month.september'),
+                                       $language->get('wcf.global.date.month.october'),
+                                       $language->get('wcf.global.date.month.november'),
+                                       $language->get('wcf.global.date.month.december')
+                               ), $date);
+                       }
+                       
+                       // short textual representation of a month (M)
+                       if (stripos($format, 'M') !== false) {
+                               $date = str_replace(array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), array(
+                                       $language->get('wcf.global.date.month.jan'),
+                                       $language->get('wcf.global.date.month.feb'),
+                                       $language->get('wcf.global.date.month.mar'),
+                                       $language->get('wcf.global.date.month.apr'),
+                                       $language->get('wcf.global.date.month.may'),
+                                       $language->get('wcf.global.date.month.jun'),
+                                       $language->get('wcf.global.date.month.jul'),
+                                       $language->get('wcf.global.date.month.aug'),
+                                       $language->get('wcf.global.date.month.sep'),
+                                       $language->get('wcf.global.date.month.oct'),
+                                       $language->get('wcf.global.date.month.nov'),
+                                       $language->get('wcf.global.date.month.dec')
+                               ), $date);
+                       }
+               }
+               
+               return $date;
+       }
+       
+       /**
+        * Creates a DateTime object with the given unix timestamp.
+        * 
+        * @param       integer         $timestamp
+        * @return      DateTime
+        */
+       public static function getDateTimeByTimestamp($timestamp) {
+               return new \DateTime('@'.$timestamp);
+       }
+       
+       /**
+        * Returns a list of available timezones.
+        * 
+        * @return      array<string>
+        */
+       public static function getAvailableTimezones() {
+               return self::$availableTimezones;
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/FileUtil.class.php b/wcfsetup/install/files/lib/util/FileUtil.class.php
new file mode 100644 (file)
index 0000000..1aa3507
--- /dev/null
@@ -0,0 +1,568 @@
+<?php\r
+namespace wcf\util;\r
+use wcf\system\io\File;\r
+use wcf\system\io\ZipFile;\r
+use wcf\system\io\RemoteFile;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * Contains file-related functions.\r
+ *\r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class FileUtil {\r
+       /** \r
+        * Generates a new temporary filename in TMP_DIR.\r
+        *\r
+        * @param       string          $prefix\r
+        * @param       string          $extension\r
+        * @param       string          $dir\r
+        * @return      string                          temporary filename\r
+        */\r
+       public static function getTemporaryFilename($prefix = 'tmpFile_', $extension = '', $dir = TMP_DIR) {\r
+               $dir = self::addTrailingSlash($dir);\r
+               do {\r
+                       $tmpFile = $dir.$prefix.StringUtil::getRandomID().$extension;\r
+               }\r
+               while (file_exists($tmpFile));  \r
+               \r
+               return $tmpFile;\r
+       }\r
+       \r
+       /**\r
+        * Removes a leading slash. \r
+        *\r
+        * @param       string          $path\r
+        * @return      string          $path\r
+        */\r
+       public static function removeLeadingSlash($path) {\r
+               if (substr($path, 0, 1) == '/') {\r
+                       return substr($path, 1);\r
+               }\r
+               else {\r
+                       return $path;   \r
+               }       \r
+       }\r
+\r
+       /**\r
+        * Removes a trailing slash. \r
+        *\r
+        * @param       string          $path\r
+        * @return      string          $path\r
+        */\r
+       public static function removeTrailingSlash($path) {\r
+               if (substr($path, -1) == '/') {\r
+                       return substr($path, 0, -1);\r
+               }\r
+               else {\r
+                       return $path;\r
+               }       \r
+       }\r
+       \r
+       /**\r
+        * Adds a trailing slash. \r
+        *\r
+        * @param       string          $path\r
+        * @return      string          $path\r
+        */\r
+       public static function addTrailingSlash($path) {\r
+               if (substr($path, -1) != '/') {\r
+                       return $path.'/';\r
+               }\r
+               else {\r
+                       return $path;\r
+               }       \r
+       }\r
+\r
+       /**\r
+        * Builds a relative path from two absolute paths.\r
+        *\r
+        * @param       string          $currentDir\r
+        * @param       string          $targetDir\r
+        * @return      string                          relative Path\r
+        */\r
+       public static function getRelativePath($currentDir, $targetDir) {\r
+               // remove trailing slashes\r
+               $currentDir = self::removeTrailingSlash(self::unifyDirSeperator($currentDir));\r
+               $targetDir = self::removeTrailingSlash(self::unifyDirSeperator($targetDir));\r
+               \r
+               if ($currentDir == $targetDir) {\r
+                       return './';    \r
+               }\r
+               \r
+               $current = explode('/', $currentDir);\r
+               $target = explode('/', $targetDir);\r
+               \r
+               $relPath = '';\r
+               //for ($i = max(count($current), count($target)) - 1; $i >= 0; $i--) {\r
+               for ($i = 0, $max = max(count($current), count($target)); $i < $max; $i++) {\r
+                       if (isset($current[$i]) && isset($target[$i])) {\r
+                               if ($current[$i] != $target[$i]) {\r
+                                       for ($j = 0; $j < $i; $j++) {\r
+                                               unset($target[$j]);     \r
+                                       }\r
+                                       $relPath .= str_repeat('../', count($current) - $i).implode('/', $target).'/';  \r
+                                       for ($j = $i + 1; $j < count($current); $j++) {\r
+                                               unset($current[$j]);    \r
+                                       }\r
+                                       break;\r
+                               }\r
+                       }       \r
+                       // go up one level\r
+                       else if (isset($current[$i]) && !isset($target[$i])) {\r
+                               $relPath .= '../';\r
+                       }\r
+                       else if (!isset($current[$i]) && isset($target[$i])) {\r
+                               $relPath .= $target[$i].'/';\r
+                       }\r
+               }\r
+               \r
+               return $relPath;\r
+       }\r
+       \r
+       /**\r
+        * Creates a path on the local filesystem. \r
+        * Parent directories do not need to exists as\r
+        * they will be created if necessary.\r
+        * Return true on success, otherwise false.\r
+        * \r
+        * @param       string          $path\r
+        * @param       integer         $chmod\r
+        * @return      boolean                         success\r
+        */\r
+       public static function makePath($path, $chmod = 0777) {\r
+               // directory already exists, abort\r
+               if (file_exists($path)) {\r
+                       return false;\r
+               }\r
+               \r
+               // check if parent directory exists\r
+               $parent = dirname($path);\r
+               if ($parent != $path) {\r
+                       // parent directory does not exist either\r
+                       // we have to create the parent directory first\r
+                       $parent = self::addTrailingSlash($parent);\r
+                       if (!@file_exists($parent)) {\r
+                               // could not create parent directory either => abort\r
+                               if (!self::makePath($parent, $chmod)) {\r
+                                       return false;   \r
+                               }\r
+                       }\r
+                       \r
+                       // well, the parent directory exists or has been created\r
+                       // lets create this path\r
+                       $oldumask = @umask(0);\r
+                       if (!@mkdir($path, $chmod)) {\r
+                               return false;\r
+                       }\r
+                       @umask($oldumask);\r
+                       /*if (!@chmod($path, $chmod)) {\r
+                               return false;\r
+                       }*/\r
+                       if (self::isApacheModule() || !@is_writable($path)) {\r
+                               @chmod($path, 0777);\r
+                       }\r
+                       \r
+                       return true;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Unifies windows and unix directory seperators.\r
+        *\r
+        * @param       string          $path\r
+        * @return      string          $path\r
+        */\r
+       public static function unifyDirSeperator($path) {\r
+               $path = str_replace('\\\\', '/', $path);\r
+               $path = str_replace('\\', '/', $path);\r
+               return $path;\r
+       }\r
+       \r
+       /**\r
+        * Scans a folder (and subfolder) for a specific file.\r
+        * Returns the filename if found, otherwise false.\r
+        *\r
+        * @param       string          $folder\r
+        * @param       string          $searchfile\r
+        * @param       boolean         $recursive\r
+        * @return      mixed           $found\r
+        */\r
+       public static function scanFolder($folder, $searchfile, $recursive = true) {\r
+               if (!@is_dir($folder)) {\r
+                       return false;\r
+               }\r
+               if (!$searchfile) {\r
+                       return false;\r
+               }\r
+\r
+               $folder = self::addTrailingSlash($folder);\r
+               $dirh = @opendir($folder);\r
+               while ($filename = @readdir($dirh)) {\r
+                       if ($filename == '.' || $filename == '..') {\r
+                               continue;\r
+                       }\r
+                       if ($filename == $searchfile) {\r
+                               @closedir($dirh);\r
+                               return $folder.$filename;\r
+                       }\r
+\r
+                       if ($recursive == true && @is_dir($folder.$filename)) {\r
+                               if ($found = self::scanFolder($folder.$filename, $searchfile, $recursive)) {\r
+                                       @closedir($dirh);\r
+                                       return $found;\r
+                               }\r
+                       }\r
+               }\r
+               @closedir($dirh);\r
+       }\r
+       \r
+       /**\r
+        * Return true, if the given filename is an url (http or ftp).\r
+        * \r
+        * @param       string          $filename\r
+        * @return      boolean\r
+        */\r
+       public static function isURL($filename) {\r
+               return preg_match('!^(https?|ftp)://!', $filename);\r
+       }\r
+       \r
+       /**\r
+        * Returns canonicalized absolute pathname.\r
+        * \r
+        * @param       string          $path\r
+        * @return      string          path\r
+        */\r
+       public static function getRealPath($path) {\r
+               $path = self::unifyDirSeperator($path);\r
+               \r
+               $result = array();\r
+               $pathA = explode('/', $path);\r
+               if ($pathA[0] === '') {\r
+                       $result[] = '';\r
+               }\r
+\r
+               foreach ($pathA as $key => $dir) {\r
+                       if ($dir == '..') {\r
+                               if (end($result) == '..') {\r
+                                       $result[] = '..';\r
+                               } \r
+                               else { \r
+                                       $lastValue = array_pop($result);\r
+                                       if ($lastValue === '' || $lastValue === null) {\r
+                                               $result[] = '..';\r
+                                       }\r
+                               }\r
+                       } \r
+                       else if ($dir !== '' && $dir != '.') {\r
+                               $result[] = $dir;\r
+                       }\r
+               }\r
+               \r
+               $lastValue = end($pathA);\r
+               if ($lastValue === '' || $lastValue === false) {\r
+                       $result[] = '';\r
+               }\r
+               \r
+               return implode('/', $result);\r
+       }\r
+       \r
+       /**\r
+        * formats a filesize\r
+        *\r
+        * @param       integer         $byte\r
+        * @param       integer         $precision\r
+        * @return      string          filesize\r
+        */\r
+       public static function formatFilesize($byte, $precision = 2) {\r
+               $symbol = 'Byte';\r
+               if ($byte >= 1000) {\r
+                       $byte /= 1000;\r
+                       $symbol = 'kB';\r
+               }\r
+               if ($byte >= 1000) {\r
+                       $byte /= 1000;\r
+                       $symbol = 'MB';\r
+               }\r
+               if ($byte >= 1000) {\r
+                       $byte /= 1000;\r
+                       $symbol = 'GB';\r
+               }\r
+               if ($byte >= 1000) {\r
+                       $byte /= 1000;\r
+                       $symbol = 'TB';\r
+               }\r
+               \r
+               return StringUtil::formatNumeric(round($byte, $precision)).' '.$symbol;\r
+       }\r
+       \r
+       /**\r
+        * formats a filesize (binary prefix)\r
+        * \r
+        * For more informations: <http://en.wikipedia.org/wiki/Binary_prefix>\r
+        *\r
+        * @param       integer         $byte\r
+        * @param       integer         $precision\r
+        * @return      string          filesize\r
+        */\r
+       public static function formatFilesizeBinary($byte, $precision = 2) {\r
+               $symbol = 'Byte';\r
+               if ($byte >= 1024) {\r
+                       $byte /= 1024;\r
+                       $symbol = 'KiB';\r
+               }\r
+               if ($byte >= 1024) {\r
+                       $byte /= 1024;\r
+                       $symbol = 'MiB';\r
+               }\r
+               if ($byte >= 1024) {\r
+                       $byte /= 1024;\r
+                       $symbol = 'GiB';\r
+               }\r
+               if ($byte >= 1024) {\r
+                       $byte /= 1024;\r
+                       $symbol = 'TiB';\r
+               }\r
+               \r
+               return StringUtil::formatNumeric(round($byte, $precision)).' '.$symbol;\r
+       }\r
+       \r
+       /**\r
+        * Downloads a package archive from an http URL.\r
+        * \r
+        * @param       string          $httpUrl\r
+        * @param       string          $prefix\r
+        * @return      string          path to the dowloaded file\r
+        */\r
+       public static function downloadFileFromHttp($httpUrl, $prefix = 'package') {\r
+               $extension = strrchr($httpUrl, '.');\r
+               //$newFileName = self::getTemporaryFilename($prefix.'_', $extension);\r
+               $newFileName = self::getTemporaryFilename($prefix.'_');\r
+               $localFile = new File($newFileName); // the file to write.\r
+               \r
+               // get proxy\r
+               $options = array();\r
+               if (PROXY_SERVER_HTTP) {\r
+                       $options['http']['proxy'] = PROXY_SERVER_HTTP;\r
+                       $options['http']['request_fulluri'] = true;\r
+               }\r
+               \r
+               // first look if php's built-in fopen() is available, and if so, use it.\r
+               if (function_exists('fopen') && ini_get('allow_url_fopen')) {\r
+                       $remoteFile = new File($httpUrl, 'rb', $options); // the file to read.\r
+                       // get the content of the remote file and write it to a local file.\r
+                       while (!$remoteFile->eof()) {\r
+                               $buffer = $remoteFile->gets(4096);\r
+                               $localFile->write($buffer);\r
+                       }\r
+               }\r
+               // if allow_url_fopen isn't active, we attempt to use our own http download functionality.\r
+               else {\r
+                       $port = 80;\r
+                       $parsedUrl = parse_url($httpUrl);\r
+                       $host = $parsedUrl['host'];\r
+                       $path = $parsedUrl['path'];\r
+                       \r
+                       $remoteFile = new RemoteFile($host, $port, 30, $options); // the file to read.\r
+                       if (!isset($remoteFile)) {\r
+                               $localFile->close();\r
+                               unlink($newFileName);\r
+                               throw new SystemException("cannot connect to http host '".$host."'", 14000);\r
+                       }\r
+                       // build and send the http request.\r
+                       $request = "GET ".$path.(!empty($parsedUrl['query']) ? '?'.$parsedUrl['query'] : '')." HTTP/1.0\r\n";\r
+                       $request .= "User-Agent: HTTP.PHP (FileUtil.class.php; WoltLab Community Framework/".WCF_VERSION."; ".WCF::getLanguage()->getLanguageCode().")\r\n";\r
+                       $request .= "Accept: */*\r\n";\r
+                       $request .= "Accept-Language: ".WCF::getLanguage()->getLanguageCode()."\r\n";\r
+                       $request .= "Host: ".$host."\r\n";\r
+                       $request .= "Connection: Close\r\n\r\n";\r
+                       $remoteFile->puts($request);\r
+                       $waiting = true;\r
+                       $readResponse = array();\r
+                       // read http response.\r
+                       while (!$remoteFile->eof()) {\r
+                               $readResponse[] = $remoteFile->gets();\r
+                               // look if we are done with transferring the requested file.                                     \r
+                               if ($waiting) {\r
+                                       if (rtrim($readResponse[count($readResponse) - 1]) == '') {\r
+                                               $waiting = false;\r
+                                       }                                               \r
+                               }\r
+                               else {\r
+                                       // look if the webserver sent an error http statuscode\r
+                                       // This has still to be checked if really sufficient!\r
+                                       $arrayHeader = array('201', '301', '302', '303', '307', '404');\r
+                                       foreach ($arrayHeader as $code) {\r
+                                               $error = strpos($readResponse[0], $code);\r
+                                       }\r
+                                       if ($error !== false) {\r
+                                               $localFile->close();\r
+                                               unlink($newFileName);                                           \r
+                                               throw new SystemException("file ".$path." not found at host '".$host."'", 14001);\r
+                                       }\r
+                                       // write to the target system.\r
+                                       $localFile->write($readResponse[count($readResponse) - 1]);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               $remoteFile->close();\r
+               $localFile->close();\r
+               return $newFileName;            \r
+       }\r
+       \r
+       /**\r
+        * Strips supernumerous BOMs from a given bytestream.\r
+        *\r
+        * If we are dealing with bytestreams being pushed from one program or script to another in a UTF-8 \r
+        * environment, we might encounter problems with BOMs (Byte Order Marks). E.g., if there's a script \r
+        * that reads a .tar file via readfile(), and this script is encoded in UTF-8, and being called from another\r
+        * script which wants to handle the bytestream that results from readfile(). But apparently because of the \r
+        * UTF-8 encoding of the called script -- at least in some PHP versions -- readfile() adds a UTF-8 BOM\r
+        * at the beginning of the bytestream. If we do write this bytestream to disk and then try to open the\r
+        * resulting file, we will get an error because it is no more a valid .tar archive. The same thing happens\r
+        * if we handle an .xml file and then try to parse it.\r
+        * So, if bytestreams are being handled in a UTF-8 environment, be sure always to use this function \r
+        * before writing the bytestream to disk or trying to parse it with an xml parser.\r
+        * This works regardless of multibyte string support (mb_strpos and friends) being enabled or not.\r
+        * \r
+        * Btw, if you try to apply the following to a bytestream read from a .tar file, \r
+        * you will end up with a file sized zero bytes:\r
+        * while (($byte = fgetc($fileHandle)) !== false) {\r
+        *      fwrite($fileHandle, $byte);\r
+        * }\r
+        * \r
+        * @param       string          $sourceContent\r
+        * @param       string          $characterEncoding\r
+        * @return      string          destinationContent\r
+        */\r
+       public static function stripBoms($sourceContent = '', $characterEncoding = 'UTF-8') {\r
+               try {\r
+                       // TODO: implement recognition of other BOMs (UTF-7, UTF-16 big endian, UTF-16 little endian etc.)\r
+                       if ($characterEncoding == 'UTF-8') {\r
+                               // get the ASCII codes for the three bytes the UTF-8 BOM is consisting of.\r
+                               $firstByte = intval(0xEF);\r
+                               $secondByte = intval(0xBB);\r
+                               $thirdByte = intval(0xBF);\r
+                       }\r
+                       else {\r
+                               return $sourceContent;\r
+                       }\r
+                       \r
+                       // put the bytestream's first three bytes to an array.\r
+                       $workArray = array();\r
+                       $workArray = unpack('C3', $sourceContent);\r
+                       if (!is_array($workArray)) {\r
+                               throw new SystemException("Unable to process bytestream.");\r
+                       }\r
+                       \r
+                       // detect the UTF-8 BOM.\r
+                       $destinationContent = '';\r
+                       if (($workArray['1'] == $firstByte) && ($workArray['2'] == $secondByte) && ($workArray['3'] == $thirdByte)) {\r
+                               $tmpname = FileUtil::getTemporaryFilename('stripBoms_');\r
+                               $tmpStream = fopen($tmpname, 'w+');\r
+                               fwrite($tmpStream, $sourceContent);\r
+                               rewind($tmpStream);\r
+                               \r
+                               // cut off the BOM.\r
+                               fseek($tmpStream, 3); // compatibility for PHP < 5.1.0\r
+                               $destinationContent = stream_get_contents($tmpStream);\r
+                               fclose($tmpStream);\r
+                               @unlink($tmpname);\r
+                               \r
+                               return $destinationContent;\r
+                       } \r
+                       else {\r
+                               return $sourceContent;\r
+                       }\r
+               }\r
+               catch (SystemException $e) {\r
+                       throw $e;\r
+               }                       \r
+       }\r
+       \r
+       /**\r
+        * Determines whether a file is text or binary by checking the first few bytes in the file.\r
+        * The exact number of bytes is system dependent, but it is typically several thousand.\r
+        * If every byte in that part of the file is non-null, considers the file to be text;\r
+        * otherwise it considers the file to be binary.\r
+        * \r
+        * @param       string          $file\r
+        * @return      boolean\r
+        */\r
+       public static function isBinary($file) {\r
+               // open file\r
+               $file = new File($file, 'rb');\r
+               \r
+               // get block size\r
+               $stat = $file->stat();\r
+               $blockSize = $stat['blksize'];\r
+               if ($blockSize < 0) $blockSize = 1024;\r
+               if ($blockSize > $file->filesize()) $blockSize = $file->filesize();\r
+               if ($blockSize <= 0) return false;\r
+               \r
+               // get bytes\r
+               $block = $file->read($blockSize);\r
+               return (strlen($block) == 0 || preg_match_all('/\x00/', $block, $match) > 0);\r
+       }\r
+       \r
+       /**\r
+        * Uncompresses a gzipped file\r
+        *\r
+        * @param       string          $gzipped\r
+        * @param       string          $destination\r
+        * @return      boolean         result\r
+        */\r
+       public static function uncompressFile($gzipped, $destination) {\r
+               if (!@is_file($gzipped)) {\r
+                       return false;   \r
+               }\r
+               \r
+               $sourceFile = new ZipFile($gzipped, 'rb');\r
+               //$filesize = $sourceFile->getFileSize();\r
+               $targetFile = new File($destination);\r
+               while (!$sourceFile->eof()) {\r
+                       $targetFile->write($sourceFile->read(512), 512);        \r
+               }\r
+               $targetFile->close();\r
+               $sourceFile->close();\r
+               @$targetFile->chmod(0777);\r
+               \r
+               /*if ($filesize != filesize($destination)) {\r
+                       @unlink($destination);\r
+                       return false;\r
+               }*/\r
+               \r
+               return true;            \r
+       }\r
+       \r
+       /**\r
+        * Returns the value of the 'safe_mode' configuration option.\r
+        * \r
+        * @return      boolean\r
+        */\r
+       public static function getSafeMode() {\r
+               $configArray = @ini_get_all();\r
+               if (is_array($configArray) && isset($configArray['safe_mode']['local_value'])) {\r
+                       return intval($configArray['safe_mode']['local_value']);\r
+               }\r
+               return intval(@ini_get('safe_mode'));\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if php is running as apache module.\r
+        * \r
+        * @return boolean\r
+        */\r
+       public static function isApacheModule() {\r
+               return function_exists('apache_get_version');\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/HeaderUtil.class.php b/wcfsetup/install/files/lib/util/HeaderUtil.class.php
new file mode 100644 (file)
index 0000000..b699c4a
--- /dev/null
@@ -0,0 +1,96 @@
+<?php\r
+namespace wcf\util;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Contains header-related functions.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class HeaderUtil {\r
+       /**\r
+        * alias to php setcookie() function\r
+        */\r
+       public static function setCookie($name, $value = '', $expire = 0) {\r
+               @header('Set-Cookie: '.rawurlencode(COOKIE_PREFIX.$name).'='.rawurlencode($value).($expire ? '; expires='.gmdate('D, d-M-Y H:i:s', $expire).' GMT' : '').(COOKIE_PATH ? '; path='.COOKIE_PATH : '').(COOKIE_DOMAIN ? '; domain='.COOKIE_DOMAIN : '').((isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') ? '; secure' : '').'; HttpOnly', false);\r
+       }\r
+       \r
+       /**\r
+        * Sends the headers of a page.\r
+        */\r
+       public static function sendHeaders() {\r
+               // send content type\r
+               @header('Content-Type: text/html; charset=UTF-8');\r
+               \r
+               // send no cache headers\r
+               if (HTTP_ENABLE_NO_CACHE_HEADERS && !WCF::getSession()->spiderID) {\r
+                       self::sendNoCacheHeaders();\r
+               }\r
+               \r
+               // enable gzip compression\r
+               if (HTTP_ENABLE_GZIP && HTTP_GZIP_LEVEL > 0 && HTTP_GZIP_LEVEL < 10 && !defined('HTTP_DISABLE_GZIP')) {\r
+                       self::compressOutput();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Sends no cache headers.\r
+        */\r
+       public static function sendNoCacheHeaders() {\r
+               @header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); \r
+               @header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');\r
+               @header('Cache-Control: no-cache, must-revalidate');\r
+               @header('Pragma: no-cache');\r
+       }\r
+       \r
+       /**\r
+        * Enables the gzip compression of the page output.\r
+        */\r
+       public static function compressOutput() {\r
+               if (function_exists('gzcompress') && !@ini_get('zlib.output_compression') && !@ini_get('output_handler') && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {\r
+                       if (strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip')) {\r
+                               @header('Content-Encoding: x-gzip');\r
+                       }\r
+                       else {\r
+                               @header('Content-Encoding: gzip');\r
+                       }\r
+                       ob_start(array('HeaderUtil', 'getCompressedOutput'));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Outputs the compressed page content.\r
+        */\r
+       public static function getCompressedOutput($output) {\r
+               $size = strlen($output);\r
+               $crc = crc32($output);\r
+\r
+               $newOutput = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff";\r
+               $newOutput .= substr(gzcompress($output, HTTP_GZIP_LEVEL), 2, -4);\r
+               unset($output);\r
+               $newOutput .= pack('V', $crc);\r
+               $newOutput .= pack('V', $size);\r
+               \r
+               return $newOutput;\r
+       }\r
+       \r
+       /**\r
+        * Redirects the user agent.\r
+        *\r
+        * @param       string          $location\r
+        * @param       boolean         $prependDir\r
+        * @param       boolean         $sendStatusCode\r
+        */\r
+       public static function redirect($location, $prependDir = true, $sendStatusCode = false) {\r
+               if ($prependDir) $location = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator(dirname(WCF::getSession()->requestURI))) . $location;\r
+               //if ($sendStatusCode) @header('HTTP/1.0 301 Moved Permanently');\r
+               if ($sendStatusCode) @header('HTTP/1.1 307 Temporary Redirect');\r
+               header('Location: '.$location);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/ImageUtil.class.php b/wcfsetup/install/files/lib/util/ImageUtil.class.php
new file mode 100644 (file)
index 0000000..567f361
--- /dev/null
@@ -0,0 +1,57 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Contains image-related functions.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf.data.image\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class ImageUtil {\r
+       /**\r
+        * Checks the content of an image for bad sections. \r
+        * e.g. the use of javascript.\r
+        * Returns false, if any bad stuff was found.\r
+        * \r
+        * @return      boolean \r
+        */\r
+       public static function checkImageContent($file) {\r
+               // get file content\r
+               $content = file_get_contents($file);\r
+               \r
+               // remove some characters\r
+               $content = strtolower(preg_replace('/[^a-z0-9<\(]+/i', '', $content));\r
+               $content = str_replace('description', '', $content);\r
+               \r
+               // search for javascript\r
+               if (strstr($content, 'script') || strstr($content, 'javascript') || strstr($content, 'expression(')) return false;\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Examines the right file extension for an image by the given mime type.\r
+        * @see http://www.php.net/manual/en/function.image-type-to-mime-type.php\r
+        * \r
+        * @param       string          $mimeType\r
+        * @return      string          file extension\r
+        */\r
+       public static function getExtensionByMimeType($mimeType) {\r
+               switch ($mimeType) {\r
+                       case 'image/gif':                       return 'gif';\r
+                       case 'image/jpeg':                      return 'jpg';\r
+                       case 'image/png':                       return 'png';\r
+                       case 'application/x-shockwave-flash':   return 'swf';\r
+                       case 'image/psd':                       return 'psd';\r
+                       case 'image/bmp':\r
+                       case 'image/x-ms-bmp':                  return 'bmp';\r
+                       case 'image/tiff':                      return 'tiff';\r
+                       default:                                return '';\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/JSON.class.php b/wcfsetup/install/files/lib/util/JSON.class.php
new file mode 100644 (file)
index 0000000..ae5a122
--- /dev/null
@@ -0,0 +1,47 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Provides methods for JSON.\r
+ *\r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2010 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class JSON {\r
+       /**\r
+        * Returns the JSON representation of a value.\r
+        * \r
+        * @param       mixed           $data\r
+        * @return      string\r
+        */\r
+       public static function encode($data) {\r
+               return json_encode($data);\r
+       }\r
+       \r
+       /**\r
+        * Decodes a JSON string.\r
+        * \r
+        * @param       string          $json\r
+        * @param       boolean         $asArray\r
+        * @return      array\r
+        */\r
+       public static function decode($json, $asArray = true) {\r
+               // decodes JSON\r
+               $data = json_decode($json, $asArray);\r
+               \r
+               return $data;\r
+       }\r
+       \r
+       /**\r
+        * Returns the last error occurred.\r
+        * \r
+        * @return      integer\r
+        */\r
+       public static function getLastError() {\r
+               return json_last_error();\r
+       }\r
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/MathUtil.class.php b/wcfsetup/install/files/lib/util/MathUtil.class.php
new file mode 100644 (file)
index 0000000..286f5d3
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+namespace wcf\util;
+
+/**
+ * Contains math-related functions.
+ * 
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage util
+ * @category   Community Framework
+ */
+class MathUtil {
+       /**
+        * Generates a random value.
+        *
+        * @param       integer         $min
+        * @param       integer         $max
+        * @return      integer
+        */
+       public static function getRandomValue($min = null, $max = null) {
+               // set seed
+               mt_srand(self::getRandomSeed());
+               
+               // generate random value
+               return (($min !== null && $max !== null) ? mt_rand($min, $max) : mt_rand());
+       }
+       
+       /**
+        * Generates a seed for the random value generator.
+        *
+        * @return      integer
+        */
+       public static function getRandomSeed() {
+               @clearstatcache();
+               if (($stat = @stat(__FILE__)) !== false) { 
+                       return crc32(microtime() . implode(microtime(), $stat));
+               }
+               else {
+                       return crc32(microtime());
+               }
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/StringStack.class.php b/wcfsetup/install/files/lib/util/StringStack.class.php
new file mode 100644 (file)
index 0000000..d998d80
--- /dev/null
@@ -0,0 +1,70 @@
+<?php\r
+namespace wcf\util;\r
+\r
+/**\r
+ * Replaces quoted strings in a text.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class StringStack {\r
+       protected static $stringStack = array();\r
+       \r
+       /**\r
+        * Replaces a string with an unique hash value.\r
+        *\r
+        * @param       string          $string\r
+        * @param       string          $type\r
+        * @return      string          $hash\r
+        */\r
+       public static function pushToStringStack($string, $type = 'default') {\r
+               $hash = '@@'.StringUtil::getHash(uniqid(microtime()).$string).'@@';\r
+               \r
+               if (!isset(self::$stringStack[$type])) {\r
+                       self::$stringStack[$type] = array();\r
+               }\r
+               \r
+               self::$stringStack[$type][$hash] = $string;\r
+               \r
+               return $hash;\r
+       }\r
+       \r
+       /**\r
+        * Reinserts Strings that have been replaced by unique hash values.\r
+        *\r
+        * @param       string          $string\r
+        * @param       string          $type\r
+        * @return      string          $string\r
+        */\r
+       public static function reinsertStrings($string, $type = 'default') {\r
+               if (isset(self::$stringStack[$type])) {\r
+                       foreach (self::$stringStack[$type] as $hash => $value) {\r
+                               if (StringUtil::indexOf($string, $hash) !== false) {\r
+                                       $string = StringUtil::replace($hash, $value, $string);\r
+                                       unset(self::$stringStack[$type][$hash]);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               return $string;\r
+       }\r
+       \r
+       /**\r
+        * Returns the stack.\r
+        *\r
+        * @param       string          $type\r
+        * @return      array\r
+        */\r
+       public static function getStack($type = 'default') {\r
+               if (isset(self::$stringStack[$type])) {\r
+                       return self::$stringStack[$type];\r
+               }\r
+               \r
+               return array();\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/StringUtil.class.php b/wcfsetup/install/files/lib/util/StringUtil.class.php
new file mode 100644 (file)
index 0000000..3e94b6a
--- /dev/null
@@ -0,0 +1,565 @@
+<?php\r
+namespace wcf\util;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Contains string-related functions.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class StringUtil {\r
+       const HTML_PATTERN = '~</?[a-z]+[1-6]?\r
+                       (?:\s*[a-z]+\s*=\s*(?:\r
+                       "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|[^\s>]\r
+                       ))*\s*/?>~ix';\r
+       \r
+       /**\r
+        * Returns a salted hash of the given value.\r
+        *\r
+        * @param       string          $value\r
+        * @param       string          $salt\r
+        * @return      string          $hash\r
+        */\r
+       public static function getSaltedHash($value, $salt) {\r
+               if (!defined('ENCRYPTION_ENABLE_SALTING') || ENCRYPTION_ENABLE_SALTING) {\r
+                       $hash = '';\r
+                       // salt\r
+                       if (!defined('ENCRYPTION_SALT_POSITION') || ENCRYPTION_SALT_POSITION == 'before') {\r
+                               $hash .= $salt;\r
+                       }\r
+                       \r
+                       // value\r
+                       if (!defined('ENCRYPTION_ENCRYPT_BEFORE_SALTING') || ENCRYPTION_ENCRYPT_BEFORE_SALTING) {\r
+                               $hash .= self::encrypt($value);\r
+                       }\r
+                       else {\r
+                               $hash .= $value;\r
+                       }\r
+                       \r
+                       // salt\r
+                       if (defined('ENCRYPTION_SALT_POSITION') && ENCRYPTION_SALT_POSITION == 'after') {\r
+                               $hash .= $salt;\r
+                       }\r
+                       \r
+                       return self::encrypt($hash);\r
+               }\r
+               else {\r
+                       return self::encrypt($value);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns a double salted hash of the given value.\r
+        *\r
+        * @param       string          $value\r
+        * @param       string          $salt\r
+        * @return      string          $hash\r
+        */\r
+       public static function getDoubleSaltedHash($value, $salt) {\r
+               return self::encrypt($salt . self::getSaltedHash($value, $salt));\r
+       }\r
+       \r
+       /**\r
+        * encrypts the given value.\r
+        *\r
+        * @param       string          $value\r
+        * @return      string          $hash\r
+        */\r
+       public static function encrypt($value) {\r
+               if (defined('ENCRYPTION_METHOD')) {\r
+                       switch (ENCRYPTION_METHOD) {\r
+                               case 'sha1': return sha1($value);\r
+                               case 'md5': return md5($value);\r
+                               case 'crc32': return crc32($value);\r
+                               case 'crypt': return crypt($value);\r
+                       }\r
+               }\r
+               return sha1($value);\r
+       }\r
+       \r
+       /**\r
+        * alias to php sha1() function.\r
+        *\r
+        * @param       string          $value\r
+        * @return      string          $hash\r
+        */\r
+       public static function getHash($value) {\r
+               return sha1($value);\r
+       }\r
+\r
+       /**\r
+        * Creates a random hash.\r
+        * \r
+        * @return      string          a random hash\r
+        */\r
+       public static function getRandomID() {\r
+               return self::getHash(microtime() . uniqid(mt_rand(), true));\r
+       }\r
+\r
+       /**\r
+        * Converts dos to unix newlines.\r
+        *\r
+        * @param       string          $string\r
+        * @return      string          $string\r
+        */\r
+       public static function unifyNewlines($string) {\r
+               return preg_replace("%(\r\n)|(\r)%", "\n", $string);\r
+       }\r
+\r
+       /**\r
+        * alias to php trim() function\r
+        * \r
+        * @param       string          $string\r
+        * @return      string          $string\r
+        */\r
+       public static function trim($text) {\r
+               return trim($text);\r
+       }\r
+\r
+       /**\r
+        * Converts html special characters.\r
+        *\r
+        * @param       string          $string\r
+        * @return      string          $string\r
+        */\r
+       public static function encodeHTML($string) {\r
+               if (is_object($string)) \r
+                       $string = $string->__toString();\r
+               \r
+               return @htmlspecialchars($string, ENT_COMPAT, 'UTF-8');\r
+       }\r
+       \r
+       /**\r
+        * Decodes html entities.\r
+        *\r
+        * @param       string          $string\r
+        * @return      string          $string\r
+        */\r
+       public static function decodeHTML($string) {\r
+               if (is_object($string)) \r
+                       $string = $string->__toString();\r
+               \r
+               $string = str_ireplace('&nbsp;', ' ', $string); // convert non-breaking spaces to ascii 32; not ascii 160\r
+               return @html_entity_decode($string, ENT_COMPAT, 'UTF-8');\r
+       }\r
+\r
+       /**\r
+        * Formats a numeric.\r
+        *\r
+        * @param       numeric         $numeric\r
+        * @return      string          \r
+        */\r
+       public static function formatNumeric($numeric) {\r
+               if (is_int($numeric)) \r
+                       return self::formatInteger($numeric);\r
+                       \r
+               else if (is_float($numeric))\r
+                       return self::formatDouble($numeric);\r
+                       \r
+               else {\r
+                       if (floatval($numeric) - (float) intval($numeric))\r
+                               return self::formatDouble($numeric);\r
+                       else \r
+                               return self::formatInteger(intval($numeric));\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Formats an integer.\r
+        * \r
+        * @param       integer         $integer\r
+        * @return      string\r
+        */\r
+       public static function formatInteger($integer) {\r
+               $integer = self::addThousandsSeparator($integer);\r
+               \r
+               return $integer;\r
+       }\r
+       \r
+       /**\r
+        * Formats a double.\r
+        * \r
+        * @param       double          $double\r
+        * @param       integer         $minDecimals\r
+        * @return      string\r
+        */\r
+       public static function formatDouble($double, $minDecimals = 0) {\r
+               // consider as integer, if no decimal places found\r
+               if (!$minDecimals && preg_match('~^(-?\d+)(?:\.(?:0*|00[0-4]\d*))?$~', $double, $match)) {\r
+                       return self::formatInteger($match[1]);\r
+               }\r
+       \r
+               // round\r
+               $double = round($double, ($minDecimals > 2 ? $minDecimals : 2));\r
+               \r
+               // remove last 0\r
+               if ($minDecimals < 2 && substr($double, -1) == '0') $double = substr($double, 0, -1);\r
+               \r
+               // replace decimal point\r
+               $double = str_replace('.', WCF::getLanguage()->get('wcf.global.decimalPoint'), $double);\r
+               \r
+               // add thousands separator\r
+               $double = self::addThousandsSeparator($double);\r
+               \r
+               return $double;\r
+       }\r
+       \r
+       /**\r
+        * Adds thousands separators to a given number.\r
+        * \r
+        * @param       mixed           $number\r
+        * @return      string\r
+        */\r
+       public static function addThousandsSeparator($number) {\r
+               if ($number >= 1000 || $number <= -1000) {\r
+                       $number = preg_replace('~(?<=\d)(?=(\d{3})+(?!\d))~', WCF::getLanguage()->get('wcf.global.thousandsSeparator'), $number);\r
+               }\r
+               \r
+               return $number;\r
+       }\r
+       \r
+       /**\r
+        * Sorts an array of strings and maintain index association.\r
+        * \r
+        * @param       array           $strings \r
+        * @return      boolean\r
+        */\r
+       public static function sort(&$strings) {\r
+               return asort($strings, SORT_LOCALE_STRING);\r
+       }\r
+               \r
+       /**\r
+        * alias to php strlen() function.\r
+        */\r
+       public static function length($string) {\r
+               return mb_strlen($string);\r
+       }\r
+       \r
+       /**\r
+        * alias to php strpos() function.\r
+        */\r
+       public static function indexOf($hayStack, $needle, $offset = 0) {\r
+               return mb_strpos($hayStack, $needle, $offset);\r
+       }\r
+       \r
+       /**\r
+        * alias to php stripos() function.\r
+        */\r
+       public static function indexOfIgnoreCase($hayStack, $needle, $offset = 0) {\r
+               return mb_strpos(self::toLowerCase($hayStack), self::toLowerCase($needle), $offset);\r
+       }\r
+       \r
+       /**\r
+        * alias to php strrpos() function.\r
+        */\r
+       public static function lastIndexOf($hayStack, $needle) {\r
+               return mb_strrpos($hayStack, $needle);\r
+       }\r
+       \r
+       /**\r
+        * alias to php substr() function.\r
+        */\r
+       public static function substring($string, $start, $length = null) {\r
+               if ($length !== null) return mb_substr($string, $start, $length);\r
+               return mb_substr($string, $start);\r
+       }\r
+       \r
+       /**\r
+        * alias to php strtolower() function.\r
+        */\r
+       public static function toLowerCase($string) {\r
+               return mb_strtolower($string);\r
+       }\r
+       \r
+       /**\r
+        * alias to php strtoupper() function.\r
+        */\r
+       public static function toUpperCase($string) {\r
+               return mb_strtoupper($string);\r
+       }\r
+       \r
+       /**\r
+        * alias to php substr_count() function.\r
+        */\r
+       public static function countSubstring($hayStack, $needle) {\r
+               return mb_substr_count($hayStack, $needle);\r
+       }\r
+       \r
+       /**\r
+        * alias to php ucfirst() function.\r
+        */\r
+       public static function firstCharToUpperCase($string) {\r
+               return self::toUpperCase(self::substring($string, 0, 1)).self::substring($string, 1);\r
+       }\r
+       \r
+       /**\r
+        * alias to php lcfirst() function.\r
+        */\r
+       public static function firstCharToLowerCase($string) {\r
+               return self::toLowerCase(self::substring($string, 0, 1)).self::substring($string, 1);\r
+       }\r
+       \r
+       /**\r
+        * alias to php ucwords() function.\r
+        */\r
+       public static function wordsToUpperCase($string) {\r
+               return mb_convert_case($string, MB_CASE_TITLE);\r
+       }\r
+       \r
+       /**\r
+        * alias to php str_replace() function.\r
+        */\r
+       public static function replace($search, $replace, $subject, &$count = null) {\r
+               return str_replace($search, $replace, $subject, $count);\r
+       }\r
+       \r
+       /**\r
+        * alias to php str_ireplace() function.\r
+        */\r
+       public static function replaceIgnoreCase($search, $replace, $subject, &$count = 0) {\r
+               $startPos = self::indexOf(self::toLowerCase($subject), self::toLowerCase($search));\r
+               if ($startPos === false) return $subject;\r
+               else {\r
+                       $endPos = $startPos + self::length($search);\r
+                       $count++;\r
+                       return self::substring($subject, 0, $startPos) . $replace . self::replaceIgnoreCase($search, $replace, self::substring($subject, $endPos), $count);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Unescapes escaped characters in a string.\r
+        * \r
+        * @param       string          $string\r
+        * @param       string          $chars\r
+        * @return      string\r
+        */\r
+       public static function unescape($string, $chars = '"') {\r
+               for ($i = 0, $j = strlen($chars); $i < $j; $i++) {\r
+                       $string = self::replace('\\'.$chars[$i], $chars[$i], $string);\r
+               }\r
+               \r
+               return $string;\r
+       }\r
+       \r
+       /**\r
+        * Takes a numeric HTML entity value and returns the appropriate UTF-8 bytes.\r
+        * \r
+        * @param       integer         $dec            html entity value\r
+        * @return      string                          utf-8 bytes\r
+        */\r
+       public static function getCharacter($dec) {\r
+               if ($dec < 128) {\r
+                       $utf = chr($dec);\r
+               }\r
+               else if ($dec < 2048) {\r
+                       $utf = chr(192 + (($dec - ($dec % 64)) / 64));\r
+                       $utf .= chr(128 + ($dec % 64));\r
+               }\r
+               else {\r
+                       $utf = chr(224 + (($dec - ($dec % 4096)) / 4096));\r
+                       $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64));\r
+                       $utf .= chr(128 + ($dec % 64));\r
+               }\r
+               return $utf;\r
+       }\r
+       \r
+       /**\r
+        * Converts UTF-8 to Unicode\r
+        * @see         http://www1.tip.nl/~t876506/utf8tbl.html\r
+        *\r
+        * @param       string          $c\r
+        * @return      integer         unicode value of $c\r
+        */\r
+       public static function getCharValue($c) {\r
+               $ud = 0;\r
+               if (ord($c{0}) >= 0 && ord($c{0}) <= 127) \r
+                       $ud = ord($c{0});\r
+               if (ord($c{0}) >= 192 && ord($c{0}) <= 223) \r
+                       $ud = (ord($c{0}) - 192) * 64 + (ord($c{1}) - 128);\r
+               if (ord($c{0}) >= 224 && ord($c{0}) <= 239) \r
+                       $ud = (ord($c{0}) - 224) * 4096 + (ord($c{1}) - 128) * 64 + (ord($c{2}) - 128);\r
+               if (ord($c{0}) >= 240 && ord($c{0}) <= 247) \r
+                       $ud = (ord($c{0}) - 240) * 262144 + (ord($c{1}) - 128) * 4096 + (ord($c{2}) - 128) * 64 + (ord($c{3}) - 128);\r
+               if (ord($c{0}) >= 248 && ord($c{0}) <= 251) \r
+                       $ud = (ord($c{0}) - 248) * 16777216 + (ord($c{1}) - 128) * 262144 + (ord($c{2}) - 128) * 4096 + (ord($c{3}) - 128) * 64 + (ord($c{4}) - 128);\r
+               if (ord($c{0}) >= 252 && ord($c{0}) <= 253) \r
+                       $ud = (ord($c{0}) - 252) * 1073741824 + (ord($c{1}) - 128) * 16777216 + (ord($c{2}) - 128) * 262144 + (ord($c{3}) - 128) * 4096 + (ord($c{4}) - 128) * 64 + (ord($c{5}) - 128);\r
+               if (ord($c{0}) >= 254 && ord($c{0}) <= 255) \r
+                       $ud = false; // error\r
+               return $ud;\r
+       }\r
+       \r
+       /**\r
+        * Returns html entities of all characters in the given string.\r
+        * \r
+        * @param       string          $string\r
+        * @return      string\r
+        */\r
+       public static function encodeAllChars($string) {\r
+               $result = '';\r
+               for ($i = 0, $j = StringUtil::length($string); $i < $j; $i++) {\r
+                       $char = StringUtil::substring($string, $i, 1);\r
+                       $result .= '&#'.StringUtil::getCharValue($char).';';\r
+               }\r
+               \r
+               return $result;\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if the given string contains only ASCII characters.\r
+        * \r
+        * @param       string          $string\r
+        * @return      boolean\r
+        */\r
+       public static function isASCII($string) {\r
+               return preg_match('/^[\x00-\x7F]*$/', $string);\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if the given string is utf-8 encoded.\r
+        * @see         http://www.w3.org/International/questions/qa-forms-utf-8\r
+        * \r
+        * @param       string          $string\r
+        * @return      boolean\r
+        */\r
+       public static function isUTF8($string) {\r
+               /*return preg_match('/^(\r
+                               [\x09\x0A\x0D\x20-\x7E]*                # ASCII\r
+                       |       [\xC2-\xDF][\x80-\xBF]                  # non-overlong 2-byte\r
+                       |       \xE0[\xA0-\xBF][\x80-\xBF]              # excluding overlongs\r
+                       |       [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}       # straight 3-byte\r
+                       |       \xED[\x80-\x9F][\x80-\xBF]              # excluding surrogates\r
+                       |       \xF0[\x90-\xBF][\x80-\xBF]{2}           # planes 1-3\r
+                       |       [\xF1-\xF3][\x80-\xBF]{3}               # planes 4-15\r
+                       |       \xF4[\x80-\x8F][\x80-\xBF]{2}           # plane 16\r
+                       )*$/x', $string);\r
+               */      \r
+               return preg_match('/(\r
+                               [\xC2-\xDF][\x80-\xBF]                  # non-overlong 2-byte\r
+                       |       \xE0[\xA0-\xBF][\x80-\xBF]              # excluding overlongs\r
+                       |       [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}       # straight 3-byte\r
+                       |       \xED[\x80-\x9F][\x80-\xBF]              # excluding surrogates\r
+                       |       \xF0[\x90-\xBF][\x80-\xBF]{2}           # planes 1-3\r
+                       |       [\xF1-\xF3][\x80-\xBF]{3}               # planes 4-15\r
+                       |       \xF4[\x80-\x8F][\x80-\xBF]{2}           # plane 16\r
+                       )/x', $string);\r
+       }\r
+       \r
+       /**\r
+        * Extracts the class name from a standardised class path.\r
+        * \r
+        * @param       string          $classPath\r
+        * @return      string          class name\r
+        */\r
+       public static function getClassName($classPath) {\r
+               return preg_replace('~(?:.*/)?([^/]+).class.php~i', '\\1', $classPath);\r
+       }\r
+       \r
+       /**\r
+        * Escapes the closing cdata tag.\r
+        * \r
+        * @param       string          $string\r
+        * @return      string\r
+        */\r
+       public static function escapeCDATA($string) {\r
+               return str_replace(']]>', ']]]]><![CDATA[>', $string);\r
+       }\r
+       \r
+       /**\r
+        * Converts a string to requested character encoding.\r
+        * @see         mb_convert_encoding()\r
+        * \r
+        * @param       string          $inCharset\r
+        * @param       string          $outCharset\r
+        * @param       string          $string\r
+        * @return      string          converted string\r
+        */\r
+       public static function convertEncoding($inCharset, $outCharset, $string) {\r
+               if ($inCharset == 'ISO-8859-1' && $outCharset == 'UTF-8') return utf8_encode($string);\r
+               if ($inCharset == 'UTF-8' && $outCharset == 'ISO-8859-1') return utf8_decode($string);\r
+               \r
+               return mb_convert_encoding($string, $outCharset, $inCharset);\r
+       }\r
+       \r
+       /**\r
+        * Strips HTML tags from a string.\r
+        * \r
+        * @param       string          $string\r
+        * @return      string\r
+        */\r
+       public static function stripHTML($string) {\r
+               return preg_replace(self::HTML_PATTERN, '', $string);\r
+       }\r
+       \r
+       /**\r
+        * Returns false, if the given word is forbidden by given word filter.\r
+        * \r
+        * @param       string          $word\r
+        * @param       string          $filter\r
+        * @return      boolean\r
+        */\r
+       public static function executeWordFilter($word, $filter) {\r
+               $word = self::toLowerCase($word);\r
+               \r
+               if ($filter != '') {\r
+                       $forbiddenNames = explode("\n", self::toLowerCase(self::unifyNewlines($filter)));\r
+                       foreach ($forbiddenNames as $forbiddenName) {\r
+                               if (self::indexOf($forbiddenName, '*') !== false) {\r
+                                       $forbiddenName = self::replace('\*', '.*', preg_quote($forbiddenName, '/'));\r
+                                       if (preg_match('/^'.$forbiddenName.'$/s', $word)) {\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       if ($word == $forbiddenName) {\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Splits given string into smaller chunks.\r
+        * \r
+        * @param       string          $string\r
+        * @param       integer         $length\r
+        * @param       string          $break\r
+        * @return      string\r
+        */\r
+       public static function splitIntoChunks($string, $length = 75, $break = "\r\n") {\r
+               return mb_ereg_replace('.{'.$length.'}', "\\0".$break, $string);\r
+       }\r
+       \r
+       /**\r
+        * Generates a random user password with the given character length.\r
+        *\r
+        * @param       integer         $length\r
+        * @return      string          new password\r
+        */\r
+       public static function getRandomPassword($length = 8) {\r
+               $availableCharacters = array(\r
+                       0 => 'abcdefghijklmnopqrstuvwxyz',\r
+                       1 => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',\r
+                       2 => '0123456789',\r
+                       3 => '+#-.,;:?!'\r
+               );\r
+               \r
+               $password = '';\r
+               $type = 0;\r
+               for ($i = 0; $i < $length; $i++) {\r
+                       $type = ($i % 4 == 0) ? 0 : ($type + 1);\r
+                       $password .= substr($availableCharacters[$type], MathUtil::getRandomValue(0, strlen($availableCharacters[$type]) - 1), 1);\r
+               }\r
+               \r
+               return str_shuffle($password);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/StyleUtil.class.php b/wcfsetup/install/files/lib/util/StyleUtil.class.php
new file mode 100644 (file)
index 0000000..0cf3eff
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+namespace wcf\util;
+use wcf\system\io\File;
+
+/**
+ * Contains Style-related functions.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2009 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage util
+ * @category   Community Framework
+ */
+class StyleUtil {
+       /**
+        * Converts css code from LTR to RTL.
+        * 
+        * @param       string          $contents
+        * @return      string
+        */
+       public static function convertCSSToRTL($contents) {
+               // parse style attributes
+               // background
+               // background-position
+               $contents = preg_replace('/background-position:\s*left/', 'wcf-background-position:left', $contents);
+               $contents = preg_replace('/background-position:\s*right/', 'background-position:left', $contents);
+               $contents = str_replace('wcf-background-position:left', 'background-position:right', $contents);
+               $contents = preg_replace_callback('/background-position:\s*([\d\.]+)%/', create_function('$matches', 'return "background-position:".(100.0-$matches[1])."%";'), $contents);
+               
+               // background-image
+               $contents = str_replace('-ltr', '-rtl', $contents);
+               
+               // (border, margin, padding) left / right
+               $contents = str_replace('left:', 'wcf-left:', $contents);
+               $contents = str_replace('right:', 'left:', $contents);
+               $contents = str_replace('wcf-left:', 'right:', $contents);
+               
+               // border-width
+               $contents = preg_replace('/border-width:\s*([^\s;\}]+)\s+([^\s;\}]+)\s+([^\s;\}]+)\s+([^\s;\}]+)/', 'border-width:\\1 \\4 \\3 \\2', $contents);
+               
+               // (border-left-width, border-right-width)
+               $contents = str_replace('border-left-width:', 'wcf-border-left-width:', $contents);
+               $contents = str_replace('border-right-width:', 'border-left-width:', $contents);
+               $contents = str_replace('wcf-border-left-width:', 'border-right-width:', $contents);
+               
+               // clear
+               $contents = preg_replace('/clear:\s*left/', 'wcf-clear:left', $contents);
+               $contents = preg_replace('/clear:\s*right/', 'clear:left', $contents);
+               $contents = str_replace('wcf-clear:left', 'clear:right', $contents);
+               
+               // clip?
+
+               // float
+               $contents = preg_replace('/float:\s*left/', 'wcf-float:left', $contents);
+               $contents = preg_replace('/float:\s*right/', 'float:left', $contents);
+               $contents = str_replace('wcf-float:left', 'float:right', $contents);
+               
+               // margin
+               $contents = preg_replace('/margin:\s*([^\s;\}]+)\s+([^\s;\}]+)\s+([^\s;\}]+)\s+([^\s;\}]+)/', 'margin:\\1 \\4 \\3 \\2', $contents);
+               
+               // padding
+               $contents = preg_replace('/padding:\s*([^\s;\}]+)\s+([^\s;\}]+)\s+([^\s;\}]+)\s+([^\s;\}]+)/', 'padding:\\1 \\4 \\3 \\2', $contents);
+               
+               // text-align
+               $contents = preg_replace('/text-align:\s*left/', 'wcf-text-align:left', $contents);
+               $contents = preg_replace('/text-align:\s*right/', 'text-align:left', $contents);
+               $contents = str_replace('wcf-text-align:left', 'text-align:right', $contents);
+               
+               // text-shadow
+               $contents = preg_replace('/text-shadow:\s*(\d)/', 'text-shadow:-\\1', $contents);
+               
+               return $contents;
+       }
+       
+       /**
+        * Compresses css code.
+        * 
+        * @param       string          $string
+        * @return      string
+        */
+       public static function compressCSS($string) {
+               $string = StringUtil::unifyNewlines($string);
+               // remove comments
+               $string = preg_replace('!/\*.*?\*/\r?\n?!s', '', $string);
+               // remove tabs
+               $string = preg_replace('!\t+!', '', $string);
+               // remove line breaks
+               $string = preg_replace('!(?<=\{|;) *\n!', '', $string);
+               $string = preg_replace('! *\n(?=})!', '', $string);
+               // remove empty lines
+               $string = preg_replace('~\n{2,}~s', "\n", $string);
+               
+               return StringUtil::trim($string);
+       }
+       
+       /**
+        * Updates the acp style file.
+        */
+       public static function updateStyleFile() {
+               // get file handle
+               $file = new File(WCF_DIR . 'acp/style/style-ltr.css', 'wb');
+               
+               // include static styles
+               $staticStyles = glob(WCF_DIR.'style/*.css');
+               if ($staticStyles) {
+                       foreach ($staticStyles as $staticStyle) {
+                               if (!preg_match('/style-\d+(?:-rtl)?\.css/', $staticStyle)) {
+                                       // get style
+                                       $contents = file_get_contents($staticStyle);
+                                       // compress style
+                                       $contents = StyleUtil::compressCSS($contents);
+                                       // fix icon/image path
+                                       $contents = str_replace('../icon/', '../../icon/', $contents);
+                                       $contents = str_replace('../images/', '../../images/', $contents);
+                                       // write style
+                                       $file->write("/* static: ".basename($staticStyle)." */\n");
+                                       $file->write(StringUtil::trim($contents)."\n");
+                               }
+                       }
+               }
+               // include static acp styles
+               $staticStyles = glob(WCF_DIR.'acp/style/*.css');
+               if ($staticStyles) {
+                       foreach ($staticStyles as $staticStyle) {
+                               if (!preg_match('/style-(?:ltr|rtl)\.css/', $staticStyle) && !preg_match('/ie\dFix\.css/', $staticStyle)) {
+                                       $contents = file_get_contents($staticStyle);
+                                       $contents = StyleUtil::compressCSS($contents);
+                                       $file->write("/* static: acp/".basename($staticStyle)." */\n");
+                                       $file->write(StringUtil::trim($contents)."\n");
+                               }
+                       }
+               }
+               // close file
+               $file->close();
+               @chmod(WCF_DIR . 'acp/style/style-ltr.css', 0777);
+               
+               // update rtl version
+               self::updateStyleFileRTL();
+       }
+       
+       /**
+        * Converts the file of this style to a RTL ("right-to-left") version. 
+        */
+       public static function updateStyleFileRTL() {
+               // get contents of LTR version
+               $contents = file_get_contents(WCF_DIR . 'acp/style/style-ltr.css');
+               
+               // convert ltr to rtl
+               $contents = StyleUtil::convertCSSToRTL($contents);
+               
+               // write file
+               $file = new File(WCF_DIR . 'acp/style/style-rtl.css');
+               $file->write($contents);
+               
+               // close file
+               $file->close();
+               @chmod(WCF_DIR . 'acp/style/style-rtl.css', 0777);
+       }
+}
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/UserUtil.class.php b/wcfsetup/install/files/lib/util/UserUtil.class.php
new file mode 100644 (file)
index 0000000..cf6f8bb
--- /dev/null
@@ -0,0 +1,166 @@
+<?php\r
+namespace wcf\util;\r
+use wcf\system\WCF;\r
+\r
+/**\r
+ * Contains user-related functions.\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2009 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class UserUtil {\r
+       protected static $privateIpList = array("/^0\./", "/^127\.0\.0\.1/", "/^192\.168\..*/", "/^172\.16\..*/", "/^10..*/", "/^224..*/", "/^240..*/");\r
+       \r
+       /**\r
+        * Returns true, if the given name is a valid username.\r
+        * \r
+        * @param       string          $name           username\r
+        * @return      boolean\r
+        */\r
+       public static function isValidUsername($name) {\r
+               // check illegal characters\r
+               if (!preg_match('!^[^,\n]+$!', $name)) {\r
+                       return false;\r
+               }\r
+               // check long words\r
+               $words = preg_split('!\s+!', $name, -1, PREG_SPLIT_NO_EMPTY);\r
+               foreach ($words as $word) {\r
+                       if (StringUtil::length($word) > 20) {\r
+                               return false;\r
+                       }\r
+               }\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if the given username is available.\r
+        * \r
+        * @param       string          $name           username\r
+        * @return      boolean\r
+        */\r
+       public static function isAvailableUsername($name) {\r
+               $sql = "SELECT  COUNT(username) AS count\r
+                       FROM    wcf".WCF_N."_user\r
+                       WHERE   username = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($name));\r
+               $row = $statement->fetchArray();\r
+               return $row['count'] == 0;\r
+       }\r
+               \r
+       /**\r
+        * Returns true, if the given e-mail is a valid address.\r
+        * @see http://www.faqs.org/rfcs/rfc821.html\r
+        * \r
+        * @param       string          $email\r
+        * @return      boolean\r
+        */\r
+       public static function isValidEmail($email) {\r
+               // local-part\r
+               $c = '!#\$%&\'\*\+\-\/0-9=\?a-z\^_`\{\}\|~';\r
+               $string = '['.$c.']*(?:\\\\[\x00-\x7F]['.$c.']*)*';\r
+               $localPart = $string.'(?:\.'.$string.')*';\r
+               \r
+               // domain\r
+               $name = '[a-z0-9](?:[a-z0-9-]*[a-z0-9])?';\r
+               $domain = $name.'(?:\.'.$name.')*\.[a-z]{2,}';\r
+               \r
+               // mailbox\r
+               $mailbox = $localPart.'@'.$domain;\r
+               \r
+               return preg_match('/^'.$mailbox.'$/i', $email);\r
+       }\r
+       \r
+       /**\r
+        * Returns true, if the given email address is available.\r
+        * \r
+        * @param       string          $email          email address\r
+        * @return      boolean\r
+        */\r
+       public static function isAvailableEmail($email) {\r
+               $sql = "SELECT  COUNT(email) AS count\r
+                       FROM    wcf".WCF_N."_user\r
+                       WHERE   email = ?";\r
+               $statement = WCF::getDB()->prepareStatement($sql);\r
+               $statement->execute(array($email));\r
+               $row = $statement->fetchArray();\r
+               return $row['count'] == 0;\r
+       }\r
+       \r
+       /**\r
+        * Returns the user agent of the client.\r
+        * \r
+        * @return      string\r
+        */\r
+       public static function getUserAgent() {\r
+               if (isset($_SERVER['HTTP_USER_AGENT'])) return substr($_SERVER['HTTP_USER_AGENT'], 0, 255);\r
+               return '';\r
+       }\r
+       \r
+       /**\r
+        * Returns the ip address of the client.\r
+        *\r
+        * @return      string          ip address\r
+        */\r
+       public static function getIpAddress() {\r
+               $REMOTE_ADDR = '';\r
+               if (isset($_SERVER['REMOTE_ADDR'])) $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];\r
+               if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR'];\r
+               else $HTTP_X_FORWARDED_FOR = '';\r
+       \r
+               if (!empty($HTTP_X_FORWARDED_FOR)) {\r
+                       $match = array();\r
+                       if (preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/", $HTTP_X_FORWARDED_FOR, $match)) {\r
+                               $REMOTE_ADDR = preg_replace(self::$privateIpList, $REMOTE_ADDR, $match[1]);     \r
+                       }\r
+               }\r
+       \r
+               // darwin fix\r
+               if ($REMOTE_ADDR == '::1' || $REMOTE_ADDR == 'fe80::1') {\r
+                       $REMOTE_ADDR = '127.0.0.1'; \r
+               }\r
+               \r
+               return $REMOTE_ADDR;\r
+       }\r
+       \r
+       /**\r
+        * Returns the request uri of the active request.\r
+        * \r
+        * @return      string\r
+        */\r
+       public static function getRequestURI() {\r
+               $REQUEST_URI = '';\r
+               /*if (!empty($_SERVER['REQUEST_URI'])) {\r
+                       $REQUEST_URI = $_SERVER['REQUEST_URI'];\r
+               }\r
+               else {*/\r
+                       if (!empty($_SERVER['ORIG_PATH_INFO']) && strpos($_SERVER['ORIG_PATH_INFO'], '.php') !== false) {\r
+                               $REQUEST_URI = $_SERVER['ORIG_PATH_INFO'];\r
+                       }\r
+                       else if (!empty($_SERVER['ORIG_SCRIPT_NAME'])) {\r
+                               $REQUEST_URI = $_SERVER['ORIG_SCRIPT_NAME'];\r
+                       }\r
+                       else if (!empty($_SERVER['SCRIPT_NAME'])) {\r
+                               $REQUEST_URI = $_SERVER['SCRIPT_NAME'];\r
+                       }\r
+                       else if (!empty($_SERVER['PHP_SELF'])) {\r
+                               $REQUEST_URI = $_SERVER['PHP_SELF'];\r
+                       }\r
+                       else if (!empty($_SERVER['PATH_INFO'])) {\r
+                               $REQUEST_URI = $_SERVER['PATH_INFO'];\r
+                       }\r
+                       if (!empty($_SERVER['QUERY_STRING'])) {\r
+                               $REQUEST_URI .= '?'.$_SERVER['QUERY_STRING'];\r
+                       }\r
+               //}\r
+               \r
+               //if (!strstr($REQUEST_URI, '.')) $REQUEST_URI = 'index.php';\r
+               \r
+               return substr(FileUtil::unifyDirSeperator($REQUEST_URI), 0, 255);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/util/XML.class.php b/wcfsetup/install/files/lib/util/XML.class.php
new file mode 100644 (file)
index 0000000..cb55078
--- /dev/null
@@ -0,0 +1,195 @@
+<?php\r
+namespace wcf\util;\r
+use wcf\system\exception\SystemException;\r
+\r
+/**\r
+ * Reads and validates xml documents.\r
+ * \r
+ * @author     Alexander Ebert\r
+ * @copyright  2001-2011 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ * @package    com.woltlab.wcf\r
+ * @subpackage util\r
+ * @category   Community Framework\r
+ */\r
+class XML {\r
+       /**\r
+        * DOMDocument object\r
+        * \r
+        * @var DOMDocument\r
+        */\r
+       protected $document = null;\r
+       \r
+       /**\r
+        * document path\r
+        * \r
+        * @var string\r
+        */\r
+       protected $path = '';\r
+       \r
+       /**\r
+        * schema file path\r
+        * \r
+        * @var string\r
+        */\r
+       protected $schema = '';\r
+       \r
+       /**\r
+        * DOMXPath object\r
+        * \r
+        * @var DOMXPath\r
+        */\r
+       protected $xpath = null;\r
+       \r
+       /**\r
+        * Prepares a new instance of DOMDocument and enables own error handler for libxml.\r
+        */     \r
+       public function __construct() {\r
+               libxml_use_internal_errors(true);\r
+               $this->document = new \DOMDocument('1.0', 'UTF-8');\r
+               $this->document->preserveWhiteSpace = false;\r
+       }\r
+       \r
+       /**\r
+        * Loads a xml file for processing.\r
+        * \r
+        * @param       string          $path\r
+        */\r
+       public function load($path) {\r
+               $this->path = $path;\r
+               \r
+               // ensure file exists and is readable\r
+               if (!file_exists($this->path) || !is_readable($this->path)) {\r
+                       throw new SystemException("Could not read xml document located at '".$this->path."'.");\r
+               }\r
+               \r
+               // load xml document\r
+               $this->document->load($path);\r
+               \r
+               // check for errors occured in libxml\r
+               $errors = $this->pollErrors();\r
+               if (count($errors)) {\r
+                       $this->throwException("XML document '".$this->path."' is not valid XML.", $errors);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Loads a xml string, specifying $path is mandatory to provide detailied error handling.\r
+        * \r
+        * @param       string          $path\r
+        * @param       string          $xml\r
+        */\r
+       public function loadXML($path, $xml) {\r
+               $this->path = $path;\r
+               \r
+               // load xml document\r
+               $this->document->loadXML($xml);\r
+               \r
+               // check for errors occured in libxml\r
+               $errors = $this->pollErrors();\r
+               if (count($errors)) {\r
+                       $this->throwException("XML document '".$this->path."' is not valid XML.", $errors);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Validate the loaded document against the specified xml schema definition.\r
+        */\r
+       public function validate() {\r
+               // determine schema\r
+               $this->getSchema();\r
+               \r
+               // validate document against schema\r
+               $this->document->schemaValidate($this->schema);\r
+               \r
+               // check for errors occured in libxml\r
+               $errors = $this->pollErrors();\r
+               if (count($errors)) {\r
+                       $this->throwException("XML document '".$this->path."' violates XML schema definition.", $errors);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Determines schema for given document.\r
+        */\r
+       protected function getSchema() {\r
+               // determine schema by looking for xsi:schemaLocation\r
+               $this->schema = $this->document->documentElement->getAttributeNS($this->document->documentElement->lookupNamespaceURI('xsi'), 'schemaLocation');\r
+               \r
+               // no valid schema found or it's lacking a valid namespace\r
+               if (strpos($this->schema, ' ') === false) {\r
+                       throw new SystemException("XML document '".$this->path."' does not provide a valid schema.");\r
+               }\r
+               \r
+               // build file path upon namespace and filename\r
+               $tmp = explode(' ', $this->schema);\r
+               $this->schema = WCF_DIR.'xsd/'.StringUtil::substring(sha1($tmp[0]), 0, 8) . '_' . basename($tmp[1]);\r
+               \r
+               if (!file_exists($this->schema) || !is_readable($this->schema)) {\r
+                       throw new SystemException("Could not read XML schema definition located at '".$this->schema."'.");\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns a DOMXPath object bound to current DOMDocument object. Default\r
+        * namespace will be bound to prefix 'ns'.\r
+        * \r
+        * @return      DOMXPath\r
+        */\r
+       public function xpath() {\r
+               if ($this->xpath === null) {\r
+                       $this->xpath = new \DOMXPath($this->document);\r
+                       \r
+                       // register default namespace with prefix 'ns'\r
+                       $namespace = $this->document->documentElement->getAttribute('xmlns');\r
+                       $this->xpath->registerNamespace('ns', $namespace);\r
+               }\r
+               \r
+               return $this->xpath;\r
+       }\r
+       \r
+       /**\r
+        * Reads errors from libxml since be bypassed built-in error handler.\r
+        * \r
+        * @see         XML::__construct()\r
+        * @return      array<array>\r
+        */\r
+       protected function pollErrors() {\r
+               $errors = array();\r
+               $errorList = libxml_get_errors();\r
+               \r
+               foreach ($errorList as $error) {\r
+                       $errors[] = array(\r
+                               'message' => $error->message,\r
+                               'line' => $error->line,\r
+                               'file' => $this->path\r
+                       );\r
+               }\r
+               \r
+               libxml_clear_errors();\r
+               \r
+               return $errors;\r
+       }\r
+       \r
+       /**\r
+        * Throws a SystemException providing details on xml errors if applicable.\r
+        * \r
+        * @param       string          $message\r
+        * @param       array           $errors\r
+        */\r
+       protected function throwException($message, array $errors = array()) {\r
+               if (count($errors)) {\r
+                       $description = '<b>LibXML output:</b><pre>';\r
+                       foreach ($errors as $error) {\r
+                               $description .= "#".$error['line']."\t".$error['message'];\r
+                       }\r
+                       $description .= '</pre>';\r
+                       \r
+                       throw new SystemException($message, 0, $description);\r
+               }\r
+               else {\r
+                       throw new SystemException($message);\r
+               }\r
+       }\r
+}\r
+?>\r
diff --git a/wcfsetup/install/files/options.inc.php b/wcfsetup/install/files/options.inc.php
new file mode 100644 (file)
index 0000000..2bdab11
--- /dev/null
@@ -0,0 +1,26 @@
+<?php\r
+/**\r
+ * default options.inc.php for package installation of package com.woltlab.wcf.\r
+ *\r
+ * @author     Marcel Werk \r
+ * @copyright  2001-2007 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ */\r
+define('COOKIE_PREFIX', 'wcf_');\r
+define('COOKIE_PATH', '');\r
+define('COOKIE_DOMAIN', '');\r
+\r
+define('HTTP_ENABLE_NO_CACHE_HEADERS', 0);\r
+define('HTTP_ENABLE_GZIP', 0);\r
+define('HTTP_GZIP_LEVEL', 1);\r
+\r
+define('BLACKLIST_IP_ADDRESSES', '');\r
+define('BLACKLIST_USER_AGENTS', '');\r
+define('BLACKLIST_HOSTNAMES', '');\r
+\r
+define('SESSION_TIMEOUT', 3600);\r
+\r
+define('CACHE_SOURCE_TYPE', 'disk');\r
+define('ENABLE_SESSION_DATA_CACHE', 0);\r
+define('MODULE_MASTER_PASSWORD', 1);\r
+?>
\ No newline at end of file
diff --git a/wcfsetup/install/files/style/buttons.css b/wcfsetup/install/files/style/buttons.css
new file mode 100644 (file)
index 0000000..59dd38b
--- /dev/null
@@ -0,0 +1,160 @@
+
+/* ### -- -- -- -- -- Button Styles -- -- -- -- -- ### */
+
+/* 
+
+File: buttons.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Large Buttons -- -- -- -- -- ### */
+
+.largeButtons:after {
+       content: "";
+       display: block;
+       clear: both;
+       height: 0;
+}
+
+.largeButtons ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+.largeButtons li {
+       border: 1px;
+       margin: 0 0 0 5px;
+       float: right;
+}
+
+.largeButtons a {
+       text-decoration: none;
+       white-space: nowrap;
+       border-width: 1px;
+       border-style: solid;
+       padding: 1px 4px;
+       display: block;
+}
+
+.largeButtons span {
+       font-weight: normal;
+}
+
+/* ### -- -- -- -- -- Small Buttons -- -- -- -- -- ### */
+
+.smallButtons:after {
+       content: "";
+       display: block;
+       clear: both;
+       height: 0;
+}
+
+.smallButtons ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+.smallButtons li {
+       border: 1px;
+       margin: 10px 0 0 4px;
+       float: right;
+}
+
+.smallButtons .pageMenu li {
+       border: 0; 
+       margin: 0;
+       padding: 0;
+       float: none;
+}
+
+.smallButtons a {
+       text-decoration: none;
+       line-height: 1.3;
+       border-width: 1px;
+       border-style: solid;
+       padding: 0 2px;
+       display: block;
+       white-space: nowrap;
+}
+
+.smallButtons .pageMenu a {
+       border: 0;
+}
+
+.smallButtons span {
+       font-weight: normal;
+       padding-left: 1px;
+}
+
+.smallButtons img {
+       margin-top: -1px;
+}
+
+.smallButtons > ul > li > a {
+       min-height: 18px !important;
+}
+
+/* ### -- -- -- -- -- Option Buttons -- -- -- -- -- ### */
+
+.optionButtons ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+.optionButtons li {
+       margin-top: .3em;
+       margin-right: 2px;
+       float: left;
+}
+
+.optionButtons .pageMenu li {
+       border: 0;
+       margin: 0;
+       padding: 0;
+       float: none;
+}
+
+.optionButtons a {
+       text-decoration: none;
+       line-height: 1.3;
+       padding: 0 4px 0 4px;
+       display: block;
+}
+
+.optionButtons .pageMenu a {
+       border: 0;
+       margin: 0;
+       padding: 0;
+       float: none;
+}
+
+ .optionButtons > ul > li > a {
+       min-height: 18px !important;
+}
+
+/* ### -- -- -- -- -- Button Bar -- -- -- -- -- ### */
+
+.buttonBar {
+       border-width: 1px 0 0 0;
+       margin-top: 5px;
+       display: block;
+       clear: both;
+}
+
+.buttonBar p {
+       margin-top: 7px;
+}
+
+.buttonBar .extraButton {
+       margin-left: 10px;
+}
+
+.buttonBar .buttonBarCaption {
+       float: left;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/colorPicker.css b/wcfsetup/install/files/style/colorPicker.css
new file mode 100644 (file)
index 0000000..0d7b992
--- /dev/null
@@ -0,0 +1,132 @@
+
+/* ### -- -- -- -- -- Color Picker Styles -- -- -- -- -- ### */
+
+/* 
+
+File: colorPicker.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Color Picker -- -- -- -- -- ### */
+
+input.colorPicker {
+       font-family: "Courier New", Courier, monospace;
+       margin-right: 3px;
+       width: auto !important;
+}
+
+input[class~='colorPicker'] + script + img.colorPicker {
+       margin-top: -5px;
+}
+
+img.colorPicker:hover {
+       cursor: pointer;
+}
+
+/* ### -- -- -- -- -- Color Picker Full -- -- -- -- -- ### */
+
+#colorPickerFull {
+       border-width: 0 0 1px 1px;
+       border-style: solid:
+       border-color: #000;
+       background-color: #000;
+       position: absolute;
+       height: 192px;
+       width: 304px;
+       z-index: 100;
+}
+
+#colorPickerFull ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+       display: block;
+       float: left;
+       position: relative;
+}
+
+#colorPickerFull ul:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+#colorPickerFull li {
+       font-size: 0; /* ie6 */
+       border-width: 1px 1px 0 0;
+       border-style: solid:
+       border-color: #000;
+       display: block;
+       float: left;
+       height: 15px;
+       width: 15px;
+}
+
+#colorPickerFull a {
+       border: 1px solid transparent;
+       display: block;
+       height: 13px;
+       width: 13px;
+}
+
+#colorPickerFull a:hover {
+       border: 1px solid #fff !important;
+}
+
+#colorPickerFull .colorColumn {
+       width: 96px;
+}
+
+#colorPickerFull .greyColumn {
+       width: 16px;
+}
+
+/* ### -- -- -- -- -- Color Picker Simple -- -- -- -- -- ### */
+
+#colorPickerSimple {
+       background-color: #000;
+       float: left;
+       width: 113px !important;
+       position: absolute;
+       z-index: 100;
+}
+
+#colorPickerSimple ul {
+       list-style: none;
+       margin: 0;
+       padding: 1px 0 0 1px;
+       width: auto;
+}
+
+#colorPickerSimple ul li {
+       font-size: 0 !important;
+       margin: 0 1px 1px 0 !important;
+       padding: 0 !important;
+       float: left !important;
+       display: block !important;
+       height: 15px !important;
+       width: 15px !important;
+}
+
+#colorPickerSimple ul li a, #colorPickerSimple ul li a:hover {
+       background-image: none;
+       background-repeat: no-repeat !important;
+       background-position: 0 !important;
+       margin: 0 !important;
+       padding: 0 !important;
+       display: block !important;
+       height: 15px !important;
+       width: 15px !important;
+}
+
+#colorPickerSimple ul li a:hover {
+       border: 1px solid #fff !important;
+       background-repeat: no-repeat !important;
+       background-position: -1px -1px !important;
+       width: 13px !important;
+       height: 13px !important;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/containers.css b/wcfsetup/install/files/style/containers.css
new file mode 100644 (file)
index 0000000..96e0510
--- /dev/null
@@ -0,0 +1,182 @@
+\r
+/* ### -- -- -- -- -- Container Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: containers.css \r
+Copyright 2006-2010 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- Border -- -- -- -- -- ### */\r
+\r
+.border {\r
+       border-width: 1px;\r
+       margin-bottom: 7px;\r
+       padding: 1px 0 0 1px;\r
+}\r
+\r
+/* Special */\r
+\r
+.borderMarginRemove {\r
+       margin-top: -8px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Container Globals -- -- -- -- -- ### */\r
+\r
+.container-1, .container-2, .container-3, .containerHead {\r
+       margin: 0 1px 1px 0;\r
+}\r
+\r
+.containerHead {\r
+       padding: 2px 5px;\r
+}\r
+\r
+.content > div {\r
+       padding: 7px 25px;\r
+}\r
+\r
+.contentStyler p {\r
+       margin: 5px 0;  \r
+}\r
+\r
+/* ### -- -- -- -- -- Info Box -- -- -- -- -- ### */\r
+\r
+.infoBox .container-1, .infoBox .container-2 {\r
+       padding: 4px;\r
+       clear: both;\r
+}\r
+\r
+.infoBox h3 {\r
+       margin: 0 !important;\r
+       font-weight: bold;\r
+}\r
+\r
+/* ### -- -- -- -- -- Containers with Icons -- -- -- -- -- ### */\r
+\r
+/* Small (16px Icon) */\r
+\r
+.containerIconSmall {\r
+       text-align: center;\r
+       float: left;\r
+       width: 30px;\r
+}\r
+\r
+.containerContentSmall {\r
+       margin-left: 30px;\r
+}\r
+\r
+/* Standard (24px Icon) */\r
+\r
+.containerIcon {\r
+       text-align: center;\r
+       float: left;\r
+       width: 30px;\r
+}\r
+\r
+.containerContent {\r
+       margin-left: 35px;\r
+}\r
+\r
+/* Large (48px Icon) */\r
+\r
+.containerIconLarge {\r
+       text-align: center;\r
+       float: left;\r
+       width: 50px;\r
+}\r
+\r
+.containerContentLarge {\r
+       margin-left: 60px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Main Headline -- -- -- -- -- ### */\r
+\r
+.mainHeadline {\r
+       margin: 3px 0 7px 0;\r
+       padding: 0;\r
+       clear: both;\r
+       display: block;\r
+       min-height: 50px;\r
+       width: 100%;\r
+}\r
+\r
+.mainHeadline img {\r
+       float: left;\r
+}\r
+\r
+.mainHeadline .headlineContainer img {\r
+       float: none;\r
+}\r
+\r
+.mainHeadline .headlineContainer {\r
+       margin: 7px 0 7px 60px;\r
+       min-height: 48px;\r
+}\r
+\r
+.mainHeadline .headlineContainer h2 {\r
+       margin: 0;\r
+       padding: 0;\r
+       overflow: hidden;\r
+}\r
+\r
+.mainHeadline .headlineContainer h2 a {\r
+       text-decoration: none;\r
+}\r
+\r
+.mainHeadline .headlineContainer p {\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+/* ### -- -- -- -- -- Sub Headline -- -- -- -- -- ### */\r
+\r
+.subHeadline {\r
+       font-size: 1.5em;\r
+       font-weight: normal;\r
+       border-left-width: 0 !important;\r
+       border-right-width: 0 !important;\r
+       border-top-width: 0 !important;\r
+       margin-top: 7px;\r
+       margin-bottom: 10px !important;\r
+       padding-bottom: 7px;\r
+}\r
+\r
+.subHeadline a {\r
+       text-decoration: none;\r
+}\r
+\r
+.subHeadline span {\r
+       font-size: 75%;\r
+}\r
+\r
+.subHeadline .inputText {\r
+       width: 95%;\r
+}\r
+\r
+/* ### -- -- -- -- -- Fieldset -- -- -- -- -- ### */\r
+\r
+fieldset {\r
+       border-width: 1px;\r
+       margin: 10px 0;\r
+       padding: 5px 13px 10px 13px;\r
+       display: block;\r
+}\r
+\r
+fieldset:after {\r
+       content: "";\r
+       display: block;\r
+       clear: both;\r
+       height: 0;\r
+}\r
+\r
+fieldset legend {\r
+       margin: 0 0 0 -5px;\r
+       padding: 0 5px;\r
+}\r
+\r
+fieldset fieldset {\r
+       margin-bottom: 5px;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/extra/ie6-fix-rtl.css b/wcfsetup/install/files/style/extra/ie6-fix-rtl.css
new file mode 100644 (file)
index 0000000..8712281
--- /dev/null
@@ -0,0 +1,723 @@
+
+/* ### -- -- -- -- -- Bugfix-Styles for Microsoft Internet Explorer 6 -- -- -- -- -- ### */
+
+/* 
+
+File: ie6-fix.css 
+Copyright 2006-2011 by WoltLab GmbH. 
+
+For full XHTML- & CSS-Compatibility be sure to include this File only within the so called "Internet Explorer Comment Hack". 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+html, body {
+       height: 100%;
+}
+
+#main {
+       height: 0;      
+}
+
+.hidden {
+       width: 0;
+}
+
+.container-1, .container-2, .container-3 {
+       zoom: 1;        
+}
+
+.containerHead, .pageMenu ul li a, .tabMenu ul, .border {
+       height: 0 !important;
+}
+
+.contentHeader, .contentFooter {
+       height: 0;
+}
+
+.avatarDisplay fieldset {
+       display: inline;
+}
+
+.avatarSelect li label {
+       width: 154px;
+       height: 154px;
+}
+
+.avatarSelect img {
+       wcf: expression(
+               this.onclick = new Function("$(this).previous().checked = 'checked';")
+       );
+}
+
+.similarThreads li {
+       height: 0;
+}
+
+.longSelect select {
+       width: 500px;
+}
+
+.tableList .columnTopic div.topic, .mainHeadline .headlineContainer h2 {
+       width: 100%;
+}
+
+.tabMenuContent div.container-1 {
+       padding: 15px 25px 5px;
+}
+
+.content .container-1, .content .container-2, .content .container-3 {
+       padding: 7px 25px;
+}
+
+.mainHeadline {
+       height: 55px;
+}
+
+.smallButtons img {
+       margin-top: 1px;
+}
+
+.sidebar hr {
+       display: none;
+}
+
+/* ### -- -- -- -- -- global.css -- -- -- -- -- ### */
+
+.itemList li {
+       height: 0; /* triggers hasLayout */
+       list-style-type: none; /* list bullets look wrong with lists that trigger hasLayout */
+}
+
+form .disabled, .tabMenu .disabled {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);     
+}
+
+/* ### -- -- -- -- -- User Menu -- -- -- -- -- ### */
+
+#userMenu ul li a { /* this line is needed for the following declaration to work! */
+       text-decoration: underline;
+}
+
+#userMenu ul li a:hover { /* this line only works together with the previous declaration! */
+       text-decoration: none;
+}
+
+/* ### -- -- -- -- -- Login Popup -- -- -- -- -- ### */
+
+.loginPopup {
+       width: 0;       
+}
+
+.loginPopup input {
+       font-size: 1em;
+       width: auto;
+}
+
+/* ### -- -- -- -- -- System Messages/States -- -- -- -- -- ### */
+
+.info, .warning, .error, .success {
+       height: 0;      
+}
+
+.deleted img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+.infoBox {
+       clear: both !important;
+}
+
+.infoBox ul {
+       margin: 7px 0;
+}
+
+/* ### -- -- -- -- -- Main Menu -- -- -- -- -- ### */
+
+#userNote, #userMenu, #userMenu li, #userMenu ul {
+       display: inline;
+       width: auto;
+}
+
+#userMenu li {
+       float: none;
+}
+
+#userPanel .userPanelInner {
+       padding-top: 10px;
+       padding-bottom: 3px;
+}
+
+.mainMenu {
+       height: 0;
+}
+
+.mainMenu li, .mainMenu a {
+       display: inline;
+}
+
+.mainMenu img {
+       margin: 3px 0;
+}
+
+.mainMenu span, .pageMenu span {
+       padding: 0 2px 0 0;
+       display: inline !important;
+}
+
+/* ### -- -- -- -- -- Page -- -- -- -- -- ### */
+
+#page { 
+       height: 100%;
+}
+
+/* ### -- -- -- -- -- Search -- -- -- -- -- ### */
+
+#search {
+       white-space: nowrap;
+       width: 0;
+}
+
+/* ### -- -- -- -- -- Tab Menu & Sub Tab Menu -- -- -- -- -- ### */
+
+.tabMenu li {
+       width: 0 !important;
+}
+
+.subTabMenu {
+       height: 0;
+}
+
+.subTabMenu div {
+       height: 5px;
+}
+
+/* ### -- -- -- -- -- Popup Menu -- -- -- -- -- ### */
+
+.popupMenu {
+       white-space: normal !important;
+       width: 200px !important;
+}
+
+.popupMenu li, .popupMenu a {
+       width: 200px !important;
+}
+
+.pageMenu li, .pageMenu a {
+       height: 0 !important;
+}
+
+/* ### -- -- -- -- -- Page Navigation -- -- -- -- -- ### */
+
+.pageNavigation a {
+       width: 0;
+       height: 0;
+}
+
+.pageNavigation li.children a img {
+       display: none;
+}
+
+.pageNavigation input {
+       padding: 2px 0;
+       width: 1.5em;
+       min-height: 1.4em;
+}
+
+.tableList .statusDisplayIcons {
+       display: inline;
+}
+
+.tableList .statusDisplay .pageNavigation {
+       display: inline;        
+}
+
+/* ### -- -- -- -- -- Fieldset -- -- -- -- -- ### */
+
+fieldset {
+       margin-top: 25px;
+       padding-top: 15px;
+       position: relative;
+}
+
+fieldset legend {
+       padding: 3px;
+       position: absolute;
+       top: -13px;
+       right: 8px;
+}
+
+/* ### -- -- -- -- -- imageViewer.css -- -- -- -- -- ### */
+
+.imageViewerBackground, .imageViewerCurrentImage, .imageViewerMenu, .imageViewerCaption, .overlay {
+       position: absolute !important;
+}
+
+/* ### -- -- -- -- -- Members List (Whitelist / Blacklist) -- -- -- -- -- ### */
+
+.memberList li a {
+       height: auto !important;
+}
+
+.memberList li .memberName {
+       width: 174px;
+       height: 1px;
+}
+
+.memberList li .memberListStatusIcon {
+       position: absolute;
+       right: 5px;
+       top: 20%;
+}
+
+.memberList li a img {
+       position: absolute;
+       left: 4px;
+       top: 20%;
+}
+
+/* ### -- -- -- -- -- PM Layout -- -- -- -- -- ### */
+
+.pmIndex {
+       margin-bottom: 7px;
+}
+
+.pmFolders {
+       height: 0;
+}
+
+.pmUsageBar div {
+       border-bottom: 7px solid #0a0;
+       background-color: #0c0;
+       height: 1px !important;
+}
+
+/* ### -- -- -- -- -- messages.css -- -- -- -- -- ### */
+
+.message, .messageInner, .messageHeader, .messageFooter, .messageFooterLeft, .messageFooterRight, .containerContent, .smallButtons {
+       height: 0;
+}
+
+.messageBody {
+       float: right;
+}
+
+.message .messageTop .messageSidebar {
+       height: 100px;
+}
+
+.message .messageFramedTop .messageSidebar {
+       height: 90px;
+}
+
+.message .guestPost .messageSidebar {
+       height: 40px !important;
+}
+
+.message .messageTop .messageAuthor, .message .messageFramedTop .messageAuthor {
+       border-width: 0;
+       margin-right: 47px;
+       height: 0;
+}
+
+.message .messageLeft .messageAuthor, .message .messageLeft .messageAuthor, .message .messageFramedLeft .messageAuthor, .message .messageFramedLeft .messageAuthor {
+       margin-bottom: -1px;
+}
+
+.message .messageTop .userAvatarFramed, .message .messageFramedTop .userAvatarFramed {
+       height: 0;
+}
+
+.message .messageTop .userAvatar, .message .messageFramedTop .userAvatar, .message .messageTop .userAvatarFramed, .message .messageFramedTop .userAvatarFramed {
+       right: 0 !important;
+       top: 0 !important;
+}
+
+.message .messageLeft .userAvatarFramed, .message .messageRight .userAvatarFramed, .message .messageFramedLeft .userAvatarFramed, .message .messageFramedRight .userAvatarFramed {
+       width: 154px;
+       height: 154px;
+}
+
+.message .messageLeft .userAvatarFramed a, .message .messageRight .userAvatarFramed a, .message .messageFramedLeft .userAvatarFramed a, .message .messageFramedRight .userAvatarFramed a {
+       width: 152px;
+       height: 152px;
+}
+
+.message .messageTop .userAvatarFramed a, .message .messageFramedTop .userAvatarFramed a {
+       position: relative !important;
+       width: 78px;
+       height: 78px;
+}
+
+.message .messageLeft .userAvatarFramed, .message .messageRight .userAvatarFramed, .message .messageFramedLeft .userAvatarFramed, .message .messageFramedRight .userAvatarFramed {
+       margin: 7px 14px;
+}
+
+.message .messageLeft .userMessenger, .message .messageRight .userMessenger, .message .messageFramedLeft .userMessenger, .message .messageFramedRight .userMessenger {
+       position: static !important;
+}
+
+/* fixes thread-page flickering */
+.message .messageContent, .message .messageContentInner {
+       position: relative;
+}
+
+.message .messageHeader .containerIcon {
+       height: 30px;
+}
+
+/* ### -- -- -- -- -- Poll -- -- -- -- -- ### */
+
+.poll .containerContent {
+       height: 0;
+}
+
+.pollOptionBar {
+       font-size: 6px; /* fixes wrong bar-heights */
+       margin: 0;
+}
+
+.pollShowResults, .pollShowForm {
+       height: 0 !important;
+}
+
+/* ### -- -- -- -- -- Code Box -- -- -- -- -- ### */
+
+.codeBox img {
+       margin-top: 5px;
+}
+
+.codeBox table {
+       font-size: 1em;
+}
+
+.codeBox div {
+       width: 100%;
+       overflow-y: hidden;
+}
+
+.codeBox pre {
+       padding-bottom: 2em;
+}
+
+/* ### -- -- -- -- -- wysiwyg.css -- -- -- -- -- ### */
+
+.mceButtonDisabled a img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
+}
+
+div.mceColors {
+       height: 0 !important;
+}
+
+div.mceColors ul {
+       height: 0 !important;
+}
+
+div.mceColors ul li {
+       font-size: 0 !important;
+       margin: 0 !important;
+}
+
+div.mceColors ul li a, div.mceColors ul li a:hover {
+       margin: 0 0 1px 1px !important;
+       width: 15px !important;
+       height: 15px !important;
+}
+
+.editor .container-1, .editor .container-2, .editor .container-3 {
+       padding: 0 !important;
+}
+
+.editor .popupMenu {
+       bottom: 24px !important;
+       height: 0 !important;
+       right: 0 !important;
+       width: auto !important;
+}
+
+.mceToolbar ul {
+       margin: 0 !important;
+}
+
+/* ### -- -- -- -- -- forms.css -- -- -- -- -- ### */
+
+.floatContainer, .formElement, .formGroup, .formGroupField {
+       height: 0;
+}
+
+.formGroup fieldset {
+       margin: 0;
+       padding: 8px;
+       position: static;
+}
+
+form textarea {
+       border-width: 1px;
+       width: 98%;
+}
+
+textarea, .inputText {
+       width: 98%;
+}
+
+/* ### -- -- -- -- -- table.css -- -- -- -- -- ### */
+
+table {
+       border-collapse: collapse;
+}
+
+.tableList {
+       font-size: 1em;
+}
+
+tr.tableHead a img {
+       margin-top: 0;
+}
+
+.tableHead .emptyHead input {
+       margin-top: -1px;
+}
+
+.tableHead a, .tableHead .emptyHead {
+       height: 21px !important;
+}
+
+/* ### -- -- -- -- -- burningboard.css -- -- -- -- -- ### */
+
+#boardlist .container-1, #boardlist .container-2 {
+       display: inline;
+       float: right;
+}
+
+#boardlist li ul .boardlistTitle .containerIcon {
+       display: inline; /* prevents double margin */
+}
+
+#boardlist li ul li ul .boardlistTitle .containerIcon {
+       display: inline; /* prevents double margin */
+}
+
+#boardlist li ul li ul li ul .boardlistTitle .containerIcon {
+       display: inline; /* prevents double margin */
+}
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+.eventList a {
+       height: 1.8em;  
+}
+
+.otherMonth {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+#repeatByDaySettings .toggleButton ul, #repeatByMonthSettings .toggleButton ul, #repeatByMonthDaySettings .toggleButton ul, #repeatByWeekSettings .toggleButton ul {
+       width: 493px;
+}
+
+.accessRights ul li {
+       height: 0;
+}
+
+.userProfileBox .border .timeLabel a {
+       width: 0;
+}
+
+/* ### -- -- -- -- -- profile.css -- -- -- -- -- ### */                        
+
+#userCard {
+       position: relative !important;
+       height: 0;
+}
+
+#userCard .userCardList {
+       position: static !important;
+}
+
+#userCardAvatar .userAvatar {
+       display: inline;
+}
+
+#userCardAvatar .userAvatar a img {
+       clear: both;
+}
+
+#userCardCredits .userPersonals {
+       height: 59px;
+       overflow: visible !important;
+}
+
+#userCard .smallButtons {
+       display: block;
+}
+
+#userCard .smallButtons ul {
+       width: 70%;
+}
+
+#userCard .smallButtons ul li {
+       width: 0;
+}
+
+#userCard .smallButtons ul li a {
+       float: right !important;
+}
+
+.dynContainer {
+       height: 0;
+}
+
+.dynContainer .last {
+       width: auto !important;
+}
+
+#userCard .friendsNone {
+       margin-bottom: -30px !important;
+}
+
+.pageMenu .twoRows a:hover {
+       padding-top: 2px !important;
+       padding-bottom: 4px !important;
+       height: 0 !important;
+}
+
+/* -- -- -- -- -- layout.css -- -- -- -- -- */
+
+.column {
+       margin-bottom: -9999px;
+       padding-bottom: 9999px;
+       display: inline-block;
+}
+
+.column {
+       display: inline;
+       float: right;
+}
+
+.columnInner {
+       height: 0;
+}
+
+.columnContainer {
+       height: 0;
+}
+
+.layout-2 .second {
+       width: auto !important;
+}
+
+.columnInner #editor {
+       width: 97.5%;   
+}
+
+.sidebar, .sidebar * {
+        display: inline-block;
+}
+
+.sidebar .subTabMenu li a {
+        display: inline !important;
+}
+
+/* ### -- -- -- -- -- gallery.css -- -- -- -- -- ### */
+
+a .thumbnail img {
+       wcf: expression(
+               this.onclick = new Function("window.location.href= $(this).up('a').href;")
+       );
+}
+
+.galleryPhoto img {
+       width: auto;
+}
+
+.galleryIndex .floatedElement {
+       border: 0;
+       padding: 8px 8px 14px;
+       overflow: hidden !important;
+}
+
+.galleryIndex .marked {
+       border-width: 1px;
+       padding: 7px 7px 13px;
+}
+
+.galleryIndex .thumbnailButtons {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);
+       visibility: visible !important;
+       width: 103%;
+       bottom: 65px;
+}
+
+.galleryIndex .thumbnailButtons input {
+       margin: 0 2px !important;
+}
+
+.galleryIndex .thumbnailButtons .container-4 {
+       display: inline !important;
+}
+
+.thumbnailView .last {
+       width: auto !important;
+}
+
+.gallery .layout-2 .first {
+       width: 65% !important;
+}
+
+.gallery .layout-2 .second {
+       width: 35% !important;
+}
+
+.sidebar .smallButtons li {
+       width: 0;
+}
+
+.balloon {
+       width: 0 !important;
+}
+
+/* ### -- -- -- -- -- rules.css -- -- -- -- -- -- ### */
+
+.rules ol {
+       margin-right: 20px;     
+}
+
+/* ### -- -- -- -- -- footer.css -- -- -- -- -- ### */
+
+.footerMenu, .footerOptions {
+       height: 0;
+}
+
+.footerOptions {
+       white-space: nowrap;
+}
+
+.footerOptions li {
+       display: inline-block;  
+}
+
+.footerMenu li, .footerMenu a, .footerOptions li, .footerOptions a {
+       display: inline;
+}
+
+.footerMenu img, .footerOptions img {
+       margin: 3px 0;
+}
+
+.footerMenu span, .footerOptions span  {
+       padding: 0 2px 0 0;
+       display: inline !important;
+}
+
+.footerOptions li.extraButton a {
+       padding: 1px 2px !important;
+       display: block;
+}
+
+.footerOptions li.extraButton a img {
+       margin: 0 !important;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/extra/ie6-fix.css b/wcfsetup/install/files/style/extra/ie6-fix.css
new file mode 100644 (file)
index 0000000..62901aa
--- /dev/null
@@ -0,0 +1,723 @@
+
+/* ### -- -- -- -- -- Bugfix-Styles for Microsoft Internet Explorer 6 -- -- -- -- -- ### */
+
+/* 
+
+File: ie6-fix.css 
+Copyright 2006-2011 by WoltLab GmbH. 
+
+For full XHTML- & CSS-Compatibility be sure to include this File only within the so called "Internet Explorer Comment Hack". 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+html, body {
+       height: 100%;
+}
+
+#main {
+       height: 0;      
+}
+
+.hidden {
+       width: 0;
+}
+
+.container-1, .container-2, .container-3 {
+       zoom: 1;        
+}
+
+.containerHead, .pageMenu ul li a, .tabMenu ul, .border {
+       height: 0 !important;
+}
+
+.contentHeader, .contentFooter {
+       height: 0;
+}
+
+.avatarDisplay fieldset {
+       display: inline;
+}
+
+.avatarSelect li label {
+       width: 154px;
+       height: 154px;
+}
+
+.avatarSelect img {
+       wcf: expression(
+               this.onclick = new Function("$(this).previous().checked = 'checked';")
+       );
+}
+
+.similarThreads li {
+       height: 0;
+}
+
+.longSelect select {
+       width: 500px;
+}
+
+.tableList .columnTopic div.topic, .mainHeadline .headlineContainer h2 {
+       width: 100%;
+}
+
+.tabMenuContent div.container-1 {
+       padding: 15px 25px 5px;
+}
+
+.content .container-1, .content .container-2, .content .container-3 {
+       padding: 7px 25px;
+}
+
+.mainHeadline {
+       height: 55px;
+}
+
+.smallButtons img {
+       margin-top: 1px;
+}
+
+.sidebar hr {
+       display: none;
+}
+
+/* ### -- -- -- -- -- global.css -- -- -- -- -- ### */
+
+.itemList li {
+       height: 0; /* triggers hasLayout */
+       list-style-type: none; /* list bullets look wrong with lists that trigger hasLayout */
+}
+
+form .disabled, .tabMenu .disabled {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);     
+}
+
+/* ### -- -- -- -- -- User Menu -- -- -- -- -- ### */
+
+#userMenu ul li a { /* this line is needed for the following declaration to work! */
+       text-decoration: underline;
+}
+
+#userMenu ul li a:hover { /* this line only works together with the previous declaration! */
+       text-decoration: none;
+}
+
+/* ### -- -- -- -- -- Login Popup -- -- -- -- -- ### */
+
+.loginPopup {
+       width: 0;       
+}
+
+.loginPopup input {
+       font-size: 1em;
+       width: auto;
+}
+
+/* ### -- -- -- -- -- System Messages/States -- -- -- -- -- ### */
+
+.info, .warning, .error, .success {
+       height: 0;      
+}
+
+.deleted img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+.infoBox {
+       clear: both !important;
+}
+
+.infoBox ul {
+       margin: 7px 0;
+}
+
+/* ### -- -- -- -- -- Main Menu -- -- -- -- -- ### */
+
+#userNote, #userMenu, #userMenu li, #userMenu ul {
+       display: inline;
+       width: auto;
+}
+
+#userMenu li {
+       float: none;
+}
+
+#userPanel .userPanelInner {
+       padding-top: 10px;
+       padding-bottom: 3px;
+}
+
+.mainMenu {
+       height: 0;
+}
+
+.mainMenu li, .mainMenu a {
+       display: inline;
+}
+
+.mainMenu img {
+       margin: 3px 0;
+}
+
+.mainMenu span, .pageMenu span {
+       padding: 0 0 0 2px;
+       display: inline !important;
+}
+
+/* ### -- -- -- -- -- Page -- -- -- -- -- ### */
+
+#page { 
+       height: 100%;
+}
+
+/* ### -- -- -- -- -- Search -- -- -- -- -- ### */
+
+#search {
+       white-space: nowrap;
+       width: 0;
+}
+
+/* ### -- -- -- -- -- Tab Menu & Sub Tab Menu -- -- -- -- -- ### */
+
+.tabMenu li {
+       width: 0 !important;
+}
+
+.subTabMenu {
+       height: 0;
+}
+
+.subTabMenu div {
+       height: 5px;
+}
+
+/* ### -- -- -- -- -- Popup Menu -- -- -- -- -- ### */
+
+.popupMenu {
+       white-space: normal !important;
+       width: 200px !important;
+}
+
+.popupMenu li, .popupMenu a {
+       width: 200px !important;
+}
+
+.pageMenu li, .pageMenu a {
+       height: 0 !important;
+}
+
+/* ### -- -- -- -- -- Page Navigation -- -- -- -- -- ### */
+
+.pageNavigation a {
+       width: 0;
+       height: 0;
+}
+
+.pageNavigation li.children a img {
+       display: none;
+}
+
+.pageNavigation input {
+       padding: 2px 0;
+       width: 1.5em;
+       min-height: 1.4em;
+}
+
+.tableList .statusDisplayIcons {
+       display: inline;
+}
+
+.tableList .statusDisplay .pageNavigation {
+       display: inline;        
+}
+
+/* ### -- -- -- -- -- Fieldset -- -- -- -- -- ### */
+
+fieldset {
+       margin-top: 25px;
+       padding-top: 15px;
+       position: relative;
+}
+
+fieldset legend {
+       padding: 3px;
+       position: absolute;
+       top: -13px;
+       left: 8px;
+}
+
+/* ### -- -- -- -- -- imageViewer.css -- -- -- -- -- ### */
+
+.imageViewerBackground, .imageViewerCurrentImage, .imageViewerMenu, .imageViewerCaption, .overlay {
+       position: absolute !important;
+}
+
+/* ### -- -- -- -- -- Members List (Whitelist / Blacklist) -- -- -- -- -- ### */
+
+.memberList li a {
+       height: auto !important;
+}
+
+.memberList li .memberName {
+       width: 174px;
+       height: 1px;
+}
+
+.memberList li .memberListStatusIcon {
+       position: absolute;
+       left: 5px;
+       top: 20%;
+}
+
+.memberList li a img {
+       position: absolute;
+       right: 4px;
+       top: 20%;
+}
+
+/* ### -- -- -- -- -- PM Layout -- -- -- -- -- ### */
+
+.pmIndex {
+       margin-bottom: 7px;
+}
+
+.pmFolders {
+       height: 0;
+}
+
+.pmUsageBar div {
+       border-bottom: 7px solid #0a0;
+       background-color: #0c0;
+       height: 1px !important;
+}
+
+/* ### -- -- -- -- -- messages.css -- -- -- -- -- ### */
+
+.message, .messageInner, .messageHeader, .messageFooter, .messageFooterLeft, .messageFooterRight, .containerContent, .smallButtons {
+       height: 0;
+}
+
+.messageBody {
+       float: left;
+}
+
+.message .messageTop .messageSidebar {
+       height: 100px;
+}
+
+.message .messageFramedTop .messageSidebar {
+       height: 90px;
+}
+
+.message .guestPost .messageSidebar {
+       height: 40px !important;
+}
+
+.message .messageTop .messageAuthor, .message .messageFramedTop .messageAuthor {
+       border-width: 0;
+       margin-left: 47px;
+       height: 0;
+}
+
+.message .messageLeft .messageAuthor, .message .messageLeft .messageAuthor, .message .messageFramedLeft .messageAuthor, .message .messageFramedLeft .messageAuthor {
+       margin-bottom: -1px;
+}
+
+.message .messageTop .userAvatarFramed, .message .messageFramedTop .userAvatarFramed {
+       height: 0;
+}
+
+.message .messageTop .userAvatar, .message .messageFramedTop .userAvatar, .message .messageTop .userAvatarFramed, .message .messageFramedTop .userAvatarFramed {
+       left: 0 !important;
+       top: 0 !important;
+}
+
+.message .messageLeft .userAvatarFramed, .message .messageRight .userAvatarFramed, .message .messageFramedLeft .userAvatarFramed, .message .messageFramedRight .userAvatarFramed {
+       width: 154px;
+       height: 154px;
+}
+
+.message .messageLeft .userAvatarFramed a, .message .messageRight .userAvatarFramed a, .message .messageFramedLeft .userAvatarFramed a, .message .messageFramedRight .userAvatarFramed a {
+       width: 152px;
+       height: 152px;
+}
+
+.message .messageTop .userAvatarFramed a, .message .messageFramedTop .userAvatarFramed a {
+       position: relative !important;
+       width: 78px;
+       height: 78px;
+}
+
+.message .messageLeft .userAvatarFramed, .message .messageRight .userAvatarFramed, .message .messageFramedLeft .userAvatarFramed, .message .messageFramedRight .userAvatarFramed {
+       margin: 7px 14px;
+}
+
+.message .messageLeft .userMessenger, .message .messageRight .userMessenger, .message .messageFramedLeft .userMessenger, .message .messageFramedRight .userMessenger {
+       position: static !important;
+}
+
+/* fixes thread-page flickering */
+.message .messageContent, .message .messageContentInner {
+       position: relative;
+}
+
+.message .messageHeader .containerIcon {
+       height: 30px;
+}
+
+/* ### -- -- -- -- -- Poll -- -- -- -- -- ### */
+
+.poll .containerContent {
+       height: 0;
+}
+
+.pollOptionBar {
+       font-size: 6px; /* fixes wrong bar-heights */
+       margin: 0;
+}
+
+.pollShowResults, .pollShowForm {
+       height: 0 !important;
+}
+
+/* ### -- -- -- -- -- Code Box -- -- -- -- -- ### */
+
+.codeBox img {
+       margin-top: 5px;
+}
+
+.codeBox table {
+       font-size: 1em;
+}
+
+.codeBox div {
+       width: 100%;
+       overflow-y: hidden;
+}
+
+.codeBox pre {
+       padding-bottom: 2em;
+}
+
+/* ### -- -- -- -- -- wysiwyg.css -- -- -- -- -- ### */
+
+.mceButtonDisabled a img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
+}
+
+div.mceColors {
+       height: 0 !important;
+}
+
+div.mceColors ul {
+       height: 0 !important;
+}
+
+div.mceColors ul li {
+       font-size: 0 !important;
+       margin: 0 !important;
+}
+
+div.mceColors ul li a, div.mceColors ul li a:hover {
+       margin: 0 1px 1px 0 !important;
+       width: 15px !important;
+       height: 15px !important;
+}
+
+.editor .container-1, .editor .container-2, .editor .container-3 {
+       padding: 0 !important;
+}
+
+.editor .popupMenu {
+       bottom: 24px !important;
+       height: 0 !important;
+       left: 0 !important;
+       width: auto !important;
+}
+
+.mceToolbar ul {
+       margin: 0 !important;
+}
+
+/* ### -- -- -- -- -- forms.css -- -- -- -- -- ### */
+
+.floatContainer, .formElement, .formGroup, .formGroupField {
+       height: 0;
+}
+
+.formGroup fieldset {
+       margin: 0;
+       padding: 8px;
+       position: static;
+}
+
+form textarea {
+       border-width: 1px;
+       width: 98%;
+}
+
+textarea, .inputText {
+       width: 98%;
+}
+
+/* ### -- -- -- -- -- table.css -- -- -- -- -- ### */
+
+table {
+       border-collapse: collapse;
+}
+
+.tableList {
+       font-size: 1em;
+}
+
+tr.tableHead a img {
+       margin-top: 0;
+}
+
+.tableHead .emptyHead input {
+       margin-top: -1px;
+}
+
+.tableHead a, .tableHead .emptyHead {
+       height: 21px !important;
+}
+
+/* ### -- -- -- -- -- burningboard.css -- -- -- -- -- ### */
+
+#boardlist .container-1, #boardlist .container-2 {
+       display: inline;
+       float: left;
+}
+
+#boardlist li ul .boardlistTitle .containerIcon {
+       display: inline; /* prevents double margin */
+}
+
+#boardlist li ul li ul .boardlistTitle .containerIcon {
+       display: inline; /* prevents double margin */
+}
+
+#boardlist li ul li ul li ul .boardlistTitle .containerIcon {
+       display: inline; /* prevents double margin */
+}
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+.eventList a {
+       height: 1.8em;  
+}
+
+.otherMonth {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+#repeatByDaySettings .toggleButton ul, #repeatByMonthSettings .toggleButton ul, #repeatByMonthDaySettings .toggleButton ul, #repeatByWeekSettings .toggleButton ul {
+       width: 493px;
+}
+
+.accessRights ul li {
+       height: 0;
+}
+
+.userProfileBox .border .timeLabel a {
+       width: 0;
+}
+
+/* ### -- -- -- -- -- profile.css -- -- -- -- -- ### */                        
+
+#userCard {
+       position: relative !important;
+       height: 0;
+}
+
+#userCard .userCardList {
+       position: static !important;
+}
+
+#userCardAvatar .userAvatar {
+       display: inline;
+}
+
+#userCardAvatar .userAvatar a img {
+       clear: both;
+}
+
+#userCardCredits .userPersonals {
+       height: 59px;
+       overflow: visible !important;
+}
+
+#userCard .smallButtons {
+       display: block;
+}
+
+#userCard .smallButtons ul {
+       width: 70%;
+}
+
+#userCard .smallButtons ul li {
+       width: 0;
+}
+
+#userCard .smallButtons ul li a {
+       float: left !important;
+}
+
+.dynContainer {
+       height: 0;
+}
+
+.dynContainer .last {
+       width: auto !important;
+}
+
+#userCard .friendsNone {
+       margin-bottom: -30px !important;
+}
+
+.pageMenu .twoRows a:hover {
+       padding-top: 2px !important;
+       padding-bottom: 4px !important;
+       height: 0 !important;
+}
+
+/* -- -- -- -- -- layout.css -- -- -- -- -- */
+
+.column {
+       margin-bottom: -9999px;
+       padding-bottom: 9999px;
+       display: inline-block;
+}
+
+.column {
+       display: inline;
+       float: left;
+}
+
+.columnInner {
+       height: 0;
+}
+
+.columnContainer {
+       height: 0;
+}
+
+.layout-2 .second {
+       width: auto !important;
+}
+
+.columnInner #editor {
+       width: 97.5%;   
+}
+
+.sidebar, .sidebar * {
+        display: inline-block;
+}
+
+.sidebar .subTabMenu li a {
+        display: inline !important;
+}
+
+/* ### -- -- -- -- -- gallery.css -- -- -- -- -- ### */
+
+a .thumbnail img {
+       wcf: expression(
+               this.onclick = new Function("window.location.href= $(this).up('a').href;")
+       );
+}
+
+.galleryPhoto img {
+       width: auto;
+}
+
+.galleryIndex .floatedElement {
+       border: 0;
+       padding: 8px 8px 14px;
+       overflow: hidden !important;
+}
+
+.galleryIndex .marked {
+       border-width: 1px;
+       padding: 7px 7px 13px;
+}
+
+.galleryIndex .thumbnailButtons {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);
+       visibility: visible !important;
+       width: 103%;
+       bottom: 65px;
+}
+
+.galleryIndex .thumbnailButtons input {
+       margin: 0 2px !important;
+}
+
+.galleryIndex .thumbnailButtons .container-4 {
+       display: inline !important;
+}
+
+.thumbnailView .last {
+       width: auto !important;
+}
+
+.gallery .layout-2 .first {
+       width: 65% !important;
+}
+
+.gallery .layout-2 .second {
+       width: 35% !important;
+}
+
+.sidebar .smallButtons li {
+       width: 0;
+}
+
+.balloon {
+       width: 0 !important;
+}
+
+/* ### -- -- -- -- -- rules.css -- -- -- -- -- -- ### */
+
+.rules ol {
+       margin-left: 20px;      
+}
+
+/* ### -- -- -- -- -- footer.css -- -- -- -- -- ### */
+
+.footerMenu, .footerOptions {
+       height: 0;
+}
+
+.footerOptions {
+       white-space: nowrap;
+}
+
+.footerOptions li {
+       display: inline-block;  
+}
+
+.footerMenu li, .footerMenu a, .footerOptions li, .footerOptions a {
+       display: inline;
+}
+
+.footerMenu img, .footerOptions img {
+       margin: 3px 0;
+}
+
+.footerMenu span, .footerOptions span  {
+       padding: 0 0 0 2px;
+       display: inline !important;
+}
+
+.footerOptions li.extraButton a {
+       padding: 1px 2px !important;
+       display: block;
+}
+
+.footerOptions li.extraButton a img {
+       margin: 0 !important;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/extra/ie7-fix-rtl.css b/wcfsetup/install/files/style/extra/ie7-fix-rtl.css
new file mode 100644 (file)
index 0000000..0d7e1eb
--- /dev/null
@@ -0,0 +1,428 @@
+
+/* ### -- -- -- -- -- Bugfix-Styles for Microsoft Internet Explorer 7 -- -- -- -- -- ### */
+
+/* 
+
+File: ie7-fix.css 
+Copyright 2006-2011 by WoltLab GmbH. 
+
+For full XHTML- & CSS-Compatibility be sure to include this File only within the so called "Internet Explorer Comment Hack". 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+#main {
+       min-height: 0;  
+}
+
+fieldset {
+       margin-top: 25px;
+}
+
+fieldset legend {
+       margin-top: -18px;
+}
+
+.container-1, .container-2, .container-3 {
+       min-height: 0;
+}
+
+.pageNavigation input {
+       margin-top: 2px !important;
+       margin-bottom: -2px !important;
+       padding: 0 !important;
+       width: 2em !important;
+       height: 10px !important;
+}
+
+.subTabMenu {
+       zoom: 1;        
+}
+
+.subTabMenu .containerHead {
+       min-height: auto;       
+}
+
+.subTabMenu .containerHead > ul {
+       min-height: 0;  
+}
+
+/* ### -- -- -- -- -- tables.css -- -- -- -- -- ### */
+
+table {
+       border-collapse: collapse;
+}
+
+.tableList .statusDisplayIcons {
+       display: inline;
+}
+
+.tableList .statusDisplay .pageNavigation {
+       display: inline;        
+}
+
+/* ### -- -- -- -- -- forms.css -- -- -- -- -- ### */
+
+.formElement {
+       min-height: 0;
+}
+
+.formGroup fieldset {
+       margin: 0;
+}
+
+form .formPrefix div {
+       margin-right: 5px;
+       min-height: 0;
+}
+
+form input[type="file"] {
+       padding: 3px;
+}
+
+textarea, .inputText {
+       width: 98%;
+}
+
+/* ### -- -- -- -- -- wysiwyg.css -- -- -- -- -- ### */
+
+.mceToolbar {
+       min-height: 0;  
+}
+
+.mceButtonDisabled a img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
+}
+
+div.mceColors {
+       min-height: 0 !important;
+       padding-bottom: 1px;
+}
+
+div.mceColors ul {
+       min-height: 0 !important;
+}
+
+#editor .border {
+       margin-top: -1px;
+       padding-bottom: 1px;    
+}
+
+.editor .popupMenu {
+       min-height: 0 !important;
+       right: 0 !important;
+       bottom: 24px !important;
+}
+
+/* ### -- -- -- -- -- header.css -- -- -- -- -- ### **/
+
+#userNote, #userMenu, #userMenu li, #userMenu ul {
+       display: inline;
+}
+
+#userMenu li {
+       float: none;
+}
+
+#userPanel .userPanelInner {
+       padding-top: 10px;
+       padding-bottom: 3px;
+}
+
+/* ### -- -- -- -- -- footer.css -- -- -- -- -- ### */
+
+#footer, #footerContainer {
+       position: relative;
+}
+
+.footerOptions {
+       white-space: nowrap;
+}
+
+.footerMenu li, .footerOptions li {
+       position: relative;
+}
+
+.footerOptions li.stylePicker {
+       position: relative;
+       top: -7px !important;
+}
+
+.footerOptions li.stylePicker div {
+       top: 25px;
+       right: 5px;
+}
+
+.footerOptions li.date  {
+       margin-bottom: 0 !important;
+}
+
+.footerOptions li.extraButton {
+       position: relative;
+       top: -5px !important;
+}
+
+.footerOptions li.extraButton a {
+       display: block;
+}
+
+.footerOptions li.extraButton a img {
+       margin: 0 !important;
+}
+
+/* ### -- -- -- -- -- Main Menu -- -- -- -- -- ### */
+
+.mainMenu a {
+       min-height: auto;       
+}
+
+.mainMenu > div > ul > li, .mainMenu a, .footerMenu li, .footerMenu a, .footerOptionsInner > ul > li, .footerOptions a {
+       display: inline;
+}
+
+.mainMenu img, .footerMenu img, .footerOptions img {
+       margin: 3px 0;
+}
+
+.mainMenu span, .footerMenu span, .footerOptions span, .pageMenu span {
+       padding: 0 2px 0 0;
+       display: inline !important;
+}
+
+/* ### -- -- -- -- -- messages.css -- -- -- -- -- ### */
+
+.message, .messageInner, .messageHeader, .messageBody, .messageFooter, .userMessenger {
+       min-height: 0 !important;
+}
+
+.messageLeft .messageSidebar, .messageRight .messageSidebar, .messageFramedLeft .messageSidebar, .messageFramedRight .messageSidebar {
+       min-width: 0 !important;
+}
+
+.message .messageTop.guestPost .messageAuthor, .message .messageFramedTop.guestPost .messageAuthor {
+       padding-bottom: 7px;
+}
+
+.messageNumber, .messageMarkCheckBox {
+       float: right;
+}
+
+.message .messageHeader {
+       position: relative;
+}
+
+.messageHeader .popupMenu {
+       top: 29px;
+       right: 0;
+}
+
+.message h3 .inputText, .message h4 .inputText {
+       margin-right: -180px;
+}
+
+.messageTop .userMessenger, .messageFramedTop .userMessenger {
+       float: right;
+}
+
+.messageFooter input {
+       margin: 0 -10px 0 0;
+       padding: 0;
+}
+
+.codeBox div {
+       overflow-y: hidden;
+}
+
+.codeBox pre {
+       padding-bottom: 2em;
+}
+
+.infoBox {
+       clear: both !important;
+}
+
+.infoBox ul {
+       margin: 7px 0;
+}
+
+/* ### -- -- -- -- -- layout.css -- -- -- -- -- ### */
+
+.columnContainer {
+       overflow: hidden;
+}
+
+.column {
+       float: right;
+       margin-bottom: -9999px;
+       padding-bottom: 9999px;
+}
+
+.columnContainerJS {
+       overflow: visible;
+}
+
+.columnJS {
+       float: right;
+       margin: 0 0 1px !important;
+       padding: 0 !important;
+}
+
+.columnInner #editor {
+       width: 99%;     
+}
+
+.layout-2 .container-3, .layout-3 .container-3 {
+       min-height: auto;       
+}
+
+/* we need a better fix here! when the editor is embedded in a floating environment, it will not be displayed. the iframe width needs to be calculated manually (instead of "width: 100%;")! */
+#tplUserMemoEdit .second {
+       float: none;    
+}
+
+.sidebar, .sidebar *, .layout-3 .second {
+       min-height: 0;
+}
+
+/* ### -- -- -- -- -- global.css -- -- -- -- -- ### */
+
+.floatContainer {
+       min-height: 0;
+}
+
+.itemList li {
+       min-height: 0; /* triggers hasLayout */
+       list-style-type: none; /* list bullets look wrong with lists that trigger hasLayout */
+}
+
+form .disabled, .tabMenu .disabled {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);     
+}
+
+/* ### -- -- -- -- -- pageMenu.css -- -- -- -- -- ### */
+
+div.pageMenu .twoRows li a {
+       min-height: 28px !important;
+}
+
+/* ### -- -- -- -- -- profile.css -- -- -- -- -- ### */
+
+.avatarSelect img {
+       wcf: expression(
+               this.onclick = new Function("$(this).previous().checked = 'checked';")
+       );
+}
+
+#userCard {
+       min-height: 0;
+}
+
+#userCardInner {
+       padding: 1px !important;
+       min-height: 0;
+}
+
+#userCard .userAvatar img {
+       margin-bottom: 15px;
+}
+
+#userCardCredits .smallButtons img {
+       margin: 0;
+}
+
+.friendsConnection, .friendsNetwork, .friendsNone, .guestAdvice {
+       min-height: 0;
+       padding: 7px 0 !important;
+       zoom: 1;
+}
+
+/* ### -- -- -- -- -- gallery.css -- -- -- -- -- ### */
+
+a .thumbnail img {
+       wcf: expression(
+               this.onclick = new Function("window.location.href= $(this).up('a').href;")
+       );
+}
+
+.galleryIndex .thumbnailButtons {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);
+       bottom: 60px;
+}
+
+.galleryIndex .thumbnailButtons input {
+       margin: 0 2px;
+}
+
+.galleryIndex .thumbnailButtons .container-4 {
+       display: inline !important;
+}
+
+.gallery .dataList .buttons * {
+       float: none !important;
+}
+
+.gallery .tagCloud {
+       overflow: hidden;
+}
+
+.thumbnailView .last {
+       width: auto !important;
+}
+
+.gallery .layout-2 .first {
+       width: 65% !important;
+}
+
+.gallery .layout-2 .second {
+       width: 35% !important;
+}
+
+/* ### -- -- -- -- -- buttons.css -- -- -- -- -- ### */
+
+.smallButtons {
+       min-height: 0 !important;
+}
+
+.smallButtons img {
+       margin-top: 1px;
+}
+
+/* ### -- -- -- -- -- privateMessages.css -- -- -- -- -- ### */
+
+.pmFolders {
+       margin-bottom: 7px;
+       min-height: 0;
+}
+
+.pmFolders .pageMenu a,.pmFolders .pageMenu a:hover {
+       padding-top: 10px !important;
+}
+
+/* ### -- -- -- -- -- rules.css -- -- -- -- -- -- ### */
+
+.rules ol {
+       margin-right: 20px;     
+}
+
+/* ### -- -- -- -- -- burningBoard.css -- -- -- -- -- ### */
+
+#boardlist span {
+        display: inline-block;
+}
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+.otherMonth {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+.monthView table, .weekView table {
+       border-collapse: separate;
+}
+
+#participantsYes, #participantsNo, #participantsMaybe {
+       zoom: 1;        
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/extra/ie7-fix.css b/wcfsetup/install/files/style/extra/ie7-fix.css
new file mode 100644 (file)
index 0000000..c8253e2
--- /dev/null
@@ -0,0 +1,428 @@
+
+/* ### -- -- -- -- -- Bugfix-Styles for Microsoft Internet Explorer 7 -- -- -- -- -- ### */
+
+/* 
+
+File: ie7-fix.css 
+Copyright 2006-2011 by WoltLab GmbH. 
+
+For full XHTML- & CSS-Compatibility be sure to include this File only within the so called "Internet Explorer Comment Hack". 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+#main {
+       min-height: 0;  
+}
+
+fieldset {
+       margin-top: 25px;
+}
+
+fieldset legend {
+       margin-top: -18px;
+}
+
+.container-1, .container-2, .container-3 {
+       min-height: 0;
+}
+
+.pageNavigation input {
+       margin-top: 2px !important;
+       margin-bottom: -2px !important;
+       padding: 0 !important;
+       width: 2em !important;
+       height: 10px !important;
+}
+
+.subTabMenu {
+       zoom: 1;        
+}
+
+.subTabMenu .containerHead {
+       min-height: auto;       
+}
+
+.subTabMenu .containerHead > ul {
+       min-height: 0;  
+}
+
+/* ### -- -- -- -- -- tables.css -- -- -- -- -- ### */
+
+table {
+       border-collapse: collapse;
+}
+
+.tableList .statusDisplayIcons {
+       display: inline;
+}
+
+.tableList .statusDisplay .pageNavigation {
+       display: inline;        
+}
+
+/* ### -- -- -- -- -- forms.css -- -- -- -- -- ### */
+
+.formElement {
+       min-height: 0;
+}
+
+.formGroup fieldset {
+       margin: 0;
+}
+
+form .formPrefix div {
+       margin-left: 5px;
+       min-height: 0;
+}
+
+form input[type="file"] {
+       padding: 3px;
+}
+
+textarea, .inputText {
+       width: 98%;
+}
+
+/* ### -- -- -- -- -- wysiwyg.css -- -- -- -- -- ### */
+
+.mceToolbar {
+       min-height: 0;  
+}
+
+.mceButtonDisabled a img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
+}
+
+div.mceColors {
+       min-height: 0 !important;
+       padding-bottom: 1px;
+}
+
+div.mceColors ul {
+       min-height: 0 !important;
+}
+
+#editor .border {
+       margin-top: -1px;
+       padding-bottom: 1px;    
+}
+
+.editor .popupMenu {
+       min-height: 0 !important;
+       left: 0 !important;
+       bottom: 24px !important;
+}
+
+/* ### -- -- -- -- -- header.css -- -- -- -- -- ### **/
+
+#userNote, #userMenu, #userMenu li, #userMenu ul {
+       display: inline;
+}
+
+#userMenu li {
+       float: none;
+}
+
+#userPanel .userPanelInner {
+       padding-top: 10px;
+       padding-bottom: 3px;
+}
+
+/* ### -- -- -- -- -- footer.css -- -- -- -- -- ### */
+
+#footer, #footerContainer {
+       position: relative;
+}
+
+.footerOptions {
+       white-space: nowrap;
+}
+
+.footerMenu li, .footerOptions li {
+       position: relative;
+}
+
+.footerOptions li.stylePicker {
+       position: relative;
+       top: -7px !important;
+}
+
+.footerOptions li.stylePicker div {
+       top: 25px;
+       left: 5px;
+}
+
+.footerOptions li.date  {
+       margin-bottom: 0 !important;
+}
+
+.footerOptions li.extraButton {
+       position: relative;
+       top: -5px !important;
+}
+
+.footerOptions li.extraButton a {
+       display: block;
+}
+
+.footerOptions li.extraButton a img {
+       margin: 0 !important;
+}
+
+/* ### -- -- -- -- -- Main Menu -- -- -- -- -- ### */
+
+.mainMenu a {
+       min-height: auto;       
+}
+
+.mainMenu > div > ul > li, .mainMenu a, .footerMenu li, .footerMenu a, .footerOptionsInner > ul > li, .footerOptions a {
+       display: inline;
+}
+
+.mainMenu img, .footerMenu img, .footerOptions img {
+       margin: 3px 0;
+}
+
+.mainMenu span, .footerMenu span, .footerOptions span, .pageMenu span {
+       padding: 0 0 0 2px;
+       display: inline !important;
+}
+
+/* ### -- -- -- -- -- messages.css -- -- -- -- -- ### */
+
+.message, .messageInner, .messageHeader, .messageBody, .messageFooter, .userMessenger {
+       min-height: 0 !important;
+}
+
+.messageLeft .messageSidebar, .messageRight .messageSidebar, .messageFramedLeft .messageSidebar, .messageFramedRight .messageSidebar {
+       min-width: 0 !important;
+}
+
+.message .messageTop.guestPost .messageAuthor, .message .messageFramedTop.guestPost .messageAuthor {
+       padding-bottom: 7px;
+}
+
+.messageNumber, .messageMarkCheckBox {
+       float: left;
+}
+
+.message .messageHeader {
+       position: relative;
+}
+
+.messageHeader .popupMenu {
+       top: 29px;
+       left: 0;
+}
+
+.message h3 .inputText, .message h4 .inputText {
+       margin-left: -180px;
+}
+
+.messageTop .userMessenger, .messageFramedTop .userMessenger {
+       float: left;
+}
+
+.messageFooter input {
+       margin: 0 0 0 -10px;
+       padding: 0;
+}
+
+.codeBox div {
+       overflow-y: hidden;
+}
+
+.codeBox pre {
+       padding-bottom: 2em;
+}
+
+.infoBox {
+       clear: both !important;
+}
+
+.infoBox ul {
+       margin: 7px 0;
+}
+
+/* ### -- -- -- -- -- layout.css -- -- -- -- -- ### */
+
+.columnContainer {
+       overflow: hidden;
+}
+
+.column {
+       float: left;
+       margin-bottom: -9999px;
+       padding-bottom: 9999px;
+}
+
+.columnContainerJS {
+       overflow: visible;
+}
+
+.columnJS {
+       float: left;
+       margin: 0 0 1px !important;
+       padding: 0 !important;
+}
+
+.columnInner #editor {
+       width: 99%;     
+}
+
+.layout-2 .container-3, .layout-3 .container-3 {
+       min-height: auto;       
+}
+
+/* we need a better fix here! when the editor is embedded in a floating environment, it will not be displayed. the iframe width needs to be calculated manually (instead of "width: 100%;")! */
+#tplUserMemoEdit .second {
+       float: none;    
+}
+
+.sidebar, .sidebar *, .layout-3 .second {
+       min-height: 0;
+}
+
+/* ### -- -- -- -- -- global.css -- -- -- -- -- ### */
+
+.floatContainer {
+       min-height: 0;
+}
+
+.itemList li {
+       min-height: 0; /* triggers hasLayout */
+       list-style-type: none; /* list bullets look wrong with lists that trigger hasLayout */
+}
+
+form .disabled, .tabMenu .disabled {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);     
+}
+
+/* ### -- -- -- -- -- pageMenu.css -- -- -- -- -- ### */
+
+div.pageMenu .twoRows li a {
+       min-height: 28px !important;
+}
+
+/* ### -- -- -- -- -- profile.css -- -- -- -- -- ### */
+
+.avatarSelect img {
+       wcf: expression(
+               this.onclick = new Function("$(this).previous().checked = 'checked';")
+       );
+}
+
+#userCard {
+       min-height: 0;
+}
+
+#userCardInner {
+       padding: 1px !important;
+       min-height: 0;
+}
+
+#userCard .userAvatar img {
+       margin-bottom: 15px;
+}
+
+#userCardCredits .smallButtons img {
+       margin: 0;
+}
+
+.friendsConnection, .friendsNetwork, .friendsNone, .guestAdvice {
+       min-height: 0;
+       padding: 7px 0 !important;
+       zoom: 1;
+}
+
+/* ### -- -- -- -- -- gallery.css -- -- -- -- -- ### */
+
+a .thumbnail img {
+       wcf: expression(
+               this.onclick = new Function("window.location.href= $(this).up('a').href;")
+       );
+}
+
+.galleryIndex .thumbnailButtons {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);
+       bottom: 60px;
+}
+
+.galleryIndex .thumbnailButtons input {
+       margin: 0 2px;
+}
+
+.galleryIndex .thumbnailButtons .container-4 {
+       display: inline !important;
+}
+
+.gallery .dataList .buttons * {
+       float: none !important;
+}
+
+.gallery .tagCloud {
+       overflow: hidden;
+}
+
+.thumbnailView .last {
+       width: auto !important;
+}
+
+.gallery .layout-2 .first {
+       width: 65% !important;
+}
+
+.gallery .layout-2 .second {
+       width: 35% !important;
+}
+
+/* ### -- -- -- -- -- buttons.css -- -- -- -- -- ### */
+
+.smallButtons {
+       min-height: 0 !important;
+}
+
+.smallButtons img {
+       margin-top: 1px;
+}
+
+/* ### -- -- -- -- -- privateMessages.css -- -- -- -- -- ### */
+
+.pmFolders {
+       margin-bottom: 7px;
+       min-height: 0;
+}
+
+.pmFolders .pageMenu a,.pmFolders .pageMenu a:hover {
+       padding-top: 10px !important;
+}
+
+/* ### -- -- -- -- -- rules.css -- -- -- -- -- -- ### */
+
+.rules ol {
+       margin-left: 20px;      
+}
+
+/* ### -- -- -- -- -- burningBoard.css -- -- -- -- -- ### */
+
+#boardlist span {
+        display: inline-block;
+}
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+.otherMonth {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+.monthView table, .weekView table {
+       border-collapse: separate;
+}
+
+#participantsYes, #participantsNo, #participantsMaybe {
+       zoom: 1;        
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/extra/ie8-fix-rtl.css b/wcfsetup/install/files/style/extra/ie8-fix-rtl.css
new file mode 100644 (file)
index 0000000..2013a64
--- /dev/null
@@ -0,0 +1,66 @@
+
+/* ### -- -- -- -- -- Bugfix-Styles for Microsoft Internet Explorer 8 -- -- -- -- -- ### */
+
+/* 
+
+File: ie8-fix.css 
+Copyright 2009-2011 by WoltLab GmbH. 
+
+For full XHTML & CSS compatibility be sure to include this file only within the so called "Internet Explorer Comment Hack". 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+fieldset {
+       margin-top: 25px;
+}
+
+fieldset legend {
+       margin-top: -18px;
+}
+
+.formGroupField > fieldset > legend {
+       margin: 0;
+       padding: 0;
+       display: block !important;
+       width: 0;
+       height: 0;
+       visibility: hidden;
+}
+
+/* ### -- -- -- -- -- layout.css -- -- -- -- -- ### */
+
+.layout-1, .layout-2, .layout-3, .layout-4 {
+       box-sizing: border-box; 
+}
+
+/* ### -- -- -- -- -- global.css -- -- -- -- -- ### */
+
+form .disabled, .tabMenu .disabled {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);     
+}
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+.otherMonth {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+/* ### -- -- -- -- -- gallery.css -- -- -- -- -- ### */
+
+.galleryIndex .thumbnailButtons {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);     
+}
+
+.galleryIndex .thumbnailButtons input {
+       margin: 1px 2px;
+}
+
+/* ### -- -- -- -- -- wysiwyg.css -- -- -- -- -- ### */
+
+.mceButtonDisabled a img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/extra/ie8-fix.css b/wcfsetup/install/files/style/extra/ie8-fix.css
new file mode 100644 (file)
index 0000000..2013a64
--- /dev/null
@@ -0,0 +1,66 @@
+
+/* ### -- -- -- -- -- Bugfix-Styles for Microsoft Internet Explorer 8 -- -- -- -- -- ### */
+
+/* 
+
+File: ie8-fix.css 
+Copyright 2009-2011 by WoltLab GmbH. 
+
+For full XHTML & CSS compatibility be sure to include this file only within the so called "Internet Explorer Comment Hack". 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+fieldset {
+       margin-top: 25px;
+}
+
+fieldset legend {
+       margin-top: -18px;
+}
+
+.formGroupField > fieldset > legend {
+       margin: 0;
+       padding: 0;
+       display: block !important;
+       width: 0;
+       height: 0;
+       visibility: hidden;
+}
+
+/* ### -- -- -- -- -- layout.css -- -- -- -- -- ### */
+
+.layout-1, .layout-2, .layout-3, .layout-4 {
+       box-sizing: border-box; 
+}
+
+/* ### -- -- -- -- -- global.css -- -- -- -- -- ### */
+
+form .disabled, .tabMenu .disabled {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);     
+}
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+.otherMonth {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+/* ### -- -- -- -- -- gallery.css -- -- -- -- -- ### */
+
+.galleryIndex .thumbnailButtons {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=70);     
+}
+
+.galleryIndex .thumbnailButtons input {
+       margin: 1px 2px;
+}
+
+/* ### -- -- -- -- -- wysiwyg.css -- -- -- -- -- ### */
+
+.mceButtonDisabled a img {
+       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/extra/print-rtl.css b/wcfsetup/install/files/style/extra/print-rtl.css
new file mode 100644 (file)
index 0000000..5e4d9a7
--- /dev/null
@@ -0,0 +1,272 @@
+\r
+/* ### -- -- -- -- -- Print Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: print.css \r
+Copyright 2006-2009 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- General -- -- -- -- -- ### */\r
+\r
+a {\r
+       color: black;\r
+}\r
+\r
+.copyright {\r
+       font-size: .7em;\r
+       text-align: center;\r
+       padding-top: 20px;\r
+       clear: both;\r
+       display: block;\r
+}\r
+\r
+#page {\r
+       width: auto !important;\r
+}\r
+\r
+/* ### -- -- -- -- -- Hidden Elements -- -- -- -- -- ### */\r
+\r
+.hidden, #header, #userPanel, .tabMenu, .subTabMenu, .signature, .pmView, th img, .messageNumber, .editNote, .pmFolders, .infoBox, .largeButtons, .smallButtons, .optionButtons, .pageNavigation, .pageOptions, .quickJump,  .userExtras, .scrollUp, .userMessenger, .mainHeadline img, .userAvatar, .userAvatarFramed, .columnUsername img, .userProfileBox, .containerIcon, .userPosts, .userName img, .boardlistLastPost, .boardlistCounter,.boardlistStats, .boardlistUsersOnline, .moderators, .smallPages, .columnIcon img, .columnMarkTopics, .columnMark, .columnReplies, .columnAvatar, .columnViews, .columnLastPost, .breadCrumbs img, legend img, .columnHomepage a img, .columnEmail a img, .columnPosts, .columnRegistrationDate, .userRank, .userTitle, .messageCount, .footerMenu, .footerOptions, .mainMenu, .quickReply, .userSymbols, .userCredits, .statusDisplay, .info, #userCard, #tplUserGalleryPhoto form, .thumbnailButtons, .quoteHeader img, #tplCalendarEvent form, #tplCalendarEvent #participation img, .monthJump {\r
+       display: none;\r
+}\r
+\r
+/* ### -- -- -- -- -- Tables -- -- -- -- -- ### */\r
+\r
+table {\r
+       border-collapse: collapse;\r
+       width: 100%;\r
+}\r
+\r
+td, th {\r
+       border: 1px solid black;\r
+}\r
+\r
+th, th a {\r
+       color: #fff;\r
+       text-align: right;\r
+       white-space: nowrap;\r
+       background-color: #000;\r
+}
+
+td {
+       vertical-align: top;    
+}\r
+\r
+.mainHeadline .headlineContainer h1 {\r
+       font-size: 1.5em;\r
+}\r
+\r
+.columnIcon {\r
+       width: 0;\r
+}\r
+\r
+td p, th p {\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.columnRating {\r
+       text-align: center;\r
+       width: 0;\r
+}\r
+\r
+.columnTopic {\r
+       width: 80%;\r
+}\r
+\r
+.columnTitle p {\r
+       overflow: hidden;\r
+}\r
+\r
+.columnDate {\r
+       white-space: nowrap;\r
+}\r
+\r
+td.columnHomepage a:after {\r
+       content: ""attr(href)"";\r
+}\r
+\r
+td.columnEmail a[href^="mailto:"]:after {\r
+       content: ""attr(href)"";\r
+}\r
+\r
+/* ### -- -- -- -- -- Breadcrumb Style Navigation -- -- -- -- -- ### */\r
+\r
+.breadCrumbs {\r
+       list-style: none;\r
+       padding: 0;\r
+       margin: 0;\r
+}\r
+\r
+.breadCrumbs li {\r
+       font-style: italic;\r
+       margin-left: 5px;\r
+       display: inline;\r
+}\r
+\r
+/* ### -- -- -- -- -- Message Layout -- -- -- -- -- ### */\r
+\r
+.message {\r
+       border: 1px solid black;\r
+       margin: 7px 3px;\r
+       padding: 13px;\r
+}\r
+\r
+.message hr {\r
+       display: none;\r
+}\r
+\r
+.messageHeader {\r
+       font-style: italic;\r
+       margin: -1em 0 0 0;\r
+       padding: 0;\r
+       text-align: left;\r
+}\r
+\r
+.messageHeader p {\r
+       margin: 0;\r
+}\r
+\r
+.messageContent h3 {\r
+       font-size: 1em;\r
+       margin: 0;\r
+       padding: 7px;\r
+       clear: both;\r
+}\r
+\r
+.messageBody {\r
+       border-top: 1px solid black;\r
+       padding-top: 7px;\r
+       clear: both;\r
+}\r
+\r
+.messageInner {\r
+       margin: -10px 0;\r
+       padding: 0;\r
+}\r
+\r
+.messageText {\r
+       margin: 7px 0;\r
+}\r
+\r
+.messageAuthor, .messageAuthor .userName {\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.messageAuthor .userName {\r
+       font-style: italic;\r
+       font-weight: bold;\r
+       display: inline;\r
+}\r
+\r
+.messageAuthor .userCredits .userTitle {\r
+       font-size: .8em;\r
+       margin: 0 0 -10px 0;\r
+       padding: 0;\r
+}\r
+\r
+blockquote {\r
+       margin: 5px;\r
+}\r
+\r
+.quoteBox {\r
+       border: 1px solid black;\r
+       margin-bottom: 5px;\r
+       padding: 10px;\r
+}\r
+\r
+.quoteBox h3 {\r
+       font-style: italic;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.codeBox h3 {\r
+       font-style: italic;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.poll .containerContent h3 {\r
+       font-style: italic;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.attachmentPreview fieldset {\r
+       margin-top: 13px;\r
+}\r
+\r
+.attachmentPreview ul {\r
+       margin: 0;\r
+       list-style: none;\r
+       padding: 0;\r
+}\r
+\r
+.attachmentPreview li {\r
+       margin-left: 10px;\r
+       float: right;\r
+}\r
+\r
+.attachmentPreview li img {\r
+       margin: 0 !important;\r
+}\r
+\r
+.attachmentFile img {\r
+       display: none;\r
+}\r
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+#tplCalendarEvent #participation .messageHeader {
+       text-align: right;      
+}
+
+/* ### -- -- -- -- -- Form Element -- -- -- -- -- ### */
+               
+.formElement {
+       margin: 5px 0 3px 0;
+       min-height: 0;
+}
+
+.formElement:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* ### -- -- -- -- -- Form Field -- -- -- -- -- ### */
+
+.formField {
+       padding: 0;
+       min-height: 1em;
+       border-bottom: 1px solid black;
+}
+
+.formElement .formField {
+       margin-right: 216px;
+}
+
+
+/* ### -- -- -- -- -- Form Field Label -- -- -- -- -- ### */
+
+.formFieldLabel {
+       text-align: left;
+       float: right;
+       width: 200px;
+       margin: 0;
+}
+
+fieldset {
+       margin: 20px 1px 0 1px !important;
+}
+
+.formSubmit {
+       display: none;
+}
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/extra/print.css b/wcfsetup/install/files/style/extra/print.css
new file mode 100644 (file)
index 0000000..f2750f2
--- /dev/null
@@ -0,0 +1,272 @@
+\r
+/* ### -- -- -- -- -- Print Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: print.css \r
+Copyright 2006-2009 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- General -- -- -- -- -- ### */\r
+\r
+a {\r
+       color: black;\r
+}\r
+\r
+.copyright {\r
+       font-size: .7em;\r
+       text-align: center;\r
+       padding-top: 20px;\r
+       clear: both;\r
+       display: block;\r
+}\r
+\r
+#page {\r
+       width: auto !important;\r
+}\r
+\r
+/* ### -- -- -- -- -- Hidden Elements -- -- -- -- -- ### */\r
+\r
+.hidden, #header, #userPanel, .tabMenu, .subTabMenu, .signature, .pmView, th img, .messageNumber, .editNote, .pmFolders, .infoBox, .largeButtons, .smallButtons, .optionButtons, .pageNavigation, .pageOptions, .quickJump,  .userExtras, .scrollUp, .userMessenger, .mainHeadline img, .userAvatar, .userAvatarFramed, .columnUsername img, .userProfileBox, .containerIcon, .userPosts, .userName img, .boardlistLastPost, .boardlistCounter,.boardlistStats, .boardlistUsersOnline, .moderators, .smallPages, .columnIcon img, .columnMarkTopics, .columnMark, .columnReplies, .columnAvatar, .columnViews, .columnLastPost, .breadCrumbs img, legend img, .columnHomepage a img, .columnEmail a img, .columnPosts, .columnRegistrationDate, .userRank, .userTitle, .messageCount, .footerMenu, .footerOptions, .mainMenu, .quickReply, .userSymbols, .userCredits, .statusDisplay, .info, #userCard, #tplUserGalleryPhoto form, .thumbnailButtons, .quoteHeader img, #tplCalendarEvent form, #tplCalendarEvent #participation img, .monthJump {\r
+       display: none;\r
+}\r
+\r
+/* ### -- -- -- -- -- Tables -- -- -- -- -- ### */\r
+\r
+table {\r
+       border-collapse: collapse;\r
+       width: 100%;\r
+}\r
+\r
+td, th {\r
+       border: 1px solid black;\r
+}\r
+\r
+th, th a {\r
+       color: #fff;\r
+       text-align: left;\r
+       white-space: nowrap;\r
+       background-color: #000;\r
+}
+
+td {
+       vertical-align: top;    
+}\r
+\r
+.mainHeadline .headlineContainer h1 {\r
+       font-size: 1.5em;\r
+}\r
+\r
+.columnIcon {\r
+       width: 0;\r
+}\r
+\r
+td p, th p {\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.columnRating {\r
+       text-align: center;\r
+       width: 0;\r
+}\r
+\r
+.columnTopic {\r
+       width: 80%;\r
+}\r
+\r
+.columnTitle p {\r
+       overflow: hidden;\r
+}\r
+\r
+.columnDate {\r
+       white-space: nowrap;\r
+}\r
+\r
+td.columnHomepage a:after {\r
+       content: ""attr(href)"";\r
+}\r
+\r
+td.columnEmail a[href^="mailto:"]:after {\r
+       content: ""attr(href)"";\r
+}\r
+\r
+/* ### -- -- -- -- -- Breadcrumb Style Navigation -- -- -- -- -- ### */\r
+\r
+.breadCrumbs {\r
+       list-style: none;\r
+       padding: 0;\r
+       margin: 0;\r
+}\r
+\r
+.breadCrumbs li {\r
+       font-style: italic;\r
+       margin-right: 5px;\r
+       display: inline;\r
+}\r
+\r
+/* ### -- -- -- -- -- Message Layout -- -- -- -- -- ### */\r
+\r
+.message {\r
+       border: 1px solid black;\r
+       margin: 7px 3px;\r
+       padding: 13px;\r
+}\r
+\r
+.message hr {\r
+       display: none;\r
+}\r
+\r
+.messageHeader {\r
+       font-style: italic;\r
+       margin: -1em 0 0 0;\r
+       padding: 0;\r
+       text-align: right;\r
+}\r
+\r
+.messageHeader p {\r
+       margin: 0;\r
+}\r
+\r
+.messageContent h3 {\r
+       font-size: 1em;\r
+       margin: 0;\r
+       padding: 7px;\r
+       clear: both;\r
+}\r
+\r
+.messageBody {\r
+       border-top: 1px solid black;\r
+       padding-top: 7px;\r
+       clear: both;\r
+}\r
+\r
+.messageInner {\r
+       margin: -10px 0;\r
+       padding: 0;\r
+}\r
+\r
+.messageText {\r
+       margin: 7px 0;\r
+}\r
+\r
+.messageAuthor, .messageAuthor .userName {\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.messageAuthor .userName {\r
+       font-style: italic;\r
+       font-weight: bold;\r
+       display: inline;\r
+}\r
+\r
+.messageAuthor .userCredits .userTitle {\r
+       font-size: .8em;\r
+       margin: 0 0 -10px 0;\r
+       padding: 0;\r
+}\r
+\r
+blockquote {\r
+       margin: 5px;\r
+}\r
+\r
+.quoteBox {\r
+       border: 1px solid black;\r
+       margin-bottom: 5px;\r
+       padding: 10px;\r
+}\r
+\r
+.quoteBox h3 {\r
+       font-style: italic;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.codeBox h3 {\r
+       font-style: italic;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.poll .containerContent h3 {\r
+       font-style: italic;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.attachmentPreview fieldset {\r
+       margin-top: 13px;\r
+}\r
+\r
+.attachmentPreview ul {\r
+       margin: 0;\r
+       list-style: none;\r
+       padding: 0;\r
+}\r
+\r
+.attachmentPreview li {\r
+       margin-right: 10px;\r
+       float: left;\r
+}\r
+\r
+.attachmentPreview li img {\r
+       margin: 0 !important;\r
+}\r
+\r
+.attachmentFile img {\r
+       display: none;\r
+}\r
+
+/* ### -- -- -- -- -- calendar.css -- -- -- -- -- ### */
+
+#tplCalendarEvent #participation .messageHeader {
+       text-align: left;       
+}
+
+/* ### -- -- -- -- -- Form Element -- -- -- -- -- ### */
+               
+.formElement {
+       margin: 5px 0 3px 0;
+       min-height: 0;
+}
+
+.formElement:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* ### -- -- -- -- -- Form Field -- -- -- -- -- ### */
+
+.formField {
+       padding: 0;
+       min-height: 1em;
+       border-bottom: 1px solid black;
+}
+
+.formElement .formField {
+       margin-left: 216px;
+}
+
+
+/* ### -- -- -- -- -- Form Field Label -- -- -- -- -- ### */
+
+.formFieldLabel {
+       text-align: right;
+       float: left;
+       width: 200px;
+       margin: 0;
+}
+
+fieldset {
+       margin: 20px 1px 0 1px !important;
+}
+
+.formSubmit {
+       display: none;
+}
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/footer.css b/wcfsetup/install/files/style/footer.css
new file mode 100644 (file)
index 0000000..de2627a
--- /dev/null
@@ -0,0 +1,151 @@
+\r
+/* ### -- -- -- -- -- Footer Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: footer.css \r
+Copyright 2008-2009 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- Footer -- -- -- -- -- ### */\r
+\r
+#footer {\r
+       border-width: 1px 0 0 0;\r
+       border-style: solid;\r
+       padding: 10px 0;\r
+}\r
+\r
+#footerContainer {\r
+       border-top-width: 0;\r
+}\r
+\r
+/* ### -- -- -- -- -- Footer Menu -- -- -- -- -- ### */\r
+\r
+.footerMenu {\r
+       margin-bottom: 10px;\r
+       float: left;\r
+}\r
+\r
+.footerMenu ul {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.footerMenu li {\r
+       white-space: nowrap;\r
+       border-width: 0 0 0 1px;\r
+       border-style: solid;\r
+       margin-top: 5px;\r
+       padding: 0 10px;\r
+       display: inline-block;\r
+}\r
+\r
+.footerMenu li.first, .footerMenu li.firstActive {\r
+       border-width: 0;\r
+       padding-left: 0;\r
+}\r
+\r
+.footerMenu a {\r
+       text-decoration: none;\r
+       display: block;\r
+}\r
+\r
+.footerMenu span {\r
+       padding: 3px 0 2px 0;   \r
+}\r
+\r
+.footerMenu a span {\r
+       text-decoration: underline;\r
+}\r
+\r
+.footerMenu a:hover span {\r
+       text-decoration: none;\r
+}\r
+\r
+.footerMenu div.popupMenu {\r
+       font-size: 1em;\r
+}\r
+\r
+/* ### -- -- -- -- -- Footer Options -- -- -- -- -- ### */\r
+\r
+.footerOptions {\r
+       margin-bottom: 10px;\r
+       float: right;\r
+}\r
+\r
+.footerOptions ul {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.footerOptionsInner > ul > li {\r
+       display: inline-block;\r
+}\r
+       \r
+.footerOptions li {\r
+       border-width: 0 1px 0 0;\r
+       border-style: solid;\r
+       margin-top: 5px;\r
+       padding: 0 10px 0 7px;\r
+}\r
+\r
+.footerOptions li.last {\r
+       border-width: 0;\r
+}\r
+\r
+.footerOptions a, .footerOptions em {\r
+       font-style: normal;\r
+       text-decoration: none;\r
+       display: block;\r
+}\r
+\r
+.footerOptionsInner > ul > li > a {\r
+       min-height: 16px;\r
+}\r
+\r
+.footerOptions span {\r
+       padding: 3px 0 2px 0;   \r
+}\r
+\r
+.footerOptions a span {\r
+       text-decoration: underline;\r
+}\r
+\r
+.footerOptions a:hover span {\r
+       text-decoration: none;\r
+}\r
+\r
+.footerOptions div.popupMenu {\r
+       font-size: 1em;\r
+}\r
+\r
+/* ### -- -- -- -- -- Extra Button -- -- -- -- -- ### */\r
+\r
+.footerOptions li.extraButton {\r
+       border-width: 1px;\r
+       margin-top: 0 !important;\r
+       padding: 0;\r
+}\r
+\r
+.footerOptions li.extraButton a {\r
+       margin: 0;\r
+       padding: 1px 2px 0 2px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Copyright -- -- -- -- -- ### */\r
+\r
+.copyright {\r
+       text-align: center;\r
+       white-space: nowrap;\r
+       padding: 10px 0 7px 0;\r
+       clear: both;\r
+}\r
+\r
+.copyright a {\r
+       text-decoration: none;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/forms.css b/wcfsetup/install/files/style/forms.css
new file mode 100644 (file)
index 0000000..bede331
--- /dev/null
@@ -0,0 +1,271 @@
+\r
+/* ### -- -- -- -- -- Form Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: forms.css \r
+Copyright 2006-2010 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */\r
+\r
+form {\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+textarea, input, select {\r
+       font-size: .95em;\r
+}\r
+\r
+input[type="submit"], input[type="reset"], input[type="button"], input[type="file"] {\r
+       font-size: 1em;\r
+}\r
+\r
+.formSubmit { /* holds submit-buttons "preview, draft, submit" */\r
+       text-align: center;\r
+       margin-top: 10px;\r
+       margin-bottom: 15px;\r
+}\r
+\r
+textarea, .inputText {\r
+       border-width: 1px;\r
+       width: 99.5%;\r
+}\r
+\r
+select {\r
+       border-width: 1px;\r
+       padding: 2px;\r
+}\r
+\r
+input[type="text"], input[type="password"] {\r
+       padding: 3px 0 3px 2px;\r
+}\r
+\r
+input[type="file"] {\r
+       padding: 2px 3px;\r
+}\r
+\r
+select[multiple="multiple"] {\r
+       padding: 0 !important;\r
+}\r
+\r
+textarea {\r
+       padding-left: 3px;\r
+}\r
+\r
+input[type="radio"] {\r
+       margin-left: 0;\r
+}\r
+\r
+select[multiple="multiple"] {\r
+       width: 100%;\r
+}\r
+\r
+input[type="image"] {\r
+       margin: 0 3px -3px 0;\r
+}\r
+\r
+.searchInput > input[type="image"] {\r
+       margin: 0;\r
+}\r
+\r
+.fourDigitInput {\r
+       width: 40px !important;\r
+}\r
+\r
+.textareaSmall {\r
+       height: 1.9em; \r
+       line-height: 2;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Element -- -- -- -- -- ### */\r
+\r
+.formElement {\r
+       margin: 5px 0 3px 0;\r
+       min-height: 0;\r
+}\r
+\r
+.formElement:after {\r
+       content: "";\r
+       height: 0;\r
+       display: block;\r
+       clear: both;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Field -- -- -- -- -- ### */\r
+\r
+.formField {\r
+       padding: 0;\r
+}\r
+\r
+.formElement .formField {\r
+       margin-left: 216px;\r
+}\r
+\r
+fieldset .formElement .formField {\r
+       margin-left: 202px;\r
+}\r
+\r
+.formField input, .formField select, .formField textarea {\r
+       margin: 2px 0;\r
+}\r
+\r
+.formField label {\r
+       font-size: 1em !important;\r
+       display: block;\r
+}\r
+\r
+.containerContent .formField {\r
+       margin-top: -5px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Field Label -- -- -- -- -- ### */\r
+\r
+.formFieldLabel {\r
+       text-align: right;\r
+       float: left;\r
+       width: 200px;\r
+}\r
+\r
+fieldset .formFieldLabel {\r
+       width: 187px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Field Description -- -- -- -- -- ### */\r
+\r
+.formFieldDesc {\r
+       padding: 0 0 2px 0;\r
+}\r
+\r
+.formElement .formFieldDesc {\r
+       margin-left: 216px;\r
+}\r
+\r
+fieldset .formElement .formFieldDesc {\r
+       margin-left: 202px;\r
+}\r
+\r
+.formCheckBox .formFieldDesc {\r
+       padding: 0 0 2px 18px;\r
+}\r
+\r
+.formFieldDesc code {\r
+       font-size: 1.3em;\r
+}\r
+\r
+.formFieldDesc > p {\r
+       clear: both;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Group -- -- -- -- -- ### */\r
+\r
+/* A form group is an element containing serveral sub form elements within a fieldset */\r
+\r
+.formGroup {\r
+       min-height: 0;\r
+       margin: 5px 0 3px 0;\r
+}\r
+\r
+.formGroup .formGroupLabel {\r
+       text-align: right;\r
+       float: left;\r
+       width: 200px;\r
+}\r
+\r
+fieldset .formGroup .formGroupLabel {\r
+       width: 187px;\r
+}\r
+\r
+.formGroup .formGroupField {\r
+       margin-left: 216px;\r
+}\r
+\r
+fieldset .formGroup .formGroupField {\r
+       margin-left: 203px;\r
+}\r
+\r
+.formGroup .formGroupField legend {\r
+       display: none;\r
+}\r
+\r
+/* ToDo: Find a better solution for that! Impossible to build long inputs as long as this is active! */\r
+.formGroup .formGroupField .formElement input {\r
+       width: auto !important;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Prefix -- -- -- -- -- ### */\r
+\r
+.formPrefix select {\r
+       float: left;\r
+       width: 150px;\r
+}\r
+\r
+.formPrefix div {\r
+       margin-left: 155px;\r
+}\r
+\r
+.formPrefix {\r
+       min-height: 0;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Options -- -- -- -- -- ### */\r
+\r
+.formOptions {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.formOptions li {\r
+       margin-top: 3px;\r
+       padding-right: 2%;\r
+       width: 23%;\r
+       float: left;\r
+}\r
+\r
+.formOptions li span {\r
+       float: none;\r
+       padding-left: 12px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Options Long -- -- -- -- -- ### */\r
+\r
+.formOptionsLong {\r
+       list-style: none;\r
+       margin: 0 0 7px 0;\r
+       padding: 0;\r
+}\r
+\r
+.formOptionsLong li {\r
+       margin: 3px 0 0 0;\r
+       padding: 0;\r
+}\r
+\r
+.formOptionsLong span, .formOptionsLong label {\r
+       display: inline;\r
+}\r
+\r
+/* ### -- -- -- -- -- Form Error -- -- -- -- -- ### */\r
+\r
+.formError, .formError a {\r
+       color: #c00;\r
+}\r
+\r
+.formError .inputText, .formError textarea, .formError select {\r
+       border-color: #c00;\r
+       background-color: #fee;\r
+}\r
+\r
+.formError .mceToolbar select { /* prevents error with dropdown borders within the editor toolbar */\r
+       border-color: transparent !important;\r
+}\r
+\r
+/* ### -- -- -- -- Long Select -- -- -- -- ### */\r
+\r
+.longSelect select {\r
+       width: 100%;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/global.css b/wcfsetup/install/files/style/global.css
new file mode 100644 (file)
index 0000000..6de776d
--- /dev/null
@@ -0,0 +1,639 @@
+
+/* ### -- -- -- -- -- Global Burning Board 3 Styles -- -- -- -- -- ### */
+
+/* 
+
+File: global.css 
+Copyright 2006-2011 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Miscellaneous -- -- -- -- -- ### */
+
+* {
+       /* remove the following comment marks for RTL-text support - note: this line leads to incorrect forum display in Internet Explorer browsers! */
+       /*unicode-bidi: embed;*/
+       text-overflow: ellipsis;
+}
+
+body, html {
+       margin: 0 !important;
+       padding: 0 !important;
+}
+
+#main {
+       padding: 10px 0 20px 0; 
+}
+
+#main:after {
+       clear: both;
+       display: block;
+       height: 0;
+       content: "";
+}
+
+p {
+       margin: 0;
+       padding: 0;
+}
+
+pre {
+       font-family: "Courier New", Courier, monospace !important;
+}
+
+img {
+       vertical-align: middle;
+       border: 0;
+}
+
+hr {
+       display: none;
+}
+
+.hidden { /* Moves elements out of the viewport in an accessible way and preserves no space for them. Use this class rather than "display: none"! */
+       height: 0;
+       overflow: hidden;
+       position: absolute;
+       left: -9000px;
+       max-width: 8000px;
+}
+
+.new {
+       font-weight: bold;
+}
+
+.buddy {
+       font-size: 1.2em;
+}
+
+.dragable * {
+       cursor: move;
+}
+
+.loading {
+       background-color: #fff;
+       background-image: url("../images/spinner.gif");
+       background-position: 50% 50%;
+       background-repeat: no-repeat;
+       min-height: 80px;
+       opacity: .5;    
+}
+
+.rating {
+       float: right;
+}
+
+/* ### -- -- -- -- -- Headings -- -- -- -- -- ### */
+
+h1 {
+       margin: 0;
+       padding: 0 0 15px 0;
+}
+
+h1 a {
+       text-decoration: none;
+}
+
+h2, h2 a {
+       text-decoration: none;
+}
+
+h2, h3, h4, h5, h6 {
+       font-size: 1em;
+       font-weight: normal;
+       text-align: left;
+       margin: 0;
+       padding: 0;
+}
+
+#main > h2 {
+       padding-bottom: 7px;
+}
+
+.pointer {
+       cursor: pointer;
+}
+
+/* ### -- -- -- -- -- Links -- -- -- -- -- ### */
+
+a {
+       cursor: pointer;
+}
+
+a:hover {
+       text-decoration: none;
+}
+
+/* ### -- -- -- -- -- External Links -- -- -- -- -- ### */
+
+.externalURL {
+       background-image: url("../icon/externalURL.png");
+       background-position: right center;
+       background-repeat: no-repeat;
+       padding-right: 15px;
+}
+
+.externalURL:hover {
+       background-image: url("../icon/externalURLHover.png");
+       background-position: right center;
+       background-repeat: no-repeat;
+}
+
+/* ### -- -- -- -- -- Quick Jump -- -- -- -- -- ### */
+
+.quickJump {
+       white-space: nowrap;
+       width: auto;
+}
+
+.quickJump select {
+       width: auto;
+       max-width: 50%;
+}
+
+/* ### -- -- -- -- -- Page Options -- -- -- -- -- ### */
+
+.pageOptions {
+       float: right;
+}
+
+.pageOptions form, .pageOptions div {
+       display: inline;
+}
+
+.pageOptions a, .pageOptions form {
+       text-decoration: none;
+       margin-left: 10px;
+}
+
+.pageOptions a span {
+       text-decoration: underline;
+}
+
+.pageOptions a:hover span {
+       text-decoration: none;
+}
+
+/* ### -- -- -- -- -- Breadcrumbs -- -- -- -- -- ### */
+
+.breadCrumbs {
+       font-size: .95em;
+       list-style: none;
+       margin: 5px 0;
+       padding: 0;
+}
+
+.breadCrumbs li {
+       font-style: italic;
+       margin-right: 1px;
+       display: inline;
+}
+
+.breadCrumbs li a, .messageFooter .breadCrumbs li a {
+       text-decoration: none;
+}
+
+.breadCrumbs li a span, .messageFooter .breadCrumbs li a {
+       text-decoration: underline;
+}
+
+.breadCrumbs li a:hover span, .messageFooter .breadCrumbs li a:hover {
+       text-decoration: none;
+}
+
+.containerHead .breadCrumbs {
+       margin: 0;      
+}
+
+/* ### -- -- -- -- -- Content Header & Content Footer -- -- -- -- -- ### */
+
+.contentHeader, .contentFooter {
+       padding-bottom: 7px;
+       width: 100%;
+}
+
+.contentFooter:after, .contentHeader:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* ### -- -- -- -- -- Floated Elements -- -- -- -- -- ### */
+
+.floatContainer:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+.floatedElement {
+       margin: 0 7px 0 0;
+       padding: 0;
+       display: block;
+       float: left;
+       position: relative;
+}
+
+.floatedElement:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+.floatedElement label {
+       font-size: .85em;
+       white-space: nowrap;
+       display: block;
+       position: absolute;
+       top: -2px;
+}
+
+.floatedElement input, .floatedElement select, .floatedElement p {
+       margin: 1.5em 0 0 0; /* First value was "1.25em" before - this is a test! */
+       width: auto;
+}
+
+.floatedElement a img {
+       margin-top: 12px;
+       display: block;
+}
+
+.floatedElementLabel {
+       min-width: 50px;
+       text-align: right;      
+}
+
+.followsFloatedElement {
+       clear: both;    
+}
+
+.floatedElementContainer {
+       padding: 3px 0;
+}
+
+.floatedElementButtons {
+       float: right;   
+}
+
+.floatedElementButtons input, .floatedElementButtons img {
+       margin: 1.25em 0 0 5px;
+}
+
+.floatTwoColumns {
+       float: left;
+       width: 49%;
+}
+
+/* ### -- -- -- -- -- ItemList -- -- -- -- -- ### */
+
+.itemList, .itemList ol, .itemList ul {
+       margin: 0 0 0 20px;
+       padding: 2px 0;
+}
+
+.itemList, .itemList ul {
+       padding-left: 23px;
+}
+
+.itemList {
+       margin: 5px 0;
+}
+
+.itemList .itemListTitle {
+       border-width: 0 0 1px 0 !important;
+       margin: 0;
+       padding: 5px;
+       min-height: 21px;
+}
+
+.itemList h3.itemListTitle, .itemList h4.itemListTitle, .itemList h5.itemListTitle {
+       font-weight: bold;      
+}
+
+.itemList > li:last-child > .itemListTitle {
+       border: 0;
+}
+
+.itemList .buttons {
+       padding: 7px 0 4px 4px;
+       float: right;
+}
+
+.itemList .buttons a {
+       margin-left: 3px !important;
+       padding: 0 !important;
+}
+
+.itemList .buttons input {
+       margin: 0 0 -4px 5px !important;
+       padding: 0 !important;
+}
+
+.itemList .buttons a.extraButton {
+       margin: 0 0 -4px 10px !important;
+       padding: 0 !important;
+}
+
+.itemList .inputText {
+       width: auto;    
+}
+
+.first .itemList {
+       list-style-type: none;
+       padding-left: 0;
+}
+
+#invitationContainer .itemList {
+       margin: 5px 0 0 0;
+}
+
+#invitationContainer .itemList li {
+       list-style-type: square;
+       list-style-image: url("../icon/userS.png");
+}
+
+/* ### -- -- -- -- -- Social Bookmarks -- -- -- -- -- ### */
+
+.socialBookmarks {
+       margin: 7px 0 0 0;
+       padding-bottom: 0;
+       padding-left: 0;
+       float: left;
+}
+
+.socialBookmarks:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+.socialBookmarks li {
+       float: left;
+       margin-bottom: 5px;
+       margin-right: 5px;
+       list-style: none;
+}
+
+/* ### -- -- -- -- -- Simple Bar -- -- -- -- -- ### */
+
+.simpleBar ul {
+       text-align: center;
+       list-style-type: none;
+       margin: 7px 0 13px 0;
+       padding: .5em 0;
+}
+
+.simpleBar li {
+       display: inline;
+}
+
+.simpleBar li a {
+       text-decoration: none;
+       padding: .3em 7px;
+}
+
+.simpleBar li.selected a {
+       text-decoration: none;
+       padding: .3em 7px;
+}
+
+.simpleBar li a img {
+       margin: -5px 0;
+}
+
+/* ### -- -- -- -- -- Slider -- -- -- -- -- ### */
+
+.slider {
+       margin: 3px 0 10px 0;
+       padding: 1px 2px 0 2px !important;
+       position: relative;
+       width: 250px;
+}
+
+.slider .handle {
+       height: 9px;
+       width: 9px;
+       cursor: move;
+}
+
+/* ### -- -- -- -- -- Overlays -- -- -- -- -- ### */
+
+/* Note: This declaration will replace ".imageviewerBackground" in an upcoming version! */
+
+.overlayBackground { 
+       color: #fff;
+       background-color: #000;
+       position: fixed;
+       top: 0;
+       right: 0;
+       left: 0;
+       bottom: 0;
+       z-index: 100;
+}
+
+.overlay {
+       position: fixed;
+       left: 0;
+       top: 0;
+       z-index: 120;
+}
+
+.overlay .buttonBar {
+       padding-bottom: 7px;
+}
+
+.overlay .subHeadline .buttons {
+       float: right;
+}
+
+.overlay .subHeadline .buttons img {
+       display: inline;
+}
+
+/* ### -- -- -- -- -- System Messages (Success, Warning, Error, Info) -- -- -- -- -- ### */
+
+/* Note: Change the colors of system messages with care! Consider that people are used to specific colors for special events (e.g. Red stands for warning). Random colors may not work as intended! */
+
+.success, .warning, .error, .info {
+       background-position: 10px center;
+       background-repeat: no-repeat;
+       margin-bottom: 20px;
+       padding: 7px 10px 7px 45px;
+}
+
+.success {
+       color: #090;
+       background-color: #efe;
+       background-image: url("../icon/successM.png");
+       border-color: #090;
+}
+
+.success a, .success a:hover {
+       color: #333;
+}
+
+.warning {
+       color: #660;
+       background-color: #ffd;
+       background-image: url("../icon/warningM.png");
+       border-color: #660;
+}
+
+.warning a, .warning a:hover {
+       color: #333;
+}
+
+.error {
+       color: #c00;
+       background-color: #fee;
+       background-image: url("../icon/errorM.png");
+       border-color: #c00;
+}
+
+.error a, .error a:hover {
+       color: #333;
+}
+
+.info {
+       color: #06f;
+       background-color: #def;
+       background-image: url("../icon/infoM.png");
+       border-color: #06f;
+}
+
+.info a, .info a:hover {
+       color: #333;
+}
+
+.info .close {
+       float: right;   
+}
+
+/* ### -- -- -- -- -- Inner Errors -- -- -- -- -- ### */
+
+.innerError {
+       background-image: url("../icon/errorS.png");
+       background-position: 1px center;
+       background-repeat: no-repeat;
+       margin-bottom: 5px;
+       padding: 5px 5px 5px 25px;
+}
+
+/* ### -- -- -- -- Disabled -- -- -- -- ### */
+
+.tableList tr.disabled,
+.tableList tr.disabled:hover,
+.disabled div.messageInner {
+       background-color: #efe; 
+}
+
+.disabled td, .disabled div.messageInner {
+       background-image: none;
+}
+
+.tabMenuContent .disabled .messageInner *,
+.disabled .messageSidebar *,
+.tableList tr.disabled td,
+.tableList tr.disabled td a,
+.tableList tr.disabled td a:hover,
+.tableList tr.disabled td .light,
+.tableList tr.disabled td .light a,
+.tableList tr.disabled:hover .columnTopic .topic a,
+.tableList tr.disabled:hover .columnTitle a,
+.tableList tr.disabled:hover .columnUsername a {
+       color: #090;
+}
+
+.disabled div.messageInner {
+       border-color: #090 !important;
+       border-style: dashed !important;
+}
+
+form .disabled, .tabMenu .disabled { /* CSS 3 */
+       opacity: .5;    
+}
+
+/* ### -- -- -- -- Deleted -- -- -- -- ### */
+
+.tableList tr.deleted,
+.tableList tr.deleted:hover,
+.deleted div.messageInner {
+       background-color: #fee;
+}
+
+.deleted td, .deleted div.messageInner {
+       background-image: none;
+}
+
+.tabMenuContent .deleted .messageInner *,
+.deleted .messageSidebar *, 
+.tableList tr.deleted td,
+.tableList tr.deleted td a,
+.tableList tr.deleted td a:hover,
+.tableList tr.deleted td .light,
+.tableList tr.deleted td .light a,
+.tableList tr.deleted:hover .columnTopic .topic a,
+.tableList tr.deleted:hover .columnTitle a,
+.tableList tr.deleted:hover .columnUsername a {
+       color: #c00;
+}
+
+.deleted {
+       border-color: #c00 !important;
+       border-style: dashed !important;
+}
+
+.deleted img {
+       opacity: .5 !important;
+}
+
+/* ### -- -- -- -- -- Marked -- -- -- -- -- ### */
+
+.tableList tr.marked,
+.tableList tr.marked:hover,
+.marked div.messageInner,
+li.floatedElement.marked {
+       background-color: #ffd;
+}
+
+.marked td,
+.marked div.messageInner,
+li.floatedElement.marked {
+       background-image: none;
+}
+
+.tabMenuContent .marked .messageInner *,
+.marked .messageSidebar *,
+li.floatedElement.marked *,
+.tableList tr.marked td,
+.tableList tr.marked td a,
+.tableList tr.marked td a:hover,
+.tableList tr.marked td .light,
+.tableList tr.marked td .light a,
+.tableList tr.marked:hover .columnTopic .topic a,
+.tableList tr.marked:hover .columnTitle a,
+.tableList tr.marked:hover .columnUsername a {
+       color: #333;
+}
+
+.marked {
+       border-style: dashed !important;
+}
+
+.tableList .marked, .tableList .deleted, .tableList .activeContainer {
+       border: none !important;
+}
+
+/* ### -- -- -- -- -- Highlight -- -- -- -- -- ### */
+
+.highlight {
+       color: #00f;
+       background-color: #ff0;
+       padding: 0 2px;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/header.css b/wcfsetup/install/files/style/header.css
new file mode 100644 (file)
index 0000000..a5394a1
--- /dev/null
@@ -0,0 +1,255 @@
+
+/* ### -- -- -- -- -- Header Styles -- -- -- -- -- ### */
+
+/* 
+
+File: header.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- User Note -- -- -- -- -- ### */
+
+#userNote {
+       white-space: nowrap;
+       padding: 10px 5px 3px 0;
+       display: table-cell;
+       vertical-align: top;
+}
+
+/* ### -- -- -- -- -- Login Popup -- -- -- -- -- ### */
+
+.loginPopup {
+       white-space: nowrap;
+       position: absolute;
+       z-index: 100;
+}
+
+.loginPopup .container-1 {
+       padding: 7px 4px 3px 7px;
+}
+
+.loginPopup input[type="text"], .loginPopup input[type="password"] {
+       font-size: 1em;
+       width: auto !important;
+}
+
+.loginPopup input[type="checkbox"] {
+       margin-top: 5px !important;
+       margin-left: 0;
+}
+
+/* ### -- -- -- -- -- User Menu -- -- -- -- -- ### */
+
+#userMenu {
+       padding: 10px 5px 3px 5px;
+       display: table-cell;
+       width: 100%;
+       vertical-align: top;
+}
+
+#userMenu ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+#userMenu li {
+       margin: 0 7px 0 0;
+       float: left;
+}
+
+#userMenu a {
+       text-decoration: none;
+}
+
+#userMenu span {
+       text-decoration: underline;
+       white-space: nowrap;
+}
+
+#userMenu a:hover span {
+       text-decoration: none;
+}
+
+#userMenu .pageMenu {
+       font-size: 1em;
+}
+
+/* ### -- -- -- -- -- Language Picker -- -- -- -- -- ### */
+
+#changeLanguageMenu img {
+       margin-left: 0;
+}
+
+#changeLanguageMenu span {
+       margin: 0 0 0 22px !important;
+}
+
+/* ### -- -- -- -- -- Header Container -- -- -- -- -- ### */
+
+#header {
+       border-width: 1px 1px 0 1px;
+       border-style: solid;
+       padding: 0;
+       clear: both;
+       position: relative;
+       min-height: 0;
+}
+
+#header:after {
+       content: "";
+       display: block;
+       clear: both;
+       height: 0;
+}
+
+#headerContainer {
+       border-bottom-width: 0;
+}
+
+#mainContainer {
+       border-top-width: 0;
+       border-bottom-width: 0;
+}
+
+/* ### -- -- -- -- -- Search -- -- -- -- -- ### */
+
+#search {
+       /* Toggle View: Set to "0" for Standard View */
+       /* Toggle View: Set to "1px" for Framed View */
+       border-width: 0; 
+       border-style: solid;
+       /* Toggle View: Set to "transparent" for Standard View */
+       /* Toggle View: Set to any Colour Value for Framed View */
+       background-color: transparent;
+       position: absolute;
+       /* Move Search: Set to any positive Value */
+       top: 13px;
+       right: 13px;
+       z-index: 100;
+}
+
+#search .searchContainer {
+       /* Toggle View: Set to "0" for Standard View */
+       /* Toggle View: Set to "1px" for Framed View */
+       border-width: 0;
+       margin: 0;
+       padding: 10px;
+}
+
+#search ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+#search noscript p {
+       margin: 3px 0 0 0;
+       padding: 0;
+}
+
+#search input.searchSubmit {
+       margin: -1px 0 0 0;
+       padding-left: 1px;
+       vertical-align: middle;
+}
+
+#searchInput {
+       background-image: url("../icon/searchHeadS.png");
+       background-repeat: no-repeat;
+       background-position: 2px center;
+       padding-left: 23px;
+       width: 13em;
+}
+
+.searchOptions {
+       background-image: url("../icon/searchHeadOptionsS.png") !important;
+}
+
+.searchInputMenu {
+       font-size: 1.2em;
+       position: relative;
+}
+
+/* ### -- -- -- -- -- Page-Logo & -Title -- -- -- -- -- ### */
+
+#logo {
+       border-width: 1px 1px 0 1px;
+       border-style: solid;
+       margin: 0 0 -1px 0;
+       padding: 0;
+       position: relative;
+       overflow: hidden;
+       z-index: 10;
+}
+
+#logo h1 a, #logo a img {
+       border: 0;
+       margin: 0;
+       padding: 0;
+}
+
+#logo a.pageLogo, #logo h1.pageTitle {
+       margin: 0;
+       padding: 0;
+       display: block;
+       position: absolute;
+       width: 100%;
+       height: 100%;
+}
+
+#logo h1.pageTitle a {
+       display: block;
+       position: relative;
+       height: 100%;
+       z-index: 20;
+}
+
+/* ### -- -- -- -- -- Main Menu -- -- -- -- -- ### */
+
+.mainMenu {
+       border-width: 0 1px 1px 1px;
+       border-style: solid;
+}
+
+.mainMenu .mainMenuInner {
+       margin: 0;
+       border-width: 0 1px 1px 1px;
+       border-style: solid;
+}
+
+.mainMenu ul {
+       list-style: none;
+       margin: 0 0 -1px 0;
+       padding: 0;
+}
+
+.mainMenu > div > ul > li {
+       display: inline-block;
+}
+
+.mainMenu a {
+       text-decoration: none;
+       border-width: 1px;
+       border-style: solid;
+       margin: 0 -1px 0 0;
+       padding: 3px 5px 2px 5px;
+       display: block;
+       min-height: 23px;
+       white-space: nowrap !important;
+}
+
+.mainMenu li.first a, .mainMenu li.firstActive a {
+       margin-left: -1px;
+}
+
+.mainMenu span {
+       padding: 0 2px 0 0;
+}
+
+.mainMenu div.popupMenu {
+       font-size: 1em;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/imageViewer.css b/wcfsetup/install/files/style/imageViewer.css
new file mode 100644 (file)
index 0000000..dd1ec42
--- /dev/null
@@ -0,0 +1,65 @@
+
+/* ### -- -- -- -- -- ImageViewer Styles -- -- -- -- -- ### */
+
+/* 
+
+File: imageViewer.css 
+Copyright 2009-2010 by WoltLab GmbH. 
+
+*/
+
+/* #### -- -- -- -- -- ImageViewer -- -- -- -- -- #### */
+
+.imageViewerBackground, .overlayBackground { /* compatibility mode */
+       color: #fff;
+       background-color: #000;
+       position: fixed;
+       top: 0;
+       right: 0;
+       left: 0;
+       bottom: 0;
+       z-index: 100;
+}
+
+.imageViewerCaption {
+       color: #fff;
+       font-size: 1em;
+       font-weight: bold;
+       text-align: center;
+       position: fixed; 
+       top: 5px;
+       right: 0;
+       left: 0;
+       z-index: 110;
+}
+
+.imageViewerCurrentImage {
+       background-color: #fff;
+       border: 10px solid #fff;
+       position: fixed; 
+       width: 400px;
+       height: 300px;
+       z-index: 110;
+}
+
+.imageViewerNavigation {
+       border-width: 5px;
+}
+
+.imageViewerLoading {
+       background-image: url("../images/spinner.gif");
+       background-position: 50% 50%;
+       background-repeat: no-repeat;
+}
+
+.imageViewerMenu {
+       background-image: url("../images/imageViewer/menu.png");
+       padding: 13px 10px;
+       position: fixed;
+       bottom: 10px;
+       height: 24px;
+       width: 224px;
+       z-index: 120;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/inlineCalendar.css b/wcfsetup/install/files/style/inlineCalendar.css
new file mode 100644 (file)
index 0000000..bd85cb3
--- /dev/null
@@ -0,0 +1,87 @@
+\r
+/* ### -- -- -- -- -- Inline Calendar Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: inlineCalendar.css \r
+Copyright 2006-2009 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* #### -- -- -- -- -- Inline Calendar -- -- -- -- -- #### */\r
+\r
+.inlineCalendar {\r
+       position: absolute; \r
+       display: none; \r
+       z-index: 100;\r
+       width: 170px;\r
+}\r
+\r
+.inlineCalendarHeader, .inlineCalendarFooter {\r
+       color: #fff;\r
+       width: 100%;\r
+       border-collapse: collapse;\r
+       border-spacing: 0;\r
+       table-layout: fixed;\r
+       border-width: 1px;\r
+}\r
+\r
+.inlineCalendarHeader td, .inlineCalendarFooter td {\r
+       text-align: center;\r
+       font-weight: bold;\r
+       padding: 0;\r
+}\r
+\r
+.inlineCalendarHeader td a, .inlineCalendarFooter td a {\r
+       text-decoration: none;\r
+       border-width: 1px;\r
+       border-style: solid;\r
+       padding: 1px;\r
+       display: block;\r
+}\r
+\r
+.inlineCalendarHeader td span, .inlineCalendarFooter td span {\r
+       border-width: 1px 0;\r
+       border-style: solid;\r
+       padding: 1px;\r
+       display: block;\r
+}\r
+\r
+.inlineCalendarHeader td a:hover, .inlineCalendarFooter td a:hover {\r
+       text-decoration: none;\r
+}\r
+\r
+.changeElement {\r
+       width: 1.5em;\r
+}\r
+\r
+.inlineCalendarTable {\r
+       border-width: 0 1px !important;\r
+       border-collapse: collapse;\r
+       border-spacing: 0;\r
+       border-top: 0;\r
+       border-bottom: 0;\r
+       table-layout: fixed;\r
+       width: 100%; \r
+}\r
+\r
+.inlineCalendarTable td {\r
+       padding: 0;\r
+       margin: 0;\r
+}\r
+\r
+.inlineCalendarTable a {\r
+       text-align: center;\r
+       text-decoration: none;\r
+       border-width: 1px;\r
+       border-style: solid;\r
+       margin: 1px;\r
+       padding: 1px;\r
+       display: block;\r
+}\r
+\r
+.weekDays {\r
+       text-align: center;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/layout.css b/wcfsetup/install/files/style/layout.css
new file mode 100644 (file)
index 0000000..234ca87
--- /dev/null
@@ -0,0 +1,131 @@
+
+/* ### -- -- -- -- -- Layout Styles -- -- -- -- -- ### */
+
+/* 
+
+File: layout.css 
+Copyright 2009-2010 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Layout -- -- -- -- -- ### */
+
+.layout-1, .layout-2, .layout-3, .layout-4 {
+       border-collapse: collapse;
+       display: table;
+       table-layout: fixed;
+       width: 100%;
+}
+
+.columnContainer {
+       display: table-row;
+       border-style: solid;
+       border-width: 0 1px 1px 0;
+}
+
+.column {
+       display: table-cell;
+       margin: 0;
+       padding: 0;
+}
+
+/* ### -- -- -- -- -- Layout 1 -- -- -- -- -- ### */
+
+/* 1 column */
+
+.layout-1 .columnInner {
+       padding: 15px 25px;     
+}
+
+/* ### -- -- -- -- -- Layout 2 -- -- -- -- -- ### */
+
+/* 1 columns flexible - 65% | 35% */
+
+.layout-2 .first {
+       width: 65%;
+}
+
+.layout-2 .second {
+       width: 35%;     
+}
+
+.layout-2 .columnInner {
+       padding: 15px 25px;     
+}
+
+/* ### -- -- -- -- -- Layout 3 -- -- -- -- -- ### */
+
+/* 2 columns fixed - 310px | auto */
+
+.layout-3 .first {
+       width: 310px;
+}
+
+.layout-3 .columnInner {
+       padding: 15px 25px;     
+}
+
+/* ### -- -- -- -- -- Layout 4 -- -- -- -- -- ### */
+/* 2 columns fixed - 20% | 60% | 20% */
+
+.layout-4 .first, .layout-4 .third {
+       width: 20%;
+}
+
+.layout-4 .second {
+       width: 60%;
+}
+
+.layout-4 .first .columnInner, .layout-4 .third .columnInner {
+       padding: 0;
+}
+
+.layout-4 .second .columnInner {
+       padding: 0 10px;
+}
+
+/* ### -- -- -- -- -- Data List -- -- -- -- -- ### */
+
+.dataList {
+       font-size: 100%;
+       line-height: 1.3;
+       list-style-type: none;
+       margin: 0;
+       padding: 0;
+}
+
+.dataList li {
+       padding: 5px;
+       margin: 0 1px 1px 0;
+}
+
+.dataList li:after {
+       content: "";
+       display: block;
+       clear: both;
+       height: 0;
+}
+
+.dataList .buttons {
+       padding: 7px 4px 4px 10px;
+       float: right;
+}
+
+.dataList .buttons * {
+       margin-right: 3px;      
+}
+
+/* ### -- -- -- -- -- Content Box -- -- -- -- -- ### */
+
+.contentBox {
+       padding-bottom: 10px;
+       min-width: 215px;
+}
+
+.contentBox .pageOptions {
+       margin-top: 7px;
+       margin-bottom: 7px;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/messages.css b/wcfsetup/install/files/style/messages.css
new file mode 100644 (file)
index 0000000..0c8fb93
--- /dev/null
@@ -0,0 +1,929 @@
+
+/* ### -- -- -- -- -- Message Layout Styles -- -- -- -- -- ### */
+
+/* 
+
+File: messages.css 
+Copyright 2006-2010 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Message -- -- -- -- -- ### */
+
+.message {
+       margin-bottom: 7px;
+       padding: 0;
+       clear: both;
+}
+
+.message h3, .message h4  {
+       font-size: 1.1em;
+       font-weight: bold;
+       margin: 0;
+       padding-top: 7px;
+       overflow: hidden;
+       text-decoration: none;
+       min-height: 0 !important;
+}
+
+.message h3 a, .message h3 a:hover, .message h4 a, .message h4 a:hover {
+       text-decoration: none;
+}
+
+.message:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* ### -- -- -- -- -- Message Inner -- -- -- -- -- ### */
+
+.messageInner {
+       border-width: 1px;
+       border-style: solid;
+       margin: 0 !important;
+       padding: 0;
+       display: block;
+}
+
+.messageInner:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* Minimized Post Views */
+
+.messageMinimized .messageInner {
+       padding: 5px 15px !important;
+       clear: both;
+}
+
+.messageMinimized .messageInner p {
+       padding: 0 35px;
+       display: block;
+}
+
+.messageMinimized .messageInner img {
+       float: left;
+}
+
+.messageMinimized .messageInner h3 {
+       padding: 0 11px;
+       display: block;
+}
+
+.messageMinimized.quickReply .messageInner h3 {
+       min-height: 25px !important;
+}
+
+/* ### -- -- -- -- -- Message Sidebar -- -- -- -- -- ### */
+
+/* Both Views: Left & Right */
+.message .messageLeft .messageSidebar, .message .messageFramedLeft .messageSidebar, .message .messageRight .messageSidebar, .message .messageFramedRight .messageSidebar {
+       line-height: 1.3;
+       margin: 0 0 -2.3em 0;
+       padding: 0;
+       width: 180px;
+       overflow: hidden;
+}
+
+/* Both Views: Top */
+.message .messageTop .messageSidebar, .message .messageFramedTop .messageSidebar {
+       line-height: 1.3;
+       text-align: left;
+       margin: 0 !important;
+       padding: 10px 0 0 0;
+       float: none;
+       clear: both;
+       width: 100%;
+       position: relative;
+       overflow: hidden;
+}
+
+/* All Views: Guest Posts */
+.message .guestPost .messageSidebar {
+       min-height: 20px !important;
+}
+
+/* Both Views: Left */
+.message .messageLeft .messageSidebar, .message .messageFramedLeft .messageSidebar {
+       float: left;
+}
+
+/* Both Views: Right */
+.message .messageRight .messageSidebar, .message .messageFramedRight .messageSidebar {
+       float: right;
+}
+
+.message .messageSidebar:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* + + + Message Sidebar: Message Author + + + */
+
+/* Both Views: Top */
+.message .messageTop .messageAuthor, .message .messageFramedTop .messageAuthor {
+       border-width: 0 !important;
+       margin: 0 0 7px 95px;
+       padding: 0 15px 1px 15px;
+       float: left;
+}
+
+/* Both Views: Left & Right */
+.message .messageLeft .messageAuthor, .message .messageRight .messageAuthor, .message .messageFramedLeft .messageAuthor, .message .messageFramedRight .messageAuthor {
+       border-width: 0;
+       margin: 0;
+       padding: 10px 15px 7px 15px;
+       display: block;
+}
+
+/* Framed View: Left & Right - Dividers */
+.message .dividers .messageAuthor {
+       border-width: 0 0 1px 0;
+       border-style: solid;
+       margin-bottom: -1px;
+}
+
+/* All Views: Guest Posts */
+.message .guestPost .messageAuthor {
+       margin-left: 0 !important;
+}
+
+/* + + + Message Sidebar: User Name + + + */
+
+.message .messageSidebar .userName {
+       margin: 0;
+       padding: 0;
+}
+
+.message .messageSidebar .userName a {
+       text-decoration: none;
+}
+
+.message .messageSidebar .userName a span {
+       font-weight: bold;
+}
+
+/* + + + Message Sidebar: User Avatar + + + */
+
+/* All Views: Standard Avatar */
+.message .userAvatar {
+       margin: 0;
+       padding: 7px 15px;
+       display: block;
+}
+
+.message .dividers .userAvatar {
+       border-width: 1px 0 0 0 !important;
+       border-style: solid;
+}
+
+.message .userAvatar a {
+       margin: 0;
+       padding: 0;
+}
+
+/* Both Views: Left & Right - Framed Avatar */
+.message .messageLeft .userAvatarFramed, .message .messageRight .userAvatarFramed, .message .messageFramedLeft .userAvatarFramed, .message .messageFramedRight .userAvatarFramed {
+       text-align: left;
+       border-width: 1px;
+       border-style: solid;
+       margin: 7px 13px;
+       padding: 0;
+       width: 152px;
+       height: 152px;
+       position: relative;
+}
+
+.message .messageLeft .userAvatarFramed a, .message .messageRight .userAvatarFramed a, .message .messageFramedLeft .userAvatarFramed a, .message .messageFramedRight .userAvatarFramed a {
+       border-width: 1px;
+       border-style: solid;
+       margin: 0;
+       padding: 0;
+       width: 150px;
+       height: 150px;
+       position: absolute;
+}
+
+/* All Views: Framed Avatar */
+.message .userAvatarFramed a img {
+       position: absolute;
+       top: 50%;
+       left: 50%;
+}
+
+/* Both Views: Top */
+.message .messageTop .userAvatar, .message .messageFramedTop .userAvatar {
+       margin: 10px 15px;
+       padding: 0;
+       width: 76px;
+       height: 76px;
+       position: relative;
+}
+
+/* Top View: Avatar */
+.message .messageTop .userAvatar, .message .messageFramedTop .userAvatar {
+       position: absolute;
+       top: 2px;
+       left: 2px;
+}
+
+/* Top View: Framed Avatar */
+.message .messageTop .userAvatarFramed, .message .messageFramedTop .userAvatarFramed {
+       position: absolute;
+       top: 0;
+       left: 0;
+}
+
+/* Both Views: Top - Framed Avatar */
+.message .messageTop .userAvatarFramed, .message .messageFramedTop .userAvatarFramed {
+       border-width: 1px;
+       border-style: solid;
+       margin: 10px 15px;
+       padding: 0;
+       width: 78px;
+       height: 78px;
+       display: block;
+}
+
+.message .messageTop .userAvatarFramed a, .message .messageFramedTop .userAvatarFramed a {
+       border-width: 1px;
+       border-style: solid;
+       margin: 0;
+       padding: 0;
+       display: block;
+       width: 76px;
+       height: 76px;
+}
+
+/* + + + Message Sidebar: User Symbols + + + */
+/* ToDo: The whole declaration block is not yet ready! */
+
+/* Both Views: Top */
+.message .messageTop .userSymbols, .message .messageFramedTop .userSymbols {
+       border-width: 0 !important;
+       margin: 0 0 7px 0;
+       padding: 0 15px;
+       float: right;
+}
+
+/* Both Views: Left & Right - Dividers */
+.message .dividers .userSymbols {
+       border-width: 1px 0 0 0;
+       border-style: solid;
+}
+
+/* Both Views: Left & Right */
+.message .messageLeft .userSymbols, .message .messageRight .userSymbols, .message .messageFramedLeft .userSymbols, .message .messageFramedRight .userSymbols {
+       margin: 0;
+       padding: 7px 15px;
+}
+
+/* Both Views & Dividers: Left & Right */
+.message .messageLeft.dividers .userSymbols, .message .messageRight.dividers .userSymbols, .message .messageFramedLeft.dividers .userSymbols, .message .messageFramedRight.dividers .userSymbols {
+       border-width: 1px 0 0 0;
+       border-style: solid;
+}
+
+/* All Views */
+.message .userSymbols ul {
+       list-style: none;
+       margin: 0;
+       padding: 2px 0;
+}
+
+/* Top View Filter */
+.message .messageTop .userSymbols ul, .message .messageFramedTop .userSymbols ul {
+       padding: 0;
+}
+
+/* All Views */
+.message .userSymbols ul li {
+       display: inline;
+}
+
+/* + + + Message Sidebar: User Credits + + + */
+
+/* Both Views: Top */
+.message .messageTop .userCredits, .message .messageFramedTop .userCredits {
+       border-width: 0 !important;
+       margin: 0 0 7px 0;
+       padding: 0;
+       float: right;
+       clear: right;
+}
+
+/* Both Views: Left & Right */
+.message .messageLeft .userCredits, .message .messageRight .userCredits, .message .messageFramedLeft .userCredits, .message .messageFramedRight .userCredits {
+       margin: 0;
+       padding: 7px 15px;
+}
+
+/* Both Views: Left & Right - Dividers */
+.message .dividers .userCredits {
+       border-width: 1px 0 0 0;
+       border-style: solid;
+}
+
+/* All Views */
+.message .userCredits .userPosts a {
+       padding: 0 0 3px 0;
+       display: block;
+}
+
+/* Both Views: Top */
+.message .messageTop .userCredits p, .message .messageFramedTop .userCredits p {
+       margin: 0;
+       padding: 0 15px;
+}
+
+/* + + + Message Sidebar: User Messenger + + + */
+
+/* Both Views: Top */
+.message .messageTop .userMessenger, .message .messageFramedTop .userMessenger {
+       text-align: left;
+       border-width: 0 !important;
+       margin: 0 0 7px 95px;
+       padding: 0 15px;
+       clear: left;
+}
+
+/* All Views: Guest Posts */
+.message .messageTop.guestPost .userMessenger, .message .messageFramedTop.guestPost .userMessenger {
+       border-width: 0 !important;
+       margin: 0;
+       padding: 10px 15px;
+       position: absolute;
+       top: 0;
+       right: 0;
+}
+
+/* Both Views: Left & Right - Dividers */
+.message .dividers .userMessenger {
+       border-width: 1px 0 0 0;
+       border-style: solid;
+}
+
+/* Both Views: Left & Right */
+.message .messageLeft .userMessenger, .message .messageRight .userMessenger, .message .messageFramedLeft .userMessenger, .message .messageFramedRight .userMessenger {
+       margin: 0;
+       padding: 7px 15px 0 15px;
+}
+
+/* Both Views & Dividers: Left & Right */
+.message .messageLeft.dividers .userMessenger, .message .messageRight.dividers .userMessenger, .message .messageFramedLeft.dividers .userMessenger, .message .messageFramedRight.dividers .userMessenger {
+       border-width: 1px 0 0 0;
+       border-style: solid;
+}
+
+/* All Views */
+.message .userMessenger ul {
+       list-style: none;
+       margin: 0;
+       padding: 2px 0;
+}
+
+/* Top View Filter */
+.message .messageTop .userMessenger ul, .message .messageFramedTop .userMessenger ul {
+       padding: 0;
+}
+
+/* All Views */
+.message .userMessenger ul li {
+       display: inline;
+}
+
+/* ### -- -- -- -- -- Message Content -- -- -- -- -- ### */
+
+/* All Views */
+.message .messageContent {
+       border-style: solid;
+       padding: 0;
+}
+
+/* Standard View: Left */
+.message .messageLeft .messageContent {
+       border-width: 0 0 0 1px;
+       margin: 0 0 0 180px; 
+}
+
+/* Framed View: Left */
+.message .messageFramedLeft .messageContent {
+       border-width: 1px;
+       margin: 10px 15px 10px 180px; 
+}
+
+/* Standard View: Right */
+.message .messageRight .messageContent {
+       border-width: 0 1px 0 0;
+       margin: 0 180px 0 0; 
+}
+
+/* Framed View: Right */
+.message .messageFramedRight .messageContent {
+       border-width: 1px;
+       margin: 10px 180px 10px 15px; 
+}
+
+/* Standard View: Top */
+.message .messageTop .messageContent {
+       border-width: 1px 0 0 0;
+       margin: 0; 
+}
+
+/* Framed View: Top */
+.message .messageFramedTop .messageContent {
+       border-width: 1px;
+       margin: 0 15px 10px 15px;
+}
+
+/* All Views */
+.message .messageContent:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* ### -- -- -- -- -- Message Content Inner -- -- -- -- -- ### */
+
+.message .messageContentInner {
+       border-width: 0;
+       border-style: solid;
+       margin: 0;
+       padding: 10px 15px;
+}
+
+/* Standard View: Left & Right */
+.message .messageLeft .messageContentInner, .message .messageRight .messageContentInner {
+       border-width: 0; 
+}
+
+/* Framed View: Top, Left & Right */
+.message .messageFramedLeft .messageContentInner, .message .messageFramedRight .messageContentInner, .message .messageFramedTop .messageContentInner {
+       border-width: 1px;
+}
+
+/* All Views */
+.message .messageContentInner:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* ### -- -- -- -- -- Message Header -- -- -- -- -- ### */
+
+.message .messageHeader {
+       border-style: solid;
+       border-top-width: 0;
+       border-left-width: 0;
+       border-right-width: 0;
+       margin: 0;
+       padding: 0;
+       min-height: 30px;
+}
+
+.message .messageHeader .containerIcon {
+       text-align: left;
+       margin: 0;
+       padding: 0 0 3px 0;
+       width: 25px;
+}
+
+.message .messageHeader .containerContent {
+       padding-bottom: 7px;
+}
+
+.message .messageHeader .containerContent p {
+       padding: 3px 0 0 0;
+}
+
+.message .messageHeader .messageMarkCheckBox {
+       margin: 0;
+       padding: 0;
+}
+
+.message .messageHeader .messageCount {
+       float: right;
+}
+
+.message .messageHeader .messageNumber {
+       text-decoration: none;
+       margin: 0 0 0 4px;
+       padding: 0 4px;
+}
+
+/* ### -- -- -- -- -- Message Body -- -- -- -- -- ### */
+
+.message .messageBody {
+       margin: 0;
+       padding: 7px 0 0 0;
+       display: block;
+       width: 100%;
+       position: relative;
+       overflow: hidden;
+}
+
+.message input {
+       margin-right: 6px;
+}
+
+/* ### -- -- -- -- -- Poll -- -- -- -- -- ### */
+
+.message .poll {
+       margin: 0 15px 7px 0;
+       float: left;
+       width: 47%;
+}
+
+.poll .container-1, .poll .container-2, .poll .container-3 {
+       padding: 4px;
+}
+
+.poll .containerContent label {
+       display: block;
+       overflow: hidden;
+}
+
+.poll h4 {
+       font-style: italic;
+       font-weight: bold;
+       padding-top: 0;
+}
+
+.poll .pollResults {
+       font-size: .95em;
+       text-align: right;
+}
+
+.pollOptionBar {
+       margin-right: 4px;
+       float: left;
+       height: 6px;
+}
+
+.pollBarColor1 { /* Blue */
+       background-color: #93befe;
+       border-bottom: 6px solid #468ffc;
+}
+
+.pollBarColor2 { /* Light Blue */
+       background-color: #6be8ff;
+       border-bottom: 6px solid #02c4e7;
+}
+
+.pollBarColor3 { /* Light Green */
+       background-color: #b8fb82;
+       border-bottom: 6px solid #30ff00;
+}
+
+.pollBarColor4 { /* Yellow */
+       background-color: #f6ff00;
+       border-bottom: 6px solid #ede502;
+}
+
+.pollBarColor5 { /* Orange */
+       background-color: #ffc676;
+       border-bottom: 6px solid #ff9600;
+}
+
+.pollBarColor6 { /* Red */
+       background-color: #fe9595;
+       border-bottom: 7px solid #fe4747;
+}
+
+.pollBarColor7 { /* Pink */
+       background-color: #f9f;
+       border-bottom: 6px solid #f6f;
+}
+
+.pollBarColor8 { /* Violet */
+       background-color: #c7a2e7;
+       border-bottom: 7px solid #a56dd5;
+}
+
+.pollBarColor9 { /* Brown */
+       background-color: #e1bb84;
+       border-bottom: 6px solid #ca8a2f;
+}
+
+.pollBarColor10 { /* Charcoal */
+       background-color: #c3bbbb;
+       border-bottom: 6px solid #967e7e;
+}
+
+/* ### -- -- -- -- -- Signature -- -- -- -- -- ### */
+
+.message .signature {
+       border-left-width: 0;
+       border-right-width: 0;
+       border-bottom-width: 0;
+       margin: 7px 0 0 0;
+       padding: 7px 0 0 0;
+       overflow: hidden;
+       position: relative;
+}
+
+/* ### -- -- -- -- -- Edit Note -- -- -- -- -- ### */
+
+.message .editNote, .message .deleteNote {
+       border-left-width: 0;
+       border-right-width: 0;
+       border-bottom-width: 0;
+       margin: 7px 0 0 0;
+       padding: 7px 0 0 0;
+       position: relative;
+}
+
+/* ### -- -- -- -- -- Message Footer -- -- -- -- -- ### */
+
+/* All Views */
+.message .messageFooter, .message .messageFooterLeft, .message .messageFooterRight {
+       text-align: left;
+       border-left: 0;
+       border-right: 0;
+       border-bottom: 0;
+       margin: 7px 0 0 0;
+       padding: 0;
+       clear: both;
+       display: block;
+       position: relative;
+}
+
+.message .messageFooter:after, .message .messageFooterLeft:after, .message .messageFooterRight:after {
+       content: "";
+       height: 0;
+       display: block;
+       clear: both;
+}
+
+/* Standard View */
+.message .messageFooter .breadCrumbs {
+       margin-top: 10px;
+}
+
+/* Standard View - Small Buttons */
+.message .messageFooter .smallButtons li {
+       float: right;
+}
+
+.message .messageFooter .smallButtons .extraButton {
+       margin-left: 10px;
+       margin-right: 0;
+}
+
+/* Left & Right */
+
+/* Left */
+.message .messageFooterLeft {
+       text-align: right;
+}
+
+.message .messageFooterLeft .smallButtons li {
+       float: left;
+}
+
+.message .messageFooterLeft .smallButtons .extraButton {
+       margin-left: 0;
+       margin-right: 10px;
+}
+
+/* Right */
+.message .messageFooterRight {
+       text-align: left;
+}
+
+.message .messageFooterRight .smallButtons li {
+       float: right;
+}
+
+.message .messageFooterRight .smallButtons .extraButton {
+       margin-left: 10px;
+       margin-right: 0;
+}
+
+/* ### -- -- -- -- -- Attachment Preview -- -- -- -- -- ### */
+
+/* Holds attachments with thumbnail-previews */
+
+.attachmentPreview {
+       margin-bottom: 0;
+}
+
+.attachmentPreview ul {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+.attachmentPreview ul li {
+       border-style: solid;
+       border-width: 1px;
+       margin-bottom: 7px;
+       text-align: center;
+}
+
+.attachmentPreview ul li a {
+       border-style: solid;
+       border-width: 1px;
+       display: block;
+}
+
+.attachmentPreview ul li img {
+       display: inline;
+       position: relative;
+       top: 50%;
+}
+
+.attachmentPreview ul li a span {
+       background-image: url("../icon/zoomInS.png");
+       background-repeat: no-repeat;
+       background-position: right top;
+       margin: 5px 3px 0 0;
+       position: absolute;
+       top: 0;
+       right: 0;
+       width: 95%;
+       height: 95%;
+       visibility: hidden;
+}
+
+.attachmentPreview ul li a:hover span {
+       visibility: visible;
+}
+
+/* ### -- -- -- -- -- Attachment File -- -- -- -- -- ### */
+
+/* holds attachment file-type-icons and descriptions (no previews) */
+
+.attachmentFile:after {
+       clear: none;
+}
+
+.attachmentFile input, .attachmentFile button {
+       float: right;
+}
+
+.attachmentFile ul {
+       list-style: none;
+       margin: 0 !important;
+       padding: 0 !important;  
+}
+
+.attachmentFile ul li {
+       border-width: 1px 0 0 0;
+       border-style: solid;
+       margin: 0;
+       padding: 5px 0;
+       min-height: 22px;
+}
+
+.attachmentFile ul li:first-child {
+       border: none;
+}
+
+.attachmentFile ul li div {
+       padding: 3px 0 0 30px;
+}
+
+.attachmentFile ul li a img {
+       float: left;
+}
+
+/* ### -- -- -- -- -- Attachment Inputs -- -- -- -- -- ### */
+
+.attachmentsInput {
+       padding: 1px 0 3px 0;
+}
+
+.attachmentsInput input {
+       margin-top: 2px;
+       width: 100%;
+}
+
+.attachmentsInputSubmit {
+       float: right;
+}
+
+/* ### -- -- -- -- -- Quote Box -- -- -- -- -- ### */
+
+.quoteBox {
+       border-width: 1px;
+       border-style: solid;
+       margin: 0 0 7px 0;
+       display: block;
+       clear: both;
+       position: relative;
+}
+
+.quoteBox .quoteHeader {
+       margin: 1px 1px 0 1px;
+       padding: 7px 15px 7px 15px;
+}
+
+.quoteBox .quoteBody {
+       margin: 0 1px 1px 1px;
+       padding: 0 15px 5px 15px;
+}
+
+.quoteBox .quoteHeader h3 {
+       font-style: italic;
+       font-weight: bold;
+       margin: 0;
+       padding: 0;
+}
+
+.quoteBox .quoteHeader h3 img {
+       margin-top: -2px;
+       padding-right: 3px;
+       vertical-align: middle;
+}
+
+/* ### -- -- -- -- -- Code Box -- -- -- -- -- ### */
+
+.codeBox {
+       border-width: 1px;
+       border-style: solid;
+       margin: 0;
+       padding: 1px;
+       clear: both;
+       position: relative;
+       /* avoid inheritance */
+       font-style: normal;
+       text-align: left;
+       font-weight: normal;
+}
+
+.codeBox h3 {
+       font-style: italic;
+       font-weight: bold;
+       margin: 0;
+       padding: 5px;
+}
+
+.codeBox table {
+       border-spacing: 0;
+       width: 100%;
+}
+
+.codeBox pre {
+       margin: 0;
+       padding: 0 5px;
+       font-family: monospace;
+}
+
+.codeBox .codeLines, .codeBox .codeLineNumbers {
+       vertical-align: top;
+}
+
+.codeBox .codeLineNumbers img {
+       padding: 5px;
+}
+
+.codeBox .codeLineNumbers {
+       text-align: right;
+}
+
+.codeBox .codeLines {
+       width: 100%;    
+}
+
+.codeBox div {
+       overflow: auto;
+}
+
+/* ### -- -- -- -- -- Smileys -- -- -- -- -- ### */
+
+.smileys {
+       margin: 0;
+       padding: 0;
+       list-style: none;
+}
+
+.smileys li {
+       margin-right: 5px;
+       display: inline;
+}
+
+/* ### -- -- -- -- -- Extra -- -- -- -- -- ### */
+
+/* Post- & PM-Preview need this to get rid of the standard container-x settings */
+.messagePreview .message {
+       margin: -1px 0 0 -1px;
+       padding: 0;
+       border: 0;
+}
+
+/* Breadcrumbs inside Message Footer */
+.message .breadCrumbs {
+       float: left;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/pageMenu.css b/wcfsetup/install/files/style/pageMenu.css
new file mode 100644 (file)
index 0000000..67ce109
--- /dev/null
@@ -0,0 +1,128 @@
+
+/* ### -- -- -- -- -- Page Menu Styles -- -- -- -- -- ### */
+
+/* 
+
+File: pageMenu.css 
+Copyright 2006-2010 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Page Menu -- -- -- -- -- ### */
+
+div.pageMenu { 
+       margin: 0;
+       margin-right: 0 !important;
+       text-align: left;
+}
+
+div.pageMenu ul {
+       display: block !important;
+       float: none !important;
+       font-weight: normal !important;
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+div.pageMenu li {
+       border: 0;
+       display: block !important;
+       float: none !important;
+       margin: 0 !important;
+       padding: 0 !important;
+}
+
+div.pageMenu a, div.pageMenu a:hover {
+       display: block !important;
+       background-color: transparent;
+       background-image: none;
+       border-width: 0;
+       float: none !important;
+       height: auto !important;
+       margin: 0 !important;
+       padding: 5px 7px 5px 35px !important;
+       text-align: left !important;
+       text-decoration: none !important;
+}
+
+div.popupMenu a, div.popupMenu a:hover {
+       padding: 5px 7px !important;
+}
+
+.mainMenu div.popupMenu a, .mainMenu div.popupMenu a:hover {
+       padding: 5px 7px 5px 35px !important;
+}
+
+div.pageMenu img {
+       margin-left: -30px;
+       margin-top: -2px;
+       position: absolute;
+}
+
+div.pageMenu span {
+       display: block;
+       margin: 0 !important;
+       padding: 3px 13px 2px 0 !important;
+       text-decoration: none !important;
+}
+
+div.pageMenu li.container-1, div.pageMenu li.container-2 {
+       margin: 0 1px 1px 0 !important;
+}
+
+/* ### -- -- -- -- -- Page Menu (2 rows) -- -- -- -- -- ### */
+/*
+        - to be used with label and span
+        - label contains the key
+        - span the value
+        - e.g. <div class="pageMenu"><ul class="twoRows"><li><a href="url2icq"><img .../> <label>ICQ</label> <span>123456789</span></a></li></ul></div>
+*/
+
+div.pageMenu .twoRows li {
+       line-height: 1.3;
+}
+
+div.pageMenu .twoRows a {
+       margin: 0 !important;
+       padding-bottom: 4px !important;
+       padding-top: 2px !important;
+       min-height: 24px;
+}
+
+div.pageMenu .twoRows img {
+       margin-left: -27px;
+       margin-top: 3px;
+}
+
+div.pageMenu .twoRows label {
+       cursor: pointer;
+       display: block;
+       margin: 0 !important;
+       padding: 0 0 0 5px !important;  
+}
+
+div.pageMenu .twoRows a span {
+       display: block;
+       margin: 0 !important;
+       padding: 0 0 0 5px !important;
+       text-decoration: underline !important;
+}
+
+div.pageMenu .twoRows a:hover span {
+       text-decoration: none !important;
+}
+
+/* ### -- -- -- -- -- Pop Up Menu -- -- -- -- -- ### */
+
+.popupMenu {
+       border-width: 1px;
+       margin: 0 0 10px 0;
+       opacity: .9 !important;
+       padding: 1px;
+       position: absolute;
+       white-space: nowrap;
+       z-index: 30;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/style/pageNavigation.css b/wcfsetup/install/files/style/pageNavigation.css
new file mode 100644 (file)
index 0000000..94f404f
--- /dev/null
@@ -0,0 +1,129 @@
+\r
+/* ### -- -- -- -- -- Page Navigation Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: pageNavigation.css \r
+Copyright 2006-2009 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- Page Navigation -- -- -- -- -- ### */\r
+\r
+.pageNavigation {\r
+       margin-top: .5em;\r
+       margin-right: 20px;\r
+       margin-bottom: 5px;\r
+       float: left;\r
+       clear: left;\r
+}\r
+\r
+.pageNavigation ul {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.pageNavigation li {\r
+       border-width: 1px;\r
+       border-style: solid;\r
+       margin-right: 3px;\r
+       float: left;\r
+       position: relative;\r
+}\r
+\r
+.pageNavigation li.active, .pageNavigation li:active {\r
+       border-width: 1px;\r
+       border-style: solid;\r
+}\r
+\r
+.pageNavigation a, .pageNavigation li span {\r
+       text-align: center;\r
+       text-decoration: none;\r
+       border-width: 1px;\r
+       border-style: solid;\r
+       padding: 0 4px;\r
+       display: block;\r
+}\r
+\r
+.pageNavigation li div {\r
+       text-align: center;\r
+       margin-left: -1px;\r
+       padding: 0 0 .4em 0;\r
+       position: absolute;\r
+       bottom: 1.6em;\r
+       width: 12em; /* opera fix */\r
+       z-index: 200;\r
+       display: none;\r
+       opacity: .9; /* css3 */\r
+}\r
+\r
+.pageNavigation li:hover div {\r
+       display: block;\r
+}\r
+\r
+.pageNavigation li ul {\r
+       border: 1px;\r
+       padding: 0 0 2px 2px;\r
+       float: left;\r
+       clear: left;\r
+}\r
+\r
+.pageNavigation li ul li {\r
+       text-align: right !important;\r
+       margin-top: 2px;\r
+}\r
+\r
+.pageNavigation .skip, .pageNavigation .skip:hover, .pageNavigation .skip:active {\r
+       border: none;\r
+}\r
+\r
+.pageNavigation .skip a, .pageNavigation .skip a:hover, .pageNavigation .skip a:active, .pageNavigation .skip span {\r
+       background-color: transparent;\r
+       background-image: none !important;\r
+       border: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.pageNavigation .skip {\r
+       padding: 1px 1px !important;\r
+       width: 16px;\r
+}\r
+\r
+.pageNavigation .skip img {\r
+       vertical-align: middle;\r
+}\r
+\r
+.pageNavigation input {\r
+       text-align: center;\r
+       background-color: transparent;\r
+       border: none;\r
+       margin: 0;\r
+       padding: 2px 0;\r
+       width: 2.5em;\r
+       min-height: 1.84em;\r
+       display: none;\r
+}\r
+\r
+.pageNavigation .children {\r
+       padding: 0;\r
+}\r
+\r
+/* Drop Down Menus (see also pageMenu.css) */\r
+.pageNavigation a, .pageNavigation li ul, .pageNavigation li {\r
+       border-width: 1px;\r
+}\r
+\r
+/* Drop Down Menus (see also pageMenu.css) */\r
+.pageNavigation a, .pageNavigation li.children span {\r
+       border-color: #fff;\r
+       border-style: solid;\r
+}\r
+\r
+.statusDisplay .pageNavigation {\r
+       margin: 0;\r
+       padding: 0 0 2px 0;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/tabbedMenus.css b/wcfsetup/install/files/style/tabbedMenus.css
new file mode 100644 (file)
index 0000000..2929b93
--- /dev/null
@@ -0,0 +1,190 @@
+\r
+/* ### -- -- -- -- -- Tabbed Menu Styles -- -- -- -- -- ### */\r
+\r
+/* \r
+\r
+File: tabbedMenus.css \r
+Copyright 2006-2009 by WoltLab GmbH. \r
+\r
+*/\r
+\r
+/* ### -- -- -- -- -- Tabs -- -- -- -- -- ### */\r
+\r
+.tabMenu {\r
+       margin-top: 5px;\r
+       clear: both;\r
+       width: 100%;\r
+}\r
+\r
+.tabMenu:after {\r
+       content: "";\r
+       clear: both;\r
+       display: block;\r
+       height: 0;\r
+}\r
+\r
+.tabMenu ul {\r
+       margin: 0; \r
+       padding: 0 0 0 10px;  \r
+}\r
+\r
+.tabMenu li {\r
+       list-style: none;\r
+       border-width: 1px 1px 0 1px;\r
+       margin-right: 3px;\r
+       float: left;\r
+}\r
+\r
+.tabMenu li a {\r
+       text-decoration: none;\r
+       white-space: nowrap;\r
+       border-width: 1px;\r
+       border-style: solid;\r
+       padding: 2px 5px 0 5px;\r
+       display: block;\r
+       position: relative;\r
+       z-index: 10;\r
+}\r
+\r
+.tabMenu li.activeTabMenu a {\r
+       border-bottom: none;\r
+       padding-bottom: 3px;\r
+       position: relative;\r
+       z-index: 20;\r
+}\r
+\r
+.tabMenu li a, .tabMenu li.activeTabMenu a {\r
+       min-height: 24px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Sub Tab Menu (Elements inside the Tab-Bar) -- -- -- -- -- ### */\r
+\r
+.subTabMenu {\r
+       border: 1px;\r
+       margin-bottom: -1px;\r
+       margin-top: -2px;\r
+       padding: 1px;\r
+       position: relative;\r
+       z-index: 0;\r
+}\r
+\r
+.subTabMenu:after {\r
+       content: "";\r
+       clear: both;\r
+       display: block;\r
+       height: 0;\r
+}\r
+\r
+.subTabMenu .containerHead {\r
+       margin: 0;\r
+       padding: 2px;\r
+       min-height: 5px;\r
+}\r
+\r
+.subTabMenu .containerHead h2, .subTabMenu .containerHead h3 {\r
+       padding: 2px 5px;\r
+}\r
+\r
+.subTabMenu .containerHead:after {\r
+       content: "";\r
+       clear: both;\r
+       display: block;\r
+       height: 0;\r
+}\r
+\r
+.subTabMenu ul {\r
+       list-style: none;\r
+       margin: 0;\r
+       padding: 0;\r
+}\r
+\r
+.subTabMenu li {\r
+       float: left;\r
+}\r
+\r
+.subTabMenu li a {\r
+       text-decoration: none;\r
+       white-space: nowrap;\r
+       margin: 1px 2px;\r
+       padding: 2px 7px;\r
+       display: block;\r
+}\r
+\r
+.subTabMenu li.activeSubTabMenu a, .subTabMenu li a:hover {\r
+       border-width: 1px;\r
+       padding: 1px 6px;\r
+}\r
+\r
+.subTabMenu .containerHead div {\r
+       font-size: 5px;\r
+       height: 5px;\r
+}\r
+\r
+/* ### -- -- -- -- -- Sub Container Menu -- -- -- -- -- ### */\r
+\r
+/* ToDo: Find a more flexible solution */\r
+\r
+.contentBox .border .subTabMenu {\r
+       border: none;\r
+       margin: 0 0 1px 0;\r
+       padding: 0;\r
+}\r
+\r
+.contentBox .border .subTabMenu .containerHead {\r
+       border: none;\r
+       margin: 0 1px 0 0;\r
+}\r
+\r
+/* ### -- -- -- -- -- Tab Menu Content (Content below the Sub Tab Menu) -- -- -- -- -- ### */\r
+\r
+.tabMenuContent {\r
+       clear: both;\r
+}\r
+\r
+.tabMenuContent > div {\r
+       padding: 15px 25px;\r
+}\r
+\r
+.tabMenuContent .subHeadline {\r
+       margin-bottom: 2px;\r
+}\r
+\r
+.tabMenuContent h3.containerContent {\r
+       margin-top: 0;\r
+       margin-bottom: 0;\r
+}\r
+\r
+.tabMenuContent fieldset.noJavaScript {\r
+       background: transparent;\r
+       border: 0;\r
+       margin: 0;\r
+       padding-top: 13px;\r
+}\r
+\r
+.tabMenuContent legend.noJavaScript {\r
+       display: none;\r
+}\r
+\r
+.tabMenuContentContainer {\r
+       clear: both;\r
+}\r
+\r
+.tabMenuContent .message {\r
+       margin-bottom: 7px;\r
+}\r
+\r
+.tabMenuContent .messageInner .smallButtons:after {\r
+       clear: none;\r
+}\r
+\r
+.tabMenuContent .message .messageHeading {\r
+       margin-top: 0 !important;\r
+}\r
+\r
+/* ### -- -- -- -- -- Specials -- -- -- -- -- ### */\r
+\r
+.tabNavigation {\r
+       float: right;\r
+}\r
+\r
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */\r
diff --git a/wcfsetup/install/files/style/tables.css b/wcfsetup/install/files/style/tables.css
new file mode 100644 (file)
index 0000000..5e542ad
--- /dev/null
@@ -0,0 +1,128 @@
+
+/* ### -- -- -- -- -- Table Styles -- -- -- -- -- ### */
+
+/* 
+
+File: tables.css 
+Copyright 2006-2009 by WoltLab GmbH. 
+
+*/
+
+/* ### -- -- -- -- -- Table List -- -- -- -- -- ### */
+
+.tableList {
+       border-spacing: 0;
+       margin: 0;
+       padding: 0;
+       width: 100%;
+}
+
+.tableList tbody tr:hover .columnTopic .topic p a, .tableList tbody tr:hover .columnUsername p a, .tableList tbody tr:hover .columnTitle p a {
+       text-decoration: none;
+}
+
+.tableList th {
+       border-width: 0 1px 1px 0;
+       border-style: solid;
+       font-weight: normal;
+}
+
+.tableList td {
+       border-width: 0 1px 1px 0;
+       border-style: solid;
+       padding: 4px;
+}
+
+.tableList td a {
+       text-align: left;
+}
+
+/* ### -- -- -- -- -- Table Head -- -- -- -- -- ### */
+
+.tableHead a, .tableHead .emptyHead {
+       border-style: solid;
+       border-width: 0 0 1px 0;
+       display: block;
+       line-height: 1.8;
+       margin: -1px;
+       min-height: 22px;
+       padding: 0 5px;
+       text-align: center;
+       text-decoration: none;
+}
+
+/* do we really need this declaration? 
+.tableHead .emptyHead {
+       white-space: normal;
+}
+*/
+
+.tableHead .emptyHead input {
+       margin-top: 0;
+}
+
+.tableHead {
+       white-space: nowrap;
+}
+
+.tableHead a img {
+       margin-top: -3px;
+       padding: 0;
+}
+
+.tableHead .active a {
+       border-width: 0 0 1px 0;
+}
+
+/* ### -- -- -- -- -- Column Globals -- -- -- -- -- ### */
+
+.tableList td.columnText {
+       text-align: left;
+}
+
+.tableList td.columnNumbers, .tableList td.columnDate {
+       text-align: right;
+       white-space: nowrap;
+}
+
+.tableList td.columnID {
+       width: 1%;
+       text-align: right;
+}
+
+.tableList td.columnMark {
+       width: 1%;
+}
+
+/* ### -- -- -- -- -- Table row -- -- -- -- -- ### */
+
+.tableList .statusDisplay {
+       float: right;
+       padding: 1px 0;
+}
+
+.tableList .statusDisplayIcons {
+       display: inline-block;
+       margin-left: 5px;
+}
+
+/* ### -- -- -- -- -- Column icon -- -- -- -- -- ### */
+
+.tableList td.columnIcon {
+       width: 1%;
+       white-space: nowrap;
+}
+
+.tableList td.actionIcons img {
+       display: inline !important;
+}
+
+/* ### -- -- -- -- -- Special -- -- -- -- -- ### */
+
+.tableList .deleteNote {
+       border-width: 0 !important;
+       margin-top: 3px;
+       padding-top: 3px;
+}
+
+/* ### -- -- -- -- -- EOF -- -- -- -- -- ### */
diff --git a/wcfsetup/install/files/templates/.htaccess b/wcfsetup/install/files/templates/.htaccess
new file mode 100644 (file)
index 0000000..3418e55
--- /dev/null
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/wcfsetup/install/lang/da.xml b/wcfsetup/install/lang/da.xml
new file mode 100644 (file)
index 0000000..96bac93
--- /dev/null
@@ -0,0 +1,820 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="da">\r
+       <category name="wcf.acp">\r
+               <item name="wcf.acp"><![CDATA[Administrator kontrolpanel]]></item>\r
+               <item name="wcf.acp.help"><![CDATA[Hjælp]]></item>\r
+               <item name="wcf.acp.help.complete"><![CDATA[Fuldstændig hjælp]]></item>\r
+               <item name="wcf.acp.help.disable"><![CDATA[Deaktiver online hjælp]]></item>\r
+               <item name="wcf.acp.help.interactive"><![CDATA[Interaktiv hjælp]]></item>\r
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Skift pakke]]></item>\r
+               <item name="wcf.acp.search.extended"><![CDATA[Udvidet søgning ...]]></item>\r
+               <item name="wcf.acp.sitemap"><![CDATA[Site-map]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cache">\r
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Tøm cache]]></item>\r
+               <item name="wcf.acp.cache.clear.success"><![CDATA[Cachen er blevet tømt.]]></item>\r
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Bekræft at du ønsker at tømme cachen fuldstændigt?]]></item>\r
+               <item name="wcf.acp.cache.data"><![CDATA[Egenskaber]]></item>\r
+               <item name="wcf.acp.cache.data.files"><![CDATA[Filer]]></item>\r
+               <item name="wcf.acp.cache.data.size"><![CDATA[Størrelse]]></item>\r
+               <item name="wcf.acp.cache.data.source"><![CDATA[Kilde]]></item>\r
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Senest opdateret]]></item>\r
+               <item name="wcf.acp.cache.list.name"><![CDATA[Navn]]></item>\r
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Tilladelser]]></item>\r
+               <item name="wcf.acp.cache.list.size"><![CDATA[Størrelse]]></item>\r
+       </category>\r
+       <category name="wcf.acp.group">\r
+               <item name="wcf.acp.group.add"><![CDATA[Tilføj ny brugergruppe]]></item>\r
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Tilladelser]]></item>\r
+               <item name="wcf.acp.group.add.success"><![CDATA[Brugergruppen er blevet tilføjet.]]></item>\r
+               <item name="wcf.acp.group.administrators"><![CDATA[Administratorer]]></item>\r
+               <item name="wcf.acp.group.data"><![CDATA[Almindelig gruppe information]]></item>\r
+               <item name="wcf.acp.group.delete"><![CDATA[Slet denne brugergruppe]]></item>\r
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Denne brugergruppe er{else}{#$deletedGroups} Disse brugergrupper er{/if} blevet slettet.]]></item>\r
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Er du sikker på, at du vil slette denne brugergruppe?]]></item>\r
+               <item name="wcf.acp.group.edit"><![CDATA[Rediger denne brugergruppe]]></item>\r
+               <item name="wcf.acp.group.edit.success"><![CDATA[Ændringerne i din brugergruppe er blevet gemt.]]></item>\r
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Du er aktuelt medlem af denne brugergruppe. Ændringer af tilladelser for denne brugergruppe kan medføre, at du lukker dig selv ude af Administrations kontrolpanelet. Vær forsigtig!]]></item>\r
+               <item name="wcf.acp.group.everyone"><![CDATA[Enhver]]></item>\r
+               <item name="wcf.acp.group.groupID"><![CDATA[Gruppe ID]]></item>\r
+               <item name="wcf.acp.group.groupName"><![CDATA[Navn på denne brugergruppe]]></item>\r
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Indtast her et navn for denne gruppe.]]></item>\r
+               <item name="wcf.acp.group.guests"><![CDATA[Gæster]]></item>\r
+               <item name="wcf.acp.group.list"><![CDATA[Brugergrupper]]></item>\r
+               <item name="wcf.acp.group.list.data"><![CDATA[I alt {#$items} brugergrupper]]></item>\r
+               <item name="wcf.acp.group.members"><![CDATA[Antal medlemmer]]></item>\r
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatorer]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Adgang til Administrations kontrolpanelet?]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Aktivering af denne mulighed giver medlemmer af denne brugergruppe adgang til Administrations kontrolpanelet og, afhængig af deres tilladelser, til at udføre visse handlinger.]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Kan se skjulte profilinformationer]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Medlemmer af denne brugergruppe kan se de skjulte informationer i brugerens profiler.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Kan ændre system indstillinger?]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Aktivering af denne mulighed giver medlemmerne af denne brugergruppe adgang til at se og ændre systemets indstillinger - fx forum on/offline.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Kan se logs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Medlemmer af denne brugergruppe kan se system loggen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Kan redigere eksisterende opdaterings-servere]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Medlemmer af denne brugergruppe kan redigere eksisterende opdaterings-servere og tilføje nye opdaterings-servere.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Kan installere nye pakker]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Medlemmer af denne brugergruppe kan installere yderligere pakker.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Kan slette eksisterende pakker]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Medlemmer af denne brugergruppe kan slette eksisterende pakker.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Kan opdatere eksisterende pakker]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Medlemmer af denne brugergruppe kan opdatere eksisterende pakker.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Tilgængelige brugergrupper]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Medlemmer af denne brugergruppe har adgang til følgende grupper. Som eksempel kan du her fastsætte, hvis en brugergruppe har tilladelse til at redigere sig selv.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Kan tilføje nye brugergrupper]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Medlemmer af denne brugergruppe kan tilføje nye brugergrupper.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Kan tilføje nye brugere]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Medlemmer af denne brugergruppe kan tilføje nye brugere. Hvis valgmuligheden &quot;Tilgængelige brugergrupper&quot; er aktiveret, vil de tilhørende brugergrupper også blive tilknyttet ved oprettelsen af en bruger.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Kan slette eksisterende brugergrupper]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Medlemmer af denne brugergruppe kan slette eksisterende brugergrupper.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Kan slette eksisterende brugere]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Medlemmer af denne brugergruppe kan slette eksisterende brugere.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Kan redigere eksisterende brugergrupper]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Medlemmer af denne brugergruppe kan redigere eksisterende brugergrupper.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Kan redigere bruger e-mail adresser]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Medlemmer af denne brugergruppe kan redigere bruger e-mail adresser.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Kan redigere bruger kodeord]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Medlemmer af denne brugergruppe kan redigere bruger kodeord.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Kan redigere eksisterende brugere]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Medlemmer af denne brugergruppe kan redigere eksisterende brugere.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Kan sende e-mail til brugere]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Medlemmer af denne brugergruppe kan se andre medlemmers e-mail adresser og som konsekvens heraf sende dem e-mails.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Kan søge brugere]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Medlemmer af denne brugergruppe kan søge eksisterende brugere og deres profiler.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Administrator tilladelser]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Indhold]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Design]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Almindelige administrative tilladelser]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Vedligeholdelse]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[System funktioner]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Styring af pakker]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Bruger funktioner]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Styring af grupper]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Styring af brugere]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderator tilladelser]]></item>\r
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Almindelige tilladelser]]></item>\r
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Informationen du har indtastet er ugyldig.]]></item>\r
+               <item name="wcf.acp.group.showMembers"><![CDATA[Vis medlemmerne af denne brugergruppe]]></item>\r
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super moderatorer]]></item>\r
+               <item name="wcf.acp.group.users"><![CDATA[Registrerede brugere]]></item>\r
+       </category>\r
+       <category name="wcf.acp.login">\r
+               <item name="wcf.acp.login"><![CDATA[Log ind]]></item>\r
+               <item name="wcf.acp.login.data"><![CDATA[Log ind detaljer]]></item>\r
+       </category>\r
+       <category name="wcf.acp.masterPassword">\r
+               <item name="wcf.acp.masterPassword"><![CDATA[Master kodeord]]></item>\r
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Bekræft master kodeord]]></item>\r
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Master kodeord påkrævet]]></item>\r
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Denne side eller handling kræver at du af sikkerhedsmæssige grunde indtaster master kodeordet. Du behøver kun at gøre det en gang i løbet af en session. Hvis du har glemt master kodeordet, kan du nulstille det ved at slette filen <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[Master kodeordet er ikke korrekt. Hvis du har glemt master kodeordet, kan du nulstille det ved at slette filen <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[De indtastede kodeord er ikke identiske.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[Kodeordet er ikke sikkert. Det skal bestå af mindst otte tegn, små og store bogstaver samt tal og særlige tegn. Det må ikke være identisk med kodeord fra administratorerne  på denne side.]]></item>\r
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Forslag]]></item>\r
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Anvend forslag]]></item>\r
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Angiv master kodeord]]></item>\r
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[Master kodeordet er en yderligere beskyttelse af funktioner knyttet til sikkerheden. Du skal anvende et meget sikkert kodeord, som ikke må være identisk med dit sædvanlige administrator kodeord, ukendt til andre og ikke benyttet på andre websites.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.menu">\r
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Automatisk opdatering]]></item>\r
+               <item name="wcf.acp.menu.link.content"><![CDATA[Indhold]]></item>\r
+               <item name="wcf.acp.menu.link.display"><![CDATA[Design]]></item>\r
+               <item name="wcf.acp.menu.link.group"><![CDATA[Brugergrupper]]></item>\r
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Tilføj ny gruppe]]></item>\r
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[E-mail alle gruppe medlemmer]]></item>\r
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Gruppe oversigt]]></item>\r
+               <item name="wcf.acp.menu.link.log"><![CDATA[Log]]></item>\r
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>\r
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Vedligeholdelse]]></item>\r
+               <item name="wcf.acp.menu.link.option"><![CDATA[Valgmuligheder]]></item>\r
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Import &amp; eksport]]></item>\r
+               <item name="wcf.acp.menu.link.package"><![CDATA[Pakker]]></item>\r
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Søg pakker]]></item>\r
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Installer ny pakke]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Tilføj ny server]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Server oversigt]]></item>\r
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Liste over installerede pakker]]></item>\r
+               <item name="wcf.acp.menu.link.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.menu.link.user"><![CDATA[Bruger]]></item>\r
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Tilføj bruger]]></item>\r
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Oplist brugere]]></item>\r
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-mail alle brugere]]></item>\r
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Brugere]]></item>\r
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Massebearbejdning af brugere]]></item>\r
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Søg efter brugere]]></item>\r
+       </category>\r
+       <category name="wcf.acp.option">\r
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Udeluk hostnavne]]></item>\r
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Indtast et hostnavn på hver række, som du vil udelukke fra dette site.]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[Udeluk IP addresser]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Indtast en IP adresse på hver række, som du vil udelukke fra dette site.]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Udeluk brugeragenter]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Indtast en brugeragent på hver række, som du vil udelukke fra dette site.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Indtast adressen på memcache serveren! Du kan indtaste en server på hver række.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Brug persistent forbindelse]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Ved aktivering af denne valgmulighed benyttes en persistent forbindelse til memcache serveren.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache type]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Vælg hvilken type af cache du vil benytte! Visse typer kræver særlige forudsætninger hos serversytemet og kan ikke anvendes i din opsætning.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[Fil system (standard)]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (eksperimentelt)]]></item>\r
+               <item name="wcf.acp.option.category.general"><![CDATA[Almindeligt]]></item>\r
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Almindeligt]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache gemmer ofte tilgået data i hukommelsen. Dette kan dramatisk reducere indlæsning af databasen. Læs mere om memcache på følgende site:\r
+               <ul>\r
+               <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>\r
+               </ul>]]></item>\r
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Dato og tid]]></item>\r
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy server]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Du kan opsætte valgfrie proxyservere til forbindelse med eksterne servere.]]></item>\r
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Almindeligt]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Transmission]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Deaktiver forum midlertidigt]]></item>\r
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module"><![CDATA[Moduler til/fra]]></item>\r
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Indhold]]></item>\r
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Visning]]></item>\r
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Bruger]]></item>\r
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security"><![CDATA[Sikkerhed]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internetsider angribes ofte af programmer og robotter. Det er fx muligt automatisk at oprette hundredevis af brugerkonti. Du kan beskytte dig selv mod denne type af spam robotter ved hjælp af et såkaldt <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">captcha billede</a> på de steder, hvor webformularer kan afsendes. Ikke-registrerede brugere skal så først identificere koden på captcha billedet, før de kan afsende formularen. Robotter kan ikke aflæse koden. Bemærk venligst, at captcha billeder ikke kan læses af blinde og synshandicappede.]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Sortliste]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Censurering]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Almindeligt]]></item>\r
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessioner]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.user"><![CDATA[Brugere]]></item>\r
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookie domæne]]></item>\r
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Indtast her det domæne, hvor cookien skal anvendes. Dette er valgfrit, så i de fleste tilfælde behøver du ikke at anføre noget cookiedomæne.]]></item>\r
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookie sti]]></item>\r
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Cookie stien svarer til dokumentroden af dit site - fx &quot;/forum&quot; for http://www.woltlab.com/forum.]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Cookie præfiks]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Indtast her en forstavelse (præfiks) der kan bruges sammen med cookie navnet.]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Aktiver automatisk skifte mellem sommer- og vintertid]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Skal tidsangivelsen automatisk skifte i henhold til sommer/vinter tid?]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Brug cache-metode til sessionsdata]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Skal den vagte cache-metode anvendes for at gemme sessionsdata?]]></item>\r
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Den indtastede information er ugyldig.]]></item>\r
+               <item name="wcf.acp.option.export"><![CDATA[Eksport valgmuligheder]]></item>\r
+               <item name="wcf.acp.option.export.download"><![CDATA[Download de eksporterede valgmuligheder]]></item>\r
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Download de eksporterede valgmuligheder som en backup fil til din lokale maskine.]]></item>\r
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Aktiver indholds typen application/xhtml+xml]]></item>\r
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[Aktivering af denne mulighed giver dig mulighed for at vise sider, der anvender indhold af typen application/xhtml+xml.]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Aktiver Gzip komprimering]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Aktivering af denne mulighed indebærer, at indhold komprimeres på serveren og afsendelse af komprimeret indhold til klienterne. Denne mulighed reducerer trafikken.]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Deaktiver caching af sider i browsere]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Aktivering af denne mulighed afskærer browsere fra at cache siderne.]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Komprimerings niveau]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Anfør en værdi mellem 1 og 9. Til optimal output for komprimering og server ydeevne anbefaler vi værdien 1.]]></item>\r
+               <item name="wcf.acp.option.import"><![CDATA[Import valgmuligheder]]></item>\r
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>\r
+               <item name="wcf.acp.option.import.success"><![CDATA[Valgmulighederne er blevet importeret korrekt.]]></item>\r
+               <item name="wcf.acp.option.import.upload"><![CDATA[Upload valgmulighederne]]></item>\r
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Upload valgmulighederne, der skal kunne importeres fra din lokale maskine.]]></item>\r
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Import &amp; eksport valgmuligheder]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Administrators e-mail adresse]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Indtast her administrators e-mail adresse.]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Stien til fejlretningslogfilen]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Indtast her stien til logfilen]]></item>\r
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Afsenders e-mail adresse]]></item>\r
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Indtast her afsenders e-mail adresse, der skal bruges ved automatisk sendte e-mails.]]></item>\r
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Afsenders navn]]></item>\r
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Indtast her afsenders navn, der skal bruges ved automatisk sendte e-mails.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-mail metode]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Fejlretning]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Vælg en e-mail afsendelsesmetode.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>\r
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Afsenders signatur]]></item>\r
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Indtast her en signatur, der skal sendes sammen med system e-mails.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP host]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Indtast her SMTP server navnet.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP kodeord]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Indtast her SMTP kodeordet]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP port]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Indtast her SMTP server porten.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP brugernavn]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Indtast her SMTP brugernavnet]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[Aktiver &quot;-f&quot; parameteren]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Visse servere kræver at &quot;-f&quot; parameteren benyttes for at afsende e-mails. Har du problemer med at brugere ikke modtager e-mails, så prøv at aktivere denne mulighed.]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Brug formaterede e-mail adresser]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Afsender og modtagers adresser er formattaret i &quot;Navn &lt;email@domain.tld&gt;&quot;. Denne mulighed understøttes ikke af alle post servere og skal deaktiveres i hvis der opstår problemer.]]></item>\r
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Aktiver master kodeord]]></item>\r
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Sider og formularer i administrationskontrolpanelet med sikkerhedsmæssig relevans, kan beskyttes med et yderligere master kodeord.]]></item>\r
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Proxyserver (FTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[Proxyserver til FTP forbindelser]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxyserver (HTTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxyserver for HTTP forbindelser]]></item>\r
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Sessionspause]]></item>\r
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Indtast her i hvor lang tid en session skal anses for at forblive gyldig [sekunder].]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Tjek IP adresse for sessionen]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Bloknummeret på en IP adresse, der skal undersøges under læsning af sessionsdata. Et højt nummer kan udelukke brugere, som anvender skiftende IP adresser.]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Tjek sessionens brugeragent]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Skal brugeragenten undersøges under læsning af sessionsdata?]]></item>\r
+               <item name="wcf.acp.option.success"><![CDATA[Dine ændringer af valgmuligheder er blevet gemt.]]></item>\r
+               <item name="wcf.acp.option.timezone"><![CDATA[Tids zone]]></item>\r
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Vis standard tidszonen for dit site.]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Brugeres online pause]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Angiv her hvor længe en bruger skal være markeret som online, efter at de har været inaktive [sekunder].]]></item>\r
+       </category>\r
+       <category name="wcf.acp.package">\r
+               <item name="wcf.acp.package.cancel"><![CDATA[Afbryd pakke installation]]></item>\r
+               <item name="wcf.acp.package.description"><![CDATA[Beskrivelse]]></item>\r
+               <item name="wcf.acp.package.ftp"><![CDATA[Indtast her adgangs detaljer for FTP]]></item>\r
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[FTP adgangs detaljer]]></item>\r
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Hvis PHP-SafeMode er aktiveret på din server, skal pakken installeres med hjælp af FTP funktioner. Indtast venligst FTP brugernavnet og kodeord for denne server. Informationen du angiver vil ikke blive gemt eller videresendt til andre og vil udelukkende blive anvendt til installations formålet. Udelukkende af denne årsag kan det hænde, at du igen vil blive anmodet om at anføre dine FTP detaljer under installationsprocessen.]]></item>\r
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Der kunne ikke oprettes FTP forbindelse med de FTP detaljer, du har indtastet.]]></item>\r
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[Der kunne ikke oprettes forbindelse til den angivne FTP server.]]></item>\r
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[Der kunne ikke etableres korrekt indlogning til den angivne FTP server.]]></item>\r
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Hostnavn]]></item>\r
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Kodeord]]></item>\r
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Brugernavn]]></item>\r
+               <item name="wcf.acp.package.install"><![CDATA[Pakke installation]]></item>\r
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Afbryd installationen]]></item>\r
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Er du sikker på, at du vil afbryde denne installation?]]></item>\r
+               <item name="wcf.acp.package.install.error"><![CDATA[Pakke afhængigheder kunne ikke opfyldes for denne pakke.]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[Pakke {if $action == 'install'}installationen{else}opdateringen{/if} af pakken &quot;{$packageName}&quot; i version {$packageVersion} kan ikke gennemføres på grund af manglende kompabilitet med følgende {if $excludedPackages|count == 1}pakke{else}pakker{/if}:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} i version {$excludedPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Følgende pakke{else}Følgende pakker{/if} tillader ikke {if $action == 'install'}pakke installationen{else}pakke opdateringen{/if} af pakke &quot;{$packageName}&quot; i version {$packageVersion} på grund af manglende kompabiliteter:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} i version {$excludingPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Følgende pakke{else}Følgende pakker{/if} er ikke kompatible med pakke &quot;{$packageName}&quot; i version {$packageVersion}. Hvis du fortsætter installationen vil {if $excludingPackages|count == 1}pakken{else}pakkerne{/if} sandsynligvis ikke fungere længere.]]></item>\r
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}Installeret{else}{if $package.file|isset}er indeholdt i denne pakke{else}Ikke tilgængelig{/if}{/if})</span>]]></item>\r
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Er du sikker på, at du vil afbryde installationen af denne pakke?]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Følgende pakker kan opdateres med denne pakke]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Vælg en af de følgende pakker, for at opdatere denne version. Hvis du vil installere pakken igen, så klik på &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Der er allerede en kopi af denne pakke installeret. Hvis du fortsætter, vil en yderligere kopi af denne pakke blive installeret. Hvis du vil opdatere en tilgængelig kopi af denne pakke, så vælg venligst kopien fra den følgende liste.]]></item>\r
+               <item name="wcf.acp.package.install.version"><![CDATA[Pakke version:]]></item>\r
+               <item name="wcf.acp.package.installDate"><![CDATA[Installationsdato]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Under udpakning af filer fra denne pakke opstod følgende fejl:]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[De følgende filer kunne ikke udpakkes korrekt. Undersøg venligst om destinationsmappen er skrivbar.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Modstridende tabeller]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Overskriv ikke disse tabeller og spørg mig ikke igen om denne installation.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Overskriv de eksisterende tabeller og spørg mig ikke igen om denne installation.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Nødvendige ændringer]]></item>\r
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Berørte tabeller]]></item>\r
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Tabellerne i den eksisterende database er i modstrid med de tabeller, der er nødvendige at installere til denne pakke. Vælg hvorvidt disse tabeller skal overskrives.]]></item>\r
+               <item name="wcf.acp.package.list"><![CDATA[Installerede pakker]]></item>\r
+               <item name="wcf.acp.package.list.author"><![CDATA[Fofatter]]></item>\r
+               <item name="wcf.acp.package.list.count"><![CDATA[Der er i alt {#$items} installerede pakker]]></item>\r
+               <item name="wcf.acp.package.list.date"><![CDATA[Dato]]></item>\r
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.package.list.name"><![CDATA[Navn]]></item>\r
+               <item name="wcf.acp.package.list.other"><![CDATA[Pakke]]></item>\r
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>\r
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Standalone applikation]]></item>\r
+               <item name="wcf.acp.package.list.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.package.optionals"><![CDATA[Installer valgfri pakker]]></item>\r
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Den valgte pakker indeholder følgende muligheder. Vælg venligst de af dem, du vil installere.]]></item>\r
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Denne pakke er allerede installeret.)]]></item>\r
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Afhængighederne for denne pakke er ikke opfyldt.)]]></item>\r
+               <item name="wcf.acp.package.packageDir"><![CDATA[Installations mappe]]></item>\r
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[En anden applikation er allerede installeret i denne mappe.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[Denne mappe er ugyldig.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Du kan ikke skrive til denne mappe.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Denne mappe er allerede i brug af WoltLab Community Framework. Vælg venligst en anden placering.]]></item>\r
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Indtast venligst installations mappen her.]]></item>\r
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Denne applikation er tilgængelig gennem følgende URL efter installering i denne mappe:]]></item>\r
+               <item name="wcf.acp.package.requirements"><![CDATA[Vælg afhængigheder]]></item>\r
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Den aktuelle pakke forudsætter en anden pakke, der er installeret adskillige gange. Vælg venligst den udgave som skal anvendes.]]></item>\r
+               <item name="wcf.acp.package.rollback"><![CDATA[Rul pakke installationen tilbage]]></item>\r
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Version {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>\r
+               <item name="wcf.acp.package.startInstall"><![CDATA[Installer ny pakke]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Den valgte pakke har ingen korrekt installations angivelse.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[Arkivet du har anført, er ikke en korrekt pakke.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Pakken &quot;{$package->getName()}&quot; kunne ikke opdateres fra det anførte arkiv.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Der kunne ikke findes filer i den angivne mappe.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Din valgte pakke er allerede installeret. Pakker kan ikke installeres mere end en gang.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[Upload af dit valgte arkiv mislykkedes.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Vælg pakke kilden]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Indtast stien til pakken placeret på din server]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Indtast her den direkte sti til din pakke-fil. En internet adresse kan benyttes eller alternativt stien til pakken ved hjælp af serverens fil system.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Upload pakken fra din lokale computer]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Indtast her pakke filen, som skal uploades fra din computer.]]></item>\r
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Opdaterer pakke &quot;{$package->getName()}&quot;]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Installerer menu indgange til Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Installerer skabelon-patches til Administrations Kontrolpanelet  ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Installerer skabeloner i Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Installerer hændelses lytter ...]]></item>\r
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Udpakker pakke filer ...]]></item>\r
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Installerer brugergruppe valgmuligheder ...]]></item>\r
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Installerer pakke sprog ...]]></item>\r
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Installerer pakke valgmuligheder ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Afvikler særlige scripts ...]]></item>\r
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Installerer database indgange ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Installerer skabelon korrektioner ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Installerer pakke skabeloner ...]]></item>\r
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Installerer bruger profil felter ...]]></item>\r
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Tjekker for mulige konflikter ...]]></item>\r
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Afvikler pakke plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Installationen er fuldendt]]></item>\r
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Installerer valgfri pakker ...]]></item>\r
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Registrerer pakke ...]]></item>\r
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Installerer pakke plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Rod pakke tildeling gennemføres ...]]></item>\r
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Tjekker afhængigheder ...]]></item>\r
+               <item name="wcf.acp.package.step.title"><![CDATA[Pakke <b>{$packageName|encodeJS}</b>: ]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Fjerner menu punkter fra Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Fjerner skabelon-patches fra Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Fjerner skabeloner fra Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Fjerner hændelses lytter  ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Fjerner pakke filer ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Fjerner brugergruppe valgmuligheder ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Fjerner pakke sprog ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Fjerner pakke valgmuligheder ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Fjerner database indgange...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Fjerner skabelon korrektioner ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Fjerner pakke skabeloner ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Fjerner bruger profil felter ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Afvikler pakke plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Pakke sletning afsluttet]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Fjerner vagfri pakker ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Fjerner pakke plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Fjerner pakke afhængigheder ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Opdaterer  menu punkter i Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Opdaterer skabelon-patches i Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Opdaterer skabeloner i Administrations Kontrolpanelet ...]]></item>\r
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Opdaterer hændelses lytter ...]]></item>\r
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Udpakker pakke filer ...]]></item>\r
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Opdaterer brugergruppe valgmuligheder ...]]></item>\r
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Opdaterer pakke sprog ...]]></item>\r
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Opdaterer pakke valgmuligheder ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Afvikler særlige scripts ...]]></item>\r
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Opdaterer database indgange ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Opdaterer skabelon korrektioner ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Opdaterer pakke skabeloner ...]]></item>\r
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Opdaterer bruger profil felter ...]]></item>\r
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Afvikler pakke plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Checking possible conflicts ...]]></item>\r
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Pakke opdatering afsluttet]]></item>\r
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Opdaterer valgfri pakker ...]]></item>\r
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Opdaterer pakke ...]]></item>\r
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Opdaterer pakke plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Rod pakke tildeling gennemføres ...]]></item>\r
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Tjekker afhængigheder ...]]></item>\r
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[Korrektionen som denne pakke forsøger at installere er fejlet, fordi denne korrektion ikke matcher modtagelsesfilen. Derfor kan denne pakke ikke installeres. Klik venligst på &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; button.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Korrigering af følgende skabeloner er mislykkedes:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Oprindelig korrigeret af: {$failure.packageName})<br />{/foreach}Den originale korrektions pakke som tidligere var lagt ind fungerer måske ikke længere. Du bør dog fortsætte med denne opdatering ved at klikke på &quot;{lang}wcf.global.button.next{/lang}&quot; knappen.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[Korrektionen, som denne pakke forsøger at fjerne, er fejlet fordi dets modtage fil er blevet ændret udefra. Som følge heraf kan denne pakke ikke fjernes. Klik venligst på &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; knappen.]]></item>\r
+               <item name="wcf.acp.package.uninstall"><![CDATA[Pakke fjernelse]]></item>\r
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Afbryd pakke fjernelse]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Det er ikke muligt at afinstallere disse pakker, fordi der er mindst en afhængig pakke, der ikke kan afinstalleres.]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Ved endelig bekræftelse vil {if $dependentPackages|count == 1}denne pakke{else}disse pakker{/if} blive fjerne uden yderlligere advarsel.]]></item>\r
+               <item name="wcf.acp.package.update"><![CDATA[Pakke opdatering]]></item>\r
+               <item name="wcf.acp.package.updateDate"><![CDATA[Dato for opdatering]]></item>\r
+               <item name="wcf.acp.package.view.author"><![CDATA[Forfatter:]]></item>\r
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Gå til Administrations Kontrolpanelet]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Fjern pakke]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Fjern alle pakker]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Er du sikker på, at du vil fjerne denne pakke?]]></item>\r
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Opdater pakke]]></item>\r
+               <item name="wcf.acp.package.view.date"><![CDATA[Dato:]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Afhængige pakker]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Denne pakke har en afhængighed fra {if $dependentPackages|count == 1}en anden pakke.{else}{#$dependentPackages|count} andre pakker.{/if}]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Denne pakker er nødvendig for en anden pakke{else}{#$dependentPackages|count} Pakker er direkte eller indirekt afhængige af denne pakke{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.dir"><![CDATA[Installationsmappe:]]></item>\r
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Identifikation:]]></item>\r
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Installerede udgaver:]]></item>\r
+               <item name="wcf.acp.package.view.parent"><![CDATA[Rod pakke:]]></item>\r
+               <item name="wcf.acp.package.view.properties"><![CDATA[Egenskaber]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Nødvendige pakker]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Denne pakke er afhængig af {if $requiredPackages|count == 1}en anden pakke.{else}{#$requiredPackages|count} andre pakker.{/if}]]></item>\r
+               <item name="wcf.acp.package.view.url"><![CDATA[Hjemmeside:]]></item>\r
+               <item name="wcf.acp.package.view.version"><![CDATA[Installeret version:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.packageUpdate">\r
+               <item name="wcf.acp.packageUpdate"><![CDATA[Opdaterer pakker]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Godkendelse af opdaterings server]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Forbindelses data]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Brugernavn og kodeord er ikke blevet accepteret.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Kodeord]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Indtast venligst et kodeord, der er nødvendig for godkendelse.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Brugernavn]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Indtast venligst et brugernavn, der er nødvendig for godkendelse.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Bruger log på]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Server meddelelse]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Server navn]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Gem permanent bruger data]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[De indtastede data gemmes permanent, så du ikke behøver at indtaste dem på ny.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adresse]]></item>\r
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Installeret version]]></item>\r
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Der opstod en fejl: ]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Download af pakken {$package} mislykkedes.]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[Der opstod en fejl under forsøg på at downloade pakkelisten.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[Følgende {if $excludedPackages|count == 1}konflikt{else}konflikter{/if} opstod:]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Den installerede pakke &quot;{$excludedPackage.existingPackageName}&quot; er ikke kompatibel med pakken &quot;{$excludedPackage.packageName}&quot; i version {$excludedPackage.packageVersion}.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[Pakken &quot;{$excludedPackage.packageName}&quot; i version {$excludedPackage.packageVersion} er ikke kompatibel med den installerede pakke &quot;{$excludedPackage.existingPackageName}&quot;.]]></item>\r
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} er installeret]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Der er i øjeblikket ingen tilgængelige opdateringer.]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Du har ikke valgt nogen opdatering.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Valgmuligheder]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Pakken er allerede installeret og unik. Den kan derfor ikke installeres yderligere en gang.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Installations pakke]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Installer en anden pakke udgave (pakken er allerede installeret {#$package.instances} gang{if $package.instances > 1}e{/if})]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Opdaterer installeret pakke {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} version {$updatableInstance.packageVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Søg pakker]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Forfatter]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Søg efter ...]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Skjul allerede installerede unikke pakker]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Pakke navn]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Pakke navn og beskrivelse]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Opdaterer server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Søg på alle opdateringsservere]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Type af pakke]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Andre pakker]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Plugin for allerede installerede pakker]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Stand alone applikation]]></item>\r
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Vælg alle pakker]]></item>\r
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} er opdateret til {$package.toVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Følgende pakke opdateringer og installationer gennemføres:]]></item>\r
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Ny version]]></item>\r
+       </category>\r
+       <category name="wcf.acp.sessionLog">\r
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Handlinger fra den loggede session af &quot;{$sessionLog->username}&quot;]]></item>\r
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Der er i alt {#$items} {if $items == 1}logget handling{else}loggede indtastninger{/if}]]></item>\r
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Handlinger]]></item>\r
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Class navn]]></item>\r
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP adresse]]></item>\r
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Seneste handling]]></item>\r
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Pakke]]></item>\r
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Metode]]></item>\r
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Dato]]></item>\r
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[Bruger agent]]></item>\r
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Loggede sessioner]]></item>\r
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Der er i alt {#$items} {if $items == 1}logget session{else}loggede sessioner{/if}]]></item>\r
+       </category>\r
+       <category name="wcf.acp.updateServer">\r
+               <item name="wcf.acp.updateServer.add"><![CDATA[Tilføj server]]></item>\r
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Serveren er blevet tilføjet.]]></item>\r
+               <item name="wcf.acp.updateServer.data"><![CDATA[Serverdata]]></item>\r
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Slet server]]></item>\r
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Serveren er blevet slettet.]]></item>\r
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Vil du virkelig slette denne server?]]></item>\r
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Deaktiver]]></item>\r
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Rediger server]]></item>\r
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Dine ændringer er blevet gemt.]]></item>\r
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Aktiver]]></item>\r
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Fejlmeddelelser]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Kodeord]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Indtast venligst et kodeord, som er nødvendig for at bekræfte adgang (valgfrit).]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Brugernavn]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Indtast venligst et brugernavn, som er nødvendig for at bekræfte adgang (valgfrit).]]></item>\r
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Den følgende fejl opstod under forsøget på at opnå forbindelse sidste gang:]]></item>\r
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} server(e) tilgængelig]]></item>\r
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Server id]]></item>\r
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Pakker]]></item>\r
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adresse]]></item>\r
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Indtast venligst URLen til en pakkeserver.]]></item>\r
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[Den indtastede adresse er ugyldig.]]></item>\r
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Seneste adgang]]></item>\r
+               <item name="wcf.acp.updateServer.view"><![CDATA[Tilgængelig opdaterings server]]></item>\r
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Der er ingen tilgængelig opdateringsserver.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.user">\r
+               <item name="wcf.acp.user.add"><![CDATA[Tilføj ny bruger]]></item>\r
+               <item name="wcf.acp.user.add.data"><![CDATA[Bruger detaljer]]></item>\r
+               <item name="wcf.acp.user.add.success"><![CDATA[Den nye bruger er blevet gemt.]]></item>\r
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Gruppe tilknytning]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Tilknyt de følgende brugere til de valgte gruppe(r)]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Brugerne er blevet tilknyttet de valgte grupper.]]></item>\r
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Gruppe tilknytning]]></item>\r
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Eksporter e-mail adresseer]]></item>\r
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Send en e-mail]]></item>\r
+               <item name="wcf.acp.user.delete"><![CDATA[Slet bruger(e)]]></item>\r
+               <item name="wcf.acp.user.delete.error"><![CDATA[Ingen bruger kunne slettes.]]></item>\r
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}Brugeren er {else}{#$deletedUsers} brugerne er{/if} blevet slettet.]]></item>\r
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Er du sikker på, at du vil slette denne bruger?]]></item>\r
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Er du sikker på, at du vil slette de(n) valgte bruger(e)?]]></item>\r
+               <item name="wcf.acp.user.edit"><![CDATA[Rediger bruger]]></item>\r
+               <item name="wcf.acp.user.edit.success"><![CDATA[Ændringerne for denne bruger er blevet gemt.]]></item>\r
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Du redigerer nu i din egen brugerkonto. Ændringer af tilladelser for denne brugergruppe kan medføre, at du låser dig selv ude fra Administrations Kontrolpanelet. Vær venligst forsigtig!]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Eksporter e-mail adresseer]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Eksporter fil format]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Eksport valgmuligheder]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Eksporter e-mail adresserne fra følgende brugere]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Adskil adresserne med et  ]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Vedlæg adresserene med ]]></item>\r
+               <item name="wcf.acp.user.groups"><![CDATA[Gruppe medlemskab]]></item>\r
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Find brugere, der ikke er medlemmer af de valgte brugergrupper.]]></item>\r
+               <item name="wcf.acp.user.list"><![CDATA[Brugere]]></item>\r
+               <item name="wcf.acp.user.list.all"><![CDATA[Oplist alle brugere]]></item>\r
+               <item name="wcf.acp.user.list.count"><![CDATA[I alt {#$items} bruger{if $items > 1}e{/if}]]></item>\r
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 bruger valgt" : this.count+" brugere valgt"]]></item>\r
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Massebearbejdning af brugere]]></item>\r
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Handling]]></item>\r
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Betingelser]]></item>\r
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Den valgte handling er blevet gennemført på {#$affectedUsers} brugere.]]></item>\r
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Massebearbejdningsprocessen vil gennemføre følgende opgaver <strong>uden yderligere meddelelse</strong>, på alle brugere, der matcher betingelserne. Massebearbejdningsprocessen kan være meget ydelseskrævende, så den bør alene gennemførs, når forummet er offline. For at kunne foretage korrekt visning af dit indhold, skal du opdatere tællerne. Processen kan ikke rulles tilbage, vær derfor meget opmærksom ved brug af denne funktion.]]></item>\r
+               <item name="wcf.acp.user.search"><![CDATA[Søg efter brugere]]></item>\r
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Søge kriterier]]></item>\r
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Generelle søge kriterier]]></item>\r
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profil søge kriterier]]></item>\r
+               <item name="wcf.acp.user.search.display"><![CDATA[Visning]]></item>\r
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Kolonner]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Øvrige]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profil]]></item>\r
+               <item name="wcf.acp.user.search.display.general"><![CDATA[Almindeligt]]></item>\r
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Brugere pr. side]]></item>\r
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sortering]]></item>\r
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Ingen brugere er fundet.]]></item>\r
+               <item name="wcf.acp.user.search.matches"><![CDATA[Din søgning fandt {if $items == 1}et resultt{else}{#$items} resultater{/if}]]></item>\r
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Søg blandt resultater]]></item>\r
+               <item name="wcf.acp.user.sendMail"><![CDATA[Send en e-mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-Mail alle brugere]]></item>\r
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[Send e-mail som HTML]]></item>\r
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Afsender]]></item>\r
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Her kan du indtaste afsender e-mail adressen i følgende format:</p>\r
+               <p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Afsenders navn &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>\r
+               <p>Hvis du fuldstændigt har udfyldt afsnittet under System -> Valgmuligheder -> E-mail, vil dette felt automatisk blive udfyldt. Sender du e-mails ved hjælp af SMTP, skal afsender e-mail-adressen også være accepteret af serveren.</p>]]></item>\r
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[E-mail alle gruppe medlemmer]]></item>\r
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Send en e-mail til medlemmerne af følgende brugergrupper:]]></item>\r
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Send en e-mail til følgende brugere]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Emne]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Indtast her e-mailens emnefelt.]]></item>\r
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Meddelelse]]></item>\r
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Indtast her den meddelelse, som du ønsker at sende til brugerne.]]></item>\r
+               <item name="wcf.acp.user.userNote"><![CDATA[Velkommen {$this->user->username}.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.worker">\r
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Igangværende proces]]></item>\r
+               <item name="wcf.acp.worker.description"><![CDATA[Lad venligst browservinduet forblive åbent indtil bearbejdningen er helt afsluttet. Prøv IKKE at logge på Administrations Kontrol Panelet ved hjælp af et separat browservindue, da dette kan forårsage skader på den igangværende proces.]]></item>\r
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Processen er afsluttet]]></item>\r
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Bearbejder ...]]></item>\r
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% færdig]]></item>\r
+               <item name="wcf.acp.worker.title"><![CDATA[Bearbejder ...]]></item>\r
+       </category>\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Tilbage]]></item>\r
+               <item name="wcf.global.button.close"><![CDATA[Luk]]></item>\r
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>\r
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>\r
+               <item name="wcf.global.button.delete"><![CDATA[Slet]]></item>\r
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Vil du virkelig slette dette emne?]]></item>\r
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Slet helt]]></item>\r
+               <item name="wcf.global.button.edit"><![CDATA[Rediger]]></item>\r
+               <item name="wcf.global.button.editor.jump"><![CDATA[Benyt fuldstændige editor]]></item>\r
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>\r
+               <item name="wcf.global.button.mark"><![CDATA[Vælg]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Næste &raquo;]]></item>\r
+               <item name="wcf.global.button.preview"><![CDATA[Forhåndsvisning]]></item>\r
+               <item name="wcf.global.button.reset"><![CDATA[Nulstil]]></item>\r
+               <item name="wcf.global.button.submit"><![CDATA[Send]]></item>\r
+               <item name="wcf.global.button.unmark"><![CDATA[Fravælg]]></item>\r
+               <item name="wcf.global.date.day"><![CDATA[Dag]]></item>\r
+               <item name="wcf.global.date.days"><![CDATA[Dage]]></item>\r
+               <item name="wcf.global.date.hour"><![CDATA[Time]]></item>\r
+               <item name="wcf.global.date.hours"><![CDATA[Timer]]></item>\r
+               <item name="wcf.global.date.minute"><![CDATA[Minut]]></item>\r
+               <item name="wcf.global.date.minutes"><![CDATA[Minutter]]></item>\r
+               <item name="wcf.global.date.month"><![CDATA[Måned]]></item>\r
+               <item name="wcf.global.date.months"><![CDATA[Måneder]]></item>\r
+               <item name="wcf.global.date.second"><![CDATA[Sekund]]></item>\r
+               <item name="wcf.global.date.seconds"><![CDATA[Sekunder]]></item>\r
+               <item name="wcf.global.date.week"><![CDATA[Uge]]></item>\r
+               <item name="wcf.global.date.weeks"><![CDATA[Uger]]></item>\r
+               <item name="wcf.global.date.year"><![CDATA[År]]></item>\r
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Angivelse af år er valgfrit.]]></item>\r
+               <item name="wcf.global.date.years"><![CDATA[År]]></item>\r
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>\r
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>I dag</b>, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[I går, %H:%M]]></item>\r
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>\r
+               <!-- system variable; do not translate -->\r
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>\r
+               <!-- system variable; do not translate -->\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.defaultValue"><![CDATA[Standard]]></item>\r
+               <item name="wcf.global.error.backward"><![CDATA[Tilbage til sidste side]]></item>\r
+               <item name="wcf.global.error.empty"><![CDATA[Indtast venligst den ønskede information for dette felt.]]></item>\r
+               <item name="wcf.global.error.file.notFound"><![CDATA[Filen kunne ikke findes.]]></item>\r
+               <item name="wcf.global.error.illegalLink"><![CDATA[Linket du prøver at nå er ikke længere tilgængeligt eller ugyldigt.]]></item>\r
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Du har ikke lov til at åbne denne side. Du har ikke de nødvendige tilladelser til at se denne side.]]></item>\r
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Du har ikke lov til at åbne denne side.]]></item>\r
+               <item name="wcf.global.error.title"><![CDATA[Fejl meddelelse]]></item>\r
+               <item name="wcf.global.form.error"><![CDATA[De data du har indtastet, er ugyldige. Tjek venligst den information du har givet i de markerede felter.]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabisk]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnisk]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Tjekkisk]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Dansk]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Tysk]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Tysk (Uformel)]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Græsk]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Engelsk]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spansk]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persisk (Farsi)]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finsk]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Fransk]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebraisk]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Kroatisk]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungarsk]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italiensk]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japansk]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Koreansk]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Hollandsk]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norsk]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polsk]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portugisisk]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugisisk (Brasiliansk)]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumænsk]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russisk]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slovakisk]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbisk]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Svensk]]></item>\r
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Tyrkisk]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Kinesisk (Forenklet)]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Kinesisk (Traditionelt)]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[da_DK]]></item>\r
+               <!-- system variable; do not translate -->\r
+               <item name="wcf.global.locale.win"><![CDATA[danish]]></item>\r
+               <!-- system variable; do not translate -->\r
+               <item name="wcf.global.multiSelect"><![CDATA[Flere elementer kan vælges ved at holde &quot;Ctrl/Shift&quot; tasterne (Windows) eller &quot;Command&quot; (Mac OS) tasten og klikke på de ønskede elementer.]]></item>\r
+               <item name="wcf.global.page.input"><![CDATA[Gå til følgende side]]></item>\r
+               <item name="wcf.global.page.next"><![CDATA[Næste side]]></item>\r
+               <item name="wcf.global.page.previous"><![CDATA[Foregående side]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>\r
+               <!-- system variable; do not translate -->\r
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>\r
+               <item name="wcf.global.redirect.title"><![CDATA[Omdirigering]]></item>\r
+               <item name="wcf.global.redirect.url"><![CDATA[Klik venligst her, hvis den automatiske omdirigering ikke virker!]]></item>\r
+               <item name="wcf.global.scrollUp"><![CDATA[Gå til toppen af siden]]></item>\r
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Præcis match]]></item>\r
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e. %B %Y, %H:%M]]></item>\r
+               <item name="wcf.global.skipToContent"><![CDATA[Udelad navigering]]></item>\r
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[stigende]]></item>\r
+               <item name="wcf.global.sortOrder.descending"><![CDATA[faldende]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[.]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>\r
+       </category>\r
+       <category name="wcf.imageViewer">\r
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Billede " + (this.currentIndex + 1) + " af " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>\r
+               <item name="wcf.imageViewer.close"><![CDATA[Luk]]></item>\r
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Vis kun dette billede (lukker billedfremviser)]]></item>\r
+               <item name="wcf.imageViewer.next"><![CDATA[Næste billede]]></item>\r
+               <item name="wcf.imageViewer.pause"><![CDATA[Stop slideshow]]></item>\r
+               <item name="wcf.imageViewer.play"><![CDATA[Start slideshow (skifter billede hvert 5. sekund)]]></item>\r
+               <item name="wcf.imageViewer.previous"><![CDATA[Foregående billede]]></item>\r
+       </category>\r
+       <category name="wcf.option">\r
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Kanariske øer, Lissabon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>\r
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Bruxelles, København, Madrid, Oslo, Paris, Prag, Rom, Sarajevo, Stockholm, Tunis, Warszawa, Wien]]></item>\r
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athen, Beirut, Bucharest, Helsinki, Istanbul, Jerusalem, Kairo, Cape Town, Khartoum, Kiev, Minsk, Sofia]]></item>\r
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Ababa, Antananarivo, Baghdad, Dodoma, Kampala, Kuwait City, Mogadishu, Moskva, Nairobi, Riyadh]]></item>\r
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Teheran]]></item>\r
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Jerevan, Muscat, R&eacute;union, Tbilisi]]></item>\r
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>\r
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Ashgabat, Bishkek, Dushanbe, Islamabad, Jekaterinburg, Karachi, Maldiverne, Tashkent]]></item>\r
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, New Delhi]]></item>\r
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>\r
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Novosibirsk]]></item>\r
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Islands, Yangon]]></item>\r
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>\r
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Beijing, Perth, Singapore, Taipei, Ulaanbaatar]]></item>\r
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Western Australia)]]></item>\r
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seoul, Tokyo]]></item>\r
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>\r
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>\r
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Island (Australia)]]></item>\r
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, New Caledonia, Solomon Islands]]></item>\r
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolk Island]]></item>\r
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, South Tarawa, Fiji, Kamchatka, Marshall Islands, Wellington]]></item>\r
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Islands (New Zealand)]]></item>\r
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenix Islands]]></item>\r
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Islands, Christmas Island]]></item>\r
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azorene, Cap Verde]]></item>\r
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mid-Atlantic]]></item>\r
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Grønland, Montevideo]]></item>\r
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Newfoundland]]></item>\r
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantic Time (Canada), Asunci&oacute;n, La Paz, Port-of-Spain, Santiago]]></item>\r
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>\r
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Eastern Time (US &amp; Canada), Bogot&aacute;, Lima, San Francisco de Quito]]></item>\r
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Central Time (US &amp; Canada), Central America, Mexico City]]></item>\r
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Time (US &amp; Canada), Chihuahua, Mazatlan]]></item>\r
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pacific Time (US &amp; Canada), Tijuana]]></item>\r
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>\r
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) Fransk Polynesien]]></item>\r
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cook Islands, Hawaii]]></item>\r
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midway Islands, Samoa]]></item>\r
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>\r
+       </category>\r
+       <category name="wcf.page">\r
+               <item name="wcf.page.pageNo"><![CDATA[Side {#$pageNo}]]></item>\r
+       </category>\r
+       <category name="wcf.user">\r
+               <item name="wcf.user.confirmEmail"><![CDATA[Bekræft E-mail adresse]]></item>\r
+               <item name="wcf.user.confirmPassword"><![CDATA[Bekræft kodeord]]></item>\r
+               <item name="wcf.user.email"><![CDATA[E-mail adresse]]></item>\r
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Den angivne e-mail adresse og bekræftelses e-mail adressen er ikke identiske.]]></item>\r
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Det anført kodeord og bekræftelseskodeordet er ikke identiske.]]></item>\r
+               <item name="wcf.user.error.email.notUnique"><![CDATA[Den e-mail adresse ydu har anført, benyttes allerede af en anden bruger.]]></item>\r
+               <item name="wcf.user.error.email.notValid"><![CDATA[Den e-mail adresse du har indtastet, er ugyldig.]]></item>\r
+               <item name="wcf.user.error.password.false"><![CDATA[Kodeordet er ikke korrekt.]]></item>\r
+               <item name="wcf.user.error.username.notFound"><![CDATA[Brugernavnet &quot;{$username}&quot; kunne ikke findes.]]></item>\r
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Det brugernavn du har indtastet, er allerede i brug.]]></item>\r
+               <item name="wcf.user.error.username.notValid"><![CDATA[Det indtastede brugernavn er ugyldigt.]]></item>\r
+               <item name="wcf.user.language"><![CDATA[Sprog]]></item>\r
+               <item name="wcf.user.language.description"><![CDATA[Vælg venligst sprog for bruger interfacet!]]></item>\r
+               <item name="wcf.user.logout"><![CDATA[Log af]]></item>\r
+               <item name="wcf.user.password"><![CDATA[Kodeord]]></item>\r
+               <item name="wcf.user.registrationDate"><![CDATA[Dato for registrering]]></item>\r
+               <item name="wcf.user.userID"><![CDATA[Bruger ID]]></item>\r
+               <item name="wcf.user.username"><![CDATA[Brugernavn]]></item>\r
+               <item name="wcf.user.visibleLanguages"><![CDATA[Vis indhold på følgende sprog]]></item>\r
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Vælg her indhold fra de sprog, der skal vises.]]></item>\r
+       </category>\r
+       <category name="wcf.user.option">\r
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Information du har indtastet er ugyldig.]]></item>\r
+       </category>\r
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/de-informal.xml b/wcfsetup/install/lang/de-informal.xml
new file mode 100644 (file)
index 0000000..bcac8b7
--- /dev/null
@@ -0,0 +1,903 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="de-informal">\r
+       <category name="wcf.acp">\r
+               <item name="wcf.acp"><![CDATA[Administrationsoberfläche]]></item>\r
+               <item name="wcf.acp.help"><![CDATA[Hilfe]]></item>\r
+               <item name="wcf.acp.help.complete"><![CDATA[Vollständige Hilfe]]></item>\r
+               <item name="wcf.acp.help.disable"><![CDATA[Hilfe deaktivieren]]></item>\r
+               <item name="wcf.acp.help.interactive"><![CDATA[Interaktive Hilfe]]></item>\r
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Paket wechseln]]></item>\r
+               <item name="wcf.acp.search.extended"><![CDATA[Erweiterte Suche ...]]></item>\r
+               <item name="wcf.acp.sitemap"><![CDATA[Sitemap]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cache">\r
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Cache leeren]]></item>\r
+               <item name="wcf.acp.cache.clear.success"><![CDATA[Der Cache wurde erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Möchtest du den Cache wirklich komplett leeren?]]></item>\r
+               <item name="wcf.acp.cache.data"><![CDATA[Eigenschaften]]></item>\r
+               <item name="wcf.acp.cache.data.files"><![CDATA[Dateien]]></item>\r
+               <item name="wcf.acp.cache.data.size"><![CDATA[Größe]]></item>\r
+               <item name="wcf.acp.cache.data.source"><![CDATA[Quelle]]></item>\r
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Letzte Aktualisierung]]></item>\r
+               <item name="wcf.acp.cache.list.name"><![CDATA[Name]]></item>\r
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Zugriffsrechte]]></item>\r
+               <item name="wcf.acp.cache.list.size"><![CDATA[Größe]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cronjob">\r
+               <item name="wcf.acp.cronjob.active"><![CDATA[Aktiv]]></item>\r
+               <item name="wcf.acp.cronjob.add"><![CDATA[Zeitgesteuerte Aufgabe hinzufügen]]></item>\r
+               <item name="wcf.acp.cronjob.add.data"><![CDATA[Allgemeine Daten]]></item>\r
+               <item name="wcf.acp.cronjob.add.success"><![CDATA[Die zeitgesteuerte Aufgabe wurde hinzugefügt.]]></item>\r
+               <item name="wcf.acp.cronjob.add.timing"><![CDATA[Zeitsteuerung]]></item>\r
+               <item name="wcf.acp.cronjob.className"><![CDATA[Pfad zur Klasse]]></item>\r
+               <item name="wcf.acp.cronjob.className.description"><![CDATA[Gib den Pfad zu der PHP-Datei an, die die entsprechende auszuführende Klasse enthält. Die Pfadangabe muss relativ zum Installationsverzeichnis der ausgewählten Endanwendung sein.]]></item>\r
+               <item name="wcf.acp.cronjob.cronjobID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.cronjob.delete"><![CDATA[Zeitgesteuerte Aufgabe löschen]]></item>\r
+               <item name="wcf.acp.cronjob.delete.disabled"><![CDATA[Die zeitgesteuerte Aufgabe kann nicht gelöscht werden.]]></item>\r
+               <item name="wcf.acp.cronjob.delete.success"><![CDATA[Die zeitgesteuerte Aufgabe wurde gelöscht.]]></item>\r
+               <item name="wcf.acp.cronjob.delete.sure"><![CDATA[Bist du sicher, dass du diese zeitgesteuerte Aufgabe löschen möchtest?]]></item>\r
+               <item name="wcf.acp.cronjob.description"><![CDATA[Beschreibung]]></item>\r
+               <item name="wcf.acp.cronjob.description.description"><![CDATA[Hier kannst du eine kurze Beschreibung der Aufgabe eintragen.]]></item>\r
+               <item name="wcf.acp.cronjob.disable"><![CDATA[Deaktivieren]]></item>\r
+               <item name="wcf.acp.cronjob.edit"><![CDATA[Zeitgesteuerte Aufgabe bearbeiten]]></item>\r
+               <item name="wcf.acp.cronjob.edit.data"><![CDATA[Allgemeine Daten]]></item>\r
+               <item name="wcf.acp.cronjob.edit.disabled"><![CDATA[Die zeitgesteuerte Aufgabe kann nicht verändert werden.]]></item>\r
+               <item name="wcf.acp.cronjob.edit.success"><![CDATA[Die zeitgesteuerte Aufgabe wurde erfolgreich geändert.]]></item>\r
+               <item name="wcf.acp.cronjob.edit.timing"><![CDATA[Zeitsteuerung]]></item>\r
+               <item name="wcf.acp.cronjob.enable"><![CDATA[Aktivieren]]></item>\r
+               <item name="wcf.acp.cronjob.error.doesNotExist"><![CDATA[Der angegebene Pfad ist ungültig.]]></item>\r
+               <item name="wcf.acp.cronjob.error.empty"><![CDATA[Bitte füll dieses Eingabefeld aus.]]></item>\r
+               <item name="wcf.acp.cronjob.error.notValid"><![CDATA[Das Zeitformat ist ungültig.]]></item>\r
+               <item name="wcf.acp.cronjob.execMultiple"><![CDATA[Zeitgesteuerte Aufgabe mehrfach ausführen]]></item>\r
+               <item name="wcf.acp.cronjob.execMultiple.description"><![CDATA[Durch Aktivieren dieser Option wird die Aufgabe mehrfach ausgeführt, wenn zwischen dem letzten Ausführungszeitpunkt und dem aktuellen Zeitpunkt weitere Ausführungszeitpunkte liegen.]]></item>\r
+               <item name="wcf.acp.cronjob.execute"><![CDATA[Aufgabe jetzt ausführen]]></item>\r
+               <item name="wcf.acp.cronjob.execute.success"><![CDATA[Die Aufgabe wurde erfolgreich ausgeführt.]]></item>\r
+               <item name="wcf.acp.cronjob.inactive"><![CDATA[Inaktiv]]></item>\r
+               <item name="wcf.acp.cronjob.info"><![CDATA[Allgemeine Informationen]]></item>\r
+               <item name="wcf.acp.cronjob.intro"><![CDATA[Das Anlegen von zeitgesteuerten Aufgaben erfordert eine genaue Kenntnis der Crontab-Syntax auf unixähnlichen Systemen. Weiterführende Informationen dazu erhältst du auf dieser Website: <a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={"http://www.unixgeeks.org/security/newbie/unix/cron-1.html"|rawurlencode}" class="externalURL">Newbie: Intro to cron</a>]]></item>\r
+               <item name="wcf.acp.cronjob.lastExec"><![CDATA[Letzte Ausführung]]></item>\r
+               <item name="wcf.acp.cronjob.list"><![CDATA[Zeitgesteuerte Aufgaben]]></item>\r
+               <item name="wcf.acp.cronjob.list.count"><![CDATA[Insgesamt {#$items} zeitgesteuerte Aufgabe{if $items != 1}n{/if}]]></item>\r
+               <item name="wcf.acp.cronjob.log"><![CDATA[Protokoll der ausgeführten zeitgesteuerten Aufgaben]]></item>\r
+               <item name="wcf.acp.cronjob.log.clear"><![CDATA[Alle löschen]]></item>\r
+               <item name="wcf.acp.cronjob.log.clear.confirm"><![CDATA[Bist du sicher, dass du alle Protokoll-Einträge löschen möchtest?]]></item>\r
+               <item name="wcf.acp.cronjob.log.data"><![CDATA[Insgesamt {#$items} {if $items == 1}Eintrag{else}Einträge{/if}]]></item>\r
+               <item name="wcf.acp.cronjob.log.error"><![CDATA[Fehler:]]></item>\r
+               <item name="wcf.acp.cronjob.log.execTime"><![CDATA[Ausgeführt]]></item>\r
+               <item name="wcf.acp.cronjob.log.noEntries"><![CDATA[Derzeit sind keine Einträge vorhanden.]]></item>\r
+               <item name="wcf.acp.cronjob.log.success"><![CDATA[OK]]></item>\r
+               <item name="wcf.acp.cronjob.nextExec"><![CDATA[Nächste Ausführung]]></item>\r
+               <item name="wcf.acp.cronjob.noneAvailable"><![CDATA[Derzeit ist keine zeitgesteuerte Aufgabe vorhanden.]]></item>\r
+               <item name="wcf.acp.cronjob.packageName"><![CDATA[Installiert von]]></item>\r
+               <item name="wcf.acp.cronjob.runNow"><![CDATA[Jetzt ausführen]]></item>\r
+               <item name="wcf.acp.cronjob.startDom"><![CDATA[Tag des Monats]]></item>\r
+               <item name="wcf.acp.cronjob.startDom.description"><![CDATA[An diesen Tagen des Monats (1 - 31) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startDomShort"><![CDATA[D]]></item>\r
+               <item name="wcf.acp.cronjob.startDow"><![CDATA[Tag der Woche]]></item>\r
+               <item name="wcf.acp.cronjob.startDow.description"><![CDATA[An diesen Tagen der Woche (0 - 6 mit Sonntag = 0 oder mon - sun) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startDowShort"><![CDATA[DoW]]></item>\r
+               <item name="wcf.acp.cronjob.startHour"><![CDATA[Stunde]]></item>\r
+               <item name="wcf.acp.cronjob.startHour.description"><![CDATA[Zu diesen Stunden (0 - 23) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startHourShort"><![CDATA[h]]></item>\r
+               <item name="wcf.acp.cronjob.startMinute"><![CDATA[Minute]]></item>\r
+               <item name="wcf.acp.cronjob.startMinute.description"><![CDATA[Zu diesen Minuten (0 - 59) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startMinuteShort"><![CDATA[m]]></item>\r
+               <item name="wcf.acp.cronjob.startMonth"><![CDATA[Monat]]></item>\r
+               <item name="wcf.acp.cronjob.startMonth.description"><![CDATA[In diesen Monaten (1 - 12 oder jan - dec) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startMonthShort"><![CDATA[M]]></item>\r
+               <item name="wcf.acp.cronjob.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.cronjob.subtitle"><![CDATA[&raquo;Cronjobs&laquo;]]></item>\r
+       </category>\r
+       <category name="wcf.acp.group">\r
+               <item name="wcf.acp.group.add"><![CDATA[Benutzergruppe hinzufügen]]></item>\r
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Zugriffsrechte]]></item>\r
+               <item name="wcf.acp.group.add.success"><![CDATA[Die Benutzergruppe wurde erfolgreich angelegt.]]></item>\r
+               <item name="wcf.acp.group.administrators"><![CDATA[Administratoren]]></item>\r
+               <item name="wcf.acp.group.data"><![CDATA[Allgemeine Daten]]></item>\r
+               <item name="wcf.acp.group.delete"><![CDATA[Benutzergruppe löschen]]></item>\r
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Die Benutzergruppe wurde{else}{#$deletedGroups} Benutzergruppen wurden{/if} erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Willst du diese Benutzergruppe wirklich löschen?]]></item>\r
+               <item name="wcf.acp.group.edit"><![CDATA[Benutzergruppe bearbeiten]]></item>\r
+               <item name="wcf.acp.group.edit.success"><![CDATA[Deine Änderungen an der Benutzergruppe wurde erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Du bist selbst Mitglied dieser Benutzergruppe. Änderungen an den Zugriffsrechten dieser Benutzergruppe können womöglich dazu führen, dass du aus der Administrationsoberfläche ausgeschlossen wirst. Bitte sei entsprechend vorsichtig!]]></item>\r
+               <item name="wcf.acp.group.everyone"><![CDATA[Jeder]]></item>\r
+               <item name="wcf.acp.group.groupID"><![CDATA[Gruppen-ID]]></item>\r
+               <item name="wcf.acp.group.groupName"><![CDATA[Name der Benutzergruppe]]></item>\r
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Gib einen Namen der Gruppe an.]]></item>\r
+               <item name="wcf.acp.group.guests"><![CDATA[Gäste]]></item>\r
+               <item name="wcf.acp.group.list"><![CDATA[Benutzergruppen]]></item>\r
+               <item name="wcf.acp.group.list.data"><![CDATA[Insgesamt {#$items} Benutzergruppen]]></item>\r
+               <item name="wcf.acp.group.members"><![CDATA[Anzahl Mitglieder]]></item>\r
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatoren]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Kann Administrationsoberfläche betreten]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Mitglieder dieser Benutzergruppe können die Administrationsoberfläche betreten und dort abhängig von den weiteren Zugriffsrechten verschiedene Aktionen durchführen. Diese Option muss aktiviert sein, wenn diesen Benutzern andere administrative Funktionen erlaubt werden sollen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Kann versteckte Profilinformationen sehen]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Mitglieder dieser Benutzergruppe können die versteckten Informationen in Benutzerprofilen sehen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Kann allgemeine Einstellungen vornehmen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Mitglieder dieser Benutzergruppe können die allgemeinen System-Einstellungen sehen und bearbeiten. Z.B. Forum ein-/ausschalten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Kann Protokolle abrufen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Mitglieder dieser Benutzergruppe können die System-Protokolle abrufen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canAddCronjob"><![CDATA[Kann neue zeitgesteuerte Aufgaben anlegen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canAddCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können neue zeitgesteuerte Aufgaben anlegen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjob"><![CDATA[Kann zeitgesteuerte Aufgaben löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene zeitgesteuerte Aufgaben löschen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjobsLog"><![CDATA[Kann Protokoll der zeitgesteuerten Aufgaben löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjobsLog.description"><![CDATA[Mitglieder dieser Benutzergruppe können das Protokoll der zeitgesteuerten Aufgaben löschen. Bei der Ausführung einer zeitgesteuerten Aufgabe wird festgehalten, ob dieser erfolgreich ausgeführt wurde.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEditCronjob"><![CDATA[Kann zeitgesteuerte Aufgaben ändern]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEditCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene zeitgesteuerte Aufgaben bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEnableDisableCronjob"><![CDATA[Kann zeitgesteuerte Aufgaben deaktivieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEnableDisableCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene zeitgesteuerte Aufgaben deaktivieren. Diese werden dann nicht mehr ausgeführt, können später jedoch auch wieder aktiviert werden.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Kann Update-Server bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Update-Server bearbeiten und neue hinzufügen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Kann Pakete installieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Mitglieder dieser Benutzergruppe können zusätzliche Pakete installieren.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Kann Pakete deinstallieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Pakete entfernen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Kann Pakete aktualisieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Pakete aktualisieren.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Zugängliche Benutzergruppen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Mitglieder dieser Benutzergruppe haben auf diese Gruppen Zugriff. Zusätzlich muss angegeben werden, ob z.B. die Benutzergruppe bearbeitet werden darf.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Kann neue Benutzergruppen erstellen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Mitglieder dieser Benutzergruppe können neue Benutzergruppen erstellen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Kann neue Benutzer erstellen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können neue Benutzer erstellen. Ist bei "Zugängliche Benutzergruppen" eine Option aktiviert, kann diese Gruppe beim Erstellen des Benutzers zugewiesen werden.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Kann Benutzergruppen löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzergruppen löschen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Kann Benutzer löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzer löschen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Kann Benutzergruppen bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzergruppen bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Kann E-Mail-Adressen bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Mitglieder dieser Benutzergruppe können die E-Mail-Adresse von anderen Benutzern bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Kann Kennwörter bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Mitglieder dieser Benutzergruppe können das Kennwort von anderen Benutzern bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Kann Benutzer bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzer bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Kann E-Mails an Benutzer senden]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können die E-Mail-Adresse von anderen Benutzern sehen und ihnen E-Mails senden.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Kann Benutzer suchen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzer und deren Profile durchsuchen.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Administrative Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Inhalte]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Allgemeine administrative Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Wartung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[System-Funktionen]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.cronjobs"><![CDATA[Zeitgesteuerte Aufgaben]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.cronjobs.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Paketverwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Benutzer-Funktionen]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Gruppenverwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Benutzerverwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderative Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Allgemeine Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Du hast einen ungültigen Inhalt eingegeben.]]></item>\r
+               <item name="wcf.acp.group.option.admin.style.canUseDisabledStyle"><![CDATA[Kann deaktivierte Stile benutzen]]></item>\r
+               <item name="wcf.acp.group.option.admin.style.canUseDisabledStyle.description"><![CDATA[Mitglieder dieser Benutzergruppe können deaktivierte Stile auswählen.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.style"><![CDATA[Stil-Verwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.style.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.showMembers"><![CDATA[Zeige die Mitglieder dieser Benutzergruppe]]></item>\r
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super Moderatoren]]></item>\r
+               <item name="wcf.acp.group.users"><![CDATA[Registrierte Benutzer]]></item>\r
+       </category>\r
+       <category name="wcf.acp.login">\r
+               <item name="wcf.acp.login"><![CDATA[Anmeldung]]></item>\r
+               <item name="wcf.acp.login.data"><![CDATA[Zugangsdaten]]></item>\r
+       </category>\r
+       <category name="wcf.acp.masterPassword">\r
+               <item name="wcf.acp.masterPassword"><![CDATA[Hauptkennwort]]></item>\r
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Hauptkennwort wiederholen]]></item>\r
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Hauptkennwort erforderlich]]></item>\r
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Die aufgerufene Seite oder Aktion erfordert aus Sicherheitsgründen die Eingabe des Hauptkennwortes. Pro Sitzung ist die Eingabe des Hauptkennwortes nur einmal erforderlich. Falls du das Hauptkennwort vergessen haben solltest, kannst du es zurücksetzen, indem du die Datei <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em> löschst.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[Das Hauptkennwort ist nicht korrekt. Falls du das Hauptkennwort vergessen haben solltest, kannst du es zurücksetzen, indem du die Datei <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em> löschst.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[Die eingegebenen Kennwörter sind nicht identisch.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[Das Kennwort wurde als unsicher erkannt. Das Kennwort sollte mindestens acht Zeichen lang sein, große und kleine lateinische Buchstaben, Zahlen und Sonderzeichen enthalten. Es darf nicht mit den Kennwörtern von anderen Administratoren übereinstimmen.]]></item>\r
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Vorschlag]]></item>\r
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Vorschlag übernehmen]]></item>\r
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Hauptkennwort festlegen]]></item>\r
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[Das Hauptkennwort ist ein zusätzlicher Schutz für sicherheitskritische Funktionen. Du solltest hier ein möglichst sicheres Kennwort verwenden, dass sich von deinem normalen Administrator-Kennwort unterscheidet, Dritten nicht bekannt ist und auch nicht auf anderen Internetseiten verwendet wird.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.menu">\r
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Automatisches Update]]></item>\r
+               <item name="wcf.acp.menu.link.content"><![CDATA[Inhalte]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.add"><![CDATA[Zeitgesteuerte Aufgabe hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.showLog"><![CDATA[Protokoll anzeigen]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.view"><![CDATA[Zeitgesteuerte Aufgaben auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.menu.link.group"><![CDATA[Benutzergruppen]]></item>\r
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Benutzergruppe hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[E-Mail an Gruppenmitglieder]]></item>\r
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Benutzergruppen auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.log"><![CDATA[Protokoll]]></item>\r
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Sitzungen]]></item>\r
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Wartung]]></item>\r
+               <item name="wcf.acp.menu.link.option"><![CDATA[Optionen]]></item>\r
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Sichern &amp; Wiederherstellen]]></item>\r
+               <item name="wcf.acp.menu.link.package"><![CDATA[Paketverwaltung]]></item>\r
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Pakete suchen]]></item>\r
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Paket installieren]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Server hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Server auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Pakete auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.menu.link.user"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Benutzer hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Benutzer auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-Mail an alle Benutzer]]></item>\r
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Massenverarbeitung von Benutzern]]></item>\r
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Benutzer suchen]]></item>\r
+       </category>\r
+       <category name="wcf.acp.option">\r
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Hostname ausschließen]]></item>\r
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Gib pro Zeile einen Hostname an, die du von der Seite ausschließen möchtest.]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[IP-Adresse ausschließen]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Gib pro Zeile eine IP-Adresse an, die du von der Seite ausschließen möchtest.]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Browser-Kennung ausschließen]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Gib pro Zeile eine Browser-Kennung (User-Agent) an, die du von der Seite ausschließen möchtest.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache-Server]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Gib hier die Adresse des Memcache-Servers ein! Mehrere Server können zeilenweise angegeben werden.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Persistente Verbindungen aktivieren]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Sollen beim Verbinden mit dem Memcache-Server persistente Verbindungen genutzt werden?]]></item>\r
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache-Methode]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Bitte wähle die gewünschte Cache-Methode aus! Beachte, dass einige Methoden spezielle Anforderungen an das Server-System stellen und nicht auf jedem Server zur Verfügung stehen.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[Dateisystem (Standard)]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (Experimentell)]]></item>\r
+               <item name="wcf.acp.option.category.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache speichert häufig benötige Daten im Arbeitsspeicher zwischen. Dies kann die Last auf die Datenbank und das Dateisystem drastisch reduzieren. Lies mehr über dieses Thema auf der folgenden Seite:\r
+<ul>\r
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>\r
+</ul>]]></item>\r
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Datum &amp; Zeit]]></item>\r
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy-Server]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Hier kannst du optional Proxy-Server für Verbindungen zu externen Servern konfigurieren.]]></item>\r
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-Mails]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Versand]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Wartungsmodus]]></item>\r
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module"><![CDATA[Module an / aus]]></item>\r
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Inhalte]]></item>\r
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security"><![CDATA[Sicherheit]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internetseiten werden häufig durch andere Programme angegriffen. So gibt es beispielsweise die Möglichkeit, automatisiert hunderte von Benutzerkonten zu erstellen. Um sich davor zu schützen, kannst du an verschiedenen Stellen ein sogenanntes <a href="http://de.wikipedia.org/wiki/Captcha" class="externalURL">Captcha-Bild</a> anzeigen lassen. Unregistrierte Benutzer müssen erst den Code eingeben, der auf diesem Bild steht. Roboter können diesen Code nicht lesen. Beachte, dass Captcha-Bilder von blinden und sehbehinderten Benutzern nicht identifiziert werden können.]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Blacklist]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Zensur]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sitzungen]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.user"><![CDATA[Mitglieder]]></item>\r
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookiedomain]]></item>\r
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Hier kannst Du optional eine Domain angeben, unter der der Cookie laufen soll. Standardmäßig solltest Du dieses Feld frei lassen, da ein Ausfüllen nur in wenigen Fällen notwendig ist.]]></item>\r
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookiepfad]]></item>\r
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Der Cookiepfad wird absolut zum Document Root angegeben - also z.B. "/forum" für http://www.woltlab.de/forum.]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Präfix für Cookienamen]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Gib einen Präfix an, der bei Cookienamen verwendet wird.]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Uhr automatisch auf Sommer-/Winterzeit umstellen]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Soll die Uhr automatisch auf Sommer-/Winterzeit umgestellt werden?]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Cache-Methode für Sitzungsdaten verwenden]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Soll für die Speicherung der Sitzungsdaten die ausgewählte Cache-Methode verwendet werden?]]></item>\r
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Du hast einen ungültigen Inhalt eingegeben.]]></item>\r
+               <item name="wcf.acp.option.export"><![CDATA[Optionen sichern]]></item>\r
+               <item name="wcf.acp.option.export.download"><![CDATA[Sicherung der Optionen herunterladen]]></item>\r
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Lade eine Sicherung der Optionen auf deinen lokalen Rechner herunter.]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Gzip-Komprimierung aktivieren]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Durch Aktivierung dieser Option werden die Inhalte komprimiert vom Server an den Client gesendet. Dies reduziert den Traffic.]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Seitencaching im Client-Browser verhindern]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Durch Aktivierung dieser Option kannst du das Caching der Seite im Browser verhindern.]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Gzip-Komprimierungslevel]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Werte von 1-9 sind zulässig. Als Optimum zwischen Komprimierung und Serverlast empfiehlt sich Level 1.]]></item>\r
+               <item name="wcf.acp.option.import"><![CDATA[Optionen wiederherstellen]]></item>\r
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[Die Optionen konnten nicht erfolgreich importiert werden.]]></item>\r
+               <item name="wcf.acp.option.import.success"><![CDATA[Die Optionen wurden erfolgreich importiert.]]></item>\r
+               <item name="wcf.acp.option.import.upload"><![CDATA[Sicherung der Optionen vom lokalen Computer hochladen]]></item>\r
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Gib eine Sicherung der Optionen von Ihrem lokalen Rechner an.]]></item>\r
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Optionen sichern &amp; wiederherstellen]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Administrator-Adresse]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Gib die E-Mail-Adresse des Administrators an.]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Logfile-Pfad]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Gib den Pfad zum Logfile an.]]></item>\r
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Absender-Adresse]]></item>\r
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Gib die Absender-Adresse bei automatisch generierten E-Mails an.]]></item>\r
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Absender-Name]]></item>\r
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Gib den Namen des Absenders bei automatisch generierten E-Mails an.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[Versandmethode]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Wähle eine Versandmethode aus.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>\r
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Signatur]]></item>\r
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Trage hier eine Signatur ein, die bei System-E-Mails angezeigt werden soll.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP-Server]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Trage hier den SMTP-Server ein.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP-Kennwort]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Gib das SMTP-Kennwort an.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP-Port]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Gib den SMTP-Port an.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP-Benutzer]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Gib den SMTP-Benutzer an.]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[&raquo;-f&laquo; Parameter verwenden]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Manche Server benötigen den &raquo;-f&laquo; Parameter beim Versenden von E-Mails. Falls du Probleme mit dem Versand von E-Mails hast, aktiviere diese Einstellung.]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Formatierte E-Mail-Adressen verwenden]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Absender- und Empfänger-Adressen werden in folgendes Format gebracht: &quot;Name &lt;email@domain.tld&gt;&quot;. Diese Funktion wird nicht von allen Mailservern unterstützt und sollte daher bei Problemen abgeschaltet werden.]]></item>\r
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Hauptkennwort aktivieren]]></item>\r
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Aktiviert die zusätzliche Eingabe eines Kennworts beim Aufruf von sicherheitskritischen Bereichen.]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server für HTTP-Verbindungen]]></item>\r
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Gültigkeitslänge einer Sitzung]]></item>\r
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Gib an, wie lange die Sitzung gültig ist [Sekunden]. ]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[IP-Adresse der Sitzung überprüfen]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Anzahl der Blöcke der IP-Adresse die beim Auslesen der Sitzung überprüft werden sollen. Eine hohe Einstellung kann Benutzer ausschließen, die mit wechselnden IP-Adressen im Internet unterwegs sind.]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Browser-Kennung der Sitzung überprüfen]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Soll die Browser-Kennung beim Auslesen der Sitzung überprüft werden?]]></item>\r
+               <item name="wcf.acp.option.success"><![CDATA[Deine Einstellungsänderungen wurden erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.option.timezone"><![CDATA[Zeitzone]]></item>\r
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Wähle die Standard Zeitzone deiner Seite.]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Timeout für Benutzer-Online]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Gib an, wie lange der Benutzer trotz Inaktivität als online markiert werden soll [Sekunden].]]></item>\r
+               <item name="wcf.acp.option.category.general.page"><![CDATA[Seite]]></item>\r
+               <item name="wcf.acp.option.category.general.page.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.meta_description"><![CDATA[Meta Description]]></item>\r
+               <item name="wcf.acp.option.meta_description.description"><![CDATA[Gib eine Meta Description an.]]></item>\r
+               <item name="wcf.acp.option.meta_keywords"><![CDATA[Meta Keywords]]></item>\r
+               <item name="wcf.acp.option.meta_keywords.description"><![CDATA[Trage die Wörter ein, die im Meta-Tag Keywords stehen sollen.]]></item>\r
+               <item name="wcf.acp.option.page_description"><![CDATA[Seitenbeschreibung]]></item>\r
+               <item name="wcf.acp.option.page_description.description"><![CDATA[Füge hier eine kurze Beschreibung deiner Seite ein.]]></item>\r
+               <item name="wcf.acp.option.page_title"><![CDATA[Titel der Seite]]></item>\r
+               <item name="wcf.acp.option.page_title.description"><![CDATA[Gib hier den Globalen Titel der Seite an. Dieser Titel wird im Seitenkopf dargestellt, wenn du die Anzeige dieses Textes im Stileditor aktiviert hast.]]></item>\r
+               <item name="wcf.acp.option.page_url"><![CDATA[Adresse (URL) der Seite]]></item>\r
+               <item name="wcf.acp.option.page_url.description"><![CDATA[Gib an, unter welcher Adresse (URL) die Seite aufzurufen ist (ohne abschließenden Slash).]]></item>\r
+               <item name="wcf.acp.option.page_urls"><![CDATA[Weitere URLs]]></item>\r
+               <item name="wcf.acp.option.page_urls.description"><![CDATA[Gib hier weitere URLs an, unter denen deine Seite erreichbar ist.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.package">\r
+               <item name="wcf.acp.package.cancel"><![CDATA[Abbruch der Paketinstallation]]></item>\r
+               <item name="wcf.acp.package.description"><![CDATA[Beschreibung]]></item>\r
+               <item name="wcf.acp.package.install"><![CDATA[Paketinstallation]]></item>\r
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Installation abbrechen]]></item>\r
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Willst du die Installation wirklich abbrechen?]]></item>\r
+               <item name="wcf.acp.package.install.error"><![CDATA[Die Abhängigkeiten dieses Paketes konnten nicht aufgelöst werden.]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[Die {if $action == 'install'}Paketinstallation{else}Paketaktualisierung{/if} von Paket &raquo;{$packageName}&laquo; in Version {$packageVersion} kann aufgrund von Inkompatibilitäten zu {if $excludedPackages|count == 1}folgendem Paket{else}folgenden Paketen{/if} nicht durchgeführt werden:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} in Version {$excludedPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Folgendes Paket lässt{else}Folgende Pakete lassen{/if} die {if $action == 'install'}Paketinstallation{else}Paketaktualisierung{/if} von Paket &raquo;{$packageName}&laquo; in Version {$packageVersion} aufgrund von Inkompatibilitäten nicht zu:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} in Version {$excludingPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Folgendes Paket ist{else}Folgende Pakete sind{/if} mit dem Paket &raquo;{$packageName}&laquo; in Version {$packageVersion} nicht kompatibel. Wenn du die Installation fortführst, {if $excludingPackages|count == 1}wird das Paket{else}werden die Pakete{/if} vermutlich nicht mehr korrekt funktionieren.]]></item>\r
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}ist bereits installiert{else}{if $package.file|isset}liegt dem Paket bei{else}fehlt{/if}{/if})</span>]]></item>\r
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Willst du die Paketinstallation wirklich abbrechen?]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Folgende Pakete können mit diesem Paket aktualisiert werden]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Wähle eines der folgenden Pakete aus, um seine Version zu aktualisieren. Falls du das Paket neu installieren möchtest, klick unten auf &raquo;Weiter&laquo;.]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Es ist bereits eine Kopie dieses Paketes installiert. Wenn du fortfährst, wird eine weitere Kopie dieses Paketes installiert. Falls du eine vorhandene Kopie dieses Paketes aktualisieren möchtest, wähle die Kopie aus der folgenden Liste aus.]]></item>\r
+               <item name="wcf.acp.package.install.version"><![CDATA[Version des Paketes:]]></item>\r
+               <item name="wcf.acp.package.installDate"><![CDATA[Installationsdatum]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Beim Versuch die Dateien des Paketes zu entpacken, ist folgender Fehler aufgetreten:]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[Folgende Dateien konnten nicht erfolgreich entpackt werden. Bitte überprüfe, ob der entsprechende Zielort beschreibbar ist.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Tabellen Konflikt]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Keine Tabellen überschreiben und während der gesamten Installation nicht mehr nachfragen.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Alle Tabellen überschreiben und während der gesamten Installation nicht mehr nachfragen.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Notwendige Änderungen]]></item>\r
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Betroffene Tabelle]]></item>\r
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Vorhandene Tabellen deiner Datenbank stehen im Konflikt mit Tabellen, die für dieses Paket installiert werden müssen. Wähle aus, ob diese Tabellen überschrieben werden sollen.]]></item>\r
+               <item name="wcf.acp.package.list"><![CDATA[Installierte Pakete]]></item>\r
+               <item name="wcf.acp.package.list.author"><![CDATA[Hersteller]]></item>\r
+               <item name="wcf.acp.package.list.count"><![CDATA[Insgesamt sind {#$items} Pakete installiert.]]></item>\r
+               <item name="wcf.acp.package.list.date"><![CDATA[Herstellungsdatum]]></item>\r
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.package.list.name"><![CDATA[Name]]></item>\r
+               <item name="wcf.acp.package.list.other"><![CDATA[Sonstiges Paket]]></item>\r
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Zusatzmodul]]></item>\r
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Endanwendung]]></item>\r
+               <item name="wcf.acp.package.list.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.package.optionals"><![CDATA[Optionale Zusatzpakete installieren]]></item>\r
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Das aktuelle Paket bringt folgende optionale Zusatzpakete mit. Wähle aus, welche Zusatzpakete du installieren möchtest.]]></item>\r
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Dieses Paket ist bereits installiert.)]]></item>\r
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Die Voraussetzungen für dieses Paket werden nicht erfüllt.)]]></item>\r
+               <item name="wcf.acp.package.packageDir"><![CDATA[Installationsverzeichnis]]></item>\r
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Es ist bereits eine andere Anwendung in dem angegebenen Verzeichnis installiert.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[Das eingegebene Verzeichnis ist ungültig.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Das angegebene Verzeichnis ist nicht beschreibbar.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Das angegebene Verzeichnis wird bereits von WoltLab Community Framework beansprucht. Wähle ein anderes Verzeichnis.]]></item>\r
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Gib hier das Installationsverzeichnis an.]]></item>\r
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Nach der Installation in das angegebene Installationsverzeichnis ist die Anwendung über folgende Adresse (URL) erreichbar:]]></item>\r
+               <item name="wcf.acp.package.requirements"><![CDATA[Abhängigkeiten auswählen]]></item>\r
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Das aktuelle Paket benötigt Pakete, von denen mehrere Instanzen installiert sind. Bitte wähle aus, zu welcher Instanz jeweils eine Abhängigkeit hergestellt werden soll.]]></item>\r
+               <item name="wcf.acp.package.rollback"><![CDATA[Paketinstallation zurücksetzen]]></item>\r
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Version {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>\r
+               <item name="wcf.acp.package.startInstall"><![CDATA[Neues Paket installieren]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Das angegebene Paket lässt keine Neuinstallation zu.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[Das angegebene Archiv ist kein gültiges Paket.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Paket &raquo;{$package->getName()}&laquo; kann mit dem angegebenen Archiv nicht aktualisiert werden.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Es konnte keine Datei unter dem angegebenen Pfad gefunden wurden.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Dieses Paket ist bereits installiert. Das Paket kann nicht mehrfach installiert werden.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[Das Hochladen der ausgewählten Datei ist fehlgeschlagen.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Quelle auswählen]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Direkten Pfad zum Paket angeben]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Gib den direkten Pfad zur Paketdatei an. Dabei kann es sich um die Internet Adresse der Paketdatei oder alternativ den Pfad zur Paketdatei im Dateisystem handeln.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Paket vom lokalen Computer hochladen]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Gib eine Paketdatei von deinem lokalen Rechner an.]]></item>\r
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Paket &raquo;{$package->getName()}&laquo; aktualisieren]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Menüpunkte der Administrationsoberfläche werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Template-Patches der Administrationsoberfläche werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Templates der Administrationsoberfläche werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.CronjobsPackageInstallationPlugin"><![CDATA[Zeitgesteuerte Aufgaben werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Dateien werden entpackt ...]]></item>\r
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Benutzergruppeneinstellungen werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Sprache wird installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Optionen werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Spezielles Skript wird ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Datenbank wird installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Template-Patches werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Templates werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Benutzerprofilfelder werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Mögliche Konflikte werden überprüft ...]]></item>\r
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Installation abgeschlossen]]></item>\r
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Optionale Pakete werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Paket wird registriert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Zuordnung zum übergeordneten Paket wird vorgenommen ...]]></item>\r
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Abhängigkeiten werden aufgelöst ...]]></item>\r
+               <item name="wcf.acp.package.step.title"><![CDATA[Paket <b>{$packageName|encodeJS}</b>: ]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Menüpunkte der Administrationsoberfläche werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Template-Patches der Administrationsoberfläche werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Templates der Administrationsoberfläche werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.CronjobsPackageInstallationPlugin"><![CDATA[Zeitgesteuerte Aufgaben werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Dateien werden gelöscht ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Benutzergruppeneinstellungen werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Sprache wird deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Optionen werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Datenbank wird deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Template-Patches werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Templates werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Benutzerprofilfelder werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Deinstallation abgeschlossen]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Optionale Pakete werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Abhängigkeiten werden aufgelöst ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Menüpunkte der Administrationsoberfläche werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Template-Patches der Administrationsoberfläche werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Templates der Administrationsoberfläche werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.CronjobsPackageInstallationPlugin"><![CDATA[Zeitgesteuerte Aufgaben werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Dateien werden entpackt ...]]></item>\r
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Benutzergruppeneinstellungen werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Sprache wird aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Optionen werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Spezielles Skript wird ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Datenbank wird aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Template-Patches werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Templates werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Benutzerprofilfelder werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Mögliche Konflikte werden überprüft ...]]></item>\r
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Paketaktualisierung abgeschlossen]]></item>\r
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Optionale Pakete werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Paket wird aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Zuordnung zum übergeordneten Paket wird vorgenommen ...]]></item>\r
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Abhängigkeiten werden aufgelöst ...]]></item>\r
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[Das Anwenden eines Patches, der zu diesem Paket gehört, ist fehlgeschlagen, da dieser Patch nicht kompatibel zu seiner Zieldatei ist. Das Paket kann deshalb nicht installiert werden. Klick auf &raquo;Installation abbrechen&laquo;.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Das erneute Patchen folgender Templates scheiterte:<br />{foreach from=$failures item=$failure}{$failure.templateName} (ursprünglich gepatcht von: {$failure.packageName})<br />{/foreach}Wahrscheinlich wird deshalb das Paket, das den jeweiligen Patch ursprünglich angewendet hatte, nicht mehr funktionieren. Du solltest dieses Update dennoch fortsetzen. Klick dazu auf &raquo;Weiter&laquo;.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[Das Entfernen eines Patches, der zu diesem Paket gehört, ist fehlgeschlagen, da seine Zieldatei anderweitig verändert worden ist. Das Paket kann deshalb nicht entfernt werden. Klick auf &raquo;Abbruch der Paketdeinstallation&laquo;.]]></item>\r
+               <item name="wcf.acp.package.uninstall"><![CDATA[Paketdeinstallation]]></item>\r
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Abbruch der Paketdeinstallation]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Die Deinstallation des Paketes ist nicht möglich, da mindestens ein abhängiges Paket nicht deinstalliert werden kann.]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Diese{if $dependentPackages|count == 1}s Paket wird{else} Pakete werden{/if}, nach deiner Bestätigung, ohne weitere Sicherheitsabfrage deinstalliert.]]></item>\r
+               <item name="wcf.acp.package.update"><![CDATA[Paketaktualisierung]]></item>\r
+               <item name="wcf.acp.package.updateDate"><![CDATA[Aktualisierungsdatum]]></item>\r
+               <item name="wcf.acp.package.view.author"><![CDATA[Hersteller:]]></item>\r
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Zur Administrationsoberfläche wechseln]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Paket deinstallieren]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Alle Pakete deinstallieren]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Willst du dieses Paket wirklich deinstallieren?]]></item>\r
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Paket aktualisieren]]></item>\r
+               <item name="wcf.acp.package.view.date"><![CDATA[Herstellungsdatum:]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Abhängige Pakete]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Dieses Paket wird von {#$dependentPackages|count} {if $dependentPackages|count == 1}anderen Paket{else}anderen Paketen{/if} benötigt.]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Dieses Paket wird von 1 anderen Paket benötigt{else}{#$dependentPackages|count} Pakete sind direkt oder indirekt von diesem Paket abhängig{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.dir"><![CDATA[Installationsverzeichnis:]]></item>\r
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Bezeichner:]]></item>\r
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Installierte Instanz:]]></item>\r
+               <item name="wcf.acp.package.view.parent"><![CDATA[Übergeordnetes Paket:]]></item>\r
+               <item name="wcf.acp.package.view.properties"><![CDATA[Eigenschaften]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Benötigte Pakete]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Dieses Paket benötigt {#$requiredPackages|count} {if $requiredPackages|count == 1}anderes Paket{else}andere Pakete{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.url"><![CDATA[Homepage:]]></item>\r
+               <item name="wcf.acp.package.view.version"><![CDATA[Installierte Version:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.packageUpdate">\r
+               <item name="wcf.acp.packageUpdate"><![CDATA[Pakete aktualisieren]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Authentifizierung mit Update-Server]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Verbindungs-Daten]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Benutzername und Kennwort wurden nicht akzeptiert.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Gib ein Kennwort an, das zur Authentifizierung benötigt wird.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Gib einen Benutzernamen an, der zur Authentifizierung benötigt wird.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Benutzeranmeldung]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Server-Meldung]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Server-Name]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Benutzerdaten dauerhaft speichern]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Speichert die eingegebenen Benutzerdaten dauerhaft, sodass du die Daten zu einem späteren Zeitpunkt nicht erneut eingeben musst.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adresse]]></item>\r
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Installierte Version]]></item>\r
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Es ist folgender Fehler aufgetreten: ]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Das Herunterladen des Paketes {$package} ist fehlgeschlagen.]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[Beim Versuch die Paketliste herunterzuladen, ist ein Fehler aufgetreten.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[Es {if $excludedPackages|count == 1}ist folgender Konflikt{else}sind folgende Konflikte{/if} aufgetreten:]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Das installierte Paket &raquo;{$excludedPackage.existingPackageName}&laquo; ist mit dem Paket &raquo;{$excludedPackage.packageName}&laquo; in Version {$excludedPackage.packageVersion} nicht kompatibel.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[Das Paket &raquo;{$excludedPackage.packageName}&laquo; in Version {$excludedPackage.packageVersion} ist mit dem installierten Paket &raquo;{$excludedPackage.existingPackageName}&laquo; nicht kompatibel.]]></item>\r
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} wird installiert]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Derzeit sind keine Updates verfügbar.]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Du hast kein Update ausgewählt.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Optionen]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Das Paket ist bereits installiert und kann kein weiteres Mal installiert werden.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Paket installieren]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Weitere Paket-Instanz installieren (Paket ist bereits {#$package.instances} mal installiert)]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Installiertes Paket {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} Version {$updatableInstance.packageVersion} aktualisieren]]></item>\r
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Pakete suchen]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Autor]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Suche nach ...]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Bereits installierte einzigartige Pakete ausblenden]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Paketname]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Paketname und -beschreibung durchsuchen]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Update-Server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Alle Update-Server durchsuchen]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Art des Paketes]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Sonstige Pakete]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Zusatzmodul für bereits installierte Pakete]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Endanwendung]]></item>\r
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Alle Pakete auswählen]]></item>\r
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} wird aktualisiert auf {$package.toVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Neue Version]]></item>\r
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Folgende Paket-Aktualisierungen/-Installationen werden durchgeführt:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.sessionLog">\r
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Aktionen der protokollierten Sitzung von &raquo;{$sessionLog->username}&laquo;]]></item>\r
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Insgesamt {#$items} protokollierte Aktion{if $items != 1}en{/if}]]></item>\r
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Aktionen]]></item>\r
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Klasse]]></item>\r
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP-Adresse]]></item>\r
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Letzte Aktion]]></item>\r
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Paket]]></item>\r
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Methode]]></item>\r
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Datum]]></item>\r
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[Browser-Kennung]]></item>\r
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Protokollierte Sitzungen]]></item>\r
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Insgesamt {#$items} protokollierte Sitzung{if $items != 1}en{/if}]]></item>\r
+       </category>\r
+       <category name="wcf.acp.updateServer">\r
+               <item name="wcf.acp.updateServer.add"><![CDATA[Server hinzufügen]]></item>\r
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Der Server wurde erfolgreich angelegt.]]></item>\r
+               <item name="wcf.acp.updateServer.data"><![CDATA[Server-Daten]]></item>\r
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Server löschen]]></item>\r
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Der Server wurde erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Willst du den Server wirklich löschen?]]></item>\r
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Deaktivieren]]></item>\r
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Server bearbeiten]]></item>\r
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Ihre Änderungen wurden erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Aktivieren]]></item>\r
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Fehlermeldungen]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Gib ein Kennwort an, das zur Authentifizierung benötigt wird (optional).]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Gib einen Benutzernamen an, der zur Authentifizierung benötigt wird (optional).]]></item>\r
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Beim letzten Verbindungsversuch trat folgende Fehlermeldungen auf:]]></item>\r
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[Insgesamt {#$items} Server eingetragen]]></item>\r
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Server-ID]]></item>\r
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Pakete]]></item>\r
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adresse]]></item>\r
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Gib die Adresse (URL) zu einem Paketserver an.]]></item>\r
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[Die eingetragene Adresse ist ungültig.]]></item>\r
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Letzter Zugriff]]></item>\r
+               <item name="wcf.acp.updateServer.view"><![CDATA[Verfügbare Update-Server]]></item>\r
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Es sind keine Update-Server eingetragen.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.user">\r
+               <item name="wcf.acp.user.add"><![CDATA[Benutzer hinzufügen]]></item>\r
+               <item name="wcf.acp.user.add.data"><![CDATA[Benutzerdaten]]></item>\r
+               <item name="wcf.acp.user.add.success"><![CDATA[Der neue Benutzer wurde erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Benutzergruppe zuweisen]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Folgende Benutzer den unten ausgewählten Benutzergruppen zuweisen]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Die Zuweisung wurde erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Benutzergruppe zuweisen]]></item>\r
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[E-Mail-Adressen exportieren]]></item>\r
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[E-Mail senden]]></item>\r
+               <item name="wcf.acp.user.delete"><![CDATA[Benutzer löschen]]></item>\r
+               <item name="wcf.acp.user.delete.error"><![CDATA[Es konnte kein Benutzer gelöscht werden.]]></item>\r
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}Der Benutzer wurde{else}{#$deletedUsers} Benutzer wurden{/if} erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Willst du diesen Benutzer wirklich löschen?]]></item>\r
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Willst du die markierten Benutzer wirklich löschen?]]></item>\r
+               <item name="wcf.acp.user.edit"><![CDATA[Benutzer bearbeiten]]></item>\r
+               <item name="wcf.acp.user.edit.success"><![CDATA[Die Änderungen an diesem Benutzer wurden erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Du bearbeitest dein eigenes Benutzerkonto. Änderungen an den Mitgliedschaften in Benutzergruppen können womöglich dazu führen, dass du aus der Administrationsoberfläche ausgeschlossen wirst. Sei bitte entsprechend vorsichtig!]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[E-Mail-Adressen exportieren]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Exportformat]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Exporteinstellungen]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[E-Mail-Adressen von folgenden Benutzern exportieren]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Trennzeichen]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Texttrenner]]></item>\r
+               <item name="wcf.acp.user.groups"><![CDATA[Benutzergruppe(n)]]></item>\r
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Finde Benutzer, die in den ausgewählten Benutzergruppen nicht Mitglied sind.]]></item>\r
+               <item name="wcf.acp.user.list"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.user.list.all"><![CDATA[Alle Benutzer]]></item>\r
+               <item name="wcf.acp.user.list.count"><![CDATA[Insgesamt {#$items} Benutzer]]></item>\r
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "Einen Benutzer markiert" : this.count+" Benutzer markiert"]]></item>\r
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Massenverarbeitung von Benutzern]]></item>\r
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Aktion]]></item>\r
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Bedingungen]]></item>\r
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Die gewählte Aktion wurde erfolgreich auf {#$affectedUsers} Benutzer ausgeführt.]]></item>\r
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Die Massenverarbeitung von Benutzern führt die unten ausgewählte Aktion <b>ohne zusätzliche Sicherheitsabfrage</b> auf alle Benutzer aus, die unter die eingestellten Bedingungen fallen. Die Bearbeitungen können unter Umständen sehr rechenintensiv werden und sollten deshalb möglichst nur dann ausgeführt werden, wenn sich die Seite im Wartungsmodus befindet! Die Veränderungen können nicht rückgängig gemacht werden. Bitte benutze diese Funktion mit der nötigen Vorsicht!]]></item>\r
+               <item name="wcf.acp.user.search"><![CDATA[Benutzer suchen]]></item>\r
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Kriterien der Suche]]></item>\r
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profil]]></item>\r
+               <item name="wcf.acp.user.search.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Angezeigte Informationen]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Sonstiges]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profil]]></item>\r
+               <item name="wcf.acp.user.search.display.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Benutzer pro Seite]]></item>\r
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sortierung]]></item>\r
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Zu den angegebenen Kriterien wurde kein Benutzer gefunden.]]></item>\r
+               <item name="wcf.acp.user.search.matches"><![CDATA[{if $items == 1}Ein Ergebnis{else}{#$items} Ergebnisse{/if}]]></item>\r
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[In den Ergebnissen suchen]]></item>\r
+               <item name="wcf.acp.user.sendMail"><![CDATA[E-Mail an Benutzer senden]]></item>\r
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-Mail an alle Benutzer]]></item>\r
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[E-Mail als HTML verschicken]]></item>\r
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Absender]]></item>\r
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Hier kannst du die E-Mail-Adresse des Absenders definieren.{if MAIL_USE_FORMATTED_ADDRESS} Es ist auch folgendes Format möglich:{/if}</p>\r
+{if MAIL_USE_FORMATTED_ADDRESS}<p style="text-align: center; line-height: 2em;"><code>Absender Name &lt;email@absender.tld&gt;</code></p>{/if}\r
+<p>Wenn du unter System -> Optionen -> E-Mail alles ausgefüllt hast, wird dieses Feld automatisch ausgefüllt. Solltest du E-Mails per SMTP senden, so achte darauf, dass die E-Mail-Adresse des Absenders auch vom Server akzeptiert werden muss.</p>]]></item>\r
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[E-Mail an Gruppenmitglieder]]></item>\r
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[E-Mail an die Mitglieder folgender Benutzergruppen senden]]></item>\r
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-Mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[E-Mail an folgende Benutzer senden]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Betreff]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Gib hier die Betreffzeile der E-Mail an.]]></item>\r
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Nachricht]]></item>\r
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Trage hier die Nachricht ein, die du den Benutzern senden möchtest.]]></item>\r
+               <item name="wcf.acp.user.userNote"><![CDATA[Angemeldet als {$this->user->username}.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.worker">\r
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Aktueller Schritt]]></item>\r
+               <item name="wcf.acp.worker.description"><![CDATA[Lass dieses Browser-Fenster offen, bis der Prozess abgeschlossen ist und melde dich auf keinen Fall in einem anderen Browser-Fenster separat in der Administrationsoberfläche an, da dies den Prozess behindern könnte.]]></item>\r
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Vorgang erfolgreich abgeschlossen]]></item>\r
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Vorgang läuft ...]]></item>\r
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% fertiggestellt]]></item>\r
+               <item name="wcf.acp.worker.title"><![CDATA[Prozess läuft ...]]></item>\r
+       </category>\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Zurück]]></item>\r
+               <item name="wcf.global.button.close"><![CDATA[Schließen]]></item>\r
+               <item name="wcf.global.button.collapse"><![CDATA[Zuklappen]]></item>\r
+               <item name="wcf.global.button.collapsible"><![CDATA[Auf- und Zuklappen]]></item>\r
+               <item name="wcf.global.button.delete"><![CDATA[Löschen]]></item>\r
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Möchtest du das Element wirklich löschen?]]></item>\r
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Endgültig löschen]]></item>\r
+               <item name="wcf.global.button.edit"><![CDATA[Bearbeiten]]></item>\r
+               <item name="wcf.global.button.editor.jump"><![CDATA[Zum Editor wechseln]]></item>\r
+               <item name="wcf.global.button.expand"><![CDATA[Aufklappen]]></item>\r
+               <item name="wcf.global.button.mark"><![CDATA[Markieren]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Weiter &raquo;]]></item>\r
+               <item name="wcf.global.button.preview"><![CDATA[Vorschau]]></item>\r
+               <item name="wcf.global.button.reset"><![CDATA[Zurücksetzen]]></item>\r
+               <item name="wcf.global.button.submit"><![CDATA[Absenden]]></item>\r
+               <item name="wcf.global.button.unmark"><![CDATA[Demarkieren]]></item>\r
+               <item name="wcf.global.date.day"><![CDATA[Tag]]></item>\r
+               <item name="wcf.global.date.days"><![CDATA[Tage]]></item>\r
+               <item name="wcf.global.date.hour"><![CDATA[Stunde]]></item>\r
+               <item name="wcf.global.date.hours"><![CDATA[Stunden]]></item>\r
+               <item name="wcf.global.date.minute"><![CDATA[Minute]]></item>\r
+               <item name="wcf.global.date.minutes"><![CDATA[Minuten]]></item>\r
+               <item name="wcf.global.date.month"><![CDATA[Monat]]></item>\r
+               <item name="wcf.global.date.months"><![CDATA[Monate]]></item>\r
+               <item name="wcf.global.date.second"><![CDATA[Sekunde]]></item>\r
+               <item name="wcf.global.date.seconds"><![CDATA[Sekunden]]></item>\r
+               <item name="wcf.global.date.week"><![CDATA[Woche]]></item>\r
+               <item name="wcf.global.date.weeks"><![CDATA[Wochen]]></item>\r
+               <item name="wcf.global.date.year"><![CDATA[Jahr]]></item>\r
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Die Angabe des Jahres ist optional.]]></item>\r
+               <item name="wcf.global.date.years"><![CDATA[Jahre]]></item>\r
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>\r
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Heute</b>, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Gestern, %H:%M]]></item>\r
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>\r
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.defaultValue"><![CDATA[Standard]]></item>\r
+               <item name="wcf.global.error.backward"><![CDATA[Zurück zur vorherigen Seite]]></item>\r
+               <item name="wcf.global.error.empty"><![CDATA[Füll dieses Eingabefeld aus.]]></item>\r
+               <item name="wcf.global.error.file.notFound"><![CDATA[Die Datei konnte nicht gefunden werden.]]></item>\r
+               <item name="wcf.global.error.illegalLink"><![CDATA[Du hast einen ungültigen oder nicht mehr gültigen Link aufgerufen.]]></item>\r
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Der Zutritt zu dieser Seite ist dir leider verwehrt. Du besitzt nicht die notwendigen Zugriffsrechte, um diese Seite aufrufen zu können.]]></item>\r
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Zutritt verwehrt]]></item>\r
+               <item name="wcf.global.error.title"><![CDATA[Fehlermeldung]]></item>\r
+               <item name="wcf.global.form.error"><![CDATA[Deine Angaben sind ungültig. Überprüfe die markierten Eingabefelder.]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabisch]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnisch]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Tschechisch]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Dänisch]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Deutsch]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Deutsch (Anrede &raquo;Du&laquo;)]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Griechisch]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Englisch]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spanisch]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persisch]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finnisch]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Französisch]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebräisch]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Kroatisch]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungarisch]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italienisch]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Koreanisch]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Niederländisch]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norwegisch]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polnisch]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portugiesisch]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugiesisch (Brasilien)]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumänisch]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russisch]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slowakisch]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbisch]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Schwedisch]]></item>\r
+               <item name="wcf.global.language.th"><![CDATA[Thailändisch]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Türkisch]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinesisch (traditionell)]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[de_DE]]></item>\r
+               <item name="wcf.global.locale.win"><![CDATA[deu_deu]]></item>\r
+               <item name="wcf.global.multiSelect"><![CDATA[Mehrfache Markierungen sind durch zusätzliches Drücken der Taste &raquo;Strg/Ctrl&laquo; (Windows) oder &raquo;Befehl/Command&laquo; (Mac OS) möglich.]]></item>\r
+               <item name="wcf.global.page.input"><![CDATA[Zu folgender Seite springen]]></item>\r
+               <item name="wcf.global.page.next"><![CDATA[nächste Seite]]></item>\r
+               <item name="wcf.global.page.previous"><![CDATA[vorherige Seite]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>\r
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>\r
+               <item name="wcf.global.redirect.title"><![CDATA[Weiterleitung]]></item>\r
+               <item name="wcf.global.redirect.url"><![CDATA[Falls die automatische Weiterleitung nicht funktioniert, klick hier!]]></item>\r
+               <item name="wcf.global.scrollUp"><![CDATA[Zum Seitenanfang]]></item>\r
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Exakter Treffer]]></item>\r
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e. %B %Y, %H:%M]]></item>\r
+               <item name="wcf.global.skipToContent"><![CDATA[Zum Seiteninhalt springen]]></item>\r
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[in aufsteigender Reihenfolge]]></item>\r
+               <item name="wcf.global.sortOrder.descending"><![CDATA[in absteigender Reihenfolge]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>\r
+       </category>\r
+       <category name="wcf.imageViewer">\r
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Bild " + (this.currentIndex + 1) + " von " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>\r
+               <item name="wcf.imageViewer.close"><![CDATA[Schließen]]></item>\r
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Nur dieses Bild anzeigen (beendet die Bildbetrachtung)]]></item>\r
+               <item name="wcf.imageViewer.next"><![CDATA[Nächstes Bild]]></item>\r
+               <item name="wcf.imageViewer.pause"><![CDATA[Diashow stoppen]]></item>\r
+               <item name="wcf.imageViewer.play"><![CDATA[Diashow starten (Bildwechsel alle 5 Sekunden)]]></item>\r
+               <item name="wcf.imageViewer.previous"><![CDATA[Vorheriges Bild]]></item>\r
+       </category>\r
+       <category name="wcf.option">\r
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Kanarische Inseln, Lissabon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>\r
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brüssel, Kopenhagen, Madrid, Paris, Prag, Rom, Sarajevo, Stockholm, Tunis, Warschau, Wien]]></item>\r
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athen, Beirut, Bukarest, Helsinki, Istanbul, Jerusalem, Kairo, Kapstadt, Khartum, Kiew, Minsk, Sofia]]></item>\r
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Abeba, Antananarivo, Bagdad, Daressalam, Kampala, Kuwait, Mogadischu, Moskau, Nairobi, Riad]]></item>\r
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Teheran]]></item>\r
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Eriwan, Maskat, R&eacute;union, Tiflis]]></item>\r
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>\r
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Asgabat, Bischkek, Duschanbe, Islamabad, Jekaterinburg, Karatschi, Malediven, Taschkent]]></item>\r
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, Neu-Delhi]]></item>\r
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>\r
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Nowosibirsk]]></item>\r
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Kokosinseln, Rangun]]></item>\r
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnojarsk, Vientiane]]></item>\r
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hongkong, Irkutsk, Kuala Lumpur, Manila, Peking, Perth, Singapur, Taipeh, Ulan Bator]]></item>\r
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Australien)]]></item>\r
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Jakutsk, Osaka, Pjöngjang, Sapporo, Seoul, Tokyo]]></item>\r
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>\r
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Wladiwostok]]></item>\r
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord-Howe-Insel (Australien)]]></item>\r
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, Neukaledonien, Salomonen]]></item>\r
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolkinsel]]></item>\r
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, Bairiki, Fidschi, Kamtschatka, Marshall-Inseln, Wellington]]></item>\r
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham-Inseln (Neuseeland)]]></item>\r
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenixinseln]]></item>\r
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Linieninseln, Weihnachtsinsel]]></item>\r
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azoren, Kapverdische Inseln]]></item>\r
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mittelatlantik]]></item>\r
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Grönland, Montevideo]]></item>\r
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Neufundland]]></item>\r
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Asunci&oacute;n, Atlantik (Kanada), La Paz, Port-of-Spain, Santiago]]></item>\r
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>\r
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Atlanta, Bogot&aacute;, Detroit, Lima, Miami, New York, San Francisco de Quito, Toronto]]></item>\r
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Chicago, Dallas, Kansas City, Mexiko-Stadt, Winnipeg, Zentralamerika]]></item>\r
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Arizona, Calgary, Chihuahua, Denver, Mazatlan, Salt Lake City]]></item>\r
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Los Angeles, Seattle, Tijuana, Vancouver]]></item>\r
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>\r
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) Französisch-Polynesien]]></item>\r
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cookinseln, Hawaii]]></item>\r
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midwayinseln, Samoa]]></item>\r
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Eniwetok, Kwajalein]]></item>\r
+       </category>\r
+       <category name="wcf.page">\r
+               <item name="wcf.page.pageNo"><![CDATA[Seite {#$pageNo}]]></item>\r
+       </category>\r
+       <category name="wcf.user">\r
+               <item name="wcf.user.confirmEmail"><![CDATA[E-Mail-Adresse wiederholen]]></item>\r
+               <item name="wcf.user.confirmPassword"><![CDATA[Kennwort wiederholen]]></item>\r
+               <item name="wcf.user.email"><![CDATA[E-Mail-Adresse]]></item>\r
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Die eingegebenen E-Mail-Adressen sind nicht identisch.]]></item>\r
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Die eingegebenen Kennwörter sind nicht identisch.]]></item>\r
+               <item name="wcf.user.error.email.notUnique"><![CDATA[Diese E-Mail-Adresse ist bereits durch einen anderen Benutzer vergeben.]]></item>\r
+               <item name="wcf.user.error.email.notValid"><![CDATA[Du hast eine ungültige E-Mail-Adresse eingegeben.]]></item>\r
+               <item name="wcf.user.error.password.false"><![CDATA[Dieses Kennwort ist falsch.]]></item>\r
+               <item name="wcf.user.error.username.notFound"><![CDATA[Der Benutzername &raquo;{$username}&laquo; konnte nicht gefunden werden.]]></item>\r
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Dieser Benutzername ist bereits vergeben.]]></item>\r
+               <item name="wcf.user.error.username.notValid"><![CDATA[Du hast einen ungültigen Benutzernamen eingegeben.]]></item>\r
+               <item name="wcf.user.language"><![CDATA[Sprache]]></item>\r
+               <item name="wcf.user.language.description"><![CDATA[Wähle aus, in welcher Sprache die Benutzeroberfläche erscheinen soll!]]></item>\r
+               <item name="wcf.user.logout"><![CDATA[Abmelden]]></item>\r
+               <item name="wcf.user.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.user.registrationDate"><![CDATA[Registrierungsdatum]]></item>\r
+               <item name="wcf.user.userID"><![CDATA[Benutzer-ID]]></item>\r
+               <item name="wcf.user.username"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.user.visibleLanguages"><![CDATA[Zeige Inhalte in folgenden Sprachen an]]></item>\r
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Gib an, in welchen Sprachen erstellte Inhalte angezeigt werden sollen.]]></item>\r
+       </category>\r
+       <category name="wcf.user.option">\r
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Du hast einen ungültigen Inhalt eingegeben.]]></item>\r
+       </category>\r
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml
new file mode 100644 (file)
index 0000000..b2acdba
--- /dev/null
@@ -0,0 +1,1031 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="de">\r
+       <category name="wcf.acp">\r
+               <item name="wcf.acp"><![CDATA[Administrationsoberfläche]]></item>\r
+               <item name="wcf.acp.help"><![CDATA[Hilfe]]></item>\r
+               <item name="wcf.acp.help.complete"><![CDATA[Vollständige Hilfe]]></item>\r
+               <item name="wcf.acp.help.disable"><![CDATA[Hilfe deaktivieren]]></item>\r
+               <item name="wcf.acp.help.interactive"><![CDATA[Interaktive Hilfe]]></item>\r
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Paket wechseln]]></item>\r
+               <item name="wcf.acp.search.extended"><![CDATA[Erweiterte Suche ...]]></item>\r
+               <item name="wcf.acp.sitemap"><![CDATA[Sitemap]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cache">\r
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Cache leeren]]></item>\r
+               <item name="wcf.acp.cache.clear.success"><![CDATA[Der Cache wurde erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Wollen Sie den Cache wirklich komplett leeren?]]></item>\r
+               <item name="wcf.acp.cache.data"><![CDATA[Eigenschaften]]></item>\r
+               <item name="wcf.acp.cache.data.files"><![CDATA[Dateien]]></item>\r
+               <item name="wcf.acp.cache.data.size"><![CDATA[Größe]]></item>\r
+               <item name="wcf.acp.cache.data.source"><![CDATA[Quelle]]></item>\r
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Letzte Aktualisierung]]></item>\r
+               <item name="wcf.acp.cache.list.name"><![CDATA[Name]]></item>\r
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Zugriffsrechte]]></item>\r
+               <item name="wcf.acp.cache.list.size"><![CDATA[Größe]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cronjob">\r
+               <item name="wcf.acp.cronjob.active"><![CDATA[Aktiv]]></item>\r
+               <item name="wcf.acp.cronjob.add"><![CDATA[Zeitgesteuerte Aufgabe hinzufügen]]></item>\r
+               <item name="wcf.acp.cronjob.add.data"><![CDATA[Allgemeine Daten]]></item>\r
+               <item name="wcf.acp.cronjob.add.success"><![CDATA[Die zeitgesteuerte Aufgabe wurde hinzugefügt.]]></item>\r
+               <item name="wcf.acp.cronjob.add.timing"><![CDATA[Zeitsteuerung]]></item>\r
+               <item name="wcf.acp.cronjob.className"><![CDATA[Pfad zur Klasse]]></item>\r
+               <item name="wcf.acp.cronjob.className.description"><![CDATA[Geben Sie den Pfad zu der PHP-Datei an, die die entsprechende auszuführende Klasse enthält. Die Pfadangabe muss relativ zum Installationsverzeichnis der ausgewählten Endanwendung sein.]]></item>\r
+               <item name="wcf.acp.cronjob.cronjobID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.cronjob.delete"><![CDATA[Zeitgesteuerte Aufgabe löschen]]></item>\r
+               <item name="wcf.acp.cronjob.delete.disabled"><![CDATA[Die zeitgesteuerte Aufgabe kann nicht gelöscht werden.]]></item>\r
+               <item name="wcf.acp.cronjob.delete.success"><![CDATA[Die zeitgesteuerte Aufgabe wurde gelöscht.]]></item>\r
+               <item name="wcf.acp.cronjob.delete.sure"><![CDATA[Sind Sie sicher, dass Sie diese zeitgesteuerte Aufgabe löschen möchten?]]></item>\r
+               <item name="wcf.acp.cronjob.description"><![CDATA[Beschreibung]]></item>\r
+               <item name="wcf.acp.cronjob.description.description"><![CDATA[Hier können Sie eine kurze Beschreibung der Aufgabe eintragen.]]></item>\r
+               <item name="wcf.acp.cronjob.disable"><![CDATA[Deaktivieren]]></item>\r
+               <item name="wcf.acp.cronjob.edit"><![CDATA[Zeitgesteuerte Aufgabe bearbeiten]]></item>\r
+               <item name="wcf.acp.cronjob.edit.data"><![CDATA[Allgemeine Daten]]></item>\r
+               <item name="wcf.acp.cronjob.edit.disabled"><![CDATA[Die zeitgesteuerte Aufgabe kann nicht verändert werden.]]></item>\r
+               <item name="wcf.acp.cronjob.edit.success"><![CDATA[Die zeitgesteuerte Aufgabe wurde erfolgreich geändert.]]></item>\r
+               <item name="wcf.acp.cronjob.edit.timing"><![CDATA[Zeitsteuerung]]></item>\r
+               <item name="wcf.acp.cronjob.enable"><![CDATA[Aktivieren]]></item>\r
+               <item name="wcf.acp.cronjob.error.doesNotExist"><![CDATA[Der angegebene Pfad ist ungültig.]]></item>\r
+               <item name="wcf.acp.cronjob.error.empty"><![CDATA[Bitte füllen Sie dieses Eingabefeld aus.]]></item>\r
+               <item name="wcf.acp.cronjob.error.notValid"><![CDATA[Das Zeitformat ist ungültig.]]></item>\r
+               <item name="wcf.acp.cronjob.execMultiple"><![CDATA[Zeitgesteuerte Aufgabe mehrfach ausführen]]></item>\r
+               <item name="wcf.acp.cronjob.execMultiple.description"><![CDATA[Durch Aktivieren dieser Option wird die Aufgabe mehrfach ausgeführt, wenn zwischen dem letzten Ausführungszeitpunkt und dem aktuellen Zeitpunkt weitere Ausführungszeitpunkte liegen.]]></item>\r
+               <item name="wcf.acp.cronjob.execute"><![CDATA[Aufgabe jetzt ausführen]]></item>\r
+               <item name="wcf.acp.cronjob.execute.success"><![CDATA[Die Aufgabe wurde erfolgreich ausgeführt.]]></item>\r
+               <item name="wcf.acp.cronjob.inactive"><![CDATA[Inaktiv]]></item>\r
+               <item name="wcf.acp.cronjob.info"><![CDATA[Allgemeine Informationen]]></item>\r
+               <item name="wcf.acp.cronjob.intro"><![CDATA[Das Anlegen von zeitgesteuerten Aufgaben erfordert eine genaue Kenntnis der Crontab-Syntax auf unixähnlichen Systemen. Weiterführende Informationen dazu erhalten Sie auf dieser Website: <a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={"http://www.unixgeeks.org/security/newbie/unix/cron-1.html"|rawurlencode}" class="externalURL">Newbie: Intro to cron</a>]]></item>\r
+               <item name="wcf.acp.cronjob.lastExec"><![CDATA[Letzte Ausführung]]></item>\r
+               <item name="wcf.acp.cronjob.list"><![CDATA[Zeitgesteuerte Aufgaben]]></item>\r
+               <item name="wcf.acp.cronjob.list.count"><![CDATA[Insgesamt {#$items} zeitgesteuerte Aufgabe{if $items != 1}n{/if}]]></item>\r
+               <item name="wcf.acp.cronjob.log"><![CDATA[Protokoll der ausgeführten zeitgesteuerten Aufgaben]]></item>\r
+               <item name="wcf.acp.cronjob.log.clear"><![CDATA[Alle löschen]]></item>\r
+               <item name="wcf.acp.cronjob.log.clear.confirm"><![CDATA[Sind Sie sicher, dass Sie alle Protokoll-Einträge löschen möchten?]]></item>\r
+               <item name="wcf.acp.cronjob.log.data"><![CDATA[Insgesamt {#$items} {if $items == 1}Eintrag{else}Einträge{/if}]]></item>\r
+               <item name="wcf.acp.cronjob.log.error"><![CDATA[Fehler:]]></item>\r
+               <item name="wcf.acp.cronjob.log.execTime"><![CDATA[Ausgeführt]]></item>\r
+               <item name="wcf.acp.cronjob.log.noEntries"><![CDATA[Derzeit sind keine Einträge vorhanden.]]></item>\r
+               <item name="wcf.acp.cronjob.log.success"><![CDATA[OK]]></item>\r
+               <item name="wcf.acp.cronjob.nextExec"><![CDATA[Nächste Ausführung]]></item>\r
+               <item name="wcf.acp.cronjob.noneAvailable"><![CDATA[Derzeit ist keine zeitgesteuerte Aufgabe vorhanden.]]></item>\r
+               <item name="wcf.acp.cronjob.packageName"><![CDATA[Installiert von]]></item>\r
+               <item name="wcf.acp.cronjob.runNow"><![CDATA[Jetzt ausführen]]></item>\r
+               <item name="wcf.acp.cronjob.startDom"><![CDATA[Tag des Monats]]></item>\r
+               <item name="wcf.acp.cronjob.startDom.description"><![CDATA[An diesen Tagen des Monats (1 - 31) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startDomShort"><![CDATA[D]]></item>\r
+               <item name="wcf.acp.cronjob.startDow"><![CDATA[Tag der Woche]]></item>\r
+               <item name="wcf.acp.cronjob.startDow.description"><![CDATA[An diesen Tagen der Woche (0 - 6 mit Sonntag = 0 oder mon - sun) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startDowShort"><![CDATA[DoW]]></item>\r
+               <item name="wcf.acp.cronjob.startHour"><![CDATA[Stunde]]></item>\r
+               <item name="wcf.acp.cronjob.startHour.description"><![CDATA[Zu diesen Stunden (0 - 23) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startHourShort"><![CDATA[h]]></item>\r
+               <item name="wcf.acp.cronjob.startMinute"><![CDATA[Minute]]></item>\r
+               <item name="wcf.acp.cronjob.startMinute.description"><![CDATA[Zu diesen Minuten (0 - 59) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startMinuteShort"><![CDATA[m]]></item>\r
+               <item name="wcf.acp.cronjob.startMonth"><![CDATA[Monat]]></item>\r
+               <item name="wcf.acp.cronjob.startMonth.description"><![CDATA[In diesen Monaten (1 - 12 oder jan - dec) soll die Aufgabe ausgeführt werden.]]></item>\r
+               <item name="wcf.acp.cronjob.startMonthShort"><![CDATA[M]]></item>\r
+               <item name="wcf.acp.cronjob.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.cronjob.subtitle"><![CDATA[&raquo;Cronjobs&laquo;]]></item>\r
+       </category>\r
+       <category name="wcf.acp.group">\r
+               <item name="wcf.acp.group.add"><![CDATA[Benutzergruppe hinzufügen]]></item>\r
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Zugriffsrechte]]></item>\r
+               <item name="wcf.acp.group.add.success"><![CDATA[Die Benutzergruppe wurde erfolgreich angelegt.]]></item>\r
+               <item name="wcf.acp.group.administrators"><![CDATA[Administratoren]]></item>\r
+               <item name="wcf.acp.group.data"><![CDATA[Allgemeine Daten]]></item>\r
+               <item name="wcf.acp.group.delete"><![CDATA[Benutzergruppe löschen]]></item>\r
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Die Benutzergruppe wurde{else}{#$deletedGroups} Benutzergruppen wurden{/if} erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Wollen Sie diese Benutzergruppe wirklich löschen?]]></item>\r
+               <item name="wcf.acp.group.edit"><![CDATA[Benutzergruppe bearbeiten]]></item>\r
+               <item name="wcf.acp.group.edit.success"><![CDATA[Ihre Änderungen an der Benutzergruppe wurde erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Sie sind selbst Mitglied dieser Benutzergruppe. Änderungen an den Zugriffsrechten dieser Benutzergruppe können womöglich dazu führen, dass Sie aus der Administrationsoberfläche ausgeschlossen werden. Bitte seien Sie entsprechend vorsichtig!]]></item>\r
+               <item name="wcf.acp.group.everyone"><![CDATA[Jeder]]></item>\r
+               <item name="wcf.acp.group.groupID"><![CDATA[Gruppen-ID]]></item>\r
+               <item name="wcf.acp.group.groupName"><![CDATA[Name der Benutzergruppe]]></item>\r
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Geben Sie einen Namen für die Gruppe an.]]></item>\r
+               <item name="wcf.acp.group.guests"><![CDATA[Gäste]]></item>\r
+               <item name="wcf.acp.group.list"><![CDATA[Benutzergruppen]]></item>\r
+               <item name="wcf.acp.group.list.data"><![CDATA[Insgesamt {#$items} Benutzergruppen]]></item>\r
+               <item name="wcf.acp.group.members"><![CDATA[Anzahl Mitglieder]]></item>\r
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatoren]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Kann Administrationsoberfläche betreten]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Mitglieder dieser Benutzergruppe können die Administrationsoberfläche betreten und dort abhängig von den weiteren Zugriffsrechten verschiedene Aktionen durchführen. Diese Option muss aktiviert sein, wenn diesen Benutzern andere administrative Funktionen erlaubt werden sollen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Kann versteckte Profilinformationen sehen]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Mitglieder dieser Benutzergruppe können die versteckten Informationen in Benutzerprofilen sehen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Kann allgemeine Einstellungen vornehmen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Mitglieder dieser Benutzergruppe können die allgemeinen System-Einstellungen sehen und bearbeiten. Z.B. Forum ein-/ausschalten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Kann Protokolle abrufen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Mitglieder dieser Benutzergruppe können die System-Protokolle abrufen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canAddCronjob"><![CDATA[Kann neue zeitgesteuerte Aufgaben anlegen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canAddCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können neue zeitgesteuerte Aufgaben anlegen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjob"><![CDATA[Kann zeitgesteuerte Aufgaben löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene zeitgesteuerte Aufgaben löschen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjobsLog"><![CDATA[Kann Protokoll der zeitgesteuerten Aufgaben löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjobsLog.description"><![CDATA[Mitglieder dieser Benutzergruppe können das Protokoll der zeitgesteuerten Aufgaben löschen. Bei der Ausführung einer zeitgesteuerten Aufgabe wird festgehalten, ob dieser erfolgreich ausgeführt wurde.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEditCronjob"><![CDATA[Kann zeitgesteuerte Aufgaben ändern]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEditCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene zeitgesteuerte Aufgaben bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEnableDisableCronjob"><![CDATA[Kann zeitgesteuerte Aufgaben deaktivieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEnableDisableCronjob.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene zeitgesteuerte Aufgaben deaktivieren. Diese werden dann nicht mehr ausgeführt, können später jedoch auch wieder aktiviert werden.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Kann Update-Server bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Update-Server bearbeiten und neue hinzufügen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Kann Pakete installieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Mitglieder dieser Benutzergruppe können zusätzliche Pakete installieren.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Kann Pakete deinstallieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Pakete entfernen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Kann Pakete aktualisieren]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Pakete aktualisieren.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Zugängliche Benutzergruppen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Mitglieder dieser Benutzergruppe haben auf diese Gruppen Zugriff. Zusätzlich muss angegeben werden, ob z.B. die Benutzergruppe bearbeitet werden darf.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Kann neue Benutzergruppen erstellen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Mitglieder dieser Benutzergruppe können neue Benutzergruppen erstellen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Kann neue Benutzer erstellen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können neue Benutzer erstellen. Ist bei "Zugängliche Benutzergruppen" eine Option aktiviert, kann diese Gruppe beim Erstellen des Benutzers zugewiesen werden.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Kann Benutzergruppen löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzergruppen löschen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Kann Benutzer löschen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzer löschen.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Kann Benutzergruppen bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzergruppen bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Kann E-Mail-Adressen bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Mitglieder dieser Benutzergruppe können die E-Mail-Adresse von anderen Benutzern bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Kann Kennwörter bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Mitglieder dieser Benutzergruppe können das Kennwort von anderen Benutzern bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Kann Benutzer bearbeiten]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzer bearbeiten.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Kann E-Mails an Benutzer senden]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können die E-Mail-Adresse von anderen Benutzern sehen und ihnen E-Mails senden.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Kann Benutzer suchen]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Mitglieder dieser Benutzergruppe können vorhandene Benutzer und deren Profile durchsuchen.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Administrative Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Inhalte]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Allgemeine administrative Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Wartung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[System-Funktionen]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.cronjobs"><![CDATA[Zeitgesteuerte Aufgaben]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.cronjobs.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Paketverwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Benutzer-Funktionen]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Gruppenverwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Benutzerverwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderative Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Allgemeine Rechte]]></item>\r
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Sie haben einen ungültigen Inhalt eingegeben.]]></item>\r
+               <item name="wcf.acp.group.option.admin.style.canUseDisabledStyle"><![CDATA[Kann deaktivierte Stile benutzen]]></item>\r
+               <item name="wcf.acp.group.option.admin.style.canUseDisabledStyle.description"><![CDATA[Mitglieder dieser Benutzergruppe können deaktivierte Stile auswählen.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.style"><![CDATA[Stil-Verwaltung]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.style.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.showMembers"><![CDATA[Zeige die Mitglieder dieser Benutzergruppe]]></item>\r
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super Moderatoren]]></item>\r
+               <item name="wcf.acp.group.users"><![CDATA[Registrierte Benutzer]]></item>\r
+       </category>\r
+       <category name="wcf.acp.login">\r
+               <item name="wcf.acp.login"><![CDATA[Anmeldung]]></item>\r
+               <item name="wcf.acp.login.data"><![CDATA[Zugangsdaten]]></item>\r
+       </category>\r
+       <category name="wcf.acp.masterPassword">\r
+               <item name="wcf.acp.masterPassword"><![CDATA[Hauptkennwort]]></item>\r
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Hauptkennwort wiederholen]]></item>\r
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Hauptkennwort erforderlich]]></item>\r
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Die aufgerufene Seite oder Aktion erfordert aus Sicherheitsgründen die Eingabe des Hauptkennwortes. Pro Sitzung ist die Eingabe des Hauptkennwortes nur einmal erforderlich. Falls Sie das Hauptkennwort vergessen haben sollten, können Sie es zurücksetzen, indem Sie die Datei <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em> löschen.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[Das Hauptkennwort ist nicht korrekt. Falls Sie das Hauptkennwort vergessen haben sollten, können Sie es zurücksetzen, indem Sie die Datei <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em> löschen.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[Die eingegebenen Kennwörter sind nicht identisch.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[Das Kennwort wurde als unsicher erkannt. Das Kennwort sollte mindestens acht Zeichen lang sein, große und kleine lateinische Buchstaben, Zahlen und Sonderzeichen enthalten. Es darf nicht mit den Kennwörtern von anderen Administratoren übereinstimmen.]]></item>\r
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Vorschlag]]></item>\r
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Vorschlag übernehmen]]></item>\r
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Hauptkennwort festlegen]]></item>\r
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[Das Hauptkennwort ist ein zusätzlicher Schutz für sicherheitskritische Funktionen. Sie sollten hier ein möglichst sicheres Kennwort verwenden, dass sich von Ihrem normalen Administrator-Kennwort unterscheidet, Dritten nicht bekannt ist und auch nicht auf anderen Internetseiten verwendet wird.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.menu">\r
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Automatisches Update]]></item>\r
+               <item name="wcf.acp.menu.link.content"><![CDATA[Inhalte]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.add"><![CDATA[Zeitgesteuerte Aufgabe hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.showLog"><![CDATA[Zeitgesteuerte Aufgaben]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.view"><![CDATA[Zeitgesteuerte Aufgaben auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.menu.link.group"><![CDATA[Benutzergruppen]]></item>\r
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Benutzergruppe hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[E-Mail an Gruppenmitglieder]]></item>\r
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Benutzergruppen auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.log"><![CDATA[Protokoll]]></item>\r
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Sitzungen]]></item>\r
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Wartung]]></item>\r
+               <item name="wcf.acp.menu.link.option"><![CDATA[Optionen]]></item>\r
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Sichern &amp; Wiederherstellen]]></item>\r
+               <item name="wcf.acp.menu.link.package"><![CDATA[Paketverwaltung]]></item>\r
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Pakete suchen]]></item>\r
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Paket installieren]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Server hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Server auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Pakete auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.menu.link.user"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Benutzer hinzufügen]]></item>\r
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Benutzer auflisten]]></item>\r
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-Mail an alle Benutzer]]></item>\r
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Massenverarbeitung von Benutzern]]></item>\r
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Benutzer suchen]]></item>\r
+       </category>\r
+       <category name="wcf.acp.option">\r
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Hostname ausschließen]]></item>\r
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Geben Sie pro Zeile einen Hostname an, die Sie von der Seite ausschließen möchten.]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[IP-Adresse ausschließen]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Geben Sie pro Zeile eine IP-Adresse an, die Sie von der Seite ausschließen möchten.]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Browser-Kennung ausschließen]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Geben Sie pro Zeile eine Browser-Kennung (User-Agent) an, die Sie von der Seite ausschließen möchten.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache-Server]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Geben Sie hier die Adresse des Memcache-Servers ein! Mehrere Server können zeilenweise angegeben werden.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Persistente Verbindungen aktivieren]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Sollen beim Verbinden mit dem Memcache-Server persistente Verbindungen genutzt werden?]]></item>\r
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache-Methode]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Bitte wählen Sie die gewünschte Cache-Methode aus! Beachten Sie, dass einige Methoden spezielle Anforderungen an das Server-System stellen und nicht auf jedem Server zur Verfügung stehen.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[Dateisystem (Standard)]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (Experimentell)]]></item>\r
+               <item name="wcf.acp.option.category.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache speichert häufig benötige Daten im Arbeitsspeicher zwischen. Dies kann die Last auf die Datenbank und das Dateisystem drastisch reduzieren. Lesen Sie mehr über dieses Thema auf der folgenden Seite:\r
+<ul>\r
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>\r
+</ul>]]></item>\r
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Datum &amp; Zeit]]></item>\r
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy-Server]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Hier können Sie optional Proxy-Server für Verbindungen zu externen Servern konfigurieren.]]></item>\r
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-Mails]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Versand]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Wartungsmodus]]></item>\r
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module"><![CDATA[Module an / aus]]></item>\r
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Inhalte]]></item>\r
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security"><![CDATA[Sicherheit]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internetseiten werden häufig durch andere Programme angegriffen. So gibt es beispielsweise die Möglichkeit, automatisiert hunderte von Benutzerkonten zu erstellen. Um sich davor zu schützen, können Sie an verschiedenen Stellen ein sogenanntes <a href="http://de.wikipedia.org/wiki/Captcha" class="externalURL">Captcha-Bild</a> anzeigen lassen. Unregistrierte Benutzer müssen erst den Code eingeben, der auf diesem Bild steht. Roboter können diesen Code nicht lesen. Beachten Sie, dass Captcha-Bilder von blinden und sehbehinderten Benutzern nicht identifiziert werden können.]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Blacklist]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Zensur]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sitzungen]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.user"><![CDATA[Mitglieder]]></item>\r
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookiedomain]]></item>\r
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Hier können Sie optional eine Domain angeben, unter der der Cookie laufen soll. Standardmäßig sollten Sie dieses Feld frei lassen, da ein Ausfüllen nur in wenigen Fällen notwendig ist.]]></item>\r
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookiepfad]]></item>\r
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Der Cookiepfad wird absolut zum Document Root angegeben - also z.B. "/forum" für http://www.woltlab.de/forum.]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Präfix für Cookienamen]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Geben Sie einen Präfix an, der bei Cookienamen verwendet wird.]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Uhr automatisch auf Sommer-/Winterzeit umstellen]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Soll die Uhr automatisch auf Sommer-/Winterzeit umgestellt werden?]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Cache-Methode für Sitzungsdaten verwenden]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Soll für die Speicherung der Sitzungsdaten die ausgewählte Cache-Methode verwendet werden?]]></item>\r
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Sie haben einen ungültigen Inhalt eingegeben.]]></item>\r
+               <item name="wcf.acp.option.export"><![CDATA[Optionen sichern]]></item>\r
+               <item name="wcf.acp.option.export.download"><![CDATA[Sicherung der Optionen herunterladen]]></item>\r
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Laden Sie eine Sicherung der Optionen auf Ihren lokalen Rechner herunter.]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Gzip-Komprimierung aktivieren]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Durch Aktivierung dieser Option werden die Inhalte komprimiert vom Server an den Client gesendet. Dies reduziert den Traffic.]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Seitencaching im Client-Browser verhindern]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Durch Aktivierung dieser Option können Sie das Caching der Seite im Browser verhindern.]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Gzip-Komprimierungslevel]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Werte von 1-9 sind zulässig. Als Optimum zwischen Komprimierung und Serverlast empfiehlt sich Level 1.]]></item>\r
+               <item name="wcf.acp.option.import"><![CDATA[Optionen wiederherstellen]]></item>\r
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[Die Optionen konnten nicht erfolgreich importiert werden.]]></item>\r
+               <item name="wcf.acp.option.import.success"><![CDATA[Die Optionen wurden erfolgreich importiert.]]></item>\r
+               <item name="wcf.acp.option.import.upload"><![CDATA[Sicherung der Optionen vom lokalen Computer hochladen]]></item>\r
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Geben Sie eine Sicherung der Optionen von Ihrem lokalen Rechner an.]]></item>\r
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Optionen sichern &amp; wiederherstellen]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Administrator-Adresse]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Geben Sie die E-Mail-Adresse des Administrators an.]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Logfile-Pfad]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Geben Sie den Pfad zum Logfile an.]]></item>\r
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Absender-Adresse]]></item>\r
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Geben Sie die Absender-Adresse bei automatisch generierten E-Mails an.]]></item>\r
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Absender-Name]]></item>\r
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Geben Sie den Namen des Absenders bei automatisch generierten E-Mails an.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[Versandmethode]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Wählen Sie eine Versandmethode aus.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>\r
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Signatur]]></item>\r
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Tragen Sie hier eine Signatur ein, die bei System-E-Mails angezeigt werden soll.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP-Server]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Tragen Sie hier den SMTP-Server ein.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP-Kennwort]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Geben Sie das SMTP-Kennwort an.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP-Port]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Geben Sie den SMTP-Port an.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP-Benutzer]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Geben Sie den SMTP-Benutzer an.]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[&raquo;-f&laquo; Parameter verwenden]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Manche Server benötigen den &raquo;-f&laquo; Parameter beim Versenden von E-Mails. Falls Sie Probleme mit dem Versand von E-Mails haben, aktivieren Sie diese Einstellung.]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Formatierte E-Mail-Adressen verwenden]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Absender- und Empfänger-Adressen werden in folgendes Format gebracht: &quot;Name &lt;email@domain.tld&gt;&quot;. Diese Funktion wird nicht von allen Mailservern unterstützt und sollte daher bei Problemen abgeschaltet werden.]]></item>\r
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Hauptkennwort aktivieren]]></item>\r
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Aktiviert die zusätzliche Eingabe eines Kennworts beim Aufruf von sicherheitskritischen Bereichen.]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server für HTTP-Verbindungen]]></item>\r
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Gültigkeitslänge einer Sitzung]]></item>\r
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Geben Sie an, wie lange die Sitzung gültig ist [Sekunden]. ]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[IP-Adresse der Sitzung überprüfen]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Anzahl der Blöcke der IP-Adresse die beim Auslesen der Sitzung überprüft werden sollen. Eine hohe Einstellung kann Benutzer ausschließen, die mit wechselnden IP-Adressen im Internet unterwegs sind.]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Browser-Kennung der Sitzung überprüfen]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Soll die Browser-Kennung beim Auslesen der Sitzung überprüft werden?]]></item>\r
+               <item name="wcf.acp.option.success"><![CDATA[Ihre Einstellungsänderungen wurden erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.option.timezone"><![CDATA[Zeitzone]]></item>\r
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Wählen Sie die Standard Zeitzone Ihrer Seite.]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Timeout für Benutzer-Online]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Geben Sie an, wie lange der Benutzer trotz Inaktivität als online markiert werden soll [Sekunden].]]></item>\r
+               <item name="wcf.acp.option.category.general.page"><![CDATA[Seite]]></item>\r
+               <item name="wcf.acp.option.category.general.page.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.meta_description"><![CDATA[Meta Description]]></item>\r
+               <item name="wcf.acp.option.meta_description.description"><![CDATA[Geben Sie eine Meta Description an.]]></item>\r
+               <item name="wcf.acp.option.meta_keywords"><![CDATA[Meta Keywords]]></item>\r
+               <item name="wcf.acp.option.meta_keywords.description"><![CDATA[Tragen Sie die Wörter ein, die im Meta-Tag Keywords stehen sollen.]]></item>\r
+               <item name="wcf.acp.option.page_description"><![CDATA[Seitenbeschreibung]]></item>\r
+               <item name="wcf.acp.option.page_description.description"><![CDATA[Fügen Sie hier eine kurze Beschreibung Ihrer Seite ein.]]></item>\r
+               <item name="wcf.acp.option.page_title"><![CDATA[Titel der Seite]]></item>\r
+               <item name="wcf.acp.option.page_title.description"><![CDATA[Geben Sie hier den Globalen Titel der Seite an. Dieser Titel wird im Seitenkopf dargestellt, wenn Sie die Anzeige dieses Textes im Stileditor aktiviert haben.]]></item>\r
+               <item name="wcf.acp.option.page_url"><![CDATA[Adresse (URL) der Seite]]></item>\r
+               <item name="wcf.acp.option.page_url.description"><![CDATA[Geben Sie an, unter welcher Adresse (URL) die Seite aufzurufen ist (ohne abschließenden Slash).]]></item>\r
+               <item name="wcf.acp.option.page_urls"><![CDATA[Weitere URLs]]></item>\r
+               <item name="wcf.acp.option.page_urls.description"><![CDATA[Geben Sie hier weitere URLs an, unter denen Ihre Seite erreichbar ist.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.package">\r
+               <item name="wcf.acp.package.cancel"><![CDATA[Abbruch der Paketinstallation]]></item>\r
+               <item name="wcf.acp.package.description"><![CDATA[Beschreibung]]></item>\r
+               <item name="wcf.acp.package.install"><![CDATA[Paketinstallation]]></item>\r
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Installation abbrechen]]></item>\r
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Wollen Sie die Installation wirklich abbrechen?]]></item>\r
+               <item name="wcf.acp.package.install.error"><![CDATA[Die Abhängigkeiten dieses Paketes konnten nicht aufgelöst werden.]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[Die {if $action == 'install'}Paketinstallation{else}Paketaktualisierung{/if} von Paket &raquo;{$packageName}&laquo; in Version {$packageVersion} kann aufgrund von Inkompatibilitäten zu {if $excludedPackages|count == 1}folgendem Paket{else}folgenden Paketen{/if} nicht durchgeführt werden:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} in Version {$excludedPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Folgendes Paket lässt{else}Folgende Pakete lassen{/if} die {if $action == 'install'}Paketinstallation{else}Paketaktualisierung{/if} von Paket &raquo;{$packageName}&laquo; in Version {$packageVersion} aufgrund von Inkompatibilitäten nicht zu:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} in Version {$excludingPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Folgendes Paket ist{else}Folgende Pakete sind{/if} mit dem Paket &raquo;{$packageName}&laquo; in Version {$packageVersion} nicht kompatibel. Wenn Sie die Installation fortführen, {if $excludingPackages|count == 1}wird das Paket{else}werden die Pakete{/if} vermutlich nicht mehr korrekt funktionieren.]]></item>\r
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}ist bereits installiert{else}{if $package.file|isset}liegt dem Paket bei{else}fehlt{/if}{/if})</span>]]></item>\r
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Wollen Sie die Paketinstallation wirklich abbrechen?]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Folgende Pakete können mit diesem Paket aktualisiert werden]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Wählen Sie eines der folgenden Pakete aus, um seine Version zu aktualisieren. Falls Sie das Paket neu installieren möchten, klicken Sie unten auf &raquo;Weiter&laquo;.]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Es ist bereits eine Kopie dieses Paketes installiert. Wenn Sie fortfahren, wird eine weitere Kopie dieses Paketes installiert. Falls Sie eine vorhandene Kopie dieses Paketes aktualisieren möchten, wählen Sie die Kopie aus der folgenden Liste aus.]]></item>\r
+               <item name="wcf.acp.package.install.version"><![CDATA[Version des Paketes:]]></item>\r
+               <item name="wcf.acp.package.installDate"><![CDATA[Installationsdatum]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Beim Versuch die Dateien des Paketes zu entpacken, ist folgender Fehler aufgetreten:]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[Folgende Dateien konnten nicht erfolgreich entpackt werden. Bitte überprüfen Sie, ob der entsprechende Zielort beschreibbar ist.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Tabellen Konflikt]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Keine Tabellen überschreiben und während der gesamten Installation nicht mehr nachfragen.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Alle Tabellen überschreiben und während der gesamten Installation nicht mehr nachfragen.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Notwendige Änderungen]]></item>\r
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Betroffene Tabelle]]></item>\r
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Vorhandene Tabellen Ihrer Datenbank stehen im Konflikt mit Tabellen, die für dieses Paket installiert werden müssen. Bitte wählen Sie aus, ob diese Tabellen überschrieben werden sollen.]]></item>\r
+               <item name="wcf.acp.package.list"><![CDATA[Installierte Pakete]]></item>\r
+               <item name="wcf.acp.package.list.author"><![CDATA[Hersteller]]></item>\r
+               <item name="wcf.acp.package.list.count"><![CDATA[Insgesamt sind {#$items} Pakete installiert.]]></item>\r
+               <item name="wcf.acp.package.list.date"><![CDATA[Herstellungsdatum]]></item>\r
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.package.list.name"><![CDATA[Name]]></item>\r
+               <item name="wcf.acp.package.list.other"><![CDATA[Sonstiges Paket]]></item>\r
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Zusatzmodul]]></item>\r
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Endanwendung]]></item>\r
+               <item name="wcf.acp.package.list.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.package.optionals"><![CDATA[Optionale Zusatzpakete installieren]]></item>\r
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Das aktuelle Paket bringt folgende optionale Zusatzpakete mit. Bitte wählen Sie aus, welche Zusatzpakete Sie installieren möchten.]]></item>\r
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Dieses Paket ist bereits installiert.)]]></item>\r
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Die Voraussetzungen für dieses Paket werden nicht erfüllt.)]]></item>\r
+               <item name="wcf.acp.package.packageDir"><![CDATA[Installationsverzeichnis]]></item>\r
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Es ist bereits eine andere Anwendung in dem angegebenen Verzeichnis installiert.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[Das eingegebene Verzeichnis ist ungültig.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Das angegebene Verzeichnis ist nicht beschreibbar.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Das angegebene Verzeichnis wird bereits von WoltLab Community Framework beansprucht. Bitte wählen Sie ein anderes Verzeichnis.]]></item>\r
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Bitte geben Sie hier das Installationsverzeichnis an.]]></item>\r
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Nach der Installation in das angegebene Installationsverzeichnis ist die Anwendung über folgende Adresse (URL) erreichbar:]]></item>\r
+               <item name="wcf.acp.package.requirements"><![CDATA[Abhängigkeiten auswählen]]></item>\r
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Das aktuelle Paket benötigt Pakete, von denen mehrere Instanzen installiert sind. Bitte wählen Sie aus, zu welcher Instanz jeweils eine Abhängigkeit hergestellt werden soll.]]></item>\r
+               <item name="wcf.acp.package.rollback"><![CDATA[Paketinstallation zurücksetzen]]></item>\r
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Version {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>\r
+               <item name="wcf.acp.package.startInstall"><![CDATA[Neues Paket installieren]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Das angegebene Paket lässt keine Neuinstallation zu.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[Das angegebene Archiv ist kein gültiges Paket.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Paket &raquo;{$package->getName()}&laquo; kann mit dem angegebenen Archiv nicht aktualisiert werden.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Es konnte keine Datei unter dem angegebenen Pfad gefunden wurden.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Dieses Paket ist bereits installiert. Das Paket kann nicht mehrfach installiert werden.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[Das Hochladen der ausgewählten Datei ist fehlgeschlagen.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Quelle auswählen]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Direkten Pfad zum Paket angeben]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Geben Sie den direkten Pfad zur Paketdatei an. Dabei kann es sich um die Internet Adresse der Paketdatei oder alternativ den Pfad zur Paketdatei im Dateisystem handeln.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Paket vom lokalen Computer hochladen]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Geben Sie eine Paketdatei von Ihrem lokalen Rechner an.]]></item>\r
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Paket &raquo;{$package->getName()}&laquo; aktualisieren]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Menüpunkte der Administrationsoberfläche werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Templates der Administrationsoberfläche werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.CronjobsPackageInstallationPlugin"><![CDATA[Zeitgesteuerte Aufgaben werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Dateien werden entpackt ...]]></item>\r
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Benutzergruppeneinstellungen werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Sprache wird installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Optionen werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Spezielles Skript wird ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Datenbank wird installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Templates werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Benutzerprofilfelder werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Mögliche Konflikte werden überprüft ...]]></item>\r
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Installation abgeschlossen]]></item>\r
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Optionale Pakete werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Paket wird registriert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden installiert ...]]></item>\r
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Zuordnung zum übergeordneten Paket wird vorgenommen ...]]></item>\r
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Abhängigkeiten werden aufgelöst ...]]></item>\r
+               <item name="wcf.acp.package.step.title"><![CDATA[Paket <b>{$packageName|encodeJS}</b>: ]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Menüpunkte der Administrationsoberfläche werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Templates der Administrationsoberfläche werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.CronjobsPackageInstallationPlugin"><![CDATA[Zeitgesteuerte Aufgaben werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Dateien werden gelöscht ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Benutzergruppeneinstellungen werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Sprache wird deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Optionen werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Datenbank wird deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Templates werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Benutzerprofilfelder werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Deinstallation abgeschlossen]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Optionale Pakete werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden deinstalliert ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Abhängigkeiten werden aufgelöst ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Menüpunkte der Administrationsoberfläche werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Templates der Administrationsoberfläche werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.CronjobsPackageInstallationPlugin"><![CDATA[Zeitgesteuerte Aufgaben werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Dateien werden entpackt ...]]></item>\r
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Benutzergruppeneinstellungen werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Sprache wird aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Optionen werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Spezielles Skript wird ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Datenbank wird aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Templates werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Benutzerprofilfelder werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden ausgeführt ...]]></item>\r
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Mögliche Konflikte werden überprüft ...]]></item>\r
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Paketaktualisierung abgeschlossen]]></item>\r
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Optionale Pakete werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Paket wird aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Paket-Installations-Zusatzmodule werden aktualisiert ...]]></item>\r
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Zuordnung zum übergeordneten Paket wird vorgenommen ...]]></item>\r
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Abhängigkeiten werden aufgelöst ...]]></item>\r
+               <item name="wcf.acp.package.uninstall"><![CDATA[Paketdeinstallation]]></item>\r
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Abbruch der Paketdeinstallation]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Die Deinstallation des Paketes ist nicht möglich, da mindestens ein abhängiges Paket nicht deinstalliert werden kann.]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Diese{if $dependentPackages|count == 1}s Paket wird{else} Pakete werden{/if}, nach Ihrer Bestätigung, ohne weitere Sicherheitsabfrage deinstalliert.]]></item>\r
+               <item name="wcf.acp.package.update"><![CDATA[Paketaktualisierung]]></item>\r
+               <item name="wcf.acp.package.updateDate"><![CDATA[Aktualisierungsdatum]]></item>\r
+               <item name="wcf.acp.package.view.author"><![CDATA[Hersteller:]]></item>\r
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Zur Administrationsoberfläche wechseln]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Paket deinstallieren]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Alle Pakete deinstallieren]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Wollen Sie dieses Paket wirklich deinstallieren?]]></item>\r
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Paket aktualisieren]]></item>\r
+               <item name="wcf.acp.package.view.date"><![CDATA[Herstellungsdatum:]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Abhängige Pakete]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Dieses Paket wird von {#$dependentPackages|count} {if $dependentPackages|count == 1}anderen Paket{else}anderen Paketen{/if} benötigt.]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Dieses Paket wird von 1 anderen Paket benötigt{else}{#$dependentPackages|count} Pakete sind direkt oder indirekt von diesem Paket abhängig{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.dir"><![CDATA[Installationsverzeichnis:]]></item>\r
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Bezeichner:]]></item>\r
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Installierte Instanz:]]></item>\r
+               <item name="wcf.acp.package.view.parent"><![CDATA[Übergeordnetes Paket:]]></item>\r
+               <item name="wcf.acp.package.view.properties"><![CDATA[Eigenschaften]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Benötigte Pakete]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Dieses Paket benötigt {#$requiredPackages|count} {if $requiredPackages|count == 1}anderes Paket{else}andere Pakete{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.url"><![CDATA[Homepage:]]></item>\r
+               <item name="wcf.acp.package.view.version"><![CDATA[Installierte Version:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.packageUpdate">\r
+               <item name="wcf.acp.packageUpdate"><![CDATA[Pakete aktualisieren]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Authentifizierung mit Update-Server]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Verbindungs-Daten]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Benutzername und Kennwort wurden nicht akzeptiert.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Geben Sie ein Kennwort an, das zur Authentifizierung benötigt wird.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Geben Sie einen Benutzernamen an, der zur Authentifizierung benötigt wird.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Benutzeranmeldung]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Server-Meldung]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Server-Name]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Benutzerdaten dauerhaft speichern]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Speichert die eingegebenen Benutzerdaten dauerhaft, sodass Sie die Daten zu einem späteren Zeitpunkt nicht erneut eingeben müssen.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adresse]]></item>\r
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Installierte Version]]></item>\r
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Es ist folgender Fehler aufgetreten: ]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Das Herunterladen des Paketes {$package} ist fehlgeschlagen.]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[Beim Versuch die Paketliste herunterzuladen, ist ein Fehler aufgetreten.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[Es {if $excludedPackages|count == 1}ist folgender Konflikt{else}sind folgende Konflikte{/if} aufgetreten:]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Das installierte Paket &raquo;{$excludedPackage.existingPackageName}&laquo; ist mit dem Paket &raquo;{$excludedPackage.packageName}&laquo; in Version {$excludedPackage.packageVersion} nicht kompatibel.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[Das Paket &raquo;{$excludedPackage.packageName}&laquo; in Version {$excludedPackage.packageVersion} ist mit dem installierten Paket &raquo;{$excludedPackage.existingPackageName}&laquo; nicht kompatibel.]]></item>\r
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} wird installiert]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Derzeit sind keine Updates verfügbar.]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Sie haben kein Update ausgewählt.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Optionen]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Paket ist bereits installiert und kann kein weiteres Mal installiert werden.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Paket installieren]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Weitere Paket-Instanz installieren (Paket ist bereits {#$package.instances} mal installiert)]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Installiertes Paket {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} Version {$updatableInstance.packageVersion} aktualisieren]]></item>\r
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Pakete suchen]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Autor]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Suche nach ...]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Bereits installierte einzigartige Pakete ausblenden]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Paketname]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Paketname und -beschreibung durchsuchen]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Update-Server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Alle Update-Server durchsuchen]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Art des Paketes]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Sonstige Pakete]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Zusatzmodul für bereits installierte Pakete]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Endanwendung]]></item>\r
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Alle Pakete auswählen]]></item>\r
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} wird aktualisiert auf {$package.toVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Neue Version]]></item>\r
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Folgende Paket-Aktualisierungen/-Installationen werden durchgeführt:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.sessionLog">\r
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Aktionen der protokollierten Sitzung von &raquo;{$sessionLog->username}&laquo;]]></item>\r
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Insgesamt {#$items} protokollierte Aktion{if $items != 1}en{/if}]]></item>\r
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Aktionen]]></item>\r
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Klasse]]></item>\r
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP-Adresse]]></item>\r
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Letzte Aktion]]></item>\r
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Paket]]></item>\r
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Methode]]></item>\r
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Datum]]></item>\r
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[Browser-Kennung]]></item>\r
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Protokollierte Sitzungen]]></item>\r
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Insgesamt {#$items} protokollierte Sitzung{if $items != 1}en{/if}]]></item>\r
+       </category>\r
+       <category name="wcf.acp.updateServer">\r
+               <item name="wcf.acp.updateServer.add"><![CDATA[Server hinzufügen]]></item>\r
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Der Server wurde erfolgreich angelegt.]]></item>\r
+               <item name="wcf.acp.updateServer.data"><![CDATA[Server-Daten]]></item>\r
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Server löschen]]></item>\r
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Der Server wurde erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Wollen Sie den Server wirklich löschen?]]></item>\r
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Deaktivieren]]></item>\r
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Server bearbeiten]]></item>\r
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Ihre Änderungen wurden erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Aktivieren]]></item>\r
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Fehlermeldungen]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Geben Sie ein Kennwort an, das zur Authentifizierung benötigt wird (optional).]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Geben Sie einen Benutzernamen an, der zur Authentifizierung benötigt wird (optional).]]></item>\r
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Beim letzten Verbindungsversuch trat folgende Fehlermeldungen auf:]]></item>\r
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[Insgesamt {#$items} Server eingetragen]]></item>\r
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Server-ID]]></item>\r
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Pakete]]></item>\r
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adresse]]></item>\r
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Geben Sie die Adresse (URL) zu einem Paketserver an.]]></item>\r
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[Die eingetragene Adresse ist ungültig.]]></item>\r
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Letzter Zugriff]]></item>\r
+               <item name="wcf.acp.updateServer.view"><![CDATA[Verfügbare Update-Server]]></item>\r
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Es sind keine Update-Server eingetragen.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.user">\r
+               <item name="wcf.acp.user.add"><![CDATA[Benutzer hinzufügen]]></item>\r
+               <item name="wcf.acp.user.add.data"><![CDATA[Benutzerdaten]]></item>\r
+               <item name="wcf.acp.user.add.success"><![CDATA[Der neue Benutzer wurde erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Benutzergruppe zuweisen]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Folgende Benutzer den unten ausgewählten Benutzergruppen zuweisen]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Die Zuweisung wurde erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Benutzergruppe zuweisen]]></item>\r
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[E-Mail-Adressen exportieren]]></item>\r
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[E-Mail senden]]></item>\r
+               <item name="wcf.acp.user.delete"><![CDATA[Benutzer löschen]]></item>\r
+               <item name="wcf.acp.user.delete.error"><![CDATA[Es konnte kein Benutzer gelöscht werden.]]></item>\r
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}Der Benutzer wurde{else}{#$deletedUsers} Benutzer wurden{/if} erfolgreich gelöscht.]]></item>\r
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Wollen Sie diesen Benutzer wirklich löschen?]]></item>\r
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Wollen Sie die markierten Benutzer wirklich löschen?]]></item>\r
+               <item name="wcf.acp.user.edit"><![CDATA[Benutzer bearbeiten]]></item>\r
+               <item name="wcf.acp.user.edit.success"><![CDATA[Die Änderungen an diesem Benutzer wurden erfolgreich gespeichert.]]></item>\r
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Sie bearbeiten Ihr eigenes Benutzerkonto. Änderungen an den Mitgliedschaften in Benutzergruppen können womöglich dazu führen, dass Sie aus der Administrationsoberfläche ausgeschlossen werden. Bitte seien Sie entsprechend vorsichtig!]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[E-Mail-Adressen exportieren]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Exportformat]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Exporteinstellungen]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[E-Mail-Adressen von folgenden Benutzern exportieren]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Trennzeichen]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Texttrenner]]></item>\r
+               <item name="wcf.acp.user.groups"><![CDATA[Benutzergruppe(n)]]></item>\r
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Finde Benutzer, die in den ausgewählten Benutzergruppen nicht Mitglied sind.]]></item>\r
+               <item name="wcf.acp.user.list"><![CDATA[Benutzer]]></item>\r
+               <item name="wcf.acp.user.list.all"><![CDATA[Alle Benutzer]]></item>\r
+               <item name="wcf.acp.user.list.count"><![CDATA[Insgesamt {#$items} Benutzer]]></item>\r
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "Einen Benutzer markiert" : this.count+" Benutzer markiert"]]></item>\r
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Massenverarbeitung von Benutzern]]></item>\r
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Aktion]]></item>\r
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Bedingungen]]></item>\r
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Die gewählte Aktion wurde erfolgreich auf {#$affectedUsers} Benutzer ausgeführt.]]></item>\r
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Die Massenverarbeitung von Benutzern führt die unten ausgewählte Aktion <b>ohne zusätzliche Sicherheitsabfrage</b> auf alle Benutzer aus, die unter die eingestellten Bedingungen fallen. Die Bearbeitungen können unter Umständen sehr rechenintensiv werden und sollten deshalb möglichst nur dann ausgeführt werden, wenn sich die Seite im Wartungsmodus befindet! Die Veränderungen können nicht rückgängig gemacht werden. Bitte benutzen Sie diese Funktion mit der nötigen Vorsicht!]]></item>\r
+               <item name="wcf.acp.user.search"><![CDATA[Benutzer suchen]]></item>\r
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Kriterien der Suche]]></item>\r
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profil]]></item>\r
+               <item name="wcf.acp.user.search.display"><![CDATA[Darstellung]]></item>\r
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Angezeigte Informationen]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Sonstiges]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profil]]></item>\r
+               <item name="wcf.acp.user.search.display.general"><![CDATA[Allgemein]]></item>\r
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Benutzer pro Seite]]></item>\r
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sortierung]]></item>\r
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Zu den angegebenen Kriterien wurde kein Benutzer gefunden.]]></item>\r
+               <item name="wcf.acp.user.search.matches"><![CDATA[{if $items == 1}Ein Ergebnis{else}{#$items} Ergebnisse{/if}]]></item>\r
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[In den Ergebnissen suchen]]></item>\r
+               <item name="wcf.acp.user.sendMail"><![CDATA[E-Mail an Benutzer senden]]></item>\r
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-Mail an alle Benutzer]]></item>\r
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[E-Mail als HTML verschicken]]></item>\r
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Absender]]></item>\r
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Hier können Sie die E-Mail-Adresse des Absenders definieren.{if MAIL_USE_FORMATTED_ADDRESS} Es ist auch folgendes Format möglich:{/if}</p>\r
+{if MAIL_USE_FORMATTED_ADDRESS}<p style="text-align: center; line-height: 2em;"><code>Absender Name &lt;email@absender.tld&gt;</code></p>{/if}\r
+<p>Wenn Sie unter System -> Optionen -> E-Mail alles ausgefüllt haben, wird dieses Feld automatisch ausgefüllt. Sollten Sie E-Mails per SMTP senden, so achten Sie darauf, dass die E-Mail-Adresse des Absenders auch vom Server akzeptiert werden muss.</p>]]></item>\r
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[E-Mail an Gruppenmitglieder]]></item>\r
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[E-Mail an die Mitglieder folgender Benutzergruppen senden]]></item>\r
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-Mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[E-Mail an folgende Benutzer senden]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Betreff]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Geben Sie hier die Betreffzeile der E-Mail an.]]></item>\r
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Nachricht]]></item>\r
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Tragen Sie hier die Nachricht ein, die Sie den Benutzern senden möchten.]]></item>\r
+               <item name="wcf.acp.user.userNote"><![CDATA[Angemeldet als {$this->user->username}.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.worker">\r
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Aktueller Schritt]]></item>\r
+               <item name="wcf.acp.worker.description"><![CDATA[Bitte lassen Sie dieses Browser-Fenster offen, bis der Prozess abgeschlossen ist und melden Sie sich auf keinen Fall in einem anderen Browser-Fenster separat in der Administrationsoberfläche an, da dies den Prozess behindern könnte.]]></item>\r
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Vorgang erfolgreich abgeschlossen]]></item>\r
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Vorgang läuft ...]]></item>\r
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% fertiggestellt]]></item>\r
+               <item name="wcf.acp.worker.title"><![CDATA[Prozess läuft ...]]></item>\r
+       </category>\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Zurück]]></item>\r
+               <item name="wcf.global.button.close"><![CDATA[Schließen]]></item>\r
+               <item name="wcf.global.button.collapse"><![CDATA[Zuklappen]]></item>\r
+               <item name="wcf.global.button.collapsible"><![CDATA[Auf- und Zuklappen]]></item>\r
+               <item name="wcf.global.button.delete"><![CDATA[Löschen]]></item>\r
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Möchten Sie das Element wirklich löschen?]]></item>\r
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Endgültig löschen]]></item>\r
+               <item name="wcf.global.button.edit"><![CDATA[Bearbeiten]]></item>\r
+               <item name="wcf.global.button.editor.jump"><![CDATA[Zum Editor wechseln]]></item>\r
+               <item name="wcf.global.button.expand"><![CDATA[Aufklappen]]></item>\r
+               <item name="wcf.global.button.mark"><![CDATA[Markieren]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Weiter &raquo;]]></item>\r
+               <item name="wcf.global.button.preview"><![CDATA[Vorschau]]></item>\r
+               <item name="wcf.global.button.reset"><![CDATA[Zurücksetzen]]></item>\r
+               <item name="wcf.global.button.submit"><![CDATA[Absenden]]></item>\r
+               <item name="wcf.global.button.unmark"><![CDATA[Demarkieren]]></item>\r
+               <item name="wcf.global.date.day"><![CDATA[Tag]]></item>\r
+               <item name="wcf.global.date.days"><![CDATA[Tage]]></item>\r
+               <item name="wcf.global.date.hour"><![CDATA[Stunde]]></item>\r
+               <item name="wcf.global.date.hours"><![CDATA[Stunden]]></item>\r
+               <item name="wcf.global.date.minute"><![CDATA[Minute]]></item>\r
+               <item name="wcf.global.date.minutes"><![CDATA[Minuten]]></item>\r
+               <item name="wcf.global.date.month"><![CDATA[Monat]]></item>\r
+               <item name="wcf.global.date.months"><![CDATA[Monate]]></item>\r
+               <item name="wcf.global.date.second"><![CDATA[Sekunde]]></item>\r
+               <item name="wcf.global.date.seconds"><![CDATA[Sekunden]]></item>\r
+               <item name="wcf.global.date.week"><![CDATA[Woche]]></item>\r
+               <item name="wcf.global.date.weeks"><![CDATA[Wochen]]></item>\r
+               <item name="wcf.global.date.year"><![CDATA[Jahr]]></item>\r
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Die Angabe des Jahres ist optional.]]></item>\r
+               <item name="wcf.global.date.years"><![CDATA[Jahre]]></item>\r
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.defaultValue"><![CDATA[Standard]]></item>\r
+               <item name="wcf.global.error.backward"><![CDATA[Zurück zur vorherigen Seite]]></item>\r
+               <item name="wcf.global.error.empty"><![CDATA[Bitte füllen Sie dieses Eingabefeld aus.]]></item>\r
+               <item name="wcf.global.error.file.notFound"><![CDATA[Die Datei konnte nicht gefunden werden.]]></item>\r
+               <item name="wcf.global.error.illegalLink"><![CDATA[Sie haben einen ungültigen oder nicht mehr gültigen Link aufgerufen.]]></item>\r
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Der Zutritt zu dieser Seite ist Ihnen leider verwehrt. Sie besitzen nicht die notwendigen Zugriffsrechte, um diese Seite aufrufen zu können.]]></item>\r
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Zutritt verwehrt]]></item>\r
+               <item name="wcf.global.error.title"><![CDATA[Fehlermeldung]]></item>\r
+               <item name="wcf.global.form.error"><![CDATA[Ihre Angaben sind ungültig. Bitte überprüfen Sie die markierten Eingabefelder.]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabisch]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnisch]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Tschechisch]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Dänisch]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Deutsch]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Deutsch (Anrede &raquo;Du&laquo;)]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Griechisch]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Englisch]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spanisch]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persisch]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finnisch]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Französisch]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebräisch]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Kroatisch]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungarisch]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italienisch]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Koreanisch]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Niederländisch]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norwegisch]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polnisch]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portugiesisch]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugiesisch (Brasilien)]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumänisch]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russisch]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slowakisch]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbisch]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Schwedisch]]></item>\r
+               <item name="wcf.global.language.th"><![CDATA[Thailändisch]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Türkisch]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinesisch (traditionell)]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[de_DE]]></item>\r
+               <item name="wcf.global.locale.win"><![CDATA[deu_deu]]></item>\r
+               <item name="wcf.global.multiSelect"><![CDATA[Mehrfache Markierungen sind durch zusätzliches Drücken der Taste &raquo;Strg/Ctrl&laquo; (Windows) oder &raquo;Befehl/Command&laquo; (Mac OS) möglich.]]></item>\r
+               <item name="wcf.global.page.input"><![CDATA[Zu folgender Seite springen]]></item>\r
+               <item name="wcf.global.page.next"><![CDATA[nächste Seite]]></item>\r
+               <item name="wcf.global.page.previous"><![CDATA[vorherige Seite]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>\r
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>\r
+               <item name="wcf.global.redirect.title"><![CDATA[Weiterleitung]]></item>\r
+               <item name="wcf.global.redirect.url"><![CDATA[Falls die automatische Weiterleitung nicht funktioniert, klicken Sie bitte hier!]]></item>\r
+               <item name="wcf.global.scrollUp"><![CDATA[Zum Seitenanfang]]></item>\r
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Exakter Treffer]]></item>\r
+               \r
+               <item name="wcf.global.skipToContent"><![CDATA[Zum Seiteninhalt springen]]></item>\r
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[in aufsteigender Reihenfolge]]></item>\r
+               <item name="wcf.global.sortOrder.descending"><![CDATA[in absteigender Reihenfolge]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>\r
+               \r
+               <item name="wcf.global.date.dateFormat"><![CDATA[j. F Y]]></item>\r
+               <item name="wcf.global.date.timeFormat"><![CDATA[H:i]]></item>\r
+               <item name="wcf.global.date.dateTimeFormat"><![CDATA[%date%, %time%]]></item>\r
+               \r
+               <!--  variables for dynamic javascript datetime -->\r
+               <item name="wcf.global.date.relative.minutes"><![CDATA['Vor ' + (($minutes > 1) ? $minutes + ' Minuten' : 'einer Minute' )]]></item>\r
+               <item name="wcf.global.date.relative.hours"><![CDATA['Vor ' + (($hours > 1) ? $hours + ' Stunden' : 'einer Stunde' )]]></item>\r
+               <item name="wcf.global.date.relative.pastDays"><![CDATA[(($days > 1) ? '%day%' : 'Gestern' ) + ', %time%']]></item>\r
+               \r
+               <!-- variables for localized date formats; unnecessary in english -->\r
+               <item name="wcf.global.date.month.january"><![CDATA[Januar]]></item>\r
+               <item name="wcf.global.date.month.february"><![CDATA[Februar]]></item>\r
+               <item name="wcf.global.date.month.march"><![CDATA[März]]></item>\r
+               <item name="wcf.global.date.month.april"><![CDATA[April]]></item>\r
+               <item name="wcf.global.date.month.may"><![CDATA[Mai]]></item>\r
+               <item name="wcf.global.date.month.june"><![CDATA[Juni]]></item>\r
+               <item name="wcf.global.date.month.july"><![CDATA[Juli]]></item>\r
+               <item name="wcf.global.date.month.august"><![CDATA[August]]></item>\r
+               <item name="wcf.global.date.month.september"><![CDATA[September]]></item>\r
+               <item name="wcf.global.date.month.october"><![CDATA[Oktober]]></item>\r
+               <item name="wcf.global.date.month.november"><![CDATA[November]]></item>\r
+               <item name="wcf.global.date.month.december"><![CDATA[Dezember]]></item>\r
+               <item name="wcf.global.date.month.jan"><![CDATA[Jan]]></item>\r
+               <item name="wcf.global.date.month.feb"><![CDATA[Feb]]></item>\r
+               <item name="wcf.global.date.month.mar"><![CDATA[Mär]]></item>\r
+               <item name="wcf.global.date.month.apr"><![CDATA[Apr]]></item>\r
+               <item name="wcf.global.date.month.may"><![CDATA[Mai]]></item>\r
+               <item name="wcf.global.date.month.jun"><![CDATA[Jun]]></item>\r
+               <item name="wcf.global.date.month.jul"><![CDATA[Jul]]></item>\r
+               <item name="wcf.global.date.month.aug"><![CDATA[Aug]]></item>\r
+               <item name="wcf.global.date.month.sep"><![CDATA[Sep]]></item>\r
+               <item name="wcf.global.date.month.oct"><![CDATA[Okt]]></item>\r
+               <item name="wcf.global.date.month.nov"><![CDATA[Nov]]></item>\r
+               <item name="wcf.global.date.month.dec"><![CDATA[Dez]]></item>\r
+               <item name="wcf.global.date.day.sunday"><![CDATA[Sonntag]]></item>\r
+               <item name="wcf.global.date.day.monday"><![CDATA[Montag]]></item>\r
+               <item name="wcf.global.date.day.tuesday"><![CDATA[Dienstag]]></item>\r
+               <item name="wcf.global.date.day.wednesday"><![CDATA[Mittwoch]]></item>\r
+               <item name="wcf.global.date.day.thursday"><![CDATA[Donnerstag]]></item>\r
+               <item name="wcf.global.date.day.friday"><![CDATA[Freitag]]></item>\r
+               <item name="wcf.global.date.day.saturday"><![CDATA[Samstag]]></item>\r
+               <item name="wcf.global.date.day.sun"><![CDATA[Son]]></item>\r
+               <item name="wcf.global.date.day.mon"><![CDATA[Mon]]></item>\r
+               <item name="wcf.global.date.day.tue"><![CDATA[Die]]></item>\r
+               <item name="wcf.global.date.day.wed"><![CDATA[Mit]]></item>\r
+               <item name="wcf.global.date.day.thu"><![CDATA[Don]]></item>\r
+               <item name="wcf.global.date.day.fri"><![CDATA[Fre]]></item>\r
+               <item name="wcf.global.date.day.sat"><![CDATA[Sam]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.kwajalein"><![CDATA[(UTC-12:00) Kwajalein]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.midway"><![CDATA[(UTC-11:00) Midway]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.samoa"><![CDATA[(UTC-11:00) Samoa]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.honolulu"><![CDATA[(UTC-10:00) Hawaii]]></item>\r
+               <item name="wcf.global.date.timezone.america.anchorage"><![CDATA[(UTC-09:00) Alaska]]></item>\r
+               <item name="wcf.global.date.timezone.america.tijuana"><![CDATA[(UTC-08:00) Tijuana, Niederkalifornien]]></item>\r
+               <item name="wcf.global.date.timezone.america.los_angeles"><![CDATA[(UTC-08:00) Pacific Zeit]]></item>\r
+               <item name="wcf.global.date.timezone.america.phoenix"><![CDATA[(UTC-07:00) Arizona]]></item>\r
+               <item name="wcf.global.date.timezone.america.chihuahua"><![CDATA[(UTC-07:00) Chihuahua, La Paz, Mazatlan]]></item>\r
+               <item name="wcf.global.date.timezone.america.denver"><![CDATA[(UTC-07:00) Mountain Zeit]]></item>\r
+               <item name="wcf.global.date.timezone.america.chicago"><![CDATA[(UTC-06:00) Central Zeit]]></item>\r
+               <item name="wcf.global.date.timezone.america.mexico_city"><![CDATA[(UTC-06:00) Guadalajara, Mexiko-Stadt, Monterrey]]></item>\r
+               <item name="wcf.global.date.timezone.america.tegucigalpa"><![CDATA[(UTC-06:00) Mittelamerika]]></item>\r
+               <item name="wcf.global.date.timezone.america.regina"><![CDATA[(UTC-06:00) Saskatchewan]]></item>\r
+               <item name="wcf.global.date.timezone.america.bogota"><![CDATA[(UTC-05:00) Bogotá, Lima, Quito]]></item>\r
+               <item name="wcf.global.date.timezone.america.new_york"><![CDATA[(UTC-05:00) Eastern Zeit]]></item>\r
+               <item name="wcf.global.date.timezone.america.indiana.indianapolis"><![CDATA[(UTC-05:00) Indiana (Ost)]]></item>\r
+               <item name="wcf.global.date.timezone.america.rio_branco"><![CDATA[(UTC-05:00) Rio Branco]]></item>\r
+               <item name="wcf.global.date.timezone.america.caracas"><![CDATA[(UTC-04:30) Caracas]]></item>\r
+               <item name="wcf.global.date.timezone.america.asuncion"><![CDATA[(UTC-04:00) Asuncion]]></item>\r
+               <item name="wcf.global.date.timezone.america.halifax"><![CDATA[(UTC-04:00) Atlantic (Kanada)]]></item>\r
+               <item name="wcf.global.date.timezone.america.cuiaba"><![CDATA[(UTC-04:00) Cuiaba]]></item>\r
+               <item name="wcf.global.date.timezone.america.la_paz"><![CDATA[(UTC-04:00) Georgetown, La Paz, Manaus, San Juan]]></item>\r
+               <item name="wcf.global.date.timezone.america.santiago"><![CDATA[(UTC-04:00) Santiago]]></item>\r
+               <item name="wcf.global.date.timezone.america.st_johns"><![CDATA[(UTC-03:30) Neufundland]]></item>\r
+               <item name="wcf.global.date.timezone.america.sao_paulo"><![CDATA[(UTC-03:00) Brasilia]]></item>\r
+               <item name="wcf.global.date.timezone.america.argentina.buenos_aires"><![CDATA[(UTC-03:00) Buenos Aires]]></item>\r
+               <item name="wcf.global.date.timezone.america.cayenne"><![CDATA[(UTC-03:00) Cayenne, Fortaleza]]></item>\r
+               <item name="wcf.global.date.timezone.america.godthab"><![CDATA[(UTC-03:00) Grönland]]></item>\r
+               <item name="wcf.global.date.timezone.america.montevideo"><![CDATA[(UTC-03:00) Montevideo]]></item>\r
+               <item name="wcf.global.date.timezone.atlantic.south_georgia"><![CDATA[(UTC-02:00) Mittelatlantik]]></item>\r
+               <item name="wcf.global.date.timezone.atlantic.azores"><![CDATA[(UTC-01:00) Azoren]]></item>\r
+               <item name="wcf.global.date.timezone.atlantic.cape_verde"><![CDATA[(UTC-01:00) Kap Verde]]></item>\r
+               <item name="wcf.global.date.timezone.africa.casablanca"><![CDATA[(UTC) Casablanca]]></item>\r
+               <item name="wcf.global.date.timezone.europe.london"><![CDATA[(UTC) Dublin, Edinburgh, Lissabon, London]]></item>\r
+               <item name="wcf.global.date.timezone.africa.monrovia"><![CDATA[(UTC) Monrovia, Reykjavik]]></item>\r
+               <item name="wcf.global.date.timezone.europe.berlin"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien]]></item>\r
+               <item name="wcf.global.date.timezone.europe.belgrade"><![CDATA[(UTC+01:00) Belgrad, Bratislava, Bupdapest, Ljubljana, Prag]]></item>\r
+               <item name="wcf.global.date.timezone.europe.paris"><![CDATA[(UTC+01:00) Brüssel, Kopenhagen, Madrid, Paris]]></item>\r
+               <item name="wcf.global.date.timezone.europe.sarajevo"><![CDATA[(UTC+01:00) Sarajevo, Skopje, Warschau, Zagreb]]></item>\r
+               <item name="wcf.global.date.timezone.africa.algiers"><![CDATA[(UTC+01:00) West-Zentralafrika]]></item>\r
+               <item name="wcf.global.date.timezone.africa.windhoek"><![CDATA[(UTC+01:00) Windhuk]]></item>\r
+               <item name="wcf.global.date.timezone.asia.amman"><![CDATA[(UTC+02:00) Amman]]></item>\r
+               <item name="wcf.global.date.timezone.europe.athens"><![CDATA[(UTC+02:00) Athen, Bukarest, Istanbul]]></item>\r
+               <item name="wcf.global.date.timezone.asia.beirut"><![CDATA[(UTC+02:00) Beirut]]></item>\r
+               <item name="wcf.global.date.timezone.asia.damascus"><![CDATA[(UTC+02:00) Damaskus]]></item>\r
+               <item name="wcf.global.date.timezone.africa.harare"><![CDATA[(UTC+02:00) Harare, Pretoria]]></item>\r
+               <item name="wcf.global.date.timezone.europe.helsinki"><![CDATA[(UTC+02:00) Helsinki, Kiew, Riga, Sofia, Tallinn, Wilna]]></item>\r
+               <item name="wcf.global.date.timezone.asia.jerusalem"><![CDATA[(UTC+02:00) Jerusalem]]></item>\r
+               <item name="wcf.global.date.timezone.africa.cairo"><![CDATA[(UTC+02:00) Kairo]]></item>\r
+               <item name="wcf.global.date.timezone.europe.minsk"><![CDATA[(UTC+02:00) Minsk]]></item>\r
+               <item name="wcf.global.date.timezone.asia.baghdad"><![CDATA[(UTC+03:00) Bagdad]]></item>\r
+               <item name="wcf.global.date.timezone.asia.kuwait"><![CDATA[(UTC+03:00) Kuwait, Riad]]></item>\r
+               <item name="wcf.global.date.timezone.europe.moscow"><![CDATA[(UTC+03:00) Moskau, St. Petersburg, Wolgograd]]></item>\r
+               <item name="wcf.global.date.timezone.africa.nairobi"><![CDATA[(UTC+03:00) Nairobi]]></item>\r
+               <item name="wcf.global.date.timezone.asia.tehran"><![CDATA[(UTC+03:30) Teheran]]></item>\r
+               <item name="wcf.global.date.timezone.asia.muscat"><![CDATA[(UTC+04:00) Abu Dhabi, Muskat]]></item>\r
+               <item name="wcf.global.date.timezone.asia.baku"><![CDATA[(UTC+04:00) Baku]]></item>\r
+               <item name="wcf.global.date.timezone.asia.yerevan"><![CDATA[(UTC+04:00) Eriwan]]></item>\r
+               <item name="wcf.global.date.timezone.indian.mauritius"><![CDATA[(UTC+04:00) Port Louis]]></item>\r
+               <item name="wcf.global.date.timezone.asia.tbilisi"><![CDATA[(UTC+04:00) Tiflis]]></item>\r
+               <item name="wcf.global.date.timezone.asia.kabul"><![CDATA[(UTC+04:30) Kabul]]></item>\r
+               <item name="wcf.global.date.timezone.asia.karachi"><![CDATA[(UTC+05:00) Islamabad, Karatschi]]></item>\r
+               <item name="wcf.global.date.timezone.asia.yekaterinburg"><![CDATA[(UTC+05:00) Jekaterinburg]]></item>\r
+               <item name="wcf.global.date.timezone.asia.tashkent"><![CDATA[(UTC+05:00) Taschkent]]></item>\r
+               <item name="wcf.global.date.timezone.asia.kolkata"><![CDATA[(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi]]></item>\r
+               <item name="wcf.global.date.timezone.asia.colombo"><![CDATA[(UTC+05:30) Sri Jayawardenepura]]></item>\r
+               <item name="wcf.global.date.timezone.asia.katmandu"><![CDATA[(UTC+05:45) Katmandu]]></item>\r
+               <item name="wcf.global.date.timezone.asia.almaty"><![CDATA[(UTC+06:00) Astana]]></item>\r
+               <item name="wcf.global.date.timezone.asia.dhaka"><![CDATA[(UTC+06:00) Dakka]]></item>\r
+               <item name="wcf.global.date.timezone.asia.novosibirsk"><![CDATA[(UTC+06:00) Nowosibirsk]]></item>\r
+               <item name="wcf.global.date.timezone.asia.rangoon"><![CDATA[(UTC+06:30) Yangon (Rangun)]]></item>\r
+               <item name="wcf.global.date.timezone.asia.bangkok"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta]]></item>\r
+               <item name="wcf.global.date.timezone.asia.krasnoyarsk"><![CDATA[(UTC+07:00) Krasnojarsk]]></item>\r
+               <item name="wcf.global.date.timezone.asia.irkutsk"><![CDATA[(UTC+08:00) Irkutsk]]></item>\r
+               <item name="wcf.global.date.timezone.asia.kuala_lumpur"><![CDATA[(UTC+08:00) Kuala Lumpur, Singapur]]></item>\r
+               <item name="wcf.global.date.timezone.asia.chongqing"><![CDATA[(UTC+08:00) Peking, Chongqing, Hongkong, Urumchi]]></item>\r
+               <item name="wcf.global.date.timezone.australia.perth"><![CDATA[(UTC+08:00) Perth]]></item>\r
+               <item name="wcf.global.date.timezone.asia.taipei"><![CDATA[(UTC+08:00) Taipeh]]></item>\r
+               <item name="wcf.global.date.timezone.asia.ulaanbaatar"><![CDATA[(UTC+08:00) Ulan-Bator]]></item>\r
+               <item name="wcf.global.date.timezone.asia.yakutsk"><![CDATA[(UTC+09:00) Jakutsk]]></item>\r
+               <item name="wcf.global.date.timezone.asia.tokyo"><![CDATA[(UTC+09:00) Osaka, Sapporo, Tokio]]></item>\r
+               <item name="wcf.global.date.timezone.asia.seoul"><![CDATA[(UTC+09:00) Seoul]]></item>\r
+               <item name="wcf.global.date.timezone.australia.adelaide"><![CDATA[(UTC+09:30) Adelaide]]></item>\r
+               <item name="wcf.global.date.timezone.australia.darwin"><![CDATA[(UTC+09:30) Darwin]]></item>\r
+               <item name="wcf.global.date.timezone.australia.brisbane"><![CDATA[(UTC+10:00) Brisbane]]></item>\r
+               <item name="wcf.global.date.timezone.australia.sydney"><![CDATA[(UTC+10:00) Canberra, Melbourne, Sydney]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.guam"><![CDATA[(UTC+10:00) Guam, Port Moresby]]></item>\r
+               <item name="wcf.global.date.timezone.australia.hobart"><![CDATA[(UTC+10:00) Hobart]]></item>\r
+               <item name="wcf.global.date.timezone.asia.vladivostok"><![CDATA[(UTC+10:00) Wladiwostok]]></item>\r
+               <item name="wcf.global.date.timezone.asia.magadan"><![CDATA[(UTC+11:00) Magadan]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.noumea"><![CDATA[(UTC+11:00) Salomonen, Neu-Kaledonien]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.auckland"><![CDATA[(UTC+12:00) Auckland, Wellington]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.fiji"><![CDATA[(UTC+12:00) Fidschi]]></item>\r
+               <item name="wcf.global.date.timezone.asia.kamchatka"><![CDATA[(UTC+12:00) Kamtschatka]]></item>\r
+               <item name="wcf.global.date.timezone.pacific.tongatapu"><![CDATA[(UTC+13:00) Nuku'alofa]]></item>\r
+       </category>\r
+       <category name="wcf.imageViewer">\r
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Bild " + (this.currentIndex + 1) + " von " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>\r
+               <item name="wcf.imageViewer.close"><![CDATA[Schließen]]></item>\r
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Nur dieses Bild anzeigen (beendet die Bildbetrachtung)]]></item>\r
+               <item name="wcf.imageViewer.next"><![CDATA[Nächstes Bild]]></item>\r
+               <item name="wcf.imageViewer.pause"><![CDATA[Diashow stoppen]]></item>\r
+               <item name="wcf.imageViewer.play"><![CDATA[Diashow starten (Bildwechsel alle 5 Sekunden)]]></item>\r
+               <item name="wcf.imageViewer.previous"><![CDATA[Vorheriges Bild]]></item>\r
+       </category>\r
+       <category name="wcf.option">\r
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Kanarische Inseln, Lissabon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>\r
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brüssel, Kopenhagen, Madrid, Paris, Prag, Rom, Sarajevo, Stockholm, Tunis, Warschau, Wien]]></item>\r
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athen, Beirut, Bukarest, Helsinki, Istanbul, Jerusalem, Kairo, Kapstadt, Khartum, Kiew, Minsk, Sofia]]></item>\r
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Abeba, Antananarivo, Bagdad, Daressalam, Kampala, Kuwait, Mogadischu, Moskau, Nairobi, Riad]]></item>\r
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Teheran]]></item>\r
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Eriwan, Maskat, R&eacute;union, Tiflis]]></item>\r
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>\r
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Asgabat, Bischkek, Duschanbe, Islamabad, Jekaterinburg, Karatschi, Malediven, Taschkent]]></item>\r
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, Neu-Delhi]]></item>\r
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>\r
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Nowosibirsk]]></item>\r
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Kokosinseln, Rangun]]></item>\r
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnojarsk, Vientiane]]></item>\r
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hongkong, Irkutsk, Kuala Lumpur, Manila, Peking, Perth, Singapur, Taipeh, Ulan Bator]]></item>\r
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Australien)]]></item>\r
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Jakutsk, Osaka, Pjöngjang, Sapporo, Seoul, Tokyo]]></item>\r
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>\r
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Wladiwostok]]></item>\r
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord-Howe-Insel (Australien)]]></item>\r
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, Neukaledonien, Salomonen]]></item>\r
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolkinsel]]></item>\r
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, Bairiki, Fidschi, Kamtschatka, Marshall-Inseln, Wellington]]></item>\r
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham-Inseln (Neuseeland)]]></item>\r
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenixinseln]]></item>\r
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Linieninseln, Weihnachtsinsel]]></item>\r
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azoren, Kapverdische Inseln]]></item>\r
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mittelatlantik]]></item>\r
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Grönland, Montevideo]]></item>\r
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Neufundland]]></item>\r
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Asunci&oacute;n, Atlantik (Kanada), La Paz, Port-of-Spain, Santiago]]></item>\r
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>\r
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Atlanta, Bogot&aacute;, Detroit, Lima, Miami, New York, San Francisco de Quito, Toronto]]></item>\r
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Chicago, Dallas, Kansas City, Mexiko-Stadt, Winnipeg, Zentralamerika]]></item>\r
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Arizona, Calgary, Chihuahua, Denver, Mazatlan, Salt Lake City]]></item>\r
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Los Angeles, Seattle, Tijuana, Vancouver]]></item>\r
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>\r
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) Französisch-Polynesien]]></item>\r
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cookinseln, Hawaii]]></item>\r
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midwayinseln, Samoa]]></item>\r
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Eniwetok, Kwajalein]]></item>\r
+       </category>\r
+       <category name="wcf.page">\r
+               <item name="wcf.page.pageNo"><![CDATA[Seite {#$pageNo}]]></item>\r
+       </category>\r
+       <category name="wcf.user">\r
+               <item name="wcf.user.confirmEmail"><![CDATA[E-Mail-Adresse wiederholen]]></item>\r
+               <item name="wcf.user.confirmPassword"><![CDATA[Kennwort wiederholen]]></item>\r
+               <item name="wcf.user.email"><![CDATA[E-Mail-Adresse]]></item>\r
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Die eingegebenen E-Mail-Adressen sind nicht identisch.]]></item>\r
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Die eingegebenen Kennwörter sind nicht identisch.]]></item>\r
+               <item name="wcf.user.error.email.notUnique"><![CDATA[Diese E-Mail-Adresse ist bereits durch einen anderen Benutzer vergeben.]]></item>\r
+               <item name="wcf.user.error.email.notValid"><![CDATA[Sie haben eine ungültige E-Mail-Adresse eingegeben.]]></item>\r
+               <item name="wcf.user.error.password.false"><![CDATA[Dieses Kennwort ist falsch.]]></item>\r
+               <item name="wcf.user.error.username.notFound"><![CDATA[Der Benutzername &raquo;{$username}&laquo; konnte nicht gefunden werden.]]></item>\r
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Dieser Benutzername ist bereits vergeben.]]></item>\r
+               <item name="wcf.user.error.username.notValid"><![CDATA[Sie haben einen ungültigen Benutzernamen eingegeben.]]></item>\r
+               <item name="wcf.user.language"><![CDATA[Sprache]]></item>\r
+               <item name="wcf.user.language.description"><![CDATA[Bitte wählen Sie aus, in welcher Sprache die Benutzeroberfläche erscheinen soll!]]></item>\r
+               <item name="wcf.user.logout"><![CDATA[Abmelden]]></item>\r
+               <item name="wcf.user.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.user.registrationDate"><![CDATA[Registrierungsdatum]]></item>\r
+               <item name="wcf.user.userID"><![CDATA[Benutzer-ID]]></item>\r
+               <item name="wcf.user.username"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.user.visibleLanguages"><![CDATA[Zeige Inhalte in folgenden Sprachen an]]></item>\r
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Geben Sie an, in welchen Sprachen erstellte Inhalte angezeigt werden sollen.]]></item>\r
+       </category>\r
+       <category name="wcf.user.option">\r
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Sie haben einen ungültigen Inhalt eingegeben.]]></item>\r
+       </category>\r
+</language>\r
diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml
new file mode 100644 (file)
index 0000000..a676ad8
--- /dev/null
@@ -0,0 +1,901 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="en">\r
+       <category name="wcf.acp">\r
+               <item name="wcf.acp"><![CDATA[Administration Control Panel]]></item>\r
+               <item name="wcf.acp.help"><![CDATA[Help]]></item>\r
+               <item name="wcf.acp.help.complete"><![CDATA[Complete Help]]></item>\r
+               <item name="wcf.acp.help.disable"><![CDATA[Disable online Help]]></item>\r
+               <item name="wcf.acp.help.interactive"><![CDATA[Interactive Help]]></item>\r
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Change Package]]></item>\r
+               <item name="wcf.acp.search.extended"><![CDATA[Extended search ...]]></item>\r
+               <item name="wcf.acp.sitemap"><![CDATA[Site-Map]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cache">\r
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Empty cache]]></item>\r
+               <item name="wcf.acp.cache.clear.success"><![CDATA[The cache has been successfully emptied.]]></item>\r
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Are you sure that you want to completely empty the cache?]]></item>\r
+               <item name="wcf.acp.cache.data"><![CDATA[Settings]]></item>\r
+               <item name="wcf.acp.cache.data.files"><![CDATA[Files]]></item>\r
+               <item name="wcf.acp.cache.data.size"><![CDATA[Size]]></item>\r
+               <item name="wcf.acp.cache.data.source"><![CDATA[Source]]></item>\r
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Last updated]]></item>\r
+               <item name="wcf.acp.cache.list.name"><![CDATA[Name]]></item>\r
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Permissions]]></item>\r
+               <item name="wcf.acp.cache.list.size"><![CDATA[Size]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cronjob">\r
+               <item name="wcf.acp.cronjob.active"><![CDATA[Enabled]]></item>\r
+               <item name="wcf.acp.cronjob.add"><![CDATA[Add a new cron job]]></item>\r
+               <item name="wcf.acp.cronjob.add.data"><![CDATA[General Information]]></item>\r
+               <item name="wcf.acp.cronjob.add.success"><![CDATA[The cron job has been added successfully.]]></item>\r
+               <item name="wcf.acp.cronjob.add.timing"><![CDATA[Schedule]]></item>\r
+               <item name="wcf.acp.cronjob.className"><![CDATA[Class path]]></item>\r
+               <item name="wcf.acp.cronjob.className.description"><![CDATA[Please enter here the path to the PHP file in which the associated cron job class is contained. This path must be relative to the installation folder of the WCF.]]></item>\r
+               <item name="wcf.acp.cronjob.cronjobID"><![CDATA[Job ID]]></item>\r
+               <item name="wcf.acp.cronjob.delete"><![CDATA[Delete]]></item>\r
+               <item name="wcf.acp.cronjob.delete.disabled"><![CDATA[This cron job cannot be deleted.]]></item>\r
+               <item name="wcf.acp.cronjob.delete.success"><![CDATA[The cron job has been deleted successfully.]]></item>\r
+               <item name="wcf.acp.cronjob.delete.sure"><![CDATA[Are you sure that you want to remove this cron job?]]></item>\r
+               <item name="wcf.acp.cronjob.description"><![CDATA[Description]]></item>\r
+               <item name="wcf.acp.cronjob.description.description"><![CDATA[Here you may enter a short description for the cron job (preferably in English).]]></item>\r
+               <item name="wcf.acp.cronjob.disable"><![CDATA[Disable]]></item>\r
+               <item name="wcf.acp.cronjob.edit"><![CDATA[Edit]]></item>\r
+               <item name="wcf.acp.cronjob.edit.data"><![CDATA[General Information]]></item>\r
+               <item name="wcf.acp.cronjob.edit.disabled"><![CDATA[This cron job cannot be edited.]]></item>\r
+               <item name="wcf.acp.cronjob.edit.success"><![CDATA[The cron job has been modified successfully.]]></item>\r
+               <item name="wcf.acp.cronjob.edit.timing"><![CDATA[Schedule]]></item>\r
+               <item name="wcf.acp.cronjob.enable"><![CDATA[Enable]]></item>\r
+               <item name="wcf.acp.cronjob.error.doesNotExist"><![CDATA[The path you have entered is invalid.]]></item>\r
+               <item name="wcf.acp.cronjob.error.empty"><![CDATA[Please enter a valid entry here.]]></item>\r
+               <item name="wcf.acp.cronjob.error.notValid"><![CDATA[The timings you have set are invalid.]]></item>\r
+               <item name="wcf.acp.cronjob.execMultiple"><![CDATA[Schedule multiple executions?]]></item>\r
+               <item name="wcf.acp.cronjob.execMultiple.description"><![CDATA[When enabled, the respective task (cronjob) will be repeatedly executed at all possible dates between the previous specified execution date and the next.]]></item>\r
+               <item name="wcf.acp.cronjob.execute"><![CDATA[Execute now]]></item>\r
+               <item name="wcf.acp.cronjob.execute.success"><![CDATA[The job has been executed successfully.]]></item>\r
+               <item name="wcf.acp.cronjob.inactive"><![CDATA[Disabled]]></item>\r
+               <item name="wcf.acp.cronjob.info"><![CDATA[General Information]]></item>\r
+               <item name="wcf.acp.cronjob.intro"><![CDATA[Configuring cronjobs (automatized scheduled tasks) requires distinct knowledge of the crontab syntax on Unix based systems. More information about this topic can be obtained on the following Webpage: <a href="{@RELATIVE_WCF_DIR}acp/dereferrer.php?url={"http://www.unixgeeks.org/security/newbie/unix/cron-1.html"|rawurlencode}" class="externalURL">Newbie: Intro to cron</a>.]]></item>\r
+               <item name="wcf.acp.cronjob.lastExec"><![CDATA[Last scheduled execution]]></item>\r
+               <item name="wcf.acp.cronjob.list"><![CDATA[Cron jobs]]></item>\r
+               <item name="wcf.acp.cronjob.list.count"><![CDATA[There is a total of {#$items} cronjob{if $items != 1}s{/if}]]></item>\r
+               <item name="wcf.acp.cronjob.log"><![CDATA[Log of executed cronjobs]]></item>\r
+               <item name="wcf.acp.cronjob.log.clear"><![CDATA[Delete all]]></item>\r
+               <item name="wcf.acp.cronjob.log.clear.confirm"><![CDATA[Are you sure that you want to remove all log entries?]]></item>\r
+               <item name="wcf.acp.cronjob.log.data"><![CDATA[There is a total of {#$items} {if $items == 1}entry{else}entries{/if}]]></item>\r
+               <item name="wcf.acp.cronjob.log.error"><![CDATA[Error:]]></item>\r
+               <item name="wcf.acp.cronjob.log.execTime"><![CDATA[Successfully executed]]></item>\r
+               <item name="wcf.acp.cronjob.log.noEntries"><![CDATA[There are currently no log entries available.]]></item>\r
+               <item name="wcf.acp.cronjob.log.success"><![CDATA[OK]]></item>\r
+               <item name="wcf.acp.cronjob.nextExec"><![CDATA[Next scheduled execution]]></item>\r
+               <item name="wcf.acp.cronjob.noneAvailable"><![CDATA[There are currently no cronjobs available.]]></item>\r
+               <item name="wcf.acp.cronjob.packageName"><![CDATA[Installed by]]></item>\r
+               <item name="wcf.acp.cronjob.runNow"><![CDATA[Run now]]></item>\r
+               <item name="wcf.acp.cronjob.startDom"><![CDATA[Day of month]]></item>\r
+               <item name="wcf.acp.cronjob.startDom.description"><![CDATA[Day of the month (1 - 31) in which the cron job should be executed.]]></item>\r
+               <item name="wcf.acp.cronjob.startDomShort"><![CDATA[D]]></item>\r
+               <item name="wcf.acp.cronjob.startDow"><![CDATA[Weekday]]></item>\r
+               <item name="wcf.acp.cronjob.startDow.description"><![CDATA[Weekday (0 - 6 with Sunday = 0 or mon - sun) in which the cron job should be executed.]]></item>\r
+               <item name="wcf.acp.cronjob.startDowShort"><![CDATA[DoW]]></item>\r
+               <item name="wcf.acp.cronjob.startHour"><![CDATA[Hour]]></item>\r
+               <item name="wcf.acp.cronjob.startHour.description"><![CDATA[Hours (0 - 23) in which the cron job should be executed.]]></item>\r
+               <item name="wcf.acp.cronjob.startHourShort"><![CDATA[h]]></item>\r
+               <item name="wcf.acp.cronjob.startMinute"><![CDATA[Minute]]></item>\r
+               <item name="wcf.acp.cronjob.startMinute.description"><![CDATA[Minutes (0 - 59) in which the cron job should be executed.]]></item>\r
+               <item name="wcf.acp.cronjob.startMinuteShort"><![CDATA[m]]></item>\r
+               <item name="wcf.acp.cronjob.startMonth"><![CDATA[Month]]></item>\r
+               <item name="wcf.acp.cronjob.startMonth.description"><![CDATA[Month (1 - 12 or jan - dec) in which the cron job should be executed.]]></item>\r
+               <item name="wcf.acp.cronjob.startMonthShort"><![CDATA[M]]></item>\r
+               <item name="wcf.acp.cronjob.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.cronjob.subtitle"><![CDATA[]]></item>\r
+       </category>\r
+       <category name="wcf.acp.group">\r
+               <item name="wcf.acp.group.add"><![CDATA[Add new user group]]></item>\r
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Permissions]]></item>\r
+               <item name="wcf.acp.group.add.success"><![CDATA[The user group has been successfully added.]]></item>\r
+               <item name="wcf.acp.group.administrators"><![CDATA[Administrators]]></item>\r
+               <item name="wcf.acp.group.data"><![CDATA[General group information]]></item>\r
+               <item name="wcf.acp.group.delete"><![CDATA[Delete this user group]]></item>\r
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}This usergroup has{else}{#$deletedGroups} These user groups have{/if} been successfully deleted.]]></item>\r
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Are you sure you would like to remove this user group?]]></item>\r
+               <item name="wcf.acp.group.edit"><![CDATA[Edit this user group]]></item>\r
+               <item name="wcf.acp.group.edit.success"><![CDATA[Your user group changes have been successfully saved.]]></item>\r
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[You are currently a member of this user group. Changing the permissions of this user group could result in locking yourself out of the Administration Control Panel. Please be careful!]]></item>\r
+               <item name="wcf.acp.group.everyone"><![CDATA[Everyone]]></item>\r
+               <item name="wcf.acp.group.groupID"><![CDATA[Group ID]]></item>\r
+               <item name="wcf.acp.group.groupName"><![CDATA[Name of this user group]]></item>\r
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Enter here a name for this group.]]></item>\r
+               <item name="wcf.acp.group.guests"><![CDATA[Guests]]></item>\r
+               <item name="wcf.acp.group.list"><![CDATA[Usergroups]]></item>\r
+               <item name="wcf.acp.group.list.data"><![CDATA[A total of {#$items} user groups]]></item>\r
+               <item name="wcf.acp.group.members"><![CDATA[Number of members]]></item>\r
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderators]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Can enter Administration Control Panel?]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Activating this option will allow members of this user group to enter the Administration Control Panel and, dependent upon their permissions, run certain actions.]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Can view private user options]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Members of this user group can view private user options.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Can change the system options?]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Activating this option will allow members of this user group to view and change the system options - e.g. Forum on/offline.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Can view logs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Members of this usergroup can view the system logs.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canAddCronjob"><![CDATA[Can add new cronjobs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canAddCronjob.description"><![CDATA[Members of this usergroup can add new cronjobs.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjob"><![CDATA[Can delete existing cronjobs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjob.description"><![CDATA[Members of this usergroup can delete existing cronjobs.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjobsLog"><![CDATA[Can delete log files of running cronjobs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canDeleteCronjobsLog.description"><![CDATA[Members of this usergroup can delete log files of running cronjobs. The log files are also checked by the associated cronjob if the log file was successfully written.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEditCronjob"><![CDATA[Can edit existing cronjobs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEditCronjob.description"><![CDATA[Members of this usergroup can edit existing cronjobs.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEnableDisableCronjob"><![CDATA[Can disable existing cronjobs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.cronjobs.canEnableDisableCronjob.description"><![CDATA[Members of this usergroup can disable existing cronjobs. Disabling a cronjob only stops the actual cronjob from running, but does not remove it.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Can edit existing update servers]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Members of this user group can edit existing update servers and add new update servers.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Can install new packages]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Members of this user group can install additional packages.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Can remove existing packages]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Members of this user group can remove existing packages.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Can update existing packages]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Members of this user group can update existing packages.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Accessible usergroups]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Members of this user group have access to the following groups. For example, here you can set if the user group has permission to edit themselves.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Can add new usergroups]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Members of this user group can add new user groups.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Can add new users]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Members of this user group can add new users. If the option for &quot;Accessible Usergroups&quot; has been enabled, then on creation of the user, the appropriate accessible user groups can also be assigned.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Can delete existing user groups]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Members of this user group can remove existing user groups.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Can delete existing users]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Members of this user group can delete existing users.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Can edit existing usergroups]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Members of this user group can edit existing user groups.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Can edit user e-mail addresses]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Members of this user group can edit user e-mail addresses.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Can edit user passwords]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Members of this user group can edit user passwords.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Can edit existing users]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Members of this user group can edit existing users.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Can send e-mails to users]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Members of this user group can view other members' e-mail addresses and consequently send them e-mails.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Can search users]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Members of this user group can search existing users and their profiles.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Administrator permissions]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Content]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Design]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[General administrative permissions]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Maintenance]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[System functions]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.cronjobs"><![CDATA[Cronjobs]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.cronjobs.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Package management]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[User functions]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Group management]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[User management]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderator permissions]]></item>\r
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.user"><![CDATA[General permissions]]></item>\r
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[The information you have entered is not valid.]]></item>\r
+               <item name="wcf.acp.group.option.admin.style.canUseDisabledStyle"><![CDATA[Can view disabled styles]]></item>\r
+               <item name="wcf.acp.group.option.admin.style.canUseDisabledStyle.description"><![CDATA[Members of this usergroup can choose to view disabled styles.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.style"><![CDATA[Style management]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.style.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.showMembers"><![CDATA[Show the members of this usergroup]]></item>\r
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super moderators]]></item>\r
+               <item name="wcf.acp.group.users"><![CDATA[Registered users]]></item>\r
+       </category>\r
+       <category name="wcf.acp.login">\r
+               <item name="wcf.acp.login"><![CDATA[Login]]></item>\r
+               <item name="wcf.acp.login.data"><![CDATA[Login details]]></item>\r
+       </category>\r
+       <category name="wcf.acp.masterPassword">\r
+               <item name="wcf.acp.masterPassword"><![CDATA[Master password]]></item>\r
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Confirm master password]]></item>\r
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Master password required]]></item>\r
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[This page or action requires you to enter the master password due to security reasons. You only need to do so once within a session. If you have forgotten the master password you can reset it by deleting the file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[The master password is not correct.If you have forgotten the master password you can reset it by deleting the file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[The entered passwords are not identical.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[The password is not secure. It has to contain at least eight characters, small and capital latin letters as well as numbers and special characters. It must not be identically with passwords of administrators of this page.]]></item>\r
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Suggestion]]></item>\r
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Use suggestion]]></item>\r
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Set master password]]></item>\r
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[The master password is an additional protection for functions that are relevant to security. You should use a very secure password that must not be identically with your normal administrator password, unknown to others and not used on other websites.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.menu">\r
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Automatic update]]></item>\r
+               <item name="wcf.acp.menu.link.content"><![CDATA[Content]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.add"><![CDATA[Add new cronjob]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.showLog"><![CDATA[View cronjob logs]]></item>\r
+               <item name="wcf.acp.menu.link.cronjobs.view"><![CDATA[List cronjobs]]></item>\r
+               <item name="wcf.acp.menu.link.display"><![CDATA[Design]]></item>\r
+               <item name="wcf.acp.menu.link.group"><![CDATA[User groups]]></item>\r
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Add new group]]></item>\r
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[E-mail all group members]]></item>\r
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Group overview]]></item>\r
+               <item name="wcf.acp.menu.link.log"><![CDATA[Log]]></item>\r
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>\r
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Maintenance]]></item>\r
+               <item name="wcf.acp.menu.link.option"><![CDATA[Options]]></item>\r
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Import &amp; export]]></item>\r
+               <item name="wcf.acp.menu.link.package"><![CDATA[Packages]]></item>\r
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Search packages]]></item>\r
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Install new package]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Add new server]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Server overview]]></item>\r
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[List installed packages]]></item>\r
+               <item name="wcf.acp.menu.link.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.menu.link.user"><![CDATA[User]]></item>\r
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Add user]]></item>\r
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[List users]]></item>\r
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-mail all users]]></item>\r
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Users]]></item>\r
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Bulk processing of users]]></item>\r
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Search for users]]></item>\r
+       </category>\r
+       <category name="wcf.acp.option">\r
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Exclude hostnames]]></item>\r
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Enter one hostname each row you want to exclude from this site.]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[Exclude IP addresses]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Enter one IP address each row you want to exclude from this site.]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Exclude user agents]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Enter one user agent each row you want to exclude from this site.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Enter the address of the memcache server. You can enter one server each row.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Use persistent connections]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[By enabling this option a persistent connection to the memcache server will be used.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache type]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Please select the type of cache you want to use. Some of the types have special requirements to the server system and cannot be used in your environment.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[File system (default)]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (experimental)]]></item>\r
+               <item name="wcf.acp.option.category.general"><![CDATA[General]]></item>\r
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[General]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache stores data in the memory that is often accessed. This may reduce the database load dramatically. Read more about the memcache on the following site:\r
+<ul>\r
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>\r
+</ul>]]></item>\r
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Date and time]]></item>\r
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy server]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[You can configure optional proxy servers for connections to external servers.]]></item>\r
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[General]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Transmission]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Disable forum temporarily]]></item>\r
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module"><![CDATA[Modules on / off]]></item>\r
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Content]]></item>\r
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Display]]></item>\r
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>\r
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.user"><![CDATA[User]]></item>\r
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security"><![CDATA[Security]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internet pages are often attacked by programs and robots. E.g. it is possible to create hundreds of user accounts automatically. You can protect yourself against these spam bots with so called <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">Captcha images</a> on every place where web forms can be submitted. Unregistered users then first have to identify the code on the Captcha before they can submit the form. Robots cannot read the code. Please not that Captcha images cannot be read by blind and visually impaired people.]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Blacklist]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Censorship]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general"><![CDATA[General]]></item>\r
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessions]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.user"><![CDATA[Users]]></item>\r
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookie domain]]></item>\r
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Enter here the domain in which the cookie should be used. This is optional, so in most cases you don't need to specify the cookie domain.]]></item>\r
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookie path]]></item>\r
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[The cookie path is concurrent to the document root of your site - e.g. &quot;/forum&quot; for http://www.woltlab.com/forum.]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Cookie prefix]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Enter a prefix to be used for the cookie name here.]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Enable automatic Daylight Savings Time]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Should the clock automatically change according to the summer/winter time?]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Use cache method for session data]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Should the selected cache method be used to save the session data?]]></item>\r
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[The information you have entered is not valid.]]></item>\r
+               <item name="wcf.acp.option.export"><![CDATA[Export options]]></item>\r
+               <item name="wcf.acp.option.export.download"><![CDATA[Download the exported options]]></item>\r
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Download the exported options as a backup file to your local machine.]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Enable Gzip compression]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Enable this option to send content from the server to clients in a compressed form. This option reduces traffic.]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Disable caching of pages in browsers]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Enabling this option will prevent browsers from caching the pages.]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Compression level]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[A value of 1 to 9 is required. For optimum output for compression and server performance, we recommend a value of 1.]]></item>\r
+               <item name="wcf.acp.option.import"><![CDATA[Import options]]></item>\r
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>\r
+               <item name="wcf.acp.option.import.success"><![CDATA[The options have been imported successfully.]]></item>\r
+               <item name="wcf.acp.option.import.upload"><![CDATA[Upload the options]]></item>\r
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Upload the options to be imported from your local machine.]]></item>\r
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Import &amp; Export options]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Administrator's e-mail address]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Enter the administrator's e-mail address here.]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Path to the debug log file]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Enter the path to the log file here]]></item>\r
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Sender's e-mail address]]></item>\r
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Enter the sender's e-mail address that should be used for automated e-mails here.]]></item>\r
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Sender's name]]></item>\r
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Enter the sender's name that should be used for automated e-mails here.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-mail method]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Choose an e-mail transmission method.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>\r
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Sender's signature]]></item>\r
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Enter a signature that should be sent with system e-mails here.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP host]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Enter the SMTP server name here.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP password]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Enter the SMTP password here.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP port]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Enter the SMTP server port here.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP username]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Enter the SMTP user name here.]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[Enable the &quot;-f&quot; parameter]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Some servers may require the &quot;-f&quot; parameter to be used when sending e-mails. If your users experience problems with receiving e-mails, try enabling this option.]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Use formatted e-mail addresses]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Sender's and receiver's addresses are formatted in &quot;Name &lt;email@domain.tld&gt;&quot;. This option is not supported by all mail servers and should be turned off in case of any problems.]]></item>\r
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Enable master password]]></item>\r
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Pages and forms within the admin panel that are relevant to security can be protected with an additional master password.]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server for HTTP connections]]></item>\r
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Session timeout]]></item>\r
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Enter how long a session should remain valid for here [seconds].]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Check IP address of session]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[The number or block of an IP address that should be checked while reading the session data. A high number can exclude users that use changing IP addresses.]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Check user agent of session]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Should the user agent be checked while reading the session data?]]></item>\r
+               <item name="wcf.acp.option.success"><![CDATA[Your option changes have been successfully saved.]]></item>\r
+               <item name="wcf.acp.option.timezone"><![CDATA[Time zone offset]]></item>\r
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Choose your default time zone for your site.]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Users online timeout]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Enter here how long users should remain marked as online after they are inactive [seconds].]]></item>\r
+               <item name="wcf.acp.option.category.general.page"><![CDATA[Page]]></item>\r
+               <item name="wcf.acp.option.category.general.page.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.meta_description"><![CDATA[Meta description]]></item>\r
+               <item name="wcf.acp.option.meta_description.description"><![CDATA[Enter a meta description here.]]></item>\r
+               <item name="wcf.acp.option.meta_keywords"><![CDATA[Meta keywords]]></item>\r
+               <item name="wcf.acp.option.meta_keywords.description"><![CDATA[Enter some meta keywords here.]]></item>\r
+               <item name="wcf.acp.option.page_description"><![CDATA[Page description]]></item>\r
+               <item name="wcf.acp.option.page_description.description"><![CDATA[Enter a short description of the page.]]></item>\r
+               <item name="wcf.acp.option.page_title"><![CDATA[Page title]]></item>\r
+               <item name="wcf.acp.option.page_title.description"><![CDATA[Enter the global title of the page here. That title will show up inside the board header, if you have enabled it with the style editor.]]></item>\r
+               <item name="wcf.acp.option.page_url"><![CDATA[Page URL]]></item>\r
+               <item name="wcf.acp.option.page_url.description"><![CDATA[Please enter the URL of the page (without trailing slash).]]></item>\r
+               <item name="wcf.acp.option.page_urls"><![CDATA[Further URLs]]></item>\r
+               <item name="wcf.acp.option.page_urls.description"><![CDATA[Enter further URLs which are also directed at your site.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.package">\r
+               <item name="wcf.acp.package.cancel"><![CDATA[Cancel package installation]]></item>\r
+               <item name="wcf.acp.package.description"><![CDATA[Description]]></item>\r
+               <item name="wcf.acp.package.install"><![CDATA[Package Installation]]></item>\r
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Cancel the installation]]></item>\r
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Are you sure you would like to cancel this installation?]]></item>\r
+               <item name="wcf.acp.package.install.error"><![CDATA[Package dependencies could not be satisfied for this Package.]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[The {if $action == 'install'}package installation{else}package update{/if} of package &quot;{$packageName}&quot; in version {$packageVersion} cannot be executed due to incompatibilities with the following {if $excludedPackages|count == 1}package{else}packages{/if}:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} in version {$excludedPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Following package doesn't{else}Following packages don't{/if} allow the {if $action == 'install'}package installation{else}package update{/if} of package &quot;{$packageName}&quot; in version {$packageVersion} due to incompatibilities:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} in version {$excludingPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Following package is{else}Following packages are{/if} incompatible with package &quot;{$packageName}&quot; in version {$packageVersion}. If you proceed installation the {if $excludingPackages|count == 1}package{else}packages{/if} probably won't work anymore.]]></item>\r
+\r
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}Installed{else}{if $package.file|isset}is located within this Package{else}Not available{/if}{/if})</span>]]></item>\r
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Are you sure you would like to cancel the installation of this package?]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[The following packages can be updated with this package]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Select one of the following packages, in order to update its version. If you would like to install the package again, please click on &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[A copy of this package is already installed. If you continue, a further copy of this package will be installed. If you would like to update an available copy of this package, please select the copy from the following list.]]></item>\r
+               <item name="wcf.acp.package.install.version"><![CDATA[Package Version:]]></item>\r
+               <item name="wcf.acp.package.installDate"><![CDATA[Installation date]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[While unpacking the files of this package the following error occured:]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[The following files could not be unpacked successfully. Please check if the destination folder is writable.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Conflicting Tables]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Do not overwrite these tables and do not ask me again for this installation.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Overwrite the existing tables and do not ask me again for this installation.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Required changes]]></item>\r
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Tables affected]]></item>\r
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Existing database tables conflict with the tables required to be installed by this package. Please choose whether to overwrite these tables.]]></item>\r
+               <item name="wcf.acp.package.list"><![CDATA[Installed packages]]></item>\r
+               <item name="wcf.acp.package.list.author"><![CDATA[Author]]></item>\r
+               <item name="wcf.acp.package.list.count"><![CDATA[A total of {#$items} packages installed]]></item>\r
+               <item name="wcf.acp.package.list.date"><![CDATA[Date]]></item>\r
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.package.list.name"><![CDATA[Name]]></item>\r
+               <item name="wcf.acp.package.list.other"><![CDATA[Package]]></item>\r
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>\r
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Standalone application]]></item>\r
+               <item name="wcf.acp.package.list.version"><![CDATA[Version]]></item>\r
+               <item name="wcf.acp.package.optionals"><![CDATA[Install optional packages]]></item>\r
+               <item name="wcf.acp.package.optionals.description"><![CDATA[The selected package brings the following options. Please select those you would like to install.]]></item>\r
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (This Package is already installed.)]]></item>\r
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (The requirements of this Package have not been fulfilled.)]]></item>\r
+               <item name="wcf.acp.package.packageDir"><![CDATA[Installation folder]]></item>\r
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Another application is already installed in this folder.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[This folder is not valid.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[This folder is not writable.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[This folder is already in use by the WoltLab Community Framework. Please choose a different location.]]></item>\r
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Please enter the installation folder name here.]]></item>\r
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[This application is accessible through the following URL after installation in this folder:]]></item>\r
+               <item name="wcf.acp.package.requirements"><![CDATA[Select dependencies]]></item>\r
+               <item name="wcf.acp.package.requirements.description"><![CDATA[The current package requires another package that is already installed several times. Please choose the instance that is required.]]></item>\r
+               <item name="wcf.acp.package.rollback"><![CDATA[Rollback package installation]]></item>\r
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Version {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>\r
+               <item name="wcf.acp.package.startInstall"><![CDATA[Install new package]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[The chosen package has no valid installation routine.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[The archive you have given is not a valid package.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[The package &quot;{$package->getName()}&quot; could not be updated with the supplied archive.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[No files were found within the specified directory.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[The chosen package is already installed. Packages can not be installed more than one time.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[The upload of the chosen archive has failed.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Select package source]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Enter the path of the package located on your server]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Enter a direct path to the package-file here. An internet address can be used or alternatively the path to the package file using the server's file system.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Upload package from your local computer]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Enter the package file to be uploaded from your computer here.]]></item>\r
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Update Package &quot;{$package->getName()}&quot;]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Installing menu entries for the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Installing template patches for the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Installing templates for the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.install.CronjobsPackageInstallationPlugin"><![CDATA[Installing cronjobs ...]]></item>\r
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Installing event listener ...]]></item>\r
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Unpacking package files ...]]></item>\r
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Installing usergroup options ...]]></item>\r
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Installing package languages ...]]></item>\r
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Installing package options ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Executing special scripts ...]]></item>\r
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Installing database entries...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Installing template patches ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Installing package templates ...]]></item>\r
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Installing user profile fields ...]]></item>\r
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Checking for possible conflicts ...]]></item>\r
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Executing package plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Installation is complete]]></item>\r
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Installing optional packages ...]]></item>\r
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Registering package ...]]></item>\r
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Installing package plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Parent package allocation is being done ...]]></item>\r
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Checking dependencies ...]]></item>\r
+               <item name="wcf.acp.package.step.title"><![CDATA[Package <b>{$packageName|encodeJS}</b>: ]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Removing menu items from the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Removing template patches of the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Removing templates from the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.CronjobsPackageInstallationPlugin"><![CDATA[Uninstalling cronjobs ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Removing event listener ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Removing package files ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Removing usergroup options ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Removing package languages ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Removing package options ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Removing database entries...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Removing template patches ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Removing package templates ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Removing user profile fields ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Executing package plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Package removal finished]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Removing optional packages ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Removing package plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Removing package requirements ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Updating menu items in the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Updating template patches in the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Updating templates in the Administration Control Panel ...]]></item>\r
+               <item name="wcf.acp.package.step.update.CronjobsPackageInstallationPlugin"><![CDATA[Updating cronjobs ...]]></item>\r
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Updating event listener ...]]></item>\r
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Unpacking package files ...]]></item>\r
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Updating usergroup options ...]]></item>\r
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Updating package languages ...]]></item>\r
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Updating package options ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Executing special scripts ...]]></item>\r
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Updating database entries ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Updating template patches ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Updating package templates ...]]></item>\r
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Updating user profile fields ...]]></item>\r
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Executing package plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Checking for possible conflicts ...]]></item>\r
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Package update finished]]></item>\r
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Updating optional packages ...]]></item>\r
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Updating package ...]]></item>\r
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Updating package plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Parent package allocation is being done ...]]></item>\r
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Checking dependencies ...]]></item>\r
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[The patch that this package is trying to apply has failed because this patch is not compliant to its target file. Therefore this package cannot be installed. Please click the &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; button.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Re-patching of the following templates has failed:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Originally patched by: {$failure.packageName})<br />{/foreach}The original patch package that was previously applied may no longer function. You should still continue with this update by clicking on the &quot;{lang}wcf.global.button.next{/lang}&quot; button.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[The patch that this package is trying to remove has failed because its target file has been externally amended. Therefore this package cannot be removed. Please click the &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; button.]]></item>\r
+               <item name="wcf.acp.package.uninstall"><![CDATA[Package removal]]></item>\r
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Cancel package-removal]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[It is not possible to uninstall these packages, because there is at least one dependent package, that cannot be uninstalled.]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Upon final confirmation {if $dependentPackages|count == 1}this package{else}these packages{/if} will be removed without any further promting.]]></item>\r
+               <item name="wcf.acp.package.update"><![CDATA[Package update]]></item>\r
+               <item name="wcf.acp.package.updateDate"><![CDATA[Date of update]]></item>\r
+               <item name="wcf.acp.package.view.author"><![CDATA[Author:]]></item>\r
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Go to the Administration Control Panel]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Remove package]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Remove all packages]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Are you sure that you would like to remove this package?]]></item>\r
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Update package]]></item>\r
+               <item name="wcf.acp.package.view.date"><![CDATA[Date:]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Dependent packages]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[This package has a requirement from {if $dependentPackages|count == 1}one other package.{else}{#$dependentPackages|count} other packages.{/if}]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}This package is required by one other Package{else}{#$dependentPackages|count} Packages are directly or indirectly dependent upon this package{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.dir"><![CDATA[Installation folder:]]></item>\r
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Identifier:]]></item>\r
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Installed instance:]]></item>\r
+               <item name="wcf.acp.package.view.parent"><![CDATA[Parent package:]]></item>\r
+               <item name="wcf.acp.package.view.properties"><![CDATA[Properties]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Required packages]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[This package has a requirement of {if $requiredPackages|count == 1}one other package.{else}{#$requiredPackages|count} other packages.{/if}]]></item>\r
+               <item name="wcf.acp.package.view.url"><![CDATA[Homepage:]]></item>\r
+               <item name="wcf.acp.package.view.version"><![CDATA[Installed version:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.packageUpdate">\r
+               <item name="wcf.acp.packageUpdate"><![CDATA[Update packages]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Authentication with update server]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Connection data]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Username and password have not been accepted.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Password]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Please enter a valid password.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Username]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Please enter a valid username.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[User login]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Server message]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Server name]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Save user data permanantly]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[The entered user data will be saved permanently, so you do not have to input them again.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Address]]></item>\r
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Installed version]]></item>\r
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[An error occured: ]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[The download of the package {$package} has been failed.]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[An error occured while trying to download the package list.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[The following {if $excludedPackages|count == 1}conflict{else}conflicts{/if} occured:]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[The installed package &quot;{$excludedPackage.existingPackageName}&quot; is incompatible with the package &quot;{$excludedPackage.packageName}&quot; in version {$excludedPackage.packageVersion}.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[The package &quot;{$excludedPackage.packageName}&quot; in version {$excludedPackage.packageVersion} is not compatible with the installed package &quot;{$excludedPackage.existingPackageName}&quot;.]]></item>\r
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} will be installed]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[There are currently no updates available.]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[You have not selected any update.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Options]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[This package is already installed and unique. Therefore it cannot be installed another time.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Install package]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Install another package instance (packages is already installed {#$package.instances} time{if $package.instances > 1}s{/if})]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Update installed package {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} version {$updatableInstance.packageVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Search packages]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Author]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Search for ...]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Hide already installed unique packages]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Package name]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Package name and description]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Update server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Search all update server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Type of package]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Other packages]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Plugin for already installed packages]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Standalone application]]></item>\r
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Select all packages]]></item>\r
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} is updated to {$package.toVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[The following package updates and installations will be processed:]]></item>\r
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[New version]]></item>\r
+       </category>\r
+       <category name="wcf.acp.sessionLog">\r
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Actions of the logged session of &quot;{$sessionLog->username}&quot;]]></item>\r
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[There is a total of {#$items} logged action{if $items != 1}s{/if}]]></item>\r
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Actions]]></item>\r
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Class name]]></item>\r
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP address]]></item>\r
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Last action]]></item>\r
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Package]]></item>\r
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Method]]></item>\r
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Date]]></item>\r
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[User agent]]></item>\r
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Logged sessions]]></item>\r
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[There is a total of {#$items} logged session{if $items != 1}s{/if}]]></item>\r
+       </category>\r
+       <category name="wcf.acp.updateServer">\r
+               <item name="wcf.acp.updateServer.add"><![CDATA[Add server]]></item>\r
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[The server has been successfully added.]]></item>\r
+               <item name="wcf.acp.updateServer.data"><![CDATA[Server data]]></item>\r
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Delete server]]></item>\r
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[The server has been successfully deleted.]]></item>\r
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Do you really want to delete this server?]]></item>\r
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Disable]]></item>\r
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Edit server]]></item>\r
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Your changes have been successfully saved.]]></item>\r
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Enable]]></item>\r
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Error messages]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Password]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Please enter a valid password (optional).]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Username]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Please enter a valid user name (optional).]]></item>\r
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[The following error occured while trying to connect:]]></item>\r
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} server available]]></item>\r
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Server id]]></item>\r
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Packages]]></item>\r
+               <item name="wcf.acp.updateServer.server"><![CDATA[Address]]></item>\r
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Please enter the URL to a package server.]]></item>\r
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[The entered address is invalid.]]></item>\r
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>\r
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Last access]]></item>\r
+               <item name="wcf.acp.updateServer.view"><![CDATA[Available update server]]></item>\r
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[There are no update server available.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.user">\r
+               <item name="wcf.acp.user.add"><![CDATA[Add new user]]></item>\r
+               <item name="wcf.acp.user.add.data"><![CDATA[User details]]></item>\r
+               <item name="wcf.acp.user.add.success"><![CDATA[The new user has been successfully saved.]]></item>\r
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Group assignment]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Assign the following users to the selected group(s)]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[The users have been successfully assigned to your chosen groups.]]></item>\r
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Group assignment]]></item>\r
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Export e-mail addresses]]></item>\r
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Send an e-mail]]></item>\r
+               <item name="wcf.acp.user.delete"><![CDATA[Delete user(s)]]></item>\r
+               <item name="wcf.acp.user.delete.error"><![CDATA[No user could be deleted.]]></item>\r
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}The user has {else}{#$deletedUsers} users have{/if} been successfully deleted.]]></item>\r
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Are you sure that you would like to delete this user?]]></item>\r
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Are you sure that you would like to delete the selected User(s)?]]></item>\r
+               <item name="wcf.acp.user.edit"><![CDATA[Edit user]]></item>\r
+               <item name="wcf.acp.user.edit.success"><![CDATA[The changes for this user have been successfully saved.]]></item>\r
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[You are currently editing your own user account. Changing the permissions of this user group might lead to locking yourself out of the Administration Control Panel. Please be careful!]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Export e-mail addresses]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Export file format]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Export options]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Export the e-mail addresses from the following users]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Separate the addresses with a ]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Enclose the addresses with ]]></item>\r
+               <item name="wcf.acp.user.groups"><![CDATA[Group memberships]]></item>\r
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Find users that are not members of the chosen user groups.]]></item>\r
+               <item name="wcf.acp.user.list"><![CDATA[Users]]></item>\r
+               <item name="wcf.acp.user.list.all"><![CDATA[All users]]></item>\r
+               <item name="wcf.acp.user.list.count"><![CDATA[A total of {#$items} user{if $items > 1}s{/if}]]></item>\r
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 user selected" : this.count+" users selected"]]></item>\r
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Bulk processing of users]]></item>\r
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Action]]></item>\r
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Conditions]]></item>\r
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[The chosen action has been executed successfully on {#$affectedUsers} users.]]></item>\r
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[The bulk processor will perform the following tasks <strong>without additional security notification</strong>, on all users matching the set conditions. Bulk processing can be very performance intensive, so it should only be executed when the forum is offline. To have a correct display of your content you should update the counters. The processing can not be reversed, so please be attentive when using this function.]]></item>\r
+               <item name="wcf.acp.user.search"><![CDATA[Search for users]]></item>\r
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Search criteria]]></item>\r
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[General search criteria]]></item>\r
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profile search criteria]]></item>\r
+               <item name="wcf.acp.user.search.display"><![CDATA[Display]]></item>\r
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Columns]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Other]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profile]]></item>\r
+               <item name="wcf.acp.user.search.display.general"><![CDATA[General]]></item>\r
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Users per page]]></item>\r
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sorting]]></item>\r
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[No users have been found.]]></item>\r
+               <item name="wcf.acp.user.search.matches"><![CDATA[Your search produced {if $items == 1}one result{else}{#$items} results{/if}]]></item>\r
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Search within results]]></item>\r
+               <item name="wcf.acp.user.sendMail"><![CDATA[Send an e-mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-Mail all Users]]></item>\r
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[Send e-mail as HTML]]></item>\r
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Sender]]></item>\r
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Here you can enter the sender's e-mail address in the following format:</p>\r
+<p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Senders name &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>\r
+<p>If you have completely filled in the section under System -> Options -> E-mail, then this field will automatically be filled in. If you are sending e-mails using SMTP, then the sender's e-mail-Address must also be accepted by the server.</p>]]></item>\r
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[E-mail all group members]]></item>\r
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Send an e-mail to the members of the following user groups:]]></item>\r
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Send an e-mail to the following users]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Subject]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Enter here the e-mail subject.]]></item>\r
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Message]]></item>\r
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Enter here the message you want to send to users.]]></item>\r
+               <item name="wcf.acp.user.userNote"><![CDATA[Welcome {$this->user->username}.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.worker">\r
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Current process]]></item>\r
+               <item name="wcf.acp.worker.description"><![CDATA[Please leave this browser window open until the process has successfully completed. Do NOT try to login to your administrations area using a separate browser window, as doing so may damage the current process.]]></item>\r
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Process completed successfully]]></item>\r
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Processing ...]]></item>\r
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% complete]]></item>\r
+               <item name="wcf.acp.worker.title"><![CDATA[Processing ...]]></item>\r
+       </category>\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Back]]></item>\r
+               <item name="wcf.global.button.close"><![CDATA[Close]]></item>\r
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>\r
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>\r
+               <item name="wcf.global.button.delete"><![CDATA[Delete]]></item>\r
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Do you really want to delete this item?]]></item>\r
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Delete completely]]></item>\r
+               <item name="wcf.global.button.edit"><![CDATA[Edit]]></item>\r
+               <item name="wcf.global.button.editor.jump"><![CDATA[Use full editor]]></item>\r
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>\r
+               <item name="wcf.global.button.mark"><![CDATA[Select]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Next &raquo;]]></item>\r
+               <item name="wcf.global.button.preview"><![CDATA[Preview]]></item>\r
+               <item name="wcf.global.button.reset"><![CDATA[Reset]]></item>\r
+               <item name="wcf.global.button.submit"><![CDATA[Submit]]></item>\r
+               <item name="wcf.global.button.unmark"><![CDATA[Unselect]]></item>\r
+               <item name="wcf.global.date.day"><![CDATA[Day]]></item>\r
+               <item name="wcf.global.date.days"><![CDATA[Days]]></item>\r
+               <item name="wcf.global.date.hour"><![CDATA[Hour]]></item>\r
+               <item name="wcf.global.date.hours"><![CDATA[Hours]]></item>\r
+               <item name="wcf.global.date.minute"><![CDATA[Minute]]></item>\r
+               <item name="wcf.global.date.minutes"><![CDATA[Minutes]]></item>\r
+               <item name="wcf.global.date.month"><![CDATA[Month]]></item>\r
+               <item name="wcf.global.date.months"><![CDATA[Months]]></item>\r
+               <item name="wcf.global.date.second"><![CDATA[Second]]></item>\r
+               <item name="wcf.global.date.seconds"><![CDATA[Seconds]]></item>\r
+               <item name="wcf.global.date.week"><![CDATA[Week]]></item>\r
+               <item name="wcf.global.date.weeks"><![CDATA[Weeks]]></item>\r
+               <item name="wcf.global.date.year"><![CDATA[Year]]></item>\r
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Specifying the year is optional.]]></item>\r
+               <item name="wcf.global.date.years"><![CDATA[Years]]></item>\r
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>\T\o\d\a\y</b>, g:ia]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[\Y\e\s\t\e\r\d\a\y, g:ia]]></item>\r
+               <item name="wcf.global.dateInputOrder"><![CDATA[month-day-year]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>\r
+               <item name="wcf.global.defaultValue"><![CDATA[Default]]></item>\r
+               <item name="wcf.global.error.backward"><![CDATA[Back to last page]]></item>\r
+               <item name="wcf.global.error.empty"><![CDATA[Please enter the required information for this field.]]></item>\r
+               <item name="wcf.global.error.file.notFound"><![CDATA[The file could not be found.]]></item>\r
+               <item name="wcf.global.error.illegalLink"><![CDATA[The link you are trying to reach is no longer available or is invalid.]]></item>\r
+               <item name="wcf.global.error.permissionDenied"><![CDATA[You are not allowed to enter this page. You do not have the required permissions to enter this page.]]></item>\r
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[You are not allowed to enter this page.]]></item>\r
+               <item name="wcf.global.error.title"><![CDATA[Error message]]></item>\r
+               <item name="wcf.global.form.error"><![CDATA[The data you have entered are invalid. Please check the information you have given in the marked fields.]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabic]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnian]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Czech]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Danish]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[German]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[German (Informal)]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Greek]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[English]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spanish]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persian (Farsi)]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finnish]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[French]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebrew]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Croatian]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Hungarian]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italian]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japanese]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Korean]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Dutch]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norwegian]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polish]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portuguese]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portuguese (Brazil)]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Romanian]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russian]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slovak]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbian]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Swedish]]></item>\r
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Turkish]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinese (Simplified)]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinese (Traditional)]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[en_US]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.locale.win"><![CDATA[english]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.multiSelect"><![CDATA[Multiple items can be selected by holding the &quot;Ctrl/Shift&quot; key (Windows) or &quot;Command&quot; (Mac OS) key and clicking the items required.]]></item>\r
+               <item name="wcf.global.page.input"><![CDATA[Go to next page]]></item>\r
+               <item name="wcf.global.page.next"><![CDATA[Next page]]></item>\r
+               <item name="wcf.global.page.previous"><![CDATA[Previous page]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>\r
+               <item name="wcf.global.redirect.title"><![CDATA[Redirection]]></item>\r
+               <item name="wcf.global.redirect.url"><![CDATA[Please click here if the automatic redirection does not work!]]></item>\r
+               <item name="wcf.global.scrollUp"><![CDATA[Go to the top of the page]]></item>\r
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Exact match]]></item>\r
+               <item name="wcf.global.shortTimeFormat"><![CDATA[M jS Y, g:ia]]></item>\r
+               <item name="wcf.global.skipToContent"><![CDATA[Skip navigation]]></item>\r
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[ascending]]></item>\r
+               <item name="wcf.global.sortOrder.descending"><![CDATA[descending]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>\r
+       </category>\r
+       <category name="wcf.imageViewer">\r
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Image " + (this.currentIndex + 1) + " of " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>\r
+               <item name="wcf.imageViewer.close"><![CDATA[Close]]></item>\r
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Show only this image (quits the image viewer)]]></item>\r
+               <item name="wcf.imageViewer.next"><![CDATA[Next image]]></item>\r
+               <item name="wcf.imageViewer.pause"><![CDATA[Stop slideshow]]></item>\r
+               <item name="wcf.imageViewer.play"><![CDATA[Start slideshow (changes the image every 5 seconds)]]></item>\r
+               <item name="wcf.imageViewer.previous"><![CDATA[Previous image]]></item>\r
+       </category>\r
+       <category name="wcf.option">\r
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Canary Islands, Lisbon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>\r
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brussels, Copenhagen, Madrid, Paris, Prague, Rome, Sarajevo, Stockholm, Tunis, Warsaw, Vienna]]></item>\r
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athens, Beirut, Bucharest, Helsinki, Istanbul, Jerusalem, Cairo, Cape Town, Khartoum, Kiev, Minsk, Sofia]]></item>\r
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Ababa, Antananarivo, Baghdad, Dodoma, Kampala, Kuwait City, Mogadishu, Moscow, Nairobi, Riyadh]]></item>\r
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Tehran]]></item>\r
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Yerevan, Muscat, R&eacute;union, Tbilisi]]></item>\r
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>\r
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Ashgabat, Bishkek, Dushanbe, Islamabad, Yekaterinburg, Karachi, Maldive Islands, Tashkent]]></item>\r
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, New Delhi]]></item>\r
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>\r
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Novosibirsk]]></item>\r
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Islands, Yangon]]></item>\r
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>\r
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Beijing, Perth, Singapore, Taipei, Ulaanbaatar]]></item>\r
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Western Australia)]]></item>\r
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seoul, Tokyo]]></item>\r
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>\r
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>\r
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Island (Australia)]]></item>\r
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, New Caledonia, Solomon Islands]]></item>\r
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolk Island]]></item>\r
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, South Tarawa, Fiji, Kamchatka, Marshall Islands, Wellington]]></item>\r
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Islands (New Zealand)]]></item>\r
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenix Islands]]></item>\r
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Islands, Christmas Island]]></item>\r
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azores, Cape Verde Islands]]></item>\r
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mid-Atlantic]]></item>\r
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Greenland, Montevideo]]></item>\r
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Newfoundland]]></item>\r
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantic Time (Canada), Asunci&oacute;n, La Paz, Port-of-Spain, Santiago]]></item>\r
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>\r
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Eastern Time (US &amp; Canada), Bogot&aacute;, Lima, San Francisco de Quito]]></item>\r
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Central Time (US &amp; Canada), Central America, Mexico City]]></item>\r
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Time (US &amp; Canada), Chihuahua, Mazatlan]]></item>\r
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pacific Time (US &amp; Canada), Tijuana]]></item>\r
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>\r
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) French Polynesia]]></item>\r
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cook Islands, Hawaii]]></item>\r
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midway Islands, Samoa]]></item>\r
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>\r
+       </category>\r
+       <category name="wcf.page">\r
+               <item name="wcf.page.pageNo"><![CDATA[Page {#$pageNo}]]></item>\r
+       </category>\r
+       <category name="wcf.user">\r
+               <item name="wcf.user.confirmEmail"><![CDATA[Confirm E-mail Address]]></item>\r
+               <item name="wcf.user.confirmPassword"><![CDATA[Confirm password]]></item>\r
+               <item name="wcf.user.email"><![CDATA[E-mail Address]]></item>\r
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[The given e-mail address and confirmation e-mail address are not identical.]]></item>\r
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[The given password and confirmation password are not identical.]]></item>\r
+               <item name="wcf.user.error.email.notUnique"><![CDATA[The e-mail address you have entered has already been used by another user.]]></item>\r
+               <item name="wcf.user.error.email.notValid"><![CDATA[The e-mail address you have entered is not valid.]]></item>\r
+               <item name="wcf.user.error.password.false"><![CDATA[The password is not correct.]]></item>\r
+               <item name="wcf.user.error.username.notFound"><![CDATA[The user name &quot;{$username}&quot; could not be found.]]></item>\r
+               <item name="wcf.user.error.username.notUnique"><![CDATA[The user name you have entered is already in use.]]></item>\r
+               <item name="wcf.user.error.username.notValid"><![CDATA[The username you have entered is not valid.]]></item>\r
+               <item name="wcf.user.language"><![CDATA[Language]]></item>\r
+               <item name="wcf.user.language.description"><![CDATA[Please select the user interface language to be shown in!]]></item>\r
+               <item name="wcf.user.logout"><![CDATA[Logout]]></item>\r
+               <item name="wcf.user.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.user.registrationDate"><![CDATA[Date of registration]]></item>\r
+               <item name="wcf.user.userID"><![CDATA[User ID]]></item>\r
+               <item name="wcf.user.username"><![CDATA[Username]]></item>\r
+               <item name="wcf.user.visibleLanguages"><![CDATA[Show content in the following languages]]></item>\r
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Select the content languages that should be shown here.]]></item>\r
+       </category>\r
+       <category name="wcf.user.option">\r
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[The information you have entered is not valid.]]></item>\r
+       </category>\r
+</language>\r
diff --git a/wcfsetup/install/lang/fr.xml b/wcfsetup/install/lang/fr.xml
new file mode 100644 (file)
index 0000000..f1efeaa
--- /dev/null
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="fr">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[Panneau de contrôle de l’administration]]></item>
+               <item name="wcf.acp.help"><![CDATA[Aide]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[Aide complète]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[Désactiver l’aide en ligne]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[Aide intéractive]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Changer le package]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[Recherche étendue ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[Plan du site]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Empty cache]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[The cache has been successfully emptied.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Are you sure that you want to completely empty the cache?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[Settings]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[Files]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[Size]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[Source]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Last updated]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[Name]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Permissions]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[Size]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[Nouveau groupe d’utilisateurs]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Permissions]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[The usergroup has been successfully added.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[Administrateurs]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[Informations générales du groupe]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[Supprimer le groupe]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}This usergroup has{else}{#$deletedGroups} These usergroups have{/if} been successfully deleted.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Êtes-vous sûr de vouloir supprimer ce groupe d’utilisateurs ?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[Modifier le groupe]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[Your usergroup changes have been successfully saved.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Vous êtes actuellement membre de ce groupe. Il est possible que les modifications de permissions du groupe vous bloquent l’accès au centre d’administration. Soyez prudent !]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Tout le monde]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[N° du groupe]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[Nom du groupe]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Indiquez le nom du groupe d’utilisateurs.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[Invités]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[Groupes d’utilisateurs]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[{#$items} groupes d’utilisateurs]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[Nombre de membres]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[Modérateurs]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Peut accéder au panneau de contrôle de l’administration ?]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[En activant cette option, les membres de ce groupe seront autorisé à entrer dans le panneau de contrôle de l’administration et, suivant leurs permissions, pourront effectuer un certain nombre d’actions.]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Can view private user options]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Members of this usergroup can view private user options.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Peut changer les options du système ?]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[En activant cette option, les membres de ce groupe seront autorisé à voir et changer les otions du système - Par exemple : Forum en ligne/hors ligne.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Can view logs]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Members of this usergroup can view the system logs.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Peut modifier les mises-à-jour actuelles du serveur]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Les membres de ce groupe peuvent modifier les mises-à-jour actuelles du serveur, et en ajouter de nouvelles.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Peut installer de nouveaux paquets]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Les membres de ce groupe peuvent installer des paquets supplémentaires.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Peut supprimer les paquets présents]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Les membres de ce groupe peuvent supprimer les paquets présents.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Peut mettre à jour les paquets présents]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Les membres de ce groupe peuvent mettre à jour les paquets présents.]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Accessible usergroups]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Members of this usergroup have access to the following groups. For example, here you can set if the usergroup has permission to edit themselves.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Peut ajouter de nouveaux groupes d’utilisateurs]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Les membres de ce groupe peuvent ajouter de nouveaux groupers d’utilisateurs.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Peut ajouter de nouveaux utilisateurs]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Les membres de ce groupe peuvent ajouter de nouveaux utilisateurs. Si l’option "Groupes d’utilisateurs accessibles" a été activée, alors le groupe d’utilisateur approprié peut aussi être assigné lors de la création de l’utilisateur.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Peut supprimer les groupes d’utilisateurs présents]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Les membres de ce groupe peuvent supprimer les groupes d’utilisateurs présents.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Peut supprimer les utilisateurs présents]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Les membres de ce groupe peuvent supprimer les utilisateurs présents.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Peut modifier les groupes d’utilisateurs présents]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Les membres de ce groupe peuvent modifier les groupes d’utilisateurs présents.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Peut modifier les adresses e-mail des utilisateurs]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Les membres de ce groupe peuvent modifier les adresses e-mail des utilisateurs.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Peut modifier les mots de passe des utilisateurs]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Les membres de ce groupe peuvent modifier les mots de passe des utilisateurs.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Peut modifier les paramètres des utilisateurs présents]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Les membres de ce groupe peuvent modifier les paramètres des utilisateurs présents.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Peut envoyer des e-mails aux utilisateurs]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Les membres de ce groupe peuvent voire les adresses e-mails des autres membres, et par conséquence leur envoyer des e-mails.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Peut rechercher les utilisateurs]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Les membres de ce groupe peuvent rechercher les utilisateurs et leurs profils.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Permissions d’administrateur]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Contenu]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Affichage]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Permissions générales administratives]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Maintenance]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[Fonctions système]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Gestion des paquets]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Fonctions d’utilisateur]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Gestion des groupes]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Gestion des utilisateurs]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Permissions de modérateur]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Permissions générales]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Les informations que vous avez indiquées sont invalides.]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[Afficher les membres de ce groupe d’utilisateurs]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super modérateur]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[Utilisateurs enregistrés]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[Identification]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[Détails d’identification]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[Master password]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Confirm master password]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Master password required]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[This page or action requires you to enter the master password due to security reasons. You only need to do so once within a session. If you have forgotten the master password you can reset it by deleting the file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[The master password is not correct.If you have forgotten the master password you can reset it by deleting the file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[The entered passwords are not identically.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[The password is not secure. It has to contain at least eight characters, small and capital latin letters as well as numbers and special characters. It must not be identically with passwords of administrators of this page.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Suggestion]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Use suggestion]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Set master password]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[The master password is an additional protection of functions that are relevant to security. You should use a very secure password that must not be identically with your normal administrator password, unknown to others and not used on other websites.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Mise à jour automatique]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[Contenu]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[Affichage]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[Groupes d’utilisateurs]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Ajouter un nouveau groupe]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[Envoyer un e-mail à tous les membres du groupe]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Vue générale des groupe]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[Log]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Maintenance]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[Options]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Import &amp; export]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[Paquets]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Recherche de paquets]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Installer un nouveau paquet]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Ajouter un nouveau serveur]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Vue générale des serveurs]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Liste des paquets installés]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[Système]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[Utilisateurs]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Add user]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[List users]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[Envoyer un e-mail à tous les utilisateurs]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Utilisateurs]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Bulk processing of users]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Recherche d’utilisateurs]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Exclude hostnames]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Enter one hostname each row you want to exclude from this site.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[Exclude IP addresses]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Enter one IP address each row you want to exclude from this site.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Exclude user agents]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Enter one user agent each row you want to exclude from this site.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Enter the address of the memcache server! You can enter one server each row.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Use persistent connections]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[By enabling this option a persistent connection to the memcache server will be used.]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache type]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Please select the type of cache you want to use! Some of the types have special requirements to the server system and cannot be used in your environment.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[File system (default)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (experimental)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[Général]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache stores data in the memory that is often accessed. This may reduce the database load dramatically. Read more about the memcache on the following site:
+<ul>
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Date et heure]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy server]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[You can configure optional proxy servers for connections to external servers.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Transmission]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Disable forum temporarily]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[Modules on / off]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Content]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Display]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[User]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[Security]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internet pages are often attacted by programs and robots. It is possible for example to create hundreds of user accounts automatically. You can protect yourself against these spam bots with the help of a so called <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">captcha image</a> on every place where web forms can be submitted. Unregistered users then have to identify the code on the captcha first before they can submit the form. Robots cannot read the code. Please not that captcha images cannot be read by blind and visually impaired people.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Blacklist]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Censorship]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessions]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[Utilisateurs]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Domaine du cookies]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Indiquez le domaine d’utilisation du cookies.]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Chemin du cookies]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Le chemin du cookie doit être relatif à la racine de votre site. Par exemple : "/" pour www.woltlab.com.]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Préfixe du cookie]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Indiquez le préfixe utilisé pour le nom du cookie.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Ajuster le passage automatique à l’heure d’été]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[En activant cette option, l’horloge du forum effectuera automatiquement les changements d’heure]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Use cache method for session data]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Should the selected cache method be used to save the session data?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Les informations que vous avez indiqué ne sont pas valide.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[Export options]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[Download the exported options]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Download the exported options as a backup file to your local machine.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Activer l’application content-type xhtml+xml]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[En activant cette option, vous autorisez l’affichage des pages utilisant l’application content-type xhtml+xml.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Activer la compression GZip]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[En activant cette option, le contenu du forum sera compressé sur le serveur, et envoyé compressé aux client. Cette option permet de réduire le trafic.]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Désactiver la mise en cache des pages dans les navigateurs]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[En activant cette option, les navigateurs ne mettront pas en cache les pages visitées du forum.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Niveau de compression]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Valeur comprise entre 1 et 9. Pour un rapport optimum entre la compression et les performances du serveur, nous vous recommandons d’utiliser la valeur 1.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[Import options]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[The options have been imported successfully.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[Upload the options]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Upload the options to be imported from your local machine.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Import &amp; Export options]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Adresse e-mail de l’administrateurs]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Indiquez l’adresse e-mail de l’administrateur.]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Chemin du fichier journal debug]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Indiquez le chemin d’accès au fichier journal debug]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Adresse e-mail de l’expéditeur]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Indiquez l’adresse utilisée pour l’envoie automatique d’e-mails.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Nom de l’expéditeur]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Indiquez le nom de l’expéditeur utilisé pour l’envoie automatique d’e-mails.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[Méthode d’envoie d’e-mail]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Choisissez une méthode de transmission des e-mails.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Signature de l’expéditeur]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Enter here a signature that should be sent with system e-mails.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[Hôte SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Indiquez le nom du serveur SMTP.]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[Mot de passe SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Indiquez le mot de passe SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[Port SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Indiquez le port du serveur SMTP.]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[Nom d’utilisateur SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Indiquez le nom d’utilisateur SMTP]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[Activer le paramètre &quot;-f&quot;]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Certains serveurs nécessite l’activation du paramètre "-f" pour l’envoie d’e-mails. Si vous rencontrez des problèmes, avec des utilisateurs ne recevant pas les e-mails, essayez l’activation de cette option.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Utiliser le format défini des adresses e-mail]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Les adresses des expéditeurs et destinataires sont formatés ainsi :  &quot;Nom &lt;email@domaine.tld&gt;&quot;. Cette option n’est pas prise en charge par tous les serveurs mails, et doit être désactivée en cas de problème.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Enable master password]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Pages and forms within the admin panel that are relevant to security can be protected with an additional master password.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Proxy-Server (FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[Proxy-Server for FTP connections]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server for HTTP connections]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Durée de session]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Indiquez la durée des sessions, en secondes.]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Check IP address of session]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[The number of block of an ip address that should be checked while reading the session data. A high number can exclude users that use changing IP addresses.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Check user agent of session]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Should the user agent be checked while reading the session data?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[Your option changes have been successfully saved.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[Fuseau horaire]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Choisissez le fuseau horaire par défaut de votre site.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Durée d’affichage d’utilisateur en ligne]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Indiquez la durée de la période d’inactivité pendant laquelle les utilisateurs apparaîssent toujours en ligne (en secondes).]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[Annuler l’installation de paquets]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[Description]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[Indiquez les détails d’accès par FTP]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[Détails d’accès par FTP]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Du fait de l’utilisation "Safe Mode" de php sur votre serveur, le paquet doit être installé avec l’aide des fonctions FTP. Veuillez indiquer un nom d’utilisateur et un mot de passe FTP pour ce serveur. Les informations rentrées ne seront pas enregistrées ni envoyées à un tier, mais ne seront utilisées que pour les besoins de l’installation. Pour cette raison, il est possibles que les informations de connexion FTP soit à nouveau demandées pendant la procédure d’installation.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Aucune connexion FTP n’a été possible avec les renseignements que vous avez entrés.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[Aucune connexion FTP sur le serveur spécifié n’a été possible.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[Il n’a pas été possible d’ouvrir une session sur le serveur spécifié.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Nom de l’hôte]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Nom d’utilisateur]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[Installation de paquet]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Annuler l’installation]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Êtes-vous sûr de vouloir annuler l’installation ?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[Les dépendances pour ce paquet ne peuvent pas être satisfaites.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[The {if $action == 'install'}package installation{else}package update{/if} of package &quot;{$packageName}&quot; in version {$packageVersion} cannot be executed due to incompatibilities with the following {if $excludedPackages|count == 1}package{else}packages{/if}:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} in version {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Following package doesn't{else}Following packages don't{/if} allow the {if $action == 'install'}package installation{else}package update{/if} of package &quot;{$packageName}&quot; in version {$packageVersion} due to incompatibilities:]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} in version {$excludingPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Following package is{else}Following packages are{/if} incompatible with package &quot;{$packageName}&quot; in version {$packageVersion}. If you proceed installation the {if $excludingPackages|count == 1}package{else}packages{/if} probably won't work anymore.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}Installé{else}{if $package.file|isset}est situé dans ce paquet{else}Non disponible{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Êtes-vous sûr de vouloir annuler l’installation de ce paquet ?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Les paquets suivants peuvent être mis à jour avec ce paquet]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Sélectionnez un des paquets suivant pour le mettre à jour. Si vous voulez réinstaller le paquer, veuillez cliquer sur &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Une copie de ce paquet est déjà installée. En continuant la procédure, une nouvelle copie du paquet sera installée. Si vous voulez mettre à jour une copie disponible de ce paquet, veuillez la sélectionner dans la liste suivante.]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[Version du paquet :]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[Installation date]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[While unpacking the files of this package the following error occured:]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[The following files could not be unpacked successfully. Please check if the destination folder is writable.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Tables conflictuelles]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Ne pas écraser ces tables et ne pas me poser à nouveau cette question pour cette installation.]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Écraser les tables existantes et ne pas me poser à nouveau cette question pour cette installation.]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Modifications nécessaires]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Tables affectées]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Les tables de la base de données existante sont en conflit avec les tables nécessaires à l’installation de ce paquet. Veuillez décider de l’écrasement ou non de ces tables.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[Paquets installés]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[Auteur]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[{#$items} paquets installés]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[Date]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[N°]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[Nom]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[Paquet]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Application unique]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[Version]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[Installation de paquets optionnels]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Le paquet sélectionné contient les options suivantes. Veuillez sélectionner celles que vous souhaitez installer.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Ce paquet est déjà installé.)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Les champs requis pour ce paquet n’ont pas été remplis.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[Répertoire d’installation]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Une autre application est déjà installée dans ce répertoire.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[This folder is invalid.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Ce répertoire n’a pas les autorisations d’écriture.]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Ce répertoire est déjà utilisé par le WoltLab Community Framework. Veuillez choisir un autre emplacement.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Veuillez indiquer le répertoire d’installation.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[This application is accessable through the following URL after installation in this folder:]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[Sélection des dépendances]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Le paquet actuel nécessite un autre paquet installé plusieurs fois. Veuillez choisir l’instance à utiliser.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[Annuler l’installation de paquet]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Version {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[Installation de nouveaux paquets]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Le paquet choisi n’a pas de routine d’installation valide.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[L’archive choisie n’est pas un paquet valide.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Le paquet &quot;{$package->getName()}&quot; ne peut pas être mis à jour à partir de l’archive que vous avez fournie.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Aucun fichier n’a été trouvé dans le répertoire spécifié.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Le paquet que vous avez choisi est déjà installé. Les paquets ne peuvent pas être installé plus d’une fois.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[L’envoie de l’archive a échoué.]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Sélectionnez le paquet source]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Indiquez l’emplacement du paquet sur votre serveur]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Indiquez un chemin direct au fichier-paquet. Vous pouvez utiliser une adresse internet ou bien le chemin au fichier du paquet en utilisant le système de fichier de votre serveur.]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Envoie du paquet à partir de votre ordinateur]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Indiquez le fichier-paquet à être envoyé de votre ordinateur.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Mettre à jour le paquet &quot;{$package->getName()}&quot;]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Installation les accès au menu pour le panneau de contrôle de l’administration ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Installing template patches for the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Installation des modèles pour le panneau de contrôle de l’administration ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Installation de l’"event-listener" ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Dépaquetage des fichiers paquet ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Installation des options de groupe d’utilisateurs ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Installation des langues ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Installation des options ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Exécution des scripts spéciaux ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Installation des entrées de la base de donnée ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Installation des patchs modèle ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Installation des modèles ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Installation des champs de profil utilisateurs ...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Checking possible conflicts ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Exécution des plugins paquets ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[L’installation est terminée]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Installation des paquets optionnels ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Enregistrement des paquets ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Installation des plugins paquets ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Mise en place du paquet parent ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Contrôle des dépendances ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[Paquet <b>{$packageName}</b>: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Suppression des sections du menu du panneau de contrôle de l’administration ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Removing template patches of the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Suppression des modèles du panneau de contrôle de l’administration ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Suppression de l’"event listener" ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Suppression des fichiers paquet ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Suppression des options de groupe d’utilisateurs ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Désinstallation des langues ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Désinstallation des options ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Suppression des entrées de la base de donnée ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Suppression des patchs modèle ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Suppression des modèles ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Suppression des champs de profil utilisateurs ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Exécution des plugins ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[La suppression de paquets est terminé]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Optionale Pakete werden deinstalliert ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Suppression des plugins ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Suppression des dépendances ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Mise à jour des sections du menu du panneau de contrôle de l’administration ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Updating template patches in the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Mise à jour des modèles dans le panneau de contrôle de l’administration ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Mise à jour des "event listener" ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Dépaquetage des fichiers paquet ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Mise à jour des options de groupe d’utilisateurs ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Mise à jour des langues ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Mise à jour des options ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Exécution des scripts spéciaux ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Mise à jour des entrées de la base de données ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Mise-à-jour des patchs modèle ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Mise à jour des modèles ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Mise à jour des champs de profil d’utilisateurs ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Checking possible conflicts ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Exécution des plugins ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Mise à jour des paquets terminée]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Mise à jour des paquets optionnels ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Mise à jour du paquet ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Mise à jour des plugins ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Mise en place du paquet parent ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Contrôle des dépendences ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[L’application du patch par ce paquet a échoué car ce patch n’est pas compatible avec le fichier cible. Le paquet ne peut donc pas être installé. Veuillez cliquer sur le bouton "{lang}wcf.acp.package.install.cancel{/lang}".]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[La réapplication du patch suivant a échoué :<br />{foreach from=$failures item=$failure}{$failure.templateName} (Originairement patché par : {$failure.packageName})<br />{/foreach}Le paquet patch original qui était appliqué auparavant ne fonctionnera peut-être plus. Vous devriez continuer cette mise à jour en cliquant sur le bouton  &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[Le patch que ce paquet essaye de supprimer a échoué car le fichier source a été modifié par une source extérieure. Ce paquet ne peut donc pas être supprimé. Veuillez cliquer sur le bouton "{lang}wcf.acp.package.uninstall.cancel{/lang}" .]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[Suppression de paquets]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Annuler la suppression]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Il n’est pas possible de désinstaller ces paquets, car au moins un paquet en dépendant ne peut pas être déinstallé.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Après confirmation, {if $dependentPackages|count == 1}ce paquet sera supprimé{else}ces paquets seront supprimés{/if} sans aucun nouvel avertissement.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[Mise à jour des paquets]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[Date of update]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[Auteur :]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Se rendre sur le panneau de contrôle de l’administration]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Supprimer le paquet]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Supprimer tous les paquets]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Êtes-vous sûr de vouloir supprimer ce paquet ?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Mettre à jour]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[Date :]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[paquets dépendants]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Ce paquet est nécessaire pour {if $dependentPackages|count == 1}un autre paquet.{else}{#$dependentPackages|count} autres paquets.{/if}]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Ce paquet est requis pour un autre paquet{else}{#$dependentPackages|count} paquets sont directement ou indirectement dépendant de ce paquet.{/if}.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[Répertoire d’installation :]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Identifiant :]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Instance installée :]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[Paquet parent :]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[Propriétés]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Paquets requis]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Ce paquet nécessite la présence {if $requiredPackages|count == 1}d’un autre paquet.{else}de {#$requiredPackages|count} autres paquets.{/if}]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[Page d’accueil :]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[Version installée :]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[Mises à jour de paquets]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Authentication au serveur du mise à jour]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Données de connexion]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Username and password have not been accepted.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Veuillez entrer un mot de passe requis pour l’authentification.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Nom d’utilisateur]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Veuillez entrer un nom d’utilisateur requis pour l’authentification.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Identification de l’utilisateur]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Message du server]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Nom du serveur]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Enregistrer les données utilisateurs]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Les données utilisateurs entrées seront enregistrées. Vous n’aurez donc pas à les entrer à nouveau.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adresse]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Version installée]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Une erreur est survenue : ]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Le téléchargement du paquet {$package} a échoué.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[An error occured while trying to download the package list.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[The following {if $excludedPackages|count == 1}conflict{else}conflicts{/if} occured:]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[The installed package &quot;{$excludedPackage.existingPackageName}&quot; is incompatible with the package &quot;{$excludedPackage.packageName}&quot; in version {$excludedPackage.packageVersion}.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[The package &quot;{$excludedPackage.packageName}&quot; in version {$excludedPackage.packageVersion} is incompatible with the installed package &quot;{$excludedPackage.existingPackageName}&quot;.]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[Installation de {$package.packageName} {$package.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[There are currently no updates available.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[You have not selected any update.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Options]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Les paquets sont déjà installés. Vous ne pouvez donc pas les installer à nouveau.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Installer le paquet]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Installer une nouvelle fois le paquet (le paquet est déjà installé  {#$package.instances} fois{if $package.instances > 1}{/if}).]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Mettre à jour le paquet {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} vers la version {$updatableInstance.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Recherche de paquets]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Auteur]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Rechercher ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Cacher les paquets déjà installés]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Nom du paquet]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Nom et description du paquet]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Serveur de mise à jour]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Rechercher dans tous les serveurs de mise à jour]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Type de paquet]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Autres paquets]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Plugin pour des paquets déjà installés]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Application indépendante]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Sélectionner tous les paquets]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} est mis à jour vers la version {$package.toVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Nouvelle version]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Les mises à jour et installations de paquets suivant vont être appliquées :]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Actions of the logged session of &quot;{$sessionLog->username}&quot;]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[There is a total of {#$items} logged action{if $items != 1}s{/if}]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Actions]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Class name]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP address]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Last action]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Package]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Method]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Date]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[User agent]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Logged sessions]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[There is a total of {#$items} logged session{if $items != 1}s{/if}]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[Ajout de serveur]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[The server has been successfully added.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[Paramètres du serveur]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Supprimer le serveur]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[The server has been successfully deleted.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Êtes-vous sûr de vouloir supprimer ce serveur ?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Inactif]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Modification de serveur]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Your changes have been successfully saved.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Actif]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Message d’erreur]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Veuillez entrer un mot de passe si requis pour l’authentification (facultatif).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Identifiant]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Veuillez entrer un identifiant si requis pour l’authentification (facultatif).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[The following error occured while trying to connect the last time:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} serveurs disponibles]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[N° du serveur]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Paquets]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adresse]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Veuillez entrer l’URL d’un serveur de paquets.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[L’adresse entrée n’est pas valide.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[État]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Dernier accès]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[Serveur de mise à jour disponible]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Aucun serveur de mise à jour n’est disponible.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[Ajouter un nouvel utilisateur]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[Détails d’utilisateur]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[The new user has been successfully saved.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Affecter à un groupe]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Affecter les utilisateurs suivant à (aux) groupe(s) sélectionné(s)]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Les utilisateurs ont bien été affectés aux groupes que vous avez choisis.]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Affectation de groupe]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Exporter les adresses e-mail]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Envoyer un e-mail]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[Supprimer]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[Aucun utilisateur ne peut être supprimé.]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}L’utilisateur a bien été supprimé{else}{#$deletedUsers} utilisateurs ont bien été supprimés{/if}.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Êtes-vous sûr de vouloir supprimer cet utilisateur ?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Êtes-vous sûr de vouloir supprimer le(s) utilisateur(s) sélectionné(s) ?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[Modifier l’utilisateur]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[The changes for this user have been successfully saved.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Vous êtes en train de modifier votre propre compte utilisateur. Le fait de changer les droits d’accès peut vous supprimer l’accès au panneau d’administration. Soyez prudent !]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Exporter les adresses e-mail]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Exporter le format de fichier]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Options d’exportation]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Exporter les adresses e-mail des utilisateurs suivant]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Séparer les adresses avec un ]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Entourer les adresses avec ]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[Appartenance de groupe]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Find users that are not members of the chosen usergroups.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[Utilisateurs]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[List all users]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[{#$items} utilisateur{if $items > 1}s{/if}]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 utilisateur sélectionné" : this.count+" utilisateurs sélectionnés"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Bulk processing of users]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Action]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Conditions]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[The chosen action has been executed successfully on {#$affectedUsers} users.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[The bulk processor will perform the following tasks <strong>without additional security notification</strong>, on all users matching the set conditions. Bulk processing can be very performance intensive, so should only be executed when the forum is offline. To have a correct display of your content you should update the counters. The processing can not be reversed, so please be attentive when using this function.]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[Recherche d’utilisateurs]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Critères de recherche]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Critères de recherche généraux]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Critères de recherche sur le profil]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[Display]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Columns]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Other]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profile]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Users per page]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sorting]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Aucun utilisateur n’a été trouvé.]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[{if $items == 1}un résultat satisfait {else}{#$items} résultats satisfont {/if}à votre recherche]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Rechercher dans les résultats]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[Envoyer un e-mail]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[Envoyer un e-Mail à tous les utilisateurs]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[Send e-mail as HTML]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Expéditeur]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Here you can enter the sender's e-mail address in the following format:</p>
+<p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Senders name &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>
+<p>If you have completely filled in the section under System -> Options -> E-mail, then this field will automatically be filled in. If you are sending e-mails using SMTP, then the sender's e-mail-Address must also be accepted by the Server.</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[Envoyer un e-mail à tous les membre du groupe]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Envoyer un e-mail aux membres des groupes suivant :]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-mail]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Envoyer un e-mail aux utilisateurs suivant]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Sujet]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Indiquez ici le sujet de l’e-mail.]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Message]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Indiquez ici le message que vous voulez envoyer aux utilisateurs.]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[Bienvenue {$this->user->username}.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Processus courant]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[Please leave this browser window open until the process has successfully completed. Do NOT try to login to your administrations area using a separate browser window, as doing so may damage the current process.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Processus achevé avec succès]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Traitement ...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% effectué]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[Traitement ...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Retour]]></item>
+               <item name="wcf.global.button.close"><![CDATA[Fermer]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[Supprimer]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Do you really want to delete this item?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Delete completely]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[Edit]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[Use full editor]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[Sélectionner]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Suivant &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[Prévisualisation]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[Annuler]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[Envoyer]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[Désélectionner]]></item>
+               <item name="wcf.global.date.day"><![CDATA[Jour]]></item>
+               <item name="wcf.global.date.days"><![CDATA[Days]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[Heure]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[Hours]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[Minute]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[Minutes]]></item>
+               <item name="wcf.global.date.month"><![CDATA[Mois]]></item>
+               <item name="wcf.global.date.months"><![CDATA[Months]]></item>
+               <item name="wcf.global.date.second"><![CDATA[Second]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[Seconds]]></item>
+               <item name="wcf.global.date.week"><![CDATA[Week]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[Weeks]]></item>
+               <item name="wcf.global.date.year"><![CDATA[Année]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Vous n’êtes pas obligé de spécifier l’année.]]></item>
+               <item name="wcf.global.date.years"><![CDATA[Years]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Aujourd’hui</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Hier, %H:%M]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[month-day-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[Par défaut]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[Retour à la page précédente]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[Veuillez indiquez les informations requises dans ce champs.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[Le fichier n’a pas été trouvé.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[Le liens que vous essayez de suivre n’est plus disponible, ou est invalide.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Vous n’avez pas l’autorisation d’entrer sur cette page. Vous ne possédez pas les droits d’accès requis.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Vous n’avez pas l’autorisation d’accéder à cette page.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[Message d’erreur]]></item>
+               <item name="wcf.global.form.error"><![CDATA[Les données entrées ne sont pas valides. Veuillez vérifier les informations que vous avez entrées dans les champs mis en valeur.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arabe]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosnien]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Tchèque]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danois]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Allemand]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Allemand (Informel &raquo;Du&laquo;)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grec]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Anglais]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Espagnol]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persan]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finnois]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Français]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hébreu]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Croate]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Hongrois]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Italien]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japonais]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Coréen]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Néerlandais]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norvégien]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polonais]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugais]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugais (Brésil)]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Roumain]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Russe]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovaque]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Serbe]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Suédois]]></item>
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turque]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinois (Simplifié)]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinois (Traditionnel)]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[fr_FR]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[french]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[Pour sélectionner plusieurs éléments, appuyez sur la touche &quot;Ctrl&quot; ou &quot;Shift&quot; (sous Windows) ou &quot;Command&quot; (sous Mac OS) et cliquez sur les éléments voulus.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[Go to next page]]></item>
+               <item name="wcf.global.page.next"><![CDATA[Page suivante]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[Page précédente]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[Redirection]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[Veuillez cliquer ici si la redirection automatique ne fonctionne pas !]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[Haut de la page]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Terme exact]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e %B %Y, %H:%M]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[Skip navigation]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[croissant]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[décroissant]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d. %m. %Y, %H:%M]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A %e %B %Y, %H:%M]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Image " + (this.currentIndex + 1) + " of " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[Close]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Show only this image (quits the image viewer)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[Next image]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[Stop slideshow]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[Start slideshow (changes the image every 5 seconds)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[Previous image]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Îles Canaries, Lisbonne, Londre, Monrovia, Ouagadougou, Reykjavík]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brussels, Copenhagen, Madrid, Paris, Prague, Rome, Sarajevo, Stockholm, Tunis, Warsaw, Vienna]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athénes, Beyrouth, Bucarest, Helsinki, İstanbul, Jérusalem, Le Caire, Le Cap, Khartoum, Kiev, Minsk, Sofia]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Abeba, Antananarivo, Bagdad, Dodoma, Kampala, Koweït, Mogadiscio, Moscou, Nairobi, Riyad]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Téhéran]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Bakou, Dubaï, Erevan, Mascate, Réunion, Tbilisi]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Achgabat, Bichkek, Douchanbé, Islamabad, Iekaterinbourg, Karachi, Maldives, Tachkent]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, New Delhi]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Katmandu]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dakka, Novosibirsk]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Islands, Yangôn]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoï, Jakarta, Phnom Penh, Krasnoïarsk, Vientiane]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkoutsk, Kuala Lumpur, Manille, Beijing, Perth, Singapour, Taipei, Ulan-bator]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Australie-Occidentale)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakoutsk, Osaka, Pyongyang, Sapporo, Séoul, Tokyo]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Island (Australie)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, Nouvelle Calédonie, Îles Salomons]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Île de Norfolk]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, Tarawa-Sud, Fidji, Kamchatka, Îles Marshall, Wellington]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Islands (New Zealand)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku’alofa, Phoenix Islands]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Islands, Christmas Island]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Açores, Îles Cap Vert]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mid-Atlantic]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Brasília, Buenos Aires, Cayenne, Georgetown, Groénland, Montevideo]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Terre Neuve]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantic Time (Canada), Asunción, La Paz, Port-of-Spain, Santiago]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Eastern Time (US &amp; Canada), Bogotá, Lima, San Francisco de Quito]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Central Time (US &amp; Canada), Amérique Centrale, Mexico City]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Time (US &amp; Canada), Chihuahua, Mazatlan]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pacific Time (US &amp; Canada), Tijuana]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) Polynésie Française]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Îles Cook, Hawaii]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Îles Midway, Samoa]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[Page {#$pageNo}]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[Confirmation de l’adresse e-mail]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[Confirmation du mot de passe]]></item>
+               <item name="wcf.user.email"><![CDATA[Adresse e-mail]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Les deux adresses e-mail que vous avez entrées sont différentes.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Les deux mots de passe que vous avez entrés sont différents.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[l’adresse e-mail que vous avez entrée est déjà utilisée par un autre membre.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[l’adresse e-mail que vous avez entrée est invalide.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[Le mot de passe est incorrect.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[Le nom d’utilisateur &quot;{$username}&quot; n’a pas été trouvé.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Le nom d’utilisateur que vous avez entré est déjà utilisé.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[Le nom d’utilisateur que vous avez entré est invalide.]]></item>
+               <item name="wcf.user.language"><![CDATA[Langue]]></item>
+               <item name="wcf.user.language.description"><![CDATA[Veuillez sélectionner la langue dans laquelle l’interface s’affichera !]]></item>
+               <item name="wcf.user.logout"><![CDATA[Déconnexion]]></item>
+               <item name="wcf.user.password"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[Date d’enregistrement]]></item>
+               <item name="wcf.user.userID"><![CDATA[N° d’utilisateur]]></item>
+               <item name="wcf.user.username"><![CDATA[Nom d’utilisateur]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[Afficher le contenu dans les langues suivantes]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Sélectionnez ici les langues dans lesquelles le contenu doit être affiché.]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Les informations que vous avez entrées ne sont pas valides.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/hr.xml b/wcfsetup/install/lang/hr.xml
new file mode 100644 (file)
index 0000000..f531356
--- /dev/null
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="hr">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[Administracijski Kontrolni Panel]]></item>
+               <item name="wcf.acp.help"><![CDATA[Pomoć]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[Puna Ppmoć]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[Isključi online Pomoć]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[Interaktivna pomoć]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Promjeni Komponentu]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[Napredna pretraga ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[Site-Map]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Cache isprazniti]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[Cache je uspješno izbrisan.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Želite li cashe stvarno kompletno isprazniti?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[Postavke]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[Datoteke]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[Veličina]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[Izvor]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[Verzija]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Zadnja Aktualizacija]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[Naziv]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Pristupna Prava]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[Veličina]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[Dodaj novu korisničku grupu]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Pristupna prava]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[Korisnička grupa je uspješno dodana.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[Administratori]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[Informacije o grupi]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[Izbriši ovu korisničku grupu]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Ova korisnička grupa je{else}{#$deletedGroups} Ove korisničke grupe su{/if} uspješno izbrisane.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Jeste li sigurni da želite izbrisati ovu grupu?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[Uredi ovu korisničku grupu]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[Promjene u korisničkoj grupi uspješno su sačuvane.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Vi ste član ove grupe. Ukoliko promjenite postavke oko pristupa ACP-u mogli bi ostati bez pristupa njemu. Molimo vas budite oprezni!]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Svi]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[ID Grupe]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[Ime ove korisničke grupe]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Upišite ime grupe.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[Gosti]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[Korisničke grupe]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[Sveukupno od {#$items} korisničkih grupi]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[Broj korisnika]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatori]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Mogu pristupiti u Administratorski Kontrolni Panel]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Članovi ove grupe mogu ući u Administratorsku Kontrolnu Ploču (acp).]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Može skrivene informacije profila vidjeti]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Članovi ove korisničke grupe mogu skrivene informacije u korisničkom profilu vidjeti.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Mogu mijenjat sistemske postavke]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Aktivacijom ove opcije članovi ove grupe moći će mijenjat postavke npr. isključiti/uključiti forum.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Mogu logove vidjeti]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Članovi ove grupe mogu sistemske logove vidjeti.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Mogu urediti postojeće update servere]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Članovi ove grupe mogu uređivati postojeće i dodavati nove update servere.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Mogu instalirati nove komponente]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Članovi ove grupe mogu instalirati nove komponente.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Mogu izbrisati postojeće komponente]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Članovi ove grupe mogu izbrisati postojeće komponente.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Mogu nadograditi postojeće komponente]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Članovi ove grupe mogu nadograđivati postojeće komponente.]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Dostupne grupe]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Članovi ove grupe imat će pristup izabranim grupama, znači moći će uređivati korisnike tih grupa. Npr. ovdje možete staviti da članovi jedne grupe mogu sami sebe uređivati.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Mogu dodavati nove korisničke grupe]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Članovi ove grupe mogu dodavati nove korisničke grupe.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Mogu dodavati nove korisnike]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Članovi ove grupe mogu dodavati nove korisnike. Ako je opcija za &quot;Dostupne grupe&quot; uključena onda će moći tog korisnika i pridružiti nekoj grupi.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Mogu izbrisati postojeće korisničke grupe]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Članovi ove grupe mogu izbrisati postojeće korisničke grupe.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Mogu izbrisati postojeće korisnike]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Članovi ove grupe mogu izbrisati postojeće korisnike.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Mogu uređivati postojeće korisničke grupe]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Članovi ove grupe mogu uređivati postojeće korisničke grupe.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Mogu uređivati korisnikove e-mail adrese]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Članovi ove grupe mogu uređivati korisnikove e-mail adrese.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Mogu uređivati korisnikove lozinke]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Članovi ove grupe mogu uređivati korisnikovu lozinku.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Mogu uređivati postojeće korisnike]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Članovi ove grupe mogu uređivati postojeće korisnike.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Mogu poslati e-mail korisnicima]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Članovi ove grupe mogu poslati e-mailove korisnicima.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Mogu pretraživati korisnike]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Članovi ove grupe mogu pretraživati korisnike.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Administrativna Prava]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Sadržaj]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Dizajn]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Opća administrativna prava]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Održavanja]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[Sistemske funkcije]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Komponente]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Korisničke funkcije]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Grupe]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Korisnici]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderatorska Prava]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Opća Prava]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Informacije koje ste unijeli nisu valjane]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[Prikaži članove ove korisničke grupe]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super Moderatori]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[Registrirani korisnici]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[Prijava]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[Pristupni podaci]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[Master Lozinka]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Master Lozinku ponoviti]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Master Lozinka je potrebna]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Stranica koju želite otovoriti ili akcija je iz sigurnosnih razloga zaštićena sa master lozinkom. Po sesiji je unos master lozinke potreban. Ako ste zaboravili master lozinku, ili ju želite povratiti, izbrišite datoteku <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[Master lozinka nije ispravna. Ako ste zaboravili master lozinku, možete ju povratiti brisanjem sljedeće datoteke <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[Upisane lozinke nisu jednake.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[Lozinka se smatra nesigurnom. Lozinka mora biti najmanje 8 znakova dugačka, mora sadržavati velika i mala latinska slova, brojeve i specijalne znakove. Ne smije se poklapati sa drugim lozinkama administratora.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Prijedlog]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Prihvati Prijedlog]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Odredi Master Lozinku]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[Master lozinka je dodatna zaštita sa sigurnosne kritične funkcije. Bilo bi poželjno da koristite što sigurniju lozinku, da se razlikuje od vaše administracijske lozinke, trećim osobama nepoznata i da se ne koristi na drugim internet stranicama.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Automatski update]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[Sadržaj]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[Prikaz]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[Korisničke Grupe]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Dodaj novu grupu]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[Pošalji e-mail svim članovima]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Pregled Grupa]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[Logovi]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Sesije]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Održavanje]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[Postavke]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Snimiti &amp; Resetirati]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[Upravljanje paketima]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Baza podataka]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Instaliraj novi paket]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Dodaj novi server]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Pregled servera]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Popis instaliranih paketa]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[Sistem]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[Korisnik]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Dodaj novog Korisnika]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Pregled Korisnika]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[Pošalji e-mail svim korisnicima]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Korisnici]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Masovno uređivanje korisnika]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Pretraži korisnike]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Ime hosta izostaviti]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Upišite po retku ime hosta, kojeg želite sa stranice izostaviti.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[IP-Adresu izostaviti]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Upišite po retku IP-Adresu, koju želite sa stranice izostaviti.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Browser-Prepoznavanje izostaviti]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Upišite po retku Browser-Prepoznavanje (User-Agent), koje želite sa stranice izostaviti.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache-Server]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Upišite ovdje adresu Memcache-Servera! Više servera se može odvojiti retkom.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Persistentno spajanje aktivirati]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Želite li kod spajanja sa Memcache-Serverom persistentno spajanje koristiti?]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache-Metoda]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Odaberite željenu Cache-Metodu! Obratite pažnju, da neke metodu koriste specijalne upite prema Server-Sistemu i nisu dostupne na svakom serveru.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[Sistem datoteka (Standardno)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (Eksperimentalno)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[Općenito]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Općenito]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache snima najčešće korištene datoteke u memoriju. Ovo može smanjiti opterećenje na bazu podataka i sistem datoteka. Pročitajte više na sljedećoj stranici:
+<ul>
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Datum i vrijeme]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy-Server]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Ovdje možete opcionalno Proxy-Server za spajanje na vanjske servere postaviti.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-Mailovi]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Općenito]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Slanje]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Offline Modus]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[Moduli u / isključiti]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Sadržaj]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Prikaz]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[Sistem]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Korisnik]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[Sigurnost]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internet stranice se često napadaju preko drugih programa. Tako postoji mogućnost, da se automatski stotine korisničkih accounta napravi. Kako bi se od toga zaštitili, možete na različitim mjestima tzv <a href="http://de.wikipedia.org/wiki/Captcha" class="externalURL">Captcha-Sliku</a> prikazati. Neregistrirani korisnici moraju prvo upisati kod, koji se nalazi na slici. Roboti ne mogu to čitati. Obratite pažnju da se Captcha-Slike ne mogu od strane slabovidnih korisnika identificirati.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Crna Lista]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Cenzura]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Općenito]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Logovi]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[Korisnici]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Domena za cookije]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Unesite domenu koju trebaju koristiti cookiji.]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Putanja cookija]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Unesite putanju za vaše cookije.]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Prefiks cookija]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Unesite prefiks za ime cookija.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Uključi automatsko spremanje]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Želite li da se sat automatski namješta po ljetnom/zimskom vremenu?]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Cache-Metodu za logove koristiti]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Želite li za snimanje logova koristiti Cache-Metodu?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Informacije koje ste unjeli nisu valjane.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[Postavke snimiti]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[Downloadati snimljene postavke]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Snimite snimljene postavke na vaše lokalno računalo.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Unesite tip aplikacije/xhtml+xml]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[Aktiviranjem ove opcije možete stranici pristupiti pomoću aplikacije/xhtml+xml.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Uključi Gzip kompresiju]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Ako ovo uključite onda se sadržaj na server šalje kompresiran i prima se kompresiran, ovo smanjuje promet.]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Isključi spremanje stranica u pregledu]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Aktiviranjem ove opcije možete cashing stranice u browseru nedozvoliti.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Gzip-stupanj kompresije]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Potrebno je unijeti od 1 do 9. Za optimalno rješenje preporučujemo vam 1.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[Postavke importirati]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[Postavke su uspješno importirane.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[Sigurnost postavki sa lokalnog računala uploadati]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Odaberite snimljene postavke na vašem računalu.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Postavke importirati &amp; eksportirati]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Administratorska e-mail adresa]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Unesite ovdje administratorsku e-mail adresu.]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Putanja prema debug-log podatku]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Unesite putanju prema log podatku.]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Adresa pošiljatelja]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Ovdje unesite e-mail adresu koja će biti prikazana kao pošiljatelj.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Ime pošiljatelja]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Ovdje unesite ime koje će biti prikazano u poslanim e-mailovima.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-mail metoda slanja]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Izaberite metodu prjenosa e-maila.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Pošiljateljev potpis]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Ovdje unesite potpis koji će biti prikazan u poslanim e-mailovima.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP host]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Unesite ime SMTP servera.]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP lozinka]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Unesite lozinku za SMTP.]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP port]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Unesite port za STMP.]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP korisničko ime]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Unesite korisničko ime za STMP.]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[Uključi &quot;-f&quot; parametar]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Za neke servere trebat će uključiti &quot;-f&quot; parameter za slanje mailova. Ako imate problema da korisnici ne primaju e-mail adrese probajte ovo uključiti.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Koristi formatirane e-mail adrese]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Adresa pošiljatelja i primatelja će se u sljedećem formati prikazati: &quot;Ime &lt;email@domain.tld&gt;&quot;. Ovu opciju ne podržavaju svi mail serveri i zbog toga tijekom problema potrebno ju je isključiti.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Master Lozinku aktivirati]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Aktivira dodatni unos lozinke kod otvaranja određenih sigurnosnih polja.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Proxy-Server (FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[Proxy-Server za FTP-Spajanja]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server za HTTP-Spajanja]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Istek sezone]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Unesite koliko dugo je sezona valjana [sekunde]]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[IP-Adrese sezone provjeriti]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Broj zabrana IP-Adresa kod isčitavanja sezone provjeriti. Visoke postvake mogu korisnika isključiti, koji se sa različitim IP-Adresama kreću internetom.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Browser-Prepoznavanje sezone provjeriti]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Želite li Browser-Prepoznavnaje kod isčitavanja sezone provjeriti?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[Vaše promjene u postavkama su uspješno sačuvane.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[Vremenska zona]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Molimo unesite početnu vremensku zonu.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Korisnici online ]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Unesite koliko dugo bi se korisnici trebali prikazati kao online, iako su napustili forum [sekunde]]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[Prekini instalaciju]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[Opis]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[Unesite pristupne detalje za FTP]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[FTP pristupni detalji]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Pošto je na vašem serveru PHP-SafeMode aktiviran, mora se ovaj paket preko FTP-Funkcije instalirati. Molim vas upišite korisničko ime i lozinku za pristup FTP-u. Podaci se neće snimiti niti dalje proslijediti, te će se samo za instalaciju ovog paketa koristiti. Iz tog razloga je moguće da će se FTP pristupni podaci više puta pitati tijekom instalacije.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Sa upisanim pristupnim podacima se nije mogla uspostaviti veza sa FTP serverom.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[Nije uspjelo spajanje na izabrani FTP server.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[Nije uspio login na izabrani FTP server.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Hostname]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Lozinka]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Korisničko ime]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[Instalacija paketa]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Prekini instalaciju]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Jeste li sigurno da želite prekinuti ovu instalaciju?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[Podaci paketa ne zadovoljavaju ovu komponentu.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[{if $action == 'install'}Instalacija paketa{else}Aktualizacija paket{/if} od paketa &raquo;{$packageName}&laquo; u verziji {$packageVersion} se radi nekompatibilnosti prema {if $excludedPackages|count == 1}sljedećem paketu{else}sljedećim paketima{/if} ne može ispuniti:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} u verziji {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Sljedeći paket{else}Sljedeći paketi{/if} ne dozvoljavaju {if $action == 'install'}instalaciju paketa{else}aktualizaciju paketa{/if} &raquo;{$packageName}&laquo; u verziji {$packageVersion} zbog nekompatibilnosti paketa:]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} u verziji {$excludingPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Sljedeći paket je{else}Sljedeći paketi su{/if} se paketom &raquo;{$packageName}&laquo; u verziji {$packageVersion} nekompatibilno. Ako želite nastaviti instalaciju, {if $excludingPackages|count == 1}onda će paket{else}onda će paketi{/if} neispravno funkcionirati.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}instaliran{else}{if $package.file|isset}je s ovom komponentom{else}Nije dostupna{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Jeste li sigurni da želite prekinuti instalaciju?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Sljedeći paketi biti će nadograđeni s ovim]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Odaberite jedan od sljedećih paketa kako bi ga aktualizirali. Ako želite paket ponovno instalirati, onda kliknite ispod na &raquo;Dalje&laquo;.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Postoji instalirana kopija ovog paketa. Ako nastavite, instalirat će se još jedna kopija ovog paketa. Ako želite postojeću kopiju paketa aktualizirati, odaberite kopiju paketa iz sljedećeg popisa.]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[Verzija paketa:]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[Instalacijski Datum]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Kod pokušaja otpakiravanja paketa je sljedeća greška nastala:]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[Sljdeće datoteke nije moguće otpakirati. Molim vas provjerite dali je moguće pisati na ciljno mjesto.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Proturiječne tablice]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Zadržati original tablice i tijekom cijele instalacije više ne pitati.]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Sve tablice prepisati i tijekom cijele instalacije više ne pitati.]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Potrebne promjene]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Tablice na koje utjeće]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Postojeće tablice Vaše baze podataka su konfliktu sa tablicama, koje su potrebne za instalaciju ovog paketa. Molimo Vas odaberite, dali da se prepišu ove tablice.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[Instalirani paketi]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[Autor paketa]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[Sveukupno je {#$items} paketa instalirano.]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[Datum]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[Naziv]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Samostojeća aplikacija]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[Verzija]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[Instaliraj dodatne pakete]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Postoji više paketa. Molimo izaberite koje želite instalirati.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[(Ova komponenta je već instalirana)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Zahtjevi ovog paketa se ne mogu ispuniti.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[Instalacijski folder]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Već je instaliran druga aplikacija u tom direktoriju.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[Upisani direktorij nije važeći.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Folder je zaštićen od pisanja(not-writeable).]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Upisani direktorij se već koristi od strane WoltLab Community Framework. Molim vas odredite drugi direktorij.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Molimo unesite instalacijski folder.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Nakon instalacije u odabrani instalacijski direktorij njegovo korištenje je moguće preko sljedeće adrese (URL):]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[Zahtjeve prikazati]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Aktualnom paketu su potrebni paketi, od kojih je više instanca instalirano. Molimo Vas, odaberite kojoj instanci je potrebna ovisnost/udruživanje paketa.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[Povrati instalaciju paketa]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Verzija {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[Instaliraj novi paket]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Izabrani paket nema valjanu instalacijsku rutinu.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[Arhiva koju ste unijeli nije valjana.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Paket &quot;{$package->getName()}&quot; se nemože sa odabranom arhivom aktualizirati.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Nisu ponađeni potrebni podaci u odabranom folderu.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Paket je već instaliran. Paket se ne može više puta instalirati.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[Upload odabrane arhive nije uspio.]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Odaberi izvor komponente]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Unesite putanju prema paketu na serveru.]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Upišite direktni put do instalacijskog paketa. Može se raditi o internet adresi paketa ili put do paketa na Vašem računalu.]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Uploadaj paket s računala]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Odaberite paket koji želite instalirati s vašeg kompjutera.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Nadogradi Paket &quot;{$package->getName()}&quot;]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Administracijski kontrolni panel se instalira...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Instalacija template patche-a u Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Plugin-i administracijskog kontrolnog panela se instalira ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Instaliranje događaja ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Datoteke se otpakiravaju ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Instaliranje opcija korisničkih grupa ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Instaliranje paketa jezika ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Instaliranje postavki ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Izvršavanje posebnih skripti ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Instaliranje ulaza u bazu ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Template patch-ovi se instaliraju ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Instaliranje paketa predložaka ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Instaliranje polja profila ...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Mogući konflikti se provjeravaju ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Izvršavanje skripti paketa ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Instalacija je završena]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Instaliranje dodatnih paketa ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Registracija paketa ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Instaliranje plugina paketa ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Smještaj izvornog paketa se provodi ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Provjera izvora ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[Paket <b>{$packageName|encodeJS}</b>: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Brisanje paketa iz Administracijskog kontrolnog panela ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Brisanje predložaka patch-a iz Administracijskog Kontrolnog Panela ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Brisanje predložaka iz Administracijskog kontrolnog panela ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Brisanje događaja ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Brisanje izvora komponente ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Brisanje postavki korisničkih grupa ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Brisanje paketa jezika ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Brisanje postavki komponente ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Brisanje ulaza u bazu ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Brisanje patcho-ova predložaka ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Brisanje predložaka ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Polja korisničkog profila se deinstaliraju ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Paket-Instalacija-dodatni moduli se provode ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Deinstalacija završena]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Dodatni paketi se deinstaliraju ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Paket-Instalacija-dodatni moduli se deinstaliraju ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Ovisnosti paketi se provode ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Administracijski kontrolni panel se aktualizira ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Updating patch-ova predložaka Administracijskog Kontrolnog Panela ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Template-i Administracijskog kontrolnog panela se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Event-Listener se aktualizira ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Datoteke se otpakiravaju ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Postavke korisničke grupe se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Jezik se aktualizira ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Postavke se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Posebne skripte se provode ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Baza podataka se aktualizira ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Update patcha predložaka ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Template-i se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Polja korisničkog profila se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Checking possible conflicts ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Paket-Instalacija-dodatni moduli se provode ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Aktualizacija paketaje završena]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Dodatni paketi se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Paketi se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Paket-Instalacija-dodatni moduli se aktualiziraju ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Smještaj izvornog paketa se provodi ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Ovisnosti paketa se provode ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[Primjena patcha koji pripada ovom paketu nije uspjela jer patch nije kompatibilan prema ciljnoj datoteci. Zbog toga nije moguće instalirati paket. Molim Vas kliknite na &raquo;Prekid Instalacija&laquo;.]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Ponovno je neuspjela primjena patcha:<br />{foreach from=$failures item=$failure}{$failure.templateName} (prethodna primjena patcha od: {$failure.packageName})<br />{/foreach}Najvjerojatnije se paket zbog tog patcha ponovni patch ne funkcionira. Ipak nastavite sa update-om. Molim vas kliknite na &raquo;Dalje&laquo;.]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[Brisanje patcha koji pripada tom paketu nije uspjelo, jer je ciljna datoteka promijenjena. Zbog toga nije moguće brisanje paketa. Molim vas kliknite na &raquo;Prekid instalacije paketa&laquo;.]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[Deinstalacija paketa]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Prekid deinstalacije paketa]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Deinstalacija paketa nije moguća jer nije moguće barem jedan ovisni paket izbrisati.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Ovaj{if $dependentPackages|count == 1} paket će se{else} Paketi će se{/if}, nakon Vaše potvrde, bez dodatnih i ponovljenih sigurnosnih pitanja deinstalirati.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[Aktualizacija paketa]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[Datum Aktualizacije]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[Proizvođać:]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Ući u administracijski kontrolni panel]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Paket deinstalirati]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Sve pakete deinstalirati]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Želite li stvarno ovaj paket deinstalirati?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Paket aktualizirati]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[Datum proizvodnje:]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Ovisni paketi]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Ovaj je paket {#$dependentPackages|count} {if $dependentPackages|count == 1}drugom paketu{else}drugim paketima{/if} potreban.]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Ovaj paket je potreban od 1 drugog paketa{else}{#$dependentPackages|count} paketi su izravno ili neizravno ovisni o ovom paketu{/if}.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[Mjesto instalacije:]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Označivać:]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Instalirani slučaj:]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[Izvorni paket:]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[Karakteristike]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Potrebni paketi]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Ovom paketu je potreban {#$requiredPackages|count} {if $requiredPackages|count == 1}drugi paket{else}drugi paketi{/if}.]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[Homepage:]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[Instalirane verzije:]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[Pakete aktualizirati]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Autentifikacija sa Update-Serverom]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Podaci spajanja]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Korisničko ime i lozinka nisu prihvaćeni.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Lozinka]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Upišite lozinku, koja je potrebna za autentifikaciju.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Korisničko ime]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Upišite korisničko ime, koje je potrebno za autentifikaciju.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Prijava korisnika]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Obavijest servera]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Naziv servera]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Korisničke podatke trajno snimiti]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Sprema upisane korisničke podatke trajno, tako da se podaci kasnije ne moraju ponovno upisivati.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adresa]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Instalirane verzije]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Sljedeća greška je nastala: ]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Download paketa {$package} nije uspio.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[Kod pokušaja downloada paketa nastala je greška.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[Sljedeći {if $excludedPackages|count == 1}konfliktje nastao{else}konflikti su nastali{/if} :]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Instalirani paket &raquo;{$excludedPackage.existingPackageName}&laquo; nije sa paketom &raquo;{$excludedPackage.packageName}&laquo; u verziji {$excludedPackage.packageVersion} kompatibilan.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[Paket &raquo;{$excludedPackage.packageName}&laquo; u verziji {$excludedPackage.packageVersion} nije sa instaliranim paketom &raquo;{$excludedPackage.existingPackageName}&laquo; kompatibilan.]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} nije moguće instalirati]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Trenutno ne postoje nadogradnje.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Niste odabrali nadogradnju.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Opcije]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Paket je već instaliran i nije ga moguće ponovno instalirati.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Paket instalirati]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Druge Paket-Instance instalirati (Paket je već {#$package.instances} puta instaliran)]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Instalirani paketi {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} Verzija {$updatableInstance.packageVersion} aktualizirati]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Pakete pretražiti]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Autor]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Traži ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Zanemari već instalirane pakete]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Naziv Paketa]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Naziv paketa i opise pretražiti]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Update-Server]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Sve Update-Servere pretražiti]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Vrsta paketa]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Ostali paketi]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Dodatni moduli za trenutno instalirane pakete]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Krajna uporaba]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Sve pakete odabrati]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} se aktualizira na {$package.toVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Nova verzija]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Sljedeće paket-aktualizicaje/-instalacije se provode:]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Akcije i sesije od &raquo;{$sessionLog->username}&laquo;]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Ukupno {#$items} akcija{if $items != 1}a{/if}]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Akcije]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Klase]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP-Adrese]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Zadnja Akcija]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Metoda]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Datum]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[Browser-Prepoznavanje]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Log sesije]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Ukupno {#$items} sesija{if $items != 1}a{/if}]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[Dodaj server]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Server je uspješno dodan.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[Podaci servera]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Izbriši server]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Server je uspješno izbrisan.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Jeste li sigurni da želite izbrisati ovaj server?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Isključi]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Uredi server]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Vaše promjene su uspješno sačuvane.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Uključi]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Poruke Greške]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Lozinka]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Molimo unesite lozinku potrebnu za ulaz u server(nije potrebno).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Korisničko ime]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Molimo unesite korisničko ime potrebnu za ulaz u server(nije potrebno).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Kod zadnjeg pokušaja spajanja nastala je sljedeća greška:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} servera ponuđeno]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[ID servera]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Paketi]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adresa]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Odredite adresu (URL) prema paketu servera.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[Unešena adresa nije valjana.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Posljednji pristup]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[Ponuđeni update serveri]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Nema update servera.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[Dodaj novog korisnika]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[Detalji korisnika]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[Novi korisnik je uspješno dodan.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Grupa]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Dodaj korisnika u sljedeću grupu(e):]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Korisnik je uspješno dodan u odabrane grupe.]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Grupa]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Eksportiraj e-mail adrese]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Pošalji e-mail]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[Izbriši korisnika(e)]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[Korisnik nije izrbisan.]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}Korisnik je {else}{#$deletedUsers} korisnici su{/if} uspješno izbrisani.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Jeste li sigurni da želite izbrisati korisnika?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Jeste li sigurni da želite izbrisati izabranog(e) korisnika(e)?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[Uredi korisnika]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[Vaše promjene su uspješno sačuvane.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Uređujete vlastiti korisnički račun. Promjene u pristupima korisničkim grupama mogu dovesti da vas se isključi iz administracijskog panela. Molimo vas budite oprezni!]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Eksportiraj e-mail adrese.]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Eksportiraj e-mail adrese.]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Postavke eksporta]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Eksportiraj e-mail adrese od sljedećih korisnika]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Podjeli adrese sa]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Zatvori adresu s]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[Grupe]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Pronađo korisnike, koji su članovi odabranih korisničkih grupa.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[Korisnici]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[Sve korisnike prikazati]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[Sveukupno {#$items} korisnik{if $items > 1}a{/if}]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 korisnik izabran" : this.count+" korisnika izabrano"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Masovno uređivanje korisnika]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Akcije]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Uvjeti]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Odabrane akcije su uspješno izvršene na sljedećem korisniku {#$affectedUsers}.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Masovno uređivanje korisnika izvršava ispod odabranu akciju <b>bez dodatnih sigurnosnih pitanja</b> ne sve korisnike koji spadaju pod dolje navedene uvjete. Uređivanje može jako puno potrajati i jako usporiti forum, te je najbolje isključiti forum na neko vrijeme i izbršiti ovu proceduru! Promjene se ne mogu povratiti, pa s toga koristite ovu opciju sa oprezom!]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[Pretraži korisnike]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Kriterij pretrage]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Opći kriteriji pretrage]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Pretraga profilnih kriterija]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[Prikaz]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Prikazane Informacije]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Ostalo]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profil]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[Općenito]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Korisnika po stranici]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Svrstavanje]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Niti jedan korisnik nije pronađen]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[Vaša pretraga ima {if $items == 1}jedan rezultat{else}{#$items} rezultata{/if}]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Pretraga unutar rezultata]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[Pošalji e-mail]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[Pošalji e-mail svim korisnicima]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[E-Mail kao HTML poslati]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Pošiljatelj]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Ovdje možete E-Mail adresu pošiljatelja definirati.{if MAIL_USE_FORMATTED_ADDRESS} Moguć je i sljdeći format:{/if}</p>
+{if MAIL_USE_FORMATTED_ADDRESS}<p style="text-align: center; line-height: 2em;"><code>Ime Pošiljatelja &lt;email@absender.tld&gt;</code></p>{/if}
+<p>Kada ste pod sistem -> opcije -> E-Mail sve ispunili, ovo polje se automatski dodaje. Šaljete li E-Mail-ove preko SMTP, obratite pažnju da se E-Mail adresa pošiljatelja od strane server prihvaća      .</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[Pošalji e-mail svim članovima grupe]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Pošalji e-mail članovima sljedećih grupa:]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-mail]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Pošalji e-mail sljedećim korisnicima]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Naslov]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Unesite naslov e-maila]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Poruka]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Ovdje upišite tekst u poruci]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[Dobrodošli {$this->user->username}.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Trenutni proces]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[Molim vas ostavite otvoren ovaj Browser dok se proces ne završi i nemojte se ni u kojem slučaju prijaviti ponovno u administracijski kontrolni panel jer bi mogli naštetiti procesu.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Proces je uspješno završen]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[U tijeku ...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% završeno]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[U tijeku ...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Natrag]]></item>
+               <item name="wcf.global.button.close"><![CDATA[Zatvoriti]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[Izbriši]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Želite li ovaj element stvarno izbrisati?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Kopletno izbrisati]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[Urediti]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[Pređi ne urednik]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[Izaberi]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Dalje &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[Pregled]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[Poništi]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[Pošalji]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[Odznači]]></item>
+               <item name="wcf.global.date.day"><![CDATA[Dan]]></item>
+               <item name="wcf.global.date.days"><![CDATA[Dana]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[Sat]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[Sati]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[Minute]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[Minuta]]></item>
+               <item name="wcf.global.date.month"><![CDATA[Mjesec]]></item>
+               <item name="wcf.global.date.months"><![CDATA[Mjeseci]]></item>
+               <item name="wcf.global.date.second"><![CDATA[Sekunde]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[Sekunda]]></item>
+               <item name="wcf.global.date.week"><![CDATA[Tjedan]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[Tjedana]]></item>
+               <item name="wcf.global.date.year"><![CDATA[Godina]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Određivanje godine nije potrebno.]]></item>
+               <item name="wcf.global.date.years"><![CDATA[Godina]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%A, %d %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Danas</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Jučer, %H:%M]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[Uobičajno]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[Povratak na prethodnu stranu]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[Molimo unesite potrebne informacije za ovo polje.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[Fajl nije pronađen.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[Otvorili ste jedan nevažeći link.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Nije vam dozvoljeno pregledati ovu stranicu. Nemate potrebna prava za pregled ove stranice. Ako nemožete vidjeti početnu stranicu vjerovatno ste BANani.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Nije vam dozvoljeno vidjeti ovu stranicu.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[Greška]]></item>
+               <item name="wcf.global.form.error"><![CDATA[Podaci koje ste unjeli nisu valjani. Molimo pogledajte podatke u označenim poljima.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arapski]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosanski]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Češki]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danski]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Njemački]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Njemački (Neslužbeni)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grčki]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Engleski]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Španjolski]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Iranski (Farsi)]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finski]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Francuski]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Židovski]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Hrvatski]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Mađarski]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Talijanski]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japanski]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Koreanski]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Nizozemski]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norveški]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Poljski]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugalski]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugalski (Brazilski)]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Rumunjski]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Ruski]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovački]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Srpski]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Švedski]]></item>
+               <item name="wcf.global.language.th"><![CDATA[Thailändisch]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turski]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Kineski (Pojednostavljeni)]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Kineski (Tradicionalni)]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[hr_HR]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[hrvatski]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[Može se označiti više stvari koristeći &quot;Ctrl/Shift&quot; tipke (Windows) ili &quot;Command&quot; (Mac OS) da biste označili više stvari.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[Skoči na sljedeću stranicu]]></item>
+               <item name="wcf.global.page.next"><![CDATA[Iduća strana]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[Prethodna strana]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab Community Framework]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[Preusmjeravanje]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[Molim kliknite ovdje ako automatsko preusmeravanje Vas ne preusmjeri dalje!]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[Idi na vrh ove strane.]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Točno poklapanje.]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[Na početak stranice skočiti]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[uzlazno]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[silazno]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[.]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %d %B %Y, %H:%M]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Slika " + (this.currentIndex + 1) + " von " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[Zatvoriti]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Samo ovu sliku prikazati (završava pregled slika)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[Sljedeća Slika]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[Diashow zaustaviti]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[Diashow pokrenuti (promjena slika svakihe 5 sekundi)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[Prethodna Slika Bild]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Canary Islands, Lisbon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brussels, Madrid, Paris, Prague, Rome, Sarajevo, Stockholm, Tunis, Warsaw, Vienna]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athens, Beirut, Bucharest, Helsinki, Istanbul, Jerusalem, Cairo, Cape Town, Khartoum, Kiev, Minsk, Sofia]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Ababa, Antananarivo, Baghdad, Dodoma, Kampala, Kuwait City, Mogadishu, Moscow, Nairobi, Riyadh]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Tehran]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Yerevan, Muscat, R&eacute;union, Tbilisi]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Ashgabat, Bishkek, Dushanbe, Islamabad, Yekaterinburg, Karachi, Maldive Islands, Tashkent]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, New Delhi]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Novosibirsk]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Islands, Yangon]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Beijing, Perth, Singapore, Taipei, Ulaanbaatar]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Western Australia)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seoul, Tokyo]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Island (Australia)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, New Caledonia, Solomon Islands]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolk Island]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, South Tarawa, Fiji, Kamchatka, Marshall Islands, Wellington]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Islands (New Zealand)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenix Islands]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Islands, Christmas Island]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azores, Cape Verde Islands]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mid-Atlantic]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Greenland, Montevideo]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Newfoundland]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantic Time (Canada), Asunci&oacute;n, La Paz, Port-of-Spain, Santiago]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Eastern Time (US &amp; Canada), Bogot&aacute;, Lima, San Francisco de Quito]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Central Time (US &amp; Canada), Central America, Mexico City]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Time (US &amp; Canada), Chihuahua, Mazatlan]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pacific Time (US &amp; Canada), Tijuana]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) French Polynesia]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cook Islands, Hawaii]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midway Islands, Samoa]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[Stranica {#$pageNo}]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[Potvrdi E-Mail adresu]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[Potrvdi lozinku]]></item>
+               <item name="wcf.user.email"><![CDATA[E-Mail adresa]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Dana E-Mail adresa i potvrđujuća e-mail adresa ne podudaraju se.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Dana lozinka i potvrđujuća lozinka ne podudaraju se.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[E-Mail adresu već koristi drugi član.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[E-Mail adresa koju ste naveli nije ispravna.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[Lozinka je netočna.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[Korisničko ime &quot;{$username}&quot; nije pronađeno.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Korisničko ime koje ste naveli već se koristi.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[Korisničko ime nije valjano.]]></item>
+               <item name="wcf.user.language"><![CDATA[Jezik]]></item>
+               <item name="wcf.user.language.description"><![CDATA[Molim odaberite jezik na kojem će korisničko sućelje biti prikazano!]]></item>
+               <item name="wcf.user.logout"><![CDATA[Odlogiraj]]></item>
+               <item name="wcf.user.password"><![CDATA[Lozinka]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[Datum registracije]]></item>
+               <item name="wcf.user.userID"><![CDATA[Korisnički ID]]></item>
+               <item name="wcf.user.username"><![CDATA[Korisničko ime]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[Pokaži sadržaj u sljedećim jezicima]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Izaberite jezik u kojem će sadržaj biti prikazan]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Informacije koje ste unijeli nisu valjane.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/it.xml b/wcfsetup/install/lang/it.xml
new file mode 100644 (file)
index 0000000..f0bc786
--- /dev/null
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="it">\r
+       <category name="wcf.acp">\r
+               <item name="wcf.acp"><![CDATA[Pannello di Controllo Amministrazione]]></item>\r
+               <item name="wcf.acp.help"><![CDATA[Aiuto]]></item>\r
+               <item name="wcf.acp.help.complete"><![CDATA[Aiuto completo]]></item>\r
+               <item name="wcf.acp.help.disable"><![CDATA[Disabilita aiuto]]></item>\r
+               <item name="wcf.acp.help.interactive"><![CDATA[Aiuto interattivo]]></item>\r
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Cambia pacchetto]]></item>\r
+               <item name="wcf.acp.search.extended"><![CDATA[Ricerca estesa ...]]></item>\r
+               <item name="wcf.acp.sitemap"><![CDATA[Mappa Sito]]></item>\r
+       </category>\r
+       <category name="wcf.acp.cache">\r
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Svuota cache]]></item>\r
+               <item name="wcf.acp.cache.clear.success"><![CDATA[La cache è stata svuotata con successo.]]></item>\r
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Siete sicuro di voler svuotare completamente la cache?]]></item>\r
+               <item name="wcf.acp.cache.data"><![CDATA[Proprietà]]></item>\r
+               <item name="wcf.acp.cache.data.files"><![CDATA[Files]]></item>\r
+               <item name="wcf.acp.cache.data.size"><![CDATA[Peso]]></item>\r
+               <item name="wcf.acp.cache.data.source"><![CDATA[Sorgente]]></item>\r
+               <item name="wcf.acp.cache.data.version"><![CDATA[Versione]]></item>\r
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Ultimo aggiornamento]]></item>\r
+               <item name="wcf.acp.cache.list.name"><![CDATA[Nome]]></item>\r
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Permessi]]></item>\r
+               <item name="wcf.acp.cache.list.size"><![CDATA[Peso]]></item>\r
+       </category>\r
+       <category name="wcf.acp.group">\r
+               <item name="wcf.acp.group.add"><![CDATA[Aggiungi nuovo Gruppo utenti]]></item>\r
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Permessi]]></item>\r
+               <item name="wcf.acp.group.add.success"><![CDATA[Il gruppo utenti è stato inserito con successo.]]></item>\r
+               <item name="wcf.acp.group.administrators"><![CDATA[Amministratori]]></item>\r
+               <item name="wcf.acp.group.data"><![CDATA[informazioni generali del gruppo]]></item>\r
+               <item name="wcf.acp.group.delete"><![CDATA[Cancella questo gruppo utenti]]></item>\r
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Questo gruppo utenti è stato cancellato{else}I seguenti gruppi utenti {#$deletedGroups} sono stati cancellati{/if} con successo.]]></item>\r
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Siete sicuri di voler rimuovere questo gruppo utenti?]]></item>\r
+               <item name="wcf.acp.group.edit"><![CDATA[Modifica questo gruppo utenti]]></item>\r
+               <item name="wcf.acp.group.edit.success"><![CDATA[Le modifiche apportate al gruppo utenti visualizzato sono state salvate con successo.]]></item>\r
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Al momento siete un membro di questo gruppo utenti. Cambiare i permessi di accesso di questo gruppo potrebbe negarvi l'accesso al Pannello di Controllo dell'Amminstrazione. Prego fare attenzione!]]></item>\r
+               <item name="wcf.acp.group.everyone"><![CDATA[Chiunque]]></item>\r
+               <item name="wcf.acp.group.groupID"><![CDATA[ID Gruppo]]></item>\r
+               <item name="wcf.acp.group.groupName"><![CDATA[Nome gruppo utenti]]></item>\r
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Inserire qui il nome che verrà utilizzato per questo Gruppo.]]></item>\r
+               <item name="wcf.acp.group.guests"><![CDATA[Ospiti]]></item>\r
+               <item name="wcf.acp.group.list"><![CDATA[Gruppo utenti]]></item>\r
+               <item name="wcf.acp.group.list.data"><![CDATA[Un totale di {#$items} gruppi utenti]]></item>\r
+               <item name="wcf.acp.group.members"><![CDATA[Numero di membri]]></item>\r
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatori]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Possono accedere al Pannello di Controllo Amministrazione?]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Attivando questa opzione permetterai ai membri di questo gruppo utenti di accedere al pannello amministrazione e in base ai loro permessi potranno eseguire certe operazioni. Prego fare massima attenzione.]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Può visualizzare opzioni private degli utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Membri di questo gruppo possono visualizzare opzioni private degli utenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Può modificare le opzioni di sistema?]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Attivando questa opzione permetterai agli utenti di questo gruppo di visualizzare e modificare le opzioni di sistema - (Ad esempio Disabilitare/Abilitare il forum)]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Può visualizzare i logs]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Membri di questo gruppo possono visualizzare i logs di sistema.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Può modificare i server degli aggiornamenti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Membri di questo gruppo possono modificare i server degli aggiornamenti esistenti e aggiungerne dei nuovi.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Può installare nuovi pacchetti]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Membri di questo gruppo possono installare nuovi Pacchetti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Può rimuovere i pacchetti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Membri di questo gruppo possono rimuovere pacchetti esistenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Può aggiornare i pacchetti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Membri di questo gruppo possono aggiornare i pacchetti esistenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Gruppi utenti accessibili]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Membri di questo gruppo hanno accesso ai seguenti gruppi. Per esempio, qui si può decidere se Il gruppo utenti può modificare se stesso.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Può aggiungere nuovi gruppi utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Membri di questo gruppo possono aggiungere nuovi Gruppi utente.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Può aggiungere nuovi utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Membri di questo gruppo possono aggiungere nuovi utenti. Se l'opzione "Gruppo utenti accessibile" risulta abilitata, durante la creazione dei nuovi utenti può essere assegnato il gruppo più opportuno.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Può cancellare Gruppi utenti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Membri di questo gruppo possono cancellare Gruppi utenti esistenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Può cancellare utenti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Membri di questo gruppo possono cancellare utenti esistenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Può modificare i gruppi utenti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Membri di questo gruppo possono modificare Gruppi utente esistenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Può modificare l'indirizzo E-Mail degli utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Membri di questo gruppo possono modificare l'indirizzo E-Mail degli utenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Può modificare le password degli utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Membri di questo gruppo possono modificare le password degli utenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Può modificare gli utenti esistenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Membri di questo gruppo possono modificare gli utenti esistenti.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Può inviare E-Mail agli utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Membri di questo gruppo possono vedere la mail degli altri utenti e conseguentemente inviare loro delle E-Mails.]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Può ricercare utenti]]></item>\r
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Membri di questo gruppo possono ricercare utenti esistenti e i loro profili.]]></item>\r
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Permessi amministratore]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Contenuto]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Design]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Permessi amministrativi generali]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Manutenzione]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[Funzioni di sistema]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Amministrazione pacchetti]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Funzioni utente]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Amministrazione gruppi]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Amministrazione utenti]]></item>\r
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Permessi dei moderatori]]></item>\r
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Permessi generali]]></item>\r
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[L'informazione inserita non è valida.]]></item>\r
+               <item name="wcf.acp.group.showMembers"><![CDATA[Mostra i membri di questo gruppo utenti]]></item>\r
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super Moderatori]]></item>\r
+               <item name="wcf.acp.group.users"><![CDATA[Utenti registrati]]></item>\r
+       </category>\r
+       <category name="wcf.acp.login">\r
+               <item name="wcf.acp.login"><![CDATA[Login]]></item>\r
+               <item name="wcf.acp.login.data"><![CDATA[Dettagli Login]]></item>\r
+       </category>\r
+       <category name="wcf.acp.masterPassword">\r
+               <item name="wcf.acp.masterPassword"><![CDATA[Master password]]></item>\r
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Conferma master password]]></item>\r
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Master password richiesta]]></item>\r
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Per ragioni di sicurezza, questa pagina/operazione richiede l'inserimento della master password. Questa operazione è richiesta una sola volta per sessione. Se avete dimenticato la password, per resettarla è sufficiente cancellare il file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[La master password non è corretta.Se avete dimenticato la password, per resettarla è sufficiente che cancellate il file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[Le password inserite non sono identiche.]]></item>\r
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[La password non è sicura. Deve contenere un minimo di otto caratteri, lettere maiuscole e minuscole come numeri e simboli speciali. Non deve essere identica alla password dell'amministratore.]]></item>\r
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Suggerimento]]></item>\r
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Usa suggerimento]]></item>\r
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Imposta master password]]></item>\r
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[La master password rappresenta una protezione aggiuntiva per quelle funzionalità sensibili del sistema. Devi usare una password davvero sicura e che non sia identica a quella del tuo account personale, sconosciuta agli altri e non utilizzata in altri siti web.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.menu">\r
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Aggiornamento automatico]]></item>\r
+               <item name="wcf.acp.menu.link.content"><![CDATA[Contenuto]]></item>\r
+               <item name="wcf.acp.menu.link.display"><![CDATA[Aspetto]]></item>\r
+               <item name="wcf.acp.menu.link.group"><![CDATA[Gestione gruppi utente]]></item>\r
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Aggiungi nuovo Gruppo]]></item>\r
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[Invia E-Mail a tutti i membri del gruppo]]></item>\r
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Dettagli Gruppo]]></item>\r
+               <item name="wcf.acp.menu.link.log"><![CDATA[Log]]></item>\r
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Sessione]]></item>\r
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Manutenzione]]></item>\r
+               <item name="wcf.acp.menu.link.option"><![CDATA[Opzioni]]></item>\r
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Importa &amp; esporta]]></item>\r
+               <item name="wcf.acp.menu.link.package"><![CDATA[Pacchetti]]></item>\r
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Cerca pacchetto]]></item>\r
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Installa nuovo pacchetto]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Aggiungi nuovo server]]></item>\r
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Dettagli server]]></item>\r
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Elenca pacchetti installati]]></item>\r
+               <item name="wcf.acp.menu.link.system"><![CDATA[Sistema]]></item>\r
+               <item name="wcf.acp.menu.link.user"><![CDATA[Utenti]]></item>\r
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Aggiungi nuovo utente]]></item>\r
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Dettagli utente]]></item>\r
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[Invia E-Mail a tutti gli utenti]]></item>\r
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Gestione utenti]]></item>\r
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Processo completo sugli utenti]]></item>\r
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Cerca per utenti]]></item>\r
+       </category>\r
+       <category name="wcf.acp.option">\r
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Escludi hostnames]]></item>\r
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Inserire un hostname per riga da escludere in questo sito.]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[Escludi indirizzi IP]]></item>\r
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Inserire un IP per riga da escludere in questo sito.]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Escludi user agents]]></item>\r
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Inserire un user agent per riga da escludere in questo sito.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Inserire l'indirizzo del memcache server! Puoi inserire un server per ogni riga.]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Utilizza connessioni persistenti]]></item>\r
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Abilitando questa opzione sarà utilizzata una connessione persistente con il memcache Server.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Tipo Cache]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Selezionare il tipo di cache che si vuole utilizzare! Molti di questi tipi hanno particolari requisiti e non possono essere utilizzate nel tuo sistema.]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[File system (predefinito)]]></item>\r
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (sperimentale)]]></item>\r
+               <item name="wcf.acp.option.category.general"><![CDATA[Generale]]></item>\r
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Generale]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>\r
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache memorizza i dati nella parte della memoria che non è mai usata. Ciò riduce drasticamente il carico del database. Per avere maggiori informazioni su questa funzionalità visita il sito:\r
+<ul>\r
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>\r
+</ul>]]></item>\r
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Data e Ora]]></item>\r
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>\r
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>\r
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Server proxy]]></item>\r
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Puoi impostare un server proxy opzionale per la connessione ad altri servers esterni.]]></item>\r
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Generale]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Transmissione]]></item>\r
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Disabilita il forum temporaneamente]]></item>\r
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module"><![CDATA[Moduli on / off]]></item>\r
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Contentuti]]></item>\r
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Visualizzazione]]></item>\r
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.system"><![CDATA[Sistema]]></item>\r
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Utenti]]></item>\r
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security"><![CDATA[Sicurezza]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>\r
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Le pagine in internet sono spesso sottoposte ad attacchi esterni da parte di programmi o robots. E' possibile ad esempio creare centinaia di account in modo automatico. Puoi proteggerti facendo ricorso alle così dette tecnologie che sfruttano le <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">immagini captcha</a> in tutte le pagine dove un modulo può essere inviato al server. Utenti non registrati dovranno confermare il codice visualizzato nella immagine prima di poter inviare il modulo. I Robots, come i software, non possono leggere questo codice.]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Lista nera]]></item>\r
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Censura]]></item>\r
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Generale]]></item>\r
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessioni]]></item>\r
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.category.user"><![CDATA[Utenti]]></item>\r
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Dominio cookie]]></item>\r
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Inserire il Dominio da assegnare al cookie.]]></item>\r
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Percorso dei Cookie]]></item>\r
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[La path del cookie deve coincidere con la radice del tuo sito - Es. "/" per www.woltlab.com]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Prefisso Cookie]]></item>\r
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Abilita passaggio automatico all'ora legale]]></item>\r
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Si deve passare automaticamente all'ora legale Estiva/Invernale?]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Use cache method for session data]]></item>\r
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Should the selected cache method be used to save the session data?]]></item>\r
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[L'informazione inserita non è valida.]]></item>\r
+               <item name="wcf.acp.option.export"><![CDATA[Esporta opzioni]]></item>\r
+               <item name="wcf.acp.option.export.download"><![CDATA[Scarica opzioni esportate]]></item>\r
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Scarica le opzioni esportate per salvarle come backup nel tuo computer.]]></item>\r
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Abilita il Content-Type application/xhtml+xml]]></item>\r
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[Abilitando questa opzione ti permetterà di visualizzare le pagine usando il Content-Type application/xhtml+xml.]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Abilita compressione Gzip]]></item>\r
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Abilitando questa opzione i contenuti verranno automaticamente compressi nel Server e inviati al Client in forma compressa. Questa opzione riduce il traffico, ma non è supportata da tutti i browsers/computer. Alcuni utenti potrebbero vedere una pagina completamente bianca.]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Disabilita il salvataggio delle pagine nella cache del browser]]></item>\r
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Abilitando questa opzione si nega il caching delle pagine nel browser.]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Livello compressione]]></item>\r
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Si richiede un valore da 1 a 9. Per una migliore resa della compressione e delle prestazioni del server, si consiglia il valore 1.]]></item>\r
+               <item name="wcf.acp.option.import"><![CDATA[Importa opzioni]]></item>\r
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>\r
+               <item name="wcf.acp.option.import.success"><![CDATA[Le opzioni sono state importate con successo.]]></item>\r
+               <item name="wcf.acp.option.import.upload"><![CDATA[Carica opzioni]]></item>\r
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Carica le opzioni dal tuo computer per essere poi importate nel forum.]]></item>\r
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Importa &amp; Esporta opzioni]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Indirizzi E-Mail degli amministratori]]></item>\r
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Inserire qui l'indirizzo E-Mail degli Amministratori.]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Percorso ai logfile di Debug]]></item>\r
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Inserire qui il percorso ai file di log.]]></item>\r
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Indirizzo E-Mail dei mittenti]]></item>\r
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Inserire qui gli indirizzi E-Mail che devono essere usati per le E-Mail automatiche.]]></item>\r
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Nome mittenti]]></item>\r
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Inserire qui il nome dei mittenti che devono essere usati per le E-Mail automatiche.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[Metodo invio E-Mail]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Selezionare un metodo di trasmissione delle E-Mail.]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>\r
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>\r
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Firma mittenti]]></item>\r
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Inserire qui la firma che verrà inserita nelle E-Mail inviate dal sistema.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP Host]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Inserire qui il nome del server SMTP.]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP Password]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Inserire qui la password dell'account di posta]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP Port]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Inserire qui la porta del server SMTP (solitamente è la 25)]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP Username]]></item>\r
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Inserire qui l'username dell'account di posta per il Server SMTP]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[Abilita il parametro &quot;-f&quot;]]></item>\r
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Alcuni Servers potrebbero richiedere il parametro "-f" abilitato per essere usato durante il processo di invio delle E-Mail. Se si riscontrano problemi con utenti che non ricevono le Emails provare ad abilitare questo parametro, o se abilitato provare a disabilitarlo.]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Utilizzare indirizzi email formattati]]></item>\r
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Gli indirizzi dei mittenti e destinatari devono essere formattati nel seguente modo &quot;Nome &lt;email@dominio.ext&gt;&quot;.<br/>Questa opzione non è supportata da tutti i server, in caso di errore nell'invio o non ricezione delle email si prega di disabilitarla.]]></item>\r
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Abilita master password]]></item>\r
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Le pagine e moduli del pannello di controllo che hanno una certa rilevanza in fatto di sicurezza possono essere protette con una master password aggiuntiva.]]></item>\r
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Server Proxy (FTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[Server Proxy per connessioni FTP]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Server Proxy (HTTP)]]></item>\r
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Server Proxy per connessioni HTTP]]></item>\r
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Timeout delle Sessioni]]></item>\r
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Inserire qui il tempo di validità di una Sessione [Secondis].]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Controlla indirizzi IP delle sessioni]]></item>\r
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Numero di blocchi di un IP da controllare durante le sessioni. Un numero elevato può escludere utenti che hanno un IP dinamico.]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Controlla user agent delle sessioni]]></item>\r
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Vuoi che l'user agent venga controllato durante la lettura dei dati delle sessioni?]]></item>\r
+               <item name="wcf.acp.option.success"><![CDATA[Le modifiche alle opzioni sono state salvate con successo.]]></item>\r
+               <item name="wcf.acp.option.timezone"><![CDATA[Impostazioni Ora locale]]></item>\r
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Selezionare l'ora locale Standard del vostro sito.]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Timeout degli utenti online]]></item>\r
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Inserire qua per quanto tempo gli utenti vengono segnalati come Online dopo che sono inattivi [Secondi].]]></item>\r
+       </category>\r
+       <category name="wcf.acp.package">\r
+               <item name="wcf.acp.package.cancel"><![CDATA[Annulla installazione del pacchetto]]></item>\r
+               <item name="wcf.acp.package.description"><![CDATA[Descrizione]]></item>\r
+               <item name="wcf.acp.package.ftp"><![CDATA[Inserire qui i dettagli per accedere via FTP]]></item>\r
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[Dettagli accesso FTP]]></item>\r
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Opzione PHP Safe-Mode attivata nel tuo server, il pacchetto necessita di essere salvato con  il supporto alle funzione FTP. Prego inserire i dati di accesso via FTP al vostro server. Le informazioni inserite non saranno registrate o spedite esternamente ma saranno solo usate per installare questo pacchetto. Per questa ragione può essere possibile che questi dati verranno successivamente richiesti durante il processo di installazione.]]></item>\r
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Con i dati di accesso inseriti non risulta possibile effettuare una connessione FTP al server.]]></item>\r
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[Impossibile effettuare una connessione al server FTP indicato.]]></item>\r
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[Impossibile effettuare una corretta autenticazione al server FTP indicato.]]></item>\r
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Username]]></item>\r
+               <item name="wcf.acp.package.install"><![CDATA[Installazione pacchetto]]></item>\r
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Annulla installazione]]></item>\r
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Siete sicuri di voler annullare questa installazione?]]></item>\r
+               <item name="wcf.acp.package.install.error"><![CDATA[Non è possibile soddisfare le dipendenze di questo pacchetto.]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[L'{if $action == 'install'}installazione{else}aggiornamento{/if} del pacchetto &quot;{$packageName}&quot; con versione {$packageVersion} non può essere eseguita per incompatibilità con {if $excludedPackages|count == 1}il seguente pacchetto{else}i seguenti pacchetti{/if}:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} con versione {$excludedPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Il seguente pacchetto non permette{else}I seguenti pacchetti non permettono{/if} l'{if $action == 'install'}installazione{else}aggiornamento{/if} del pacchetto &quot;{$packageName}&quot; con versione {$packageVersion} a causa di incompatibilità:]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} in version {$excludingPackage.packageVersion}]]></item>\r
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Il seguente pacchetto è incompatibile{else}I seguenti pacchetti sono incompatibili{/if} con il pacchetto &quot;{$packageName}&quot; con versione {$packageVersion}. Se procedete con la sua installazione {if $excludingPackages|count == 1}il pacchetto{else}i pacchetti{/if} smetteranno, probabilemnte, di funzionare correttamente.]]></item>\r
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}Installato{else}{if $package.file|isset}è incluso in questo pacchetto{else}Non disponibile{/if}{/if})</span>]]></item>\r
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Siete sicuri di voler annullare la installazione di questo pacchetto?]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[I seguenti pacchetti possono essere aggiornati con questo pacchetto]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Selezionare uno dei seguenti pacchetti per aggiornare la loro versione. Se si vuole reinstallare il pacchetto, cliccare sul pulsante &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>\r
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Risulta già installata una copia di questo pacchetto. Se possedete una diversa versione (aggiornata) di questo pacchetto l'installazione procederà normalmente. Se volete aggiornare una copia esistente di questo pacchetto, selezionare la copia dalla seguente lista.]]></item>\r
+               <item name="wcf.acp.package.install.version"><![CDATA[Versione pacchetto:]]></item>\r
+               <item name="wcf.acp.package.installDate"><![CDATA[Data installazione]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Durante il processo di decompressione dei file del pacchetto si è verificato il seguente errore:]]></item>\r
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[I files seguenti non possono essere depachettizzati. Controllare se la cartella di destinazione ha i premessi di scrittura abilitati.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Tabelle in conflitto]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Non sovrascrivere queste tabelle e non chiedere nuovamente per questa operazione.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Sovrascrivi le tabelle esistenti e non chiedere nuovamente per questa operazione.]]></item>\r
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Modifiche richieste]]></item>\r
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Tabelle interessate]]></item>\r
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Sono stati rilevati dei conflitti fra le tabelle del database e le taballe richieste dalla installazione di questo pacchetto. Prego scegliere se sovrascrivere queste tabelle.]]></item>\r
+               <item name="wcf.acp.package.list"><![CDATA[Pacchetti installati]]></item>\r
+               <item name="wcf.acp.package.list.author"><![CDATA[Autore]]></item>\r
+               <item name="wcf.acp.package.list.count"><![CDATA[Risultano installati un totale di {#$items} pacchetto(i)]]></item>\r
+               <item name="wcf.acp.package.list.date"><![CDATA[Data]]></item>\r
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.package.list.name"><![CDATA[Nome]]></item>\r
+               <item name="wcf.acp.package.list.other"><![CDATA[Pacchetto]]></item>\r
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>\r
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Applicazione autonoma]]></item>\r
+               <item name="wcf.acp.package.list.version"><![CDATA[Versione]]></item>\r
+               <item name="wcf.acp.package.optionals"><![CDATA[Installa pacchetto aggiuntivo]]></item>\r
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Il pacchetto selezionato comprende i seguenti pacchetti aggiuntivi. Prego selezionare quale di questi volete installare.]]></item>\r
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[(Questo pacchetto risulta già installato.)]]></item>\r
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[(I requisiti di questo pacchetto non sono stati soddisfatti.)]]></item>\r
+               <item name="wcf.acp.package.packageDir"><![CDATA[Cartella installazione]]></item>\r
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[In questa cartella risulta già installata un'altra applicazione.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[This folder is invalid.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[La cartella non risulta avere i diritti di scrittura.]]></item>\r
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Questa cartella risulta già usata da WoltLab Community Framework. Prego selezionare una cartella di installazione differente.]]></item>\r
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Prego inserire qui la cartella di installazione.]]></item>\r
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Questa applicazione è accessibile, dopo la sua installazione, all'url:]]></item>\r
+               <item name="wcf.acp.package.requirements"><![CDATA[Selezionare le dipendenze]]></item>\r
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Questo pacchetto richiede la presenza di un altro pacchetto che è stato installato in precedenza. Prego selezionare l'istanza richiesta.]]></item>\r
+               <item name="wcf.acp.package.rollback"><![CDATA[Ripristino installazione pacchetto]]></item>\r
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Versione {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>\r
+               <item name="wcf.acp.package.startInstall"><![CDATA[Installa nuovo pacchetto]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Il pacchetto selezionato non ha una routine di installazione valida.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[L'archivio inserito non risulta un pacchetto valido.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Il pacchetto &quot;{$package->getName()}&quot; non può essere caricato dall'archivio di cui è dotato.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Non sono stati trovati file all'interno della directory indicata.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Il pacchetto scelto è già installato. I pacchetti non possono essere installati più di una volta.]]></item>\r
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[L'Upload dell'archivio scelto è fallito.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Sorgente pacchetto selezionato]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Inserire il percorso del pacchetto presente sul vostro server]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Inserire qui il percorso diretto al file del pacchetto. Si può indicare un indirizzo internet o alternativamente, il percorso al file del pacchetto usando il File System del Server.]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Carica pacchetto dal tuo computer locale]]></item>\r
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Inserire qui il file del pacchetto che si vuole caricare dal tuo computer.]]></item>\r
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Carica pacchetto &quot;{$package->getName()}&quot;]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Installazione dei valori del menù per il pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Installazione del percorso dei templates per il pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Installazione dei template per il pannello di controllo degli amministratori ...]]></item>\r
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Installazione Event-Listener ...]]></item>\r
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Unpacking dei file del pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Installazione opzioni Gruppi Utente ...]]></item>\r
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Installazione dei pacchetti delle lingue ...]]></item>\r
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Installazione opzioni pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Esecuzione script speciali ...]]></item>\r
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Installazione valori Database...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Installazione percorsi dei template ...]]></item>\r
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Installazione pacchetto dei templates ...]]></item>\r
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Installazione campi profilo utente ...]]></item>\r
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Controllo possibili conflitti ...]]></item>\r
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Esecuzione pacchetto plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Installazione terminata]]></item>\r
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Installazione pacchetti aggiuntivi ...]]></item>\r
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Registrazione pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Installazione pacchetto Plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Allocazione pacchetto principale ...]]></item>\r
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Controllo dipendenze ...]]></item>\r
+               <item name="wcf.acp.package.step.title"><![CDATA[Pacchetto <b>{$packageName|encodeJS}</b>: ]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Disinstallazione dei valori del menù dal pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Disinstallazione dei percorsi dei template del pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Disinstallazione dei tamplate del pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Disinstallazione Event-Listener ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Disinstallazione files del pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Disinstallazione delle opzioni dei Gruppi utente ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Disinstallazione pacchetto lingue ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Disinstallazione opzioni pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Disinstallazione valori del Database ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Disinstallazione percorso templates ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Disinstallazione pacchetto templates ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Disinstallazione campi del profilo utenti ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Esecuzione Pacchetto Plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Rimozione pacchetto terminato]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Disinstallazione pacchetti aggiuntivi ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Rimozione pacchetto Plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Rimozione requisiti del pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Aggiornamento dei campi del menù del pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Aggiornamento dei percorsi dei tamplate del pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Aggiornamento dei templates del pannello amministrazione ...]]></item>\r
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Aggiornamento Event-Listener ...]]></item>\r
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Unpacking dei file del pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Aggiornamento opzioni dei gruppi utenti ...]]></item>\r
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Aggiornamento pacchetto lingue ...]]></item>\r
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Aggiornamento opzioni pacchetto ...]]></item>\r
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Esecuzione script speciali ...]]></item>\r
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Aggiornamento valori Database ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Aggiornamento  percorso templates ...]]></item>\r
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Aggiornamento pacchetto dei Templates ...]]></item>\r
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Aggiornamento valori del profilo utente ...]]></item>\r
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Controllo possibili conflitti ...]]></item>\r
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Esecuzione Pacchetto Plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Aggiornamento pacchetto terminato]]></item>\r
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Aggiornamento Pacchetti opzionali ...]]></item>\r
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Aggiornamento pacchetti ...]]></item>\r
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Aggiornamento Pacchetto Plugins ...]]></item>\r
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Inizio allocazione Pacchetto Principale ...]]></item>\r
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Controllo dipendenze ...]]></item>\r
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[La patch che questo pacchetto vuole applicare non è conforme a quella riguardante la destinazione del file. Il pacchetto non può esser installato. Prego cliccare sul pulsante &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot;.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[L'aggiornamento della patch dei seguenti templates è fallito:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Originariamento corretto da: {$failure.packageName})<br />{/foreach}Il pacchetto con la patch che è stata applicata in precedente potrebbe non funzionare correttamente. E' possibile continuare l'aggiornamento cliccando sul pulsante &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>\r
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[La patch che questo pacchetto cerca di rimuovere è fallita poichè il pacchetto è stato modificato dall'esterno. Questo pacchetto non può essere rimosso. Prego cliccare sul pulsante &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot;.]]></item>\r
+               <item name="wcf.acp.package.uninstall"><![CDATA[Rimozione pacchetto]]></item>\r
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Annulla la rimozione del pacchetto]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Non è possibile disinstallare questi pacchetti, poichè questi possiedono almeno una dipendenza, che non può essere disinstallata.]]></item>\r
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Successivamente alla conferma finale {if $dependentPackages|count == 1}sarà rimosso questo pacchetto{else}saranno rimossi questi pacchetti{/if} senza ulteriore notifica.]]></item>\r
+               <item name="wcf.acp.package.update"><![CDATA[Aggiornamento pacchetto]]></item>\r
+               <item name="wcf.acp.package.updateDate"><![CDATA[Data aggiornamento]]></item>\r
+               <item name="wcf.acp.package.view.author"><![CDATA[Autore:]]></item>\r
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Vai al Pannello Amministrazione]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Rimuovi pacchetto]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Rimuovi tutti i pacchetti]]></item>\r
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Siete sicuri di voler rimuovere questo pacchetto?]]></item>\r
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Aggiornamento pacchetto]]></item>\r
+               <item name="wcf.acp.package.view.date"><![CDATA[Data:]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Pacchetti dipendenti]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Questo pacchetto richiede la presenza di {if $dependentPackages|count == 1}un altro pacchetto.{else}altri {#$dependentPackages|count}  pacchetti.{/if}]]></item>\r
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Questo pacchetto è richiesto da un altro pacchetto{else}{#$dependentPackages|count} pacchetti dipendono direttamente o indirittamente da questo pacchetto{/if}.]]></item>\r
+               <item name="wcf.acp.package.view.dir"><![CDATA[Cartella di installazione:]]></item>\r
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Contrassegno:]]></item>\r
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Istanza installata:]]></item>\r
+               <item name="wcf.acp.package.view.parent"><![CDATA[Pacchetto principale:]]></item>\r
+               <item name="wcf.acp.package.view.properties"><![CDATA[Proprietà]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Pacchetti richiesti]]></item>\r
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Questo pacchetto richiede l'installazione di {if $requiredPackages|count == 1}un altro pacchetto.{else}altri {#$requiredPackages|count} pacchetti.{/if}]]></item>\r
+               <item name="wcf.acp.package.view.url"><![CDATA[Homepage:]]></item>\r
+               <item name="wcf.acp.package.view.version"><![CDATA[Versione installata:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.packageUpdate">\r
+               <item name="wcf.acp.packageUpdate"><![CDATA[Aggiorna pacchetti]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Autenticazione con il server degli aggiornamenti]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Dati connessione]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Username and password have not been accepted.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Password]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Prego inserire la password richiesta per l'autenticazione.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Username]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Prego inserire l'username richiesto per l'autenticazione.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Login utente]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Messaggio server]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Nome server]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Salva i dati in modo permanente]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[I dati inseriti saranno salvati in modo permanente, non dovrai reinserirli in seguito.]]></item>\r
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Indirizzo]]></item>\r
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Versione installata]]></item>\r
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Si è verificato un errore: ]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Il download del pacchetto {$package} è fallito.]]></item>\r
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[Non è stato possibile trovare la lista dei pacchetti.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[{if $excludedPackages|count == 1}Si è verificato il seguente conflitto{else}Si sono verificati i seguenti conflitti{/if}:]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Il pacchetto installato &quot;{$excludedPackage.existingPackageName}&quot; è incompatibile con il pacchetto &quot;{$excludedPackage.packageName}&quot; con versione {$excludedPackage.packageVersion}.]]></item>\r
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[Il pacchetto &quot;{$excludedPackage.packageName}&quot; con versione {$excludedPackage.packageVersion} è incompatibile con il pacchetto installato &quot;{$excludedPackage.existingPackageName}&quot;.]]></item>\r
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} risulta aggiornato]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Non risultano esseri aggiornamenti disponibili.]]></item>\r
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Non hai selezionato alcun aggiornamento.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Opzioni]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Il pacchetto risulta già installato. Non può essere installato una seconda volta.]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Installa pacchetto]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Installa una nuova istanza del pacchetto (il pacchetto risulta già installato {#$package.instances} volt{if $package.instances > 1}e{else}a{/if})]]></item>\r
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Aggiorna pacchetto installato {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} versione {$updatableInstance.packageVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Cerca pacchetti]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Autore]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Cerca per ...]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Nascondi i pacchetti unici già installati]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Nome pacchetto]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Nome pacchetto e descrizione]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Aggiorna server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Cerca tutti gli aggiornamenti dei server]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Tipo di pacchetto]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Altri pacchetti]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Plugin per pacchetti già installati]]></item>\r
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Applicazione autonoma]]></item>\r
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Seleziona tutti i pacchetti]]></item>\r
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} aggiornato alla versione {$package.toVersion}]]></item>\r
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Nuova versione]]></item>\r
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Sono state processate le seguenti installazioni e aggiornamenti dei pacchetti:]]></item>\r
+       </category>\r
+       <category name="wcf.acp.sessionLog">\r
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Azioni delle sessioni di lavoro di &quot;{$sessionLog->username}&quot;]]></item>\r
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Ci sono un totale di {#$items} azion{if $items != 1}i registrate{else}e registrata{/if}]]></item>\r
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Azioni]]></item>\r
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Nome classe]]></item>\r
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[Indirizzo IP]]></item>\r
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Ultima azione]]></item>\r
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Pacchetto]]></item>\r
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Metodo]]></item>\r
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>\r
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Data]]></item>\r
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[User agent]]></item>\r
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Sessioni registrate]]></item>\r
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Ci sono un totale di {#$items} session{if $items != 1}i registrate{else}e registrata{/if}]]></item>\r
+       </category>\r
+       <category name="wcf.acp.updateServer">\r
+               <item name="wcf.acp.updateServer.add"><![CDATA[Aggiungi server]]></item>\r
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Il server è stato aggiunto con successo.]]></item>\r
+               <item name="wcf.acp.updateServer.data"><![CDATA[Dati del server]]></item>\r
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Cancella server]]></item>\r
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Il server è stato cancellato con successo.]]></item>\r
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Siete sicuro di voler cancellare questo server?]]></item>\r
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Disabilita]]></item>\r
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Modifica server]]></item>\r
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Le modifiche sono state salvate con successo.]]></item>\r
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Abilita]]></item>\r
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Messaggi di errori]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Password]]></item>\r
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Prego inserire la password che è richeista per l'autenticazione (opzionale).]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Username]]></item>\r
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Prego inserire l'username che è richiesto per l'autenticazione (opzionale).]]></item>\r
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Durante l'ultimo tentativo di connessione sono occorsi i seguenti errori:]]></item>\r
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} server disponibili]]></item>\r
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Id server]]></item>\r
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Pacchetti]]></item>\r
+               <item name="wcf.acp.updateServer.server"><![CDATA[Indirizzo]]></item>\r
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Prego inserire l'indirizzo al pacchetto del server.]]></item>\r
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[L'indirizzo inserito non è valido.]]></item>\r
+               <item name="wcf.acp.updateServer.status"><![CDATA[Stato]]></item>\r
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Ultimo accesso]]></item>\r
+               <item name="wcf.acp.updateServer.view"><![CDATA[Aggiornamenti nei server disponibili]]></item>\r
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Non risultano essere disponibili aggiornamenti nei server.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.user">\r
+               <item name="wcf.acp.user.add"><![CDATA[Aggiungi nuovo utente]]></item>\r
+               <item name="wcf.acp.user.add.data"><![CDATA[Dettagli utente]]></item>\r
+               <item name="wcf.acp.user.add.success"><![CDATA[Il nuovo utente è stato salvato con successo.]]></item>\r
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Assegnazione gruppo]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Assegna il seguente utente al gruppo(i) scelto(i)]]></item>\r
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Utente correttamente assegnato al gruppo scelto.]]></item>\r
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Assegnazione gruppo]]></item>\r
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Esporta indirizzi E-Mail]]></item>\r
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Invia una E-Mail]]></item>\r
+               <item name="wcf.acp.user.delete"><![CDATA[Cancella Utente(i)]]></item>\r
+               <item name="wcf.acp.user.delete.error"><![CDATA[Non è possibile cancellare l'utente.]]></item>\r
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}L'utente è stato rimosso{else}{#$deletedUsers} utenti sono stati rimossi{/if} con successo.]]></item>\r
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Siete sicuri di voler rimuovere questo utente?]]></item>\r
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Siete sicuri di voler rimuovere gli utenti selezionati?]]></item>\r
+               <item name="wcf.acp.user.edit"><![CDATA[Modifica utente]]></item>\r
+               <item name="wcf.acp.user.edit.success"><![CDATA[Le modifiche all'utente sono state salvate con successo.]]></item>\r
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Al momento stai modificando il tuo profilo personale.<br/>Cambiare i diritti di questo gruppo utenti potrebbe negare in futuro l'accesso al pannello di controllo dell'amministrazione. Prego fare attenzione!]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Esporta indirizzi E-Mail]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Esporta formati dei file]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Esporta opzioni]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Esporta gli indirizzi E-Mail dei seguenti utenti]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Separa gli indirizzi con un ]]></item>\r
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Racchiudi gli indirizzi tra ]]></item>\r
+               <item name="wcf.acp.user.groups"><![CDATA[Gruppi iscritti]]></item>\r
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Cerca utenti non appartenenti a questi gruppi.]]></item>\r
+               <item name="wcf.acp.user.list"><![CDATA[Utenti]]></item>\r
+               <item name="wcf.acp.user.list.all"><![CDATA[Elenca tutti gli utenti]]></item>\r
+               <item name="wcf.acp.user.list.count"><![CDATA[Un totale di {#$items} {if $items > 1}utenti{else}utente{/if}]]></item>\r
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 utente selezionato" : this.count+" utenti selezionati"]]></item>\r
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Processo completo degli utenti]]></item>\r
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Azione]]></item>\r
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Condizioni]]></item>\r
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Le azioni selezionate sono state correttamente eseguite su {#$affectedUsers} utenti.]]></item>\r
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Questo processo eseguirà le seguenti operazioni <strong>senza ulteriore notifica di sicurezza</strong>, su tutti gli utenti che soddisferanno le condizioni. Può essere un'operazione molto intensiva, per questo so consiglia di eseguirla solo dopo aver impostato il forum in modalità offline. Al termine del processo è necessario effettuare un aggiornamento dei contatori. Il processo, infine, non è reversibile. Prego prestare la massima attenzione durante il suo utilizzo. .]]></item>\r
+               <item name="wcf.acp.user.search"><![CDATA[Cerca per utenti]]></item>\r
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Criteri di ricerca]]></item>\r
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Criteri generali di ricerca]]></item>\r
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Criteri di ricerca del profilo]]></item>\r
+               <item name="wcf.acp.user.search.display"><![CDATA[Visualizza]]></item>\r
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Colonne]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Altro]]></item>\r
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profilo]]></item>\r
+               <item name="wcf.acp.user.search.display.general"><![CDATA[General]]></item>\r
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Utenti per pagina]]></item>\r
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Ordinamento]]></item>\r
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Non sono stati trovati utenti.]]></item>\r
+               <item name="wcf.acp.user.search.matches"><![CDATA[La ricerca ha prodotto {if $items == 1}un risultato{else}{#$items} risultati{/if}]]></item>\r
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Cerca fra i risultati]]></item>\r
+               <item name="wcf.acp.user.sendMail"><![CDATA[Invia una E-mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[Invia e-mail a tutti gli utenti]]></item>\r
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[Invia e-mail come HTML]]></item>\r
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Mittente]]></item>\r
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Qui potete inserire gli indirizzi E-Mail dei mittenti, nel seguente formato:</p>\r
+<p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Nome mittente &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>\r
+<p>Se avete compilato completamente la sezione sotto Sistema -> Opzioni -> Email, allora questo campo verrà automaticamente compilato. Se il metodo di invio delle E-Mail usato è attravverso connessione SMTP, l'indirizzo E-Mail del mittente deve essere accettato anche dal Server SMTP usato.</p>]]></item>\r
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[Invia E-Mail a tutti i membri del gruppo]]></item>\r
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Invia una e-mail a tutti i membri dei seguenti gruppi]]></item>\r
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-Mail]]></item>\r
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Invia una E-Mail ai seguenti utenti]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Oggetto]]></item>\r
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Inserire qui l'oggetto dell'E-Mail.]]></item>\r
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Messaggio]]></item>\r
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Inserire qui il corpo del messaggio dell'E-Mail che volete inviare agli utenti.]]></item>\r
+               <item name="wcf.acp.user.userNote"><![CDATA[Benvenuto(a) {$this->user->username}.]]></item>\r
+       </category>\r
+       <category name="wcf.acp.worker">\r
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Processo corrente]]></item>\r
+               <item name="wcf.acp.worker.description"><![CDATA[Prego lasciare la finestra di questo Browser aperta fino a che il processo non sarà completato con successo. Non cercare di effettuare il login all'area amministrazione usando una finestra separata del tuo browser. In caso contrario si rischia di danneggiare il processo corrente.]]></item>\r
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Processo terminato con successo]]></item>\r
+               <item name="wcf.acp.worker.progress.working"><![CDATA[In elaborazione ...]]></item>\r
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% completato]]></item>\r
+               <item name="wcf.acp.worker.title"><![CDATA[Sotto processo ...]]></item>\r
+       </category>\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Indietro]]></item>\r
+               <item name="wcf.global.button.close"><![CDATA[Chiudi]]></item>\r
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>\r
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>\r
+               <item name="wcf.global.button.delete"><![CDATA[Cancella]]></item>\r
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Siete sicuro di voler cancellare questo dato?]]></item>\r
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Cancella completamente]]></item>\r
+               <item name="wcf.global.button.edit"><![CDATA[Modifica]]></item>\r
+               <item name="wcf.global.button.editor.jump"><![CDATA[Use full editor]]></item>\r
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>\r
+               <item name="wcf.global.button.mark"><![CDATA[Seleziona]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Avanti &raquo;]]></item>\r
+               <item name="wcf.global.button.preview"><![CDATA[Anteprima]]></item>\r
+               <item name="wcf.global.button.reset"><![CDATA[Reimposta]]></item>\r
+               <item name="wcf.global.button.submit"><![CDATA[Invia]]></item>\r
+               <item name="wcf.global.button.unmark"><![CDATA[Deseleziona]]></item>\r
+               <item name="wcf.global.date.day"><![CDATA[Giorno]]></item>\r
+               <item name="wcf.global.date.days"><![CDATA[Giorni]]></item>\r
+               <item name="wcf.global.date.hour"><![CDATA[Ora]]></item>\r
+               <item name="wcf.global.date.hours"><![CDATA[Ore]]></item>\r
+               <item name="wcf.global.date.minute"><![CDATA[Minuto]]></item>\r
+               <item name="wcf.global.date.minutes"><![CDATA[Minuti]]></item>\r
+               <item name="wcf.global.date.month"><![CDATA[Mese]]></item>\r
+               <item name="wcf.global.date.months"><![CDATA[Mesi]]></item>\r
+               <item name="wcf.global.date.second"><![CDATA[Secondo]]></item>\r
+               <item name="wcf.global.date.seconds"><![CDATA[Secondi]]></item>\r
+               <item name="wcf.global.date.week"><![CDATA[Settimana]]></item>\r
+               <item name="wcf.global.date.weeks"><![CDATA[Settimane]]></item>\r
+               <item name="wcf.global.date.year"><![CDATA[Anno]]></item>\r
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Specificare l'anno di nascita non è obbligatorio.]]></item>\r
+               <item name="wcf.global.date.years"><![CDATA[Years]]></item>\r
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>          \r
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Oggi</b>, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Ieri,  %H:%M]]></item>\r
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>\r
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.defaultValue"><![CDATA[Predefinito]]></item>\r
+               <item name="wcf.global.error.backward"><![CDATA[Torna alla pagina precedente]]></item>\r
+               <item name="wcf.global.error.empty"><![CDATA[Prego inserire le informazioni richieste da questo campo.]]></item>\r
+               <item name="wcf.global.error.file.notFound"><![CDATA[Impossibile trovare il file.]]></item>\r
+               <item name="wcf.global.error.illegalLink"><![CDATA[Il link che cercate di visualizzare non è disponibile oppure non è valido.]]></item>\r
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Non siete abilitato alla visualizzazione di questa pagina. Non avete i permessi per visualizzarla.]]></item>\r
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Non siete abilitato a visitare questa pagina.]]></item>\r
+               <item name="wcf.global.error.title"><![CDATA[Messaggio di errore]]></item>\r
+               <item name="wcf.global.form.error"><![CDATA[I dati inseriti non sono validi. Prego controllare i dati nei campi indicati in rosso.]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabo]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosniaco]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Ceco]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Danese]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Tedesco]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Tedesco (Informale)]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Greco]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Inglese]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spagnolo]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persiano]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finlandese]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Francese]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Ebraico]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Croato]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungherese]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italiano]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Giapponese]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Coreano]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Olandese]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norvegese]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polacco]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portoghese]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portuguese (Brazil)]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumeno]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russo]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slovacco]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbo]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Svedese]]></item>\r
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Turco]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Cinese (Semplificato)]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Cinese (Tradizionale)]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[it_IT]]></item>\r
+               <item name="wcf.global.locale.win"><![CDATA[italian]]></item>\r
+               <item name="wcf.global.multiSelect"><![CDATA[Più valori possono essere selezionati usando la combinazione di tasti &quot;Ctrl/Shift&quot; (per Windows) oppure &quot;Command&quot; (per Mac OS) e cliccando sui valori scelti.]]></item>\r
+               <item name="wcf.global.page.input"><![CDATA[Nella pagina sottostante]]></item>\r
+               <item name="wcf.global.page.next"><![CDATA[Pagina successiva]]></item>\r
+               <item name="wcf.global.page.previous"><![CDATA[Pagina precedente]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>\r
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>\r
+               <item name="wcf.global.redirect.title"><![CDATA[Reindirizzamento]]></item>\r
+               <item name="wcf.global.redirect.url"><![CDATA[Cliccare qui se il reindirizzamento automatico non funziona!]]></item>\r
+               <item name="wcf.global.scrollUp"><![CDATA[Vai all'inizio della pagina]]></item>\r
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Corrispondenza esatta]]></item>\r
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e. %B %Y, %H:%M]]></item>\r
+               <item name="wcf.global.skipToContent"><![CDATA[Skip navigation]]></item>\r
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[Ascendente]]></item>\r
+               <item name="wcf.global.sortOrder.descending"><![CDATA[Discendente]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[.]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>\r
+       </category>\r
+       <category name="wcf.imageViewer">\r
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Immagine " + (this.currentIndex + 1) + " di " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>\r
+               <item name="wcf.imageViewer.close"><![CDATA[Chiudi]]></item>\r
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Mostra solo questa immagine (chiudi il visualizzatore delle immagini)]]></item>\r
+               <item name="wcf.imageViewer.next"><![CDATA[Immagine successiva]]></item>\r
+               <item name="wcf.imageViewer.pause"><![CDATA[Ferma presentazione]]></item>\r
+               <item name="wcf.imageViewer.play"><![CDATA[Avvia presentazione (le immagini cambiano ogni 5 secondi)]]></item>\r
+               <item name="wcf.imageViewer.previous"><![CDATA[Immagine precedente]]></item>\r
+       </category>\r
+       <category name="wcf.option">\r
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Canary Islands, Lisbon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>\r
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brussels, Madrid, Paris, Prague, Rome, Sarajevo, Stockholm, Tunis, Warsaw, Vienna]]></item>\r
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athens, Beirut, Bucharest, Helsinki, Istanbul, Jerusalem, Cairo, Cape Town, Khartum, Kiev, Minsk, Sofia]]></item>\r
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Ababa, Antananarivo, Baghdad, Dodoma, Kampala, Kuwait City, Mogadishu, Moscow, Nairobi, Riyadh]]></item>\r
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Tehran]]></item>\r
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Yerevan, Muscat, R&eacute;union, Tbilisi]]></item>\r
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>\r
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Asgabat, Bishkek, Dushanbe, Islamabad, Yekaterinburg, Karachi, Maldive Islands, Tashkent]]></item>\r
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, New Delhi]]></item>\r
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>\r
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Novosibirsk]]></item>\r
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Islands, Yangon]]></item>\r
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>\r
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Beijing, Perth, Singapore, Taipei, Ulaanbaatar]]></item>\r
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Western Australia)]]></item>\r
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seoul, Tokyo]]></item>\r
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>\r
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>\r
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Island (Australia)]]></item>\r
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, New Caledonia, Solomon Islands]]></item>\r
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolk Island]]></item>\r
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, South Tarawa, Fiji, Kamchatka, Marshall Islands, Wellington]]></item>\r
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Islands (New Zealand)]]></item>\r
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenix Islands]]></item>\r
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Islands, Christmas Island]]></item>\r
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azores, Cape Verde Islands]]></item>\r
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mid-Atlantic]]></item>\r
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Greenland, Montevideo]]></item>\r
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Newfoundland]]></item>\r
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantic Time (Canada), Asunci&oacute;n, La Paz, Port-of-Spain, Santiago]]></item>\r
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>\r
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Eastern Time (US &amp; Canada), Bogot&aacute;, Lima, San Francisco de Quito]]></item>\r
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Central Time (US &amp; Canada), Central America, Mexico City]]></item>\r
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Time (US &amp; Canada), Chihuahua, Mazatlan]]></item>\r
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pacific Time (US &amp; Canada), Tijuana]]></item>\r
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>\r
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) French Polynesia]]></item>\r
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cook Islands, Hawaii]]></item>\r
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midway Islands, Samoa]]></item>\r
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>\r
+       </category>\r
+       <category name="wcf.page">\r
+               <item name="wcf.page.pageNo"><![CDATA[Pagina {#$pageNo}]]></item>\r
+       </category>\r
+       <category name="wcf.user">\r
+               <item name="wcf.user.confirmEmail"><![CDATA[Conferma indirizzo E-Mail]]></item>\r
+               <item name="wcf.user.confirmPassword"><![CDATA[Conferma Password]]></item>\r
+               <item name="wcf.user.email"><![CDATA[Indirizzo E-Mail]]></item>\r
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[L'indirizzo E-Mail inserito e il campo di conferma dell'indirizzo non corrispondono.]]></item>\r
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[La password inserita e il valore nel campo di conferma della password non corrispondono.]]></item>\r
+               <item name="wcf.user.error.email.notUnique"><![CDATA[L'indirizzo E-Mail inserito risulta già usato da un'altro utente.]]></item>\r
+               <item name="wcf.user.error.email.notValid"><![CDATA[L'indirizzo E-Mail inserito non è valido.]]></item>\r
+               <item name="wcf.user.error.password.false"><![CDATA[La Password non è valida.]]></item>\r
+               <item name="wcf.user.error.username.notFound"><![CDATA[L'Username &quot;{$username}&quot; non può essere trovato.]]></item>\r
+               <item name="wcf.user.error.username.notUnique"><![CDATA[L'Username inserito risulta già usato.]]></item>\r
+               <item name="wcf.user.error.username.notValid"><![CDATA[L'Username inserito non è valido.]]></item>\r
+               <item name="wcf.user.language"><![CDATA[Lingua]]></item>\r
+               <item name="wcf.user.language.description"><![CDATA[Prego selezionare la lingua da usare nell'interfaccia utente!]]></item>\r
+               <item name="wcf.user.logout"><![CDATA[Logout]]></item>\r
+               <item name="wcf.user.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.user.registrationDate"><![CDATA[Data di registrazione]]></item>\r
+               <item name="wcf.user.userID"><![CDATA[User ID]]></item>\r
+               <item name="wcf.user.username"><![CDATA[Username]]></item>\r
+               <item name="wcf.user.visibleLanguages"><![CDATA[Mostra contenuti nella seguente lingua]]></item>\r
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[]]></item>\r
+       </category>\r
+       <category name="wcf.user.option">\r
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Le informazioni inserite non sono valide.]]></item>\r
+       </category>\r
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/pt-BR.xml b/wcfsetup/install/lang/pt-BR.xml
new file mode 100644 (file)
index 0000000..a873a41
--- /dev/null
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="pt-BR">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[Painel de Controle]]></item>
+               <item name="wcf.acp.help"><![CDATA[Ajuda]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[Ajuda Completa]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[Desativar Ajuda Online]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[Ajuda Interativa]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Escolher Pacote]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[Pesquisa extendida ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[Mapa do site]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Empty cache]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[The cache has been successfully emptied.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Are you sure that you want to completely empty the cache?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[Settings]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[Files]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[Size]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[Source]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Last updated]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[Name]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Permissions]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[Size]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[Adicionar novo grupo]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Permissões]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[The usergroup has been successfully added.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[Administradores]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[Informação Geral do Grupo]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[Excluir este grupo]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}This usergroup has{else}{#$deletedGroups} These usergroups have{/if} been successfully deleted.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Tem certeza que deseja excluir este grupo?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[Editar este grupo]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[Your usergroup changes have been successfully saved.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Você atualmente é membro deste grupo. Alterando as permissões deste grupo poderá resultar no bloqueio ao acesso ao Painel de Administração inclusive na seção atual. Por favor, tenha cuidado!]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Todos]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[Nome do grupo]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Digite um nome para este grupo.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[Visitantes]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[Grupos]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[Existe(m) {#$items} grupo(s)]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[Membros]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderadores]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Pode entrar no Painel de administração?]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Habilitando esta opção permitirá ao grupo acesso ao Painel de Administração e, dependendo das permissões, executar algumas ações.]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Can view private user options]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Members of this usergroup can view private user options.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Pode alterar sistema de opções?]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Habilitando esta função os usuários deste grupo poderão ver e alterar o sistema de opções - Ex. Fórum online/offline.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Can view logs]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Members of this usergroup can view the system logs.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Pode editar e atualizar servidores existentes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Membros deste grupo podem  editar e atualizar servidores existentes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Pode instalar novos pacotes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Membros deste grupo podem instalar novos pacotes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Pode excluir pacotes existentes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Membros deste grupo podem excluir pacotes existentes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Pode atualizar pacotes existentes]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Membros deste grupo podem atualizar pacotes existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Grupos acessíveis]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Membros deste grupo tem acesso aos seguintes grupos. Exemplo, aqui você pode definir se o grupo tem permissão para editar-se.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Pode adicionar novos grupo]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Membros deste grupo podem adicionar novos grupo]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Pode adicionar novos usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Membros deste grupo podem adicionar novos usuários. Se a opção &quot;Grupos Acessíveis&quot; foi habilitada, em seguida, sobre a criação do usuário, o acesso adequado ao grupo também pode ser atribuído.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Pode excluir grupos existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Membros deste grupo podem excluir grupos existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Pode excluir usuários existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Membros deste grupo podem excluir usuários existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Pode editar grupos existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Membros deste grupo podem editar grupos existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Pode editar e-mail de usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Membros deste grupo podem editar e-mail de usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Pode editar senha de usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Membros deste grupo podem editar senha de usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Pode editar usuários existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Membros deste grupo podem editar usuários existentes]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Pode enviar e-mail aos usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Membros deste grupo podem ver e-mail dos usuários e consequentemente enviar e-mails a eles.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Pode pesquisar usuários]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Membros deste grupo podem pesquisar usuários e seus perfis.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Permissões de Administrador]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Conteúdo]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Visual]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Permissão Administrativa Geral]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Manutenção]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[Funções do Sistema]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Gerenciamento de Pacotes]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Funções de Usuário]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Gerenciamento de Grupos]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Gerenciamento de Usuário]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Permissão de Moderador]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Permissões Gerais]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[A informação digitada é inválida.]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[Exibir membros deste grupo]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super Moderadores]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[Membros]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[Login]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[Detalhes de login]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[Master password]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Confirm master password]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Master password required]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[This page or action requires you to enter the master password due to security reasons. You only need to do so once within a session. If you have forgotten the master password you can reset it by deleting the file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[The master password is not correct.If you have forgotten the master password you can reset it by deleting the file <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[The entered passwords are not identically.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[The password is not secure. It has to contain at least eight characters, small and capital latin letters as well as numbers and special characters. It must not be identically with passwords of administrators of this page.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Suggestion]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Use suggestion]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Set master password]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[The master password is an additional protection of functions that are relevant to security. You should use a very secure password that must not be identically with your normal administrator password, unknown to others and not used on other websites.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Atualização Automática]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[Conteúdo]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[Design]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[Grupos]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Adicionar novo grupo]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[E-mail para todos do grupo]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Visualização do Grupo]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[Log]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Manuntenção]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[Opções]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Import &amp; export]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[Pacotes]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Pesquisar Pacotes]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Instalar novo pacote]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Adicionar novo servidor]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Visualizar servidores]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Lista de pacotes instalados]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[Sistema]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[Usuários]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Add user]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[List users]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-mail para todos usuários]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Usuários]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Bulk processing of users]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Pesquisar por usuários]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Exclude hostnames]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Enter one hostname each row you want to exclude from this site.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[Exclude IP addresses]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Enter one IP address each row you want to exclude from this site.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Exclude user agents]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Enter one user agent each row you want to exclude from this site.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Enter the address of the memcache server! You can enter one server each row.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Use persistent connections]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[By enabling this option a persistent connection to the memcache server will be used.]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache type]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Please select the type of cache you want to use! Some of the types have special requirements to the server system and cannot be used in your environment.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[File system (default)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (experimental)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[Geral]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache stores data in the memory that is often accessed. This may reduce the database load dramatically. Read more about the memcache on the following site:
+<ul>
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Data e horário]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy server]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[You can configure optional proxy servers for connections to external servers.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Transmission]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Disable forum temporarily]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[Modules on / off]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Content]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Display]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[User]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[Security]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internet pages are often attacted by programs and robots. It is possible for example to create hundreds of user accounts automatically. You can protect yourself against these spam bots with the help of a so called <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">captcha image</a> on every place where web forms can be submitted. Unregistered users then have to identify the code on the captcha first before they can submit the form. Robots cannot read the code. Please not that captcha images cannot be read by blind and visually impaired people.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Blacklist]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Censorship]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessions]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[Usuários]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Domínio do Cookie]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Digite o domínio responsável pelos cookie criados. Isto é opcional, apenas em alguns casos é necessário.]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Caminho do Cookie]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[O caminho do cookie é geralmente o caminho para o diretório root do site - e.g. &quot;/forum&quot; for http://www.seusite.com/forum.]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Prefixo do Cookie]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Digite um prefixo para ser usado com o nome do cookie.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Habilitar horário de verão]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Deseja que automaticamente o relogío seja alterado para o horário de verão?]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Use cache method for session data]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Should the selected cache method be used to save the session data?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[A informação digitada é inválida.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[Export options]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[Download the exported options]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Download the exported options as a backup file to your local machine.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Habilitar conteúdo application/xhtml+xml]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[Habilitando esta opção permite que sejam exibidas em suas páginas conteúdo tipo application/xhtml+xml.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Habilitar compressão Gzip]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Habilitando esta opção o conteúdo será comprimido no servidor e enviado aos clientes. Esta opção reduz o tráfego. ]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Desabilitar o cache em navegadores]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Habilitando esta opção restringirá aos navegadores os cache de páginas.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Nível de compressão]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Um valor de 1 a 9 é requerido. Para melhor perfomance recomendamos valor 1.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[Import options]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[The options have been imported successfully.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[Upload the options]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Upload the options to be imported from your local machine.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Import &amp; Export options]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Endereço de e-mail do administrador]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Digite aqui o endereço de e-mail do administrador]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Caminho para o arquivo log]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Digite aqui o caminha para o arquivo log]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Endereço de e-mail]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Digite aqui o endereço de e-mail que será usado nos e-mails automáticos.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Nome]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Digite aqui o nome que será usado nos e-mails automáticos.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[Método do e-mail]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Escolha um método de envio de e-mails.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Assinatura]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Enter here a signature that should be sent with system e-mails.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[Servidor SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Digite o nome do servidor SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[Senha SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Digite a senha do servidor SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[Porta SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Digite a porta do servidor SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[Usuário SMTP]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Digite o usuário do servidor SMTP]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[habilitar parâmetro &quot;-f&quot; ]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Alguns servidores requerem o parâmetro &quot;-f&quot; para ser usando quando envia e-mails. Se você tiver problemas com envio de e-mails, tente habilitar esta função.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Usar endereços de e-mails formatados]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Endereços de e-mail dos destinatários são formatado em &quot;Nome &lt;email@dominio.com.br&gt;&quot;. Esta opção não é suportada por todos servidores e deverá ser desbilitada em caso de problemas.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Enable master password]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Pages and forms within the admin panel that are relevant to security can be protected with an additional master password.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Proxy-Server (FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[Proxy-Server for FTP connections]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server for HTTP connections]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Tempo limite da sessão]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Digite quanto temo a sessão se manterá válida [segundos].]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Check IP address of session]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[The number of block of an ip address that should be checked while reading the session data. A high number can exclude users that use changing IP addresses.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Check user agent of session]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Should the user agent be checked while reading the session data?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[Your option changes have been successfully saved.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[Fuso horário]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Escolha o fuso horário padrão para seu site.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Tempo limite de usuários online]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Digite quanto tempo um usuários será exibido como online até ser exibido offline por inatividade [segundos].]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[Cancelar instalação de pacotes]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[Description]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[Digite as informações de FTP]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[Detalhes de acesso ao FTP]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Com PHP-SafeMode (modo seguro ou mode de segurança) habilitado no seu servidor o pacote deve ser instalado com a ajuda da função FTP. Digite o nome de usuário e a senha do FTP para este servidor. As informações fornecidas não serão registradas ou transmitidas e vão ser utilizadas exclusivamente para fins de instalação. Por esta razão, pode ser necessário informar os do FTP novamente durante o processo de instalação.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Com os dados digitados, não foi possível realizar uma conexão FTP.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[Não foi possível realizar uma conexão FTP.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[Com o nome de usuário especificado, não foi possível realizar uma conexão FTP.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Servidor]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Senha]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Nome de Usuário]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[Instalação de Pacotes]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Cancelar instalação]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Tem certeza que deseja cancelar a instalação?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[Pacotes dependentes não foram localizados neste pacote.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[The {if $action == 'install'}package installation{else}package update{/if} of package &quot;{$packageName}&quot; in version {$packageVersion} cannot be executed due to incompatibilities with the following {if $excludedPackages|count == 1}package{else}packages{/if}:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} in version {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Following package doesn't{else}Following packages don't{/if} allow the {if $action == 'install'}package installation{else}package update{/if} of package &quot;{$packageName}&quot; in version {$packageVersion} due to incompatibilities:]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} in version {$excludingPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Following package is{else}Following packages are{/if} incompatible with package &quot;{$packageName}&quot; in version {$packageVersion}. If you proceed installation the {if $excludingPackages|count == 1}package{else}packages{/if} probably won't work anymore.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}Instalado{else}{if $package.file|isset}Localização dentro do pacote{else}Indisponível{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Tem certeza que deseja cancelar a instalação deste pacote?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Os seguintes pacotes podem ser atualizados com este pacote]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Selecione um dos seguintes pacotes para atualizar esta versão. Se você desejar instalar o pacote novamente, por favor clique em &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Já existe uma cópia deste pacote instalada. Se você continuar uma nova cópia deste pacote será instalada. Se você quiser atualizar uma cópia disponível deste pacote, selecione na lista seguinte.]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[Versão do pacote:]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[Installation date]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[While unpacking the files of this package the following error occured:]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[The following files could not be unpacked successfully. Please check if the destination folder is writable.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Tabelas conflitantes]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Não substituir estas tabelas e não me pergunte novamente durante a instalação.]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Substituir estas tabelas e não me pergunte novamente durate a instalação.]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Alterações requeridas]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Tabelas afetadas]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Existe tabelas em conflito com as tabelas necessárias para a instalação do pacote. Favor escolher se deseja subscrever estas tabelas.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[Pacotes instalados]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[Autor]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[Um total de {#$items} pacote(s) foi(foram) instalado(s)]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[Data]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[Nome]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[Pacote]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Aplicação independente]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[Versão]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[Instalação de pacotes opcionais]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[O pacote selecionado tem as seguintes opções. Selecione o que deseja instalar.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Este pacote já está instalado.)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[(Os requisitos deste pacote não foram atendidos.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[Pasta de instalação]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Outra aplicação já está instalada nesta pasta.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[This folder is invalid.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Esta pasta não tem permissão para escrita.]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Esta pasta já está em uso pelo WCF (WoltLab Community Framework). Escolha uma pasta diferente.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Por favor digite a pasta de instalação aqui.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[This application is accessable through the following URL after installation in this folder:]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[Selecione dependências]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[O atual pacote requer um outro pacote que está instalado várias vezes. Escolha a instância que será sendo requerida.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[Desfazer instalação do pacote]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Versão {$packageVersion} - {@$packageDate|date} - Direitos Reservados &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[Instalar novo pacote]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[O pacote escolhido não tem uma rotina de instalação válida.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[O arquivo informado não é um pacote válido]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[O pacote &quot;{$package->getName()}&quot; não pode ser atualizado a partir do arquivo fornecido.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Nenhum arquivo encontrado no diretório especificado.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[O pacote escolhido já está instalado. Pacotes não podem ser instalados mais de uma vez.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[O envio do arquivo escolhido falhou]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Selecione a fonte de um pacote]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Digite o caminho onde o pacote pode ser localizado no seu servidor]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Digite o caminho direto de acesso ao arquivo. Como alternativa pode ser usado um endereço URL. O arquivo do pacotes deve estar em umas das extensões permitidas no sistema.]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Enviar pacote do seu computador]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Digite o pacote que será enviado a partir de seu computador.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Atualizar pacote &quot;{$package->getName()}&quot;]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Instalando menus de entrada para o Painel de Controle da Administração ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Installing template patches for the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Instalando temas para o Painel de Controle da Administração ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Instalando lista de eventos ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Descomprimindo arquivos do pacote ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Instalando opções de grupo ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Instalando pacotes de idioma ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Instalando opções de pacote ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Executando scripts especiais ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Instalando entrada de banco de dados ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Instalando patches de temas ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Instalando pacote de temas ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Instalando campos do perfil de usuário ...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Checking possible conflicts ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Executando plugins do pacote ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Instalação Completa]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Instalando opcionais do pacote ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Registrando pacote ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Instalando plugins do pacote ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Alocação do pacote sendo feita ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Checando arquivos dependentes ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[Pacote <b>{$packageName|encodeJS}</b>: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Removendo entradas de menu para o Painel de Controle da Administração ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Removing template patches of the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Removendo temas para o Painel de Controle da Administração ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Removendo lista de eventos ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Removendo arquivos de pacote ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Removendo opções de grupo ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Removendo pacotes de idiomas ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Removendo opções de pacote ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Removendo entradas no banco de dados ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Removendo patches de temas ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Removendo pacote de temas ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Removendo campos do perfil de usuários ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Executando plugins do pacote ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Remoção Finalizada]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Removendo opcionais do pacote ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Removendo plugins do pacote ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Removendo requirementos do pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Atualizando menus de entrada para o Painel de Controle da Administração ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Updating template patches in the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Atualizando temas para o Painel de Controle da Administração ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Atualizando lista de eventos ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Descompactando arquivos do pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Atualizando opções de grupo ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Atualizando pacotes de idioma ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Atualizando opções de pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Executando scripts especiais ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Atualizando entrada de banco de dados ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Atualizando patches de temas ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Atualizando pacote de temas ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Atualizando campos do perfil de usuário ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Checking possible conflicts ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Executando plugins do pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Atualização Completa]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Atualizando opcionais do pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Registrando pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Atualizando plugins do pacote ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Alocação do pacote sendo feita ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Checando arquivos dependentes ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[O arquivo que está tentando ser aplicado no pacote não é compilado para o arquivo em questão. O pacote não pode ser instalado. Por favor clique no botão &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; .]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Os seguintes patches dos temas falharam:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Originalmente feito por: {$failure.packageName})<br />{/foreach}O patch original foi aplicado sem função. Você poderá ainda continuar a atualização clicando no notão &quot;{lang}wcf.global.button.next{/lang}&quot; .]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[O patch que este pacote está tentando excluir falhou pois foi externamente alterado. Por isso, este pacote não pode ser excluído. Por favor clique no botão &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; .]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[Pacote de remoção]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Cancelar pacote de remoção]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Não é possível remover estes pacotes porque há pelo menos um pacote dependente que não pode ser desinstalado.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Após a confirmação final {if $dependentPackages|count == 1}este pacote será removido{else}estes pacotes serão removidos{/if} sem nenhum outro aviso.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[Atualização do pacote]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[Date of update]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[Autor:]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Ir ao Painel de Controle da Administração]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Excluir pacotes]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Excluir todos os pacotes]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Tem certeza de que deseja excluir este pacote?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Atualizar pacote]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[Data:]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Pacotes dependentes]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Este pacote é requerido de {if $dependentPackages|count == 1}outro pacote.{else}{#$dependentPackages|count} outros pacotes.{/if}]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Este pacote é requerido de um outro pacote{else}{#$dependentPackages|count} pacotes são direta ou indiretamente dependentes deste pacote{/if}.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[Pasta de instalação:]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Identificador:]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Instância instalada:]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[Pacote:]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[Propriedades]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Pacotes requeridos]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Este pacote foi requerido por {if $requiredPackages|count == 1} outro pacote.{else}{#$requiredPackages|count} outros pacotes.{/if}]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[Site:]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[Versão instalada:]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[Atualizar pacotes]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Atualizar autenticação com o servidor]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Conexão de dados]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[O nome de usuário ou a senha não foram aceita.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Senha]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Digite a senha que é necessária para autenticação.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Usuário]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Digite o nome de usuário que é necessário para autenticação.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Login do Usuário]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Mensagem do Servidor]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Nome do Servidor]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Salvar os dados do usuário permanente]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Os dados do usuário serão salvos permanentemente, de modo que não será necessário fornecer os dados novamente mais tarde.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Endereço]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Versão instalada]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Ocorreu um erro:]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[O download do pacote {$package} falhou.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[An error occured while trying to download the package list.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[The following {if $excludedPackages|count == 1}conflict{else}conflicts{/if} occured:]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[The installed package &quot;{$excludedPackage.existingPackageName}&quot; is incompatible with the package &quot;{$excludedPackage.packageName}&quot; in version {$excludedPackage.packageVersion}.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[The package &quot;{$excludedPackage.packageName}&quot; in version {$excludedPackage.packageVersion} is incompatible with the installed package &quot;{$excludedPackage.existingPackageName}&quot;.]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} está instalado]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[There are currently no updates available.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[You have not selected any update.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Opções]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Pacote já está instalado e exclusivo. Por isso não pode ser instalado novamente.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Instalar pacote]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Instalar pacote em outra instância (pacote já está instalado {#$package.instances} vez{if $package.instances > 1}es{/if})]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Atualizar pacote instalado {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} versão {$updatableInstance.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Pesquisar pacotes]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Autor]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Pesquisar ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Ocultar pacotes exclusivos já instalados]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Nome do pacote]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Nome do pacote e descrição]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Atualizar servidor]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Pesquisar em todos os servidores atualizados]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Tipo de pacote]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Outros pacotes]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Plugin de pacotes já instalados]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Aplicativos independentes]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Selecionar todos os pacotes]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} foi atualizado para {$package.toVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Nova versão]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Os seguintes pacotes de atualizações e instalações serão processados:]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Actions of the logged session of &quot;{$sessionLog->username}&quot;]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[There is a total of {#$items} logged action{if $items != 1}s{/if}]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Actions]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Class name]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP address]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Last action]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Package]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Method]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Date]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[User agent]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Logged sessions]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[There is a total of {#$items} logged session{if $items != 1}s{/if}]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[Adicionar servidor]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[The server has been successfully added.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[Servidor de dados]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Excluir servidor]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[The server has been successfully deleted.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Você realmente deseja excluir este servidor?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Desativar]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Editar servidor]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Your changes have been successfully saved.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Ativar]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Mensagem de Erro]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Senha]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Digite a senha necessária para autenticação (opcional).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Usuário]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Digite o nome de usuário necessário para autenticação (opcional).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[The following error occured while trying to connect the last time:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} servidores disponíveis]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Servidor ID]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Pacotes]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[Endereço]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Digite a URL de um pacote do servidor.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[O endereço digitado não é válido.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Último acesso]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[Servidor de atualização disponível]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Não há nenhum servidor de atualização disponível.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[Adicionar novo usuario]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[Detalhes de usuários]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[The new user has been successfully saved.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Atribuição do grupo]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Atribuir os seguintes usuários ao(s) grupo(s) selecionado(s)]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Os usuários foram atribuidos ao grupo escolhido com sucesso!]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Atribuição do grupo]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Exportar endereço de e-mail]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Enviar um e-mail]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[Excluir usuário(s)]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[O usuário não pode ser excluído]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}O usuário foi excluído{else}{#$deletedUsers} usuários foram excluídos{/if} com sucesso.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Tem certeza de que deseja excluír este usuário?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Tem certeza de que deseja excluir o(s) usuário(s) selecionado(s)?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[Editar usuário]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[The changes for this user have been successfully saved.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Você está atualmente editando sua própria conta de usuário. Alterar permissões deste grupo de usuário pode levar ao travamento de sua conta no Painel de Controle de Administrador. Por favor tenha cuidado!]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Exportar endereço de e-mail]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Exportar formato de arquivo]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Comma Separated Values</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Opções de exportação]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Exportar os endereços de e-mail a partir dos seguintes usuários]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Separe os endereços com]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Incluir os endereços com]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[Grupo de membros]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Find users that are not members of the chosen usergroups.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[Usuários]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[List all users]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[Um total de {#$items} usuário{if $items > 1}s{/if}]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 usuário selecionado" : this.count+" usuários selecionados"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Bulk processing of users]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Action]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Conditions]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[The chosen action has been executed successfully on {#$affectedUsers} users.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[The bulk processor will perform the following tasks <strong>without additional security notification</strong>, on all users matching the set conditions. Bulk processing can be very performance intensive, so should only be executed when the forum is offline. To have a correct display of your content you should update the counters. The processing can not be reversed, so please be attentive when using this function.]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[Pesquisar por usuários]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Critério de pesquisa]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Critérios gerais de pesquisa]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Pesquisar perfil]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[Display]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Columns]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Other]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profile]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[General]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Users per page]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sorting]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Nenhum usuário foi encontrado.]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[A sua pesquisa produziu {if $items == 1}um resultado{else}{#$items} resultados{/if}]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Pesquisar nos resultados]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[Enviar um e-mail]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-mail para todos os usuários]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[Send e-mail as HTML]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Enviar]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Here you can enter the sender's e-mail address in the following format:</p>
+<p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Senders name &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>
+<p>If you have completely filled in the section under System -> Options -> E-mail, then this field will automatically be filled in. If you are sending e-mails using SMTP, then the sender's e-mail-Address must also be accepted by the Server.</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[E-mail para todos membros do grupo]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Enviar um e-mail para os membros dos seguintes grupos:]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-mail]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Enviar um e-mail para os seguintes usuários]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Assunto]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Digite aqui o assunto do e-mail.]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Mensagem]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Digite aqui a mensagem que deseja enviar aos usuários.]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[Bem Vindo {$this->user->username}.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Processo atual]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[Please leave this browser window open until the process has successfully completed. Do NOT try to login to your administrations area using a separate browser window, as doing so may damage the current process.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Processo completado com sucesso]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Processando...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% completo]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[Processando...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Voltar]]></item>
+               <item name="wcf.global.button.close"><![CDATA[Fechar]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[Excluir]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Do you really want to delete this item?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Delete completely]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[Edit]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[Use full editor]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[Marcar]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Próximo &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[Visualizar]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[Limpar]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[Enviar]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[Desmarcar]]></item>
+               <item name="wcf.global.date.day"><![CDATA[Dia]]></item>
+               <item name="wcf.global.date.days"><![CDATA[Days]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[Hora]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[Hours]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[Minute]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[Minutos]]></item>
+               <item name="wcf.global.date.month"><![CDATA[Mês]]></item>
+               <item name="wcf.global.date.months"><![CDATA[Months]]></item>
+               <item name="wcf.global.date.second"><![CDATA[Second]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[Seconds]]></item>
+               <item name="wcf.global.date.week"><![CDATA[Week]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[Weeks]]></item>
+               <item name="wcf.global.date.year"><![CDATA[Ano]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Especifique a data de aniversário. É opcional.]]></item>
+               <item name="wcf.global.date.years"><![CDATA[Years]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%A, %d %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Hoje</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Ontem, %H:%M]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[Padrão]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[Voltar para última página]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[Por favor digite as informações requeridas para este campo.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[O arquivo não pôde ser encontrado.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[O link que você está tentando visualizar não está mais disponível ou é inválido.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Você não tem permissões para visualizar esta página.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Sem permissão.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[Mensagem de erro]]></item>
+               <item name="wcf.global.form.error"><![CDATA[As informações digitada está inválida. Por favor verifique as informações digitadas nos campos marcados.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Árabe]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bósnio]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Checa]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Dinamarquês]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Alemão]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Alemão (Informal)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grego]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Inglês]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Espanhol]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persa (Farsi)]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finlandês]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Francês]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hebraico]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Croata]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Húngaro]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Itáliano]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japonês]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Koreano]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Holandês]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norueguês]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polonês]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Português]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Português (Brasil)]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Romeno]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Russo]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Eslovaco]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Sérvio]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Sueco]]></item>
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turco]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinês (simplificado)]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinês (tradicional)]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[pt_BR]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[brazil]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[Multíplos itens pode ser selecionado segurando o botão &quot;Ctrl/Shift&quot; (Windows) ou &quot;Command&quot; (Mac OS) e clicando nos itens requeridos.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[Go to next page]]></item>
+               <item name="wcf.global.page.next"><![CDATA[Próxima página]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[Página anterior]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[Woltlab]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[Redirecionando]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[Por favor, clique aqui se você não for redirecionado automaticamente!]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[Ir para o topo da página]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Forma exata]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%d/%m/%Y, %H:%M]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[Skip navigation]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[A-Z]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[Z-A]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %d %B %Y - %H:%M]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Image " + (this.currentIndex + 1) + " of " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[Close]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Show only this image (quits the image viewer)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[Next image]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[Stop slideshow]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[Start slideshow (changes the image every 5 seconds)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[Previous image]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Canárias, Lisboa, Londres, Monrovia, Ouagadougou, Reykjavík]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brussels, Copenhagen, Madrid, Paris, Prague, Rome, Sarajevo, Stockholm, Tunis, Warsaw, Vienna]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC +02:00) Atenas, Beirute, Bucharest, Helsinki, Istambul, em Jerusalém, Cairo, Cidade do Cabo, Cartum, Kiev, Minsk, Sofia]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC +03:00) Addis Abeba, Antananarivo, Bagdad, Dodoma, Kampala, Kuwait City, Mogadíscio, Moscow, Nairobi, Riyadh]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC +03:30) Teerã]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC +04:00) Abu Dhabi, Baku, Dubai, Yerevan, Muscat, Reunião, Tbilisi]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC +04:30) Cabul]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC +05:00) Ashgabat, Bishkek, Dushanbe, Islamabad, Yekaterinburg, Karachi, Maldive Islands, Tashkent]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC +05:30) Chennai, Colombo, Kolkata, Mumbai, Nova Deli]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC +05:45) Kathmandu]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC +06:00) Almaty, Astana, Dhaka, Novosibirsk]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC +06:30) Cocos (Keeling), Yangon]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC +07:00) Bangkok, Hanói, Jacarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC +08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Pequim, Perth, Singapura, Taipei, Ulaanbaatar]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC +08:45) Eucla (Austrália Ocidental)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC +09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seul, Tóquio]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC +09:30) Adelaide, Darwin]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC +10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC +10:30) Lord Howe Island (Austrália)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC +11:00) Magadan, Nova Caledônia, Ilhas Salomão]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC +11:30) Ilha Norfolk Island]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC +12:00) Auckland, South Tarawa, Fiji, Kamchatka, Ilhas Marshall, Wellington]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC +12:45) Chatham Islands (Nova Zelândia)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC +13:00) Nuku'alofa, Ilhas Phoenix]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC +14:00) Ilhas Line, Christmas Island]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC -01:00) Açores, Ilhas de Cabo Verde]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC -02:00) Mid-Atlantic]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC -03:00) Brasília, Buenos Aires, Cayenne, Georgetown, Gronelândia, Montevideo]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC -03:30) Newfoundland]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC -04:00) Hora do Atlântico (Canadá), Assunção, La Paz, Port-of-Spain, Santiago]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC -04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC -05:00) Horário do Leste (E.U. e Canadá), Bogotá, Lima, San Francisco de Quito]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC -06:00) Horário Central (E.U. e Canadá), América Central, México City]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC -07:00) Mountain Time (E.U. e Canadá), Chihuahua, Mazatlán]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC -08:00) Horário do Pacífico (E.U. e Canadá), Tijuana]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC -09:00) Anchorage (Alasca)]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC -09:30) Polinésia Francesa]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC -10:00) Ilhas Cook, Havaí]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC -11:00) Ilhas Midway, Samoa]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC -12:00) Enewetak, Kwajalein]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[Page {#$pageNo}]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[Confirmar endereço de e-mail]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[Confirmar senha]]></item>
+               <item name="wcf.user.email"><![CDATA[Endereço de e-mail]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Os dados do  endereço de e-mail e a confirmação de e-mail não são os mesmos.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Os dados da senha e a confirmação da senha não são as mesmas.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[O endereço de e-mail digitado já está sendo usado por outro membro.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[O endereço de e-mail digitado é inválido.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[A senha está incorreta.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[O nome de usuário &quot;{$username}&quot; não pôde ser encontrado.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[O nome de usuário digitado já está sendo usado por outro membro.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[O nome de usuário digitado é inválido.]]></item>
+               <item name="wcf.user.language"><![CDATA[Idioma]]></item>
+               <item name="wcf.user.language.description"><![CDATA[Selecione a linguagem que será mostrada para o usuário!]]></item>
+               <item name="wcf.user.logout"><![CDATA[Sair]]></item>
+               <item name="wcf.user.password"><![CDATA[Senha]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[Data de registro]]></item>
+               <item name="wcf.user.userID"><![CDATA[ID]]></item>
+               <item name="wcf.user.username"><![CDATA[Nome de usuário]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[Exibir o índice nas seguintes línguas]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Selecione aqui as línguas que devem ser mostradas.]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[A informação digitada é inválida.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/sv.xml b/wcfsetup/install/lang/sv.xml
new file mode 100644 (file)
index 0000000..ec79d7e
--- /dev/null
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="sv">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[Administration Kontrollpanelen]]></item>
+               <item name="wcf.acp.help"><![CDATA[Hjälp]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[Komplett Hjälp]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[Inaktivera onlinehjälpen]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[Interaktiv Hjälp]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Ändra paket]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[Avancerad sökning ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[Sido-Karta]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Töm cache]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[Cache har blivit successfullt tömt.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Är du säker på att du vill tömma cacheminnet?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[Inställningar]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[Filer]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[Storlek]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[Källa]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[Version]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Senast Uppdaterat]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[Namn]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[Rättigheter]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[Storlek]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[Lägg till ny användargrupp]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[Behörigheter]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[Användargruppen har lagts till successfullt.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[Administratörer]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[Allmän grupp information]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[Radera denna användargrupp]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Denna användargrupp har{else}{#$deletedGroups} Dessa användargrupper har{/if} tagits bort successfullt.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Är du säker på att du vill ta bort denna användargrupp?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[Redigera denna användargrupp]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[Din användargrupps ändringar har sparats successfullt.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Du är förnärvarande medlem av denna användargrupp. Ändra rättigheter för denna användargrupp kan resultera i att du låser dig själva ute från Administrations Kontroll Panelen. Var försiktig!]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Alla]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[Grupp ID]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[Namnet på denna användargrupp]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Ange här ett namn för den här gruppen.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[Gäster]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[Användargrupper]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[Totalt finns {#$items} användargrupper]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[Antal medlemmar]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatorer]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Kan gå in i Administrations Kontroll Panel?]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Aktivering av det här alternativet gör det möjligt för medlemmar i denna användargrupp att gå till Administrations Kontroll Panelen och, beroende av sin behörighet köra vissa åtgärder.]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Kan granska privata användar alternativ]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Medlemmar av denna användargrupp kan granska privata användar alternativ.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Kan ändra system alternativ?]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Aktivering av det här alternativet gör det möjligt för medlemmar i denna användargrupp att visa och ändra system alternativ - till exempel Forum on / offline.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Kan granska loggar]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Medlemmar av denna användargrupp kan granska systemloggarnas.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Kan redigera befintliga uppdaterings upplägg]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Medlemmar i denna användargrupp kan redigera befintliga uppdaterings upplägg och lägga till nya uppdaterings upplägg.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Kan installera nya paket]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Medlemmar i denna användargrupp kan installera ytterligare paket.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Kan ta bort befintliga paket]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Medlemmar i denna användargrupp kan ta bort befintliga paket.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Kan uppdatera befintliga paket]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Medlemmar i denna användargrupp kan uppdatera befintliga paket.]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Tillgängliga användargrupper]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Medlemmar i denna användargrupp har tillgång till följande grupper. Till exempel, här kan du ställa in om användargruppen har rättigheter att redigera sig själv.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Kan lägga till nya användargrupper]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Medlemmar i denna användargrupp kan lägga till nya användargruper.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Kan lägga till nya användare]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Medlemmar i denna användargrupp kan lägga till nya användare. Om alternativet för &quot;Tillgängliga Användargrupper&quot; har aktiverats, sedan om skapandet av användaren, är lämpligt, tillgänglig användargrupper kan detta också tilldelas.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Kan ta bort befintliga användargrupper]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Medlemmar i denna användargrupp kan ta bort befintliga användargrupper.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Kan ta bort befintliga användare]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Medlemmar i denna användargrupp kan ta bort befintliga användare.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Kan redigera befintliga användargrupper]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Medlemmar i denna användargrupp kan redigera befintliga användargrupper.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Kan redigera användarens e-postadresser]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Medlemmar i denna användargrupp kan redigera användarens e-postadresser.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Kan redigera användarens lösenord]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Medlemmar i denna användargrupp kan redigera användarens lösenord.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Kan redigera befintliga användare]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Medlemmar i denna användargrupp kan redigera befintliga användare.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Kan skicka e-post till användare]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Medlemmar i denna användargrupp kan se andra medlemmars e-postadresser och därmed skicka dem e-post.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Kan söka användare]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Medlemmar i denna användargrupp kan söka befintliga användare och deras profiler.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Administratörs behörigheter]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[Innehåll]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Design]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Allmänna administrativa behörigheter]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Underhåll]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[System funktioner]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Pakethantering]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Användare funktioner]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Grupphantering]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Användarhantering]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderator behörighet]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Allmän behörighet]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Den information du har angett är ogiltigt.]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[Visa medlemmarna i denna användargrupp]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[Super moderatorer]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[Registrerade användare]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[Logga in]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[Inloggnings Information]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[Huvudlösenord]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Bekräfta huvudlösenord]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Huvudlösenord krävs]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Denna sidan eller åtgärd kräver att du anger huvudlösenordet på grund av säkerhetsskäl. Du behöver bara göra det en gång under en session. Om du har glömt huvudlösenordet kan du återställa det genom att ta bort filen <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[Huvudlösenordet är inte korrekt.Om du har glömt huvudlösenordet du kan återställa det genom att ta bort filen <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[De inmatade lösenorden är inte identiska.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[Lösenordet är inte säkert. Det måste innehålla minst åtta tecken, små och stora bokstäver samt siffror och specialtecken. Det får inte vara identiskt med lösenord för administratörer av denna sida.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Förslag]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Använd Förslag]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Ange huvudlösenord]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[Huvudlösenordet är ett ytterligare skydd av funktioner som är relevanta för säkerheten. Du bör använda ett mycket säkert lösenord som inte får vara identiskt med ditt normala administratörslösenord, okända för andra och inte användas på andra webbplatser.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Automatisk uppdatering]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[Innehåll]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[Design]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[Användargrupper]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Lägg till ny grupp]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[E-posta alla gruppmedlemmar]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Grupp översikt]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[Logg]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Underhåll]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[Val]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[Import &amp; export]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Sök paket]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Installera nya paket]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Lägg till nytt upplägg]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Uppläggs översikt]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Visa en lista över installerade paket]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[System]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[Användare]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Lägg till en ny användare]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Användare översikt]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-posta alla användare]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Användare]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Bulk behandling av användare]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Sök efter användare]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Uteslut värdnamn]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Ange ett värdnamn på varje rad som du vill undanta från denna webbplats.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[Uteslut IP-adresser]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Ange en IP-adress på varje rad som du vill undanta från denna webbplats.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Uteslut användar agenter]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Ange en användar agent på varje rad som du vill undanta från denna webbplats.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Ange adressen till Memcache server! Du kan ange en server på varje rad.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Använd beständiga anslutningar]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Genom att aktivera denna möjlighet kommer en ihållande anslutning till Memcache servern att användas.]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache typ]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Välj den typ av cache som du vill använda! Några av de typer har särskilda krav på servern och kan inte användas i din omgivning.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[Filsystem (standard)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (experimentell)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[Allmänt]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Cache]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Allmänt]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache lagrar data i minnet som ofta används. Detta kan minska databasens belastningen dramatiskt. Läs mer om Memcache på följande webbplats:
+<ul>
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Datum och tid]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Proxy server]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Du kan konfigurera valfri proxyservrar för anslutningar till externa servrar.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-post]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Allmän]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[Transmission]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Inaktivera forum tillfälligt]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[Moduler på / av]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[Innehåll]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Visa]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[System]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Användare]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[Säkerhet]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Captcha]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Internetsidor är ofta attackerade av program och robotar. Det går till exempel att skapa hundratals användarkonton automatiskt. Du kan skydda dig mot dessa spam bots med hjälp av en så kallad <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">captcha bild</a> på varje plats där webbformulär används. Oregistrerade användare måste först identifiera koden innan de kan skicka formuläret. Robotar kan inte läsa koden. Vänligen notera att captcha bilder inte kan läsas av blinda och synskadade.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Svartlista]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Censur]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Allmän]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Session]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[Användare]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookie domänen]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Ange här den domän som cookien ska användas. Detta är frivilligt, så i de flesta fall behöver du inte ange cookiedomänen.]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookie sökväg]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Cookien vägen är parallell till dokument roten på din webbplats - t.ex. &quot;/forum&quot; för http://www.woltlab.com/forum.]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Cookie prefix]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Ange här ett prefix som skall användas för cookienamnet.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Aktivera automatisk sommartid]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Ska klockan automatiskt ändras beroende på sommar / vintertid?]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Använd cache metod för session data]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Ska den valda cache metod användas för att spara session data?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Den information du har angett är ogiltigt.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[Export alternativ]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[Ladda ner de exporterade alternativen]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Hämta de exporterade alternativen som en backup-fil till din lokala dator.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Aktivera innehålls typen ansökan/ xhtml + xml]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[Aktivering av det här alternativet kan du visa dina sidor med innehålls typen ansökan/ xhtml + xml.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Aktivera gzip-komprimering]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Aktivering av detta alternativ kommer att resultera i att innehållet är komprimeratpå servern och skickar det komprimerade innehållet till kunderna. Detta alternativ minskar trafiken.]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Inaktivera cachning av sidor i webbläsare]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Aktivering av denna möjlighet kommer att begränsa webbläsare från cachning av sidor.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Komprimerings nivå]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[Ett värde på 1 till 9 krävs. För bästa möjliga resultat för komprimering och serverns prestanda rekommenderar vi ett värde av 1.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[Importalternativ]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[Alternativen har importerats successfullt.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[Ladda upp alternativen]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[Lägg upp de alternativ som ska importeras från din lokala dator.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Import &amp; Export alternativ]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Administratörers e-postadress]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Ange här administratörernas e-postadress.]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Sökvägen till debug loggfil]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Skriv in sökvägen till loggfilen]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Avsändares e-postadress]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Ange här avsändarnas e-postadress som ska användas för automatisk e-post.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Avsändares namn]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Ange här avsändarnas namn som ska användas för automatisk e-post.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-post metod]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Välj en e-post överförings metod.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Avsändares signatur]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Enter here a signature that should be sent with system e-mails.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP värd]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Ange här SMTP-serverns namn.]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP lösenord]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Ange här SMTP-lösenord]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP port]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Ange här SMTP server port.]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP användarnamn]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Ange här SMTP användarnamn]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[Aktivera &quot;-f&quot; parameter]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[En del servrar kan kräva &quot;-f&quot; parametrar som skall användas när du skickar e-post. Om du har problem med användare som inte tar emot e-post, försök aktivera detta alternativet.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Använd formaterade e-postadresser]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Avsändare och mottagares adresser är formaterade i &quot;Namn &lt;epostl@domän.tld&gt;&quot;. Det här alternativet stöds inte av alla e-postservrar och bör stängas av vid eventuella problem.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Aktivera huvudlösenord]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Sidor och formulär inom admin panelen som är relevanta för säkerheten kan skyddas med ett extra Huvudlösenord.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Proxy-Server (FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[Proxy-Server för FTP anslutningar]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Proxy-Server (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[Proxy-Server för HTTP anslutningar]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Session timeout]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Ange här hur länge en session skall gälla i [sekunder].]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Kontrollera IP-adress av sessionen]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Antalet block av en IP-adress som ska kontrolleras när man läser session data. Ett högt antal kan utesluta användare som använder ändrade IP-adresser.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Kolla användar agent av sessionen]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Bör användare agenten kontrolleras när man läser session data?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[Din val ändringar har sparats successfullt.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[Tidszonsangivelse]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Välj din standard tidszon för din webbplats.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Användare online timeout]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Ange här hur länge en användare ska markeras som online när de är inaktiva [sekunder].]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[Avbryt paketinstallationsåtgärder]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[Description]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[Ange här tillgångs information för FTP]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[FTP access detaljer]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Med PHP-safemode aktiverat på din server, behöver paket installeras med hjälp av FTP-funktioner. Ange FTP-användarnamn och lösenord för denna server. De uppgifter du lämnar kommer inte att registreras eller lämnas vidare till någon annan part och kommer enbart att användas för installation. Av detta skäl kan det vara möjligt att FTP information kommer att krävas för att tas upp igen under installationsprocessen.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Med den FTP information du har angett, kan inte FTP-anslutning göras.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[En anslutning till den angivna FTP-servern kunde inte göras.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[En korrekt inloggning till den angivna FTP-servern kunde inte göras.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Värdnamn]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Lösenord]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[Paket Installation]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Avbryt installationen]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Är du säker på att du vill avbryta denna installation?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[Paket beroendet kan inte vara nöjd för det här paketet.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[The {if $action == 'install'}paket installation{else}paket uppdatering{/if} av paket &quot;{$packageName}&quot; i version {$packageVersion} kan inte verkställas på grund av oförenligheter med följande {if $excludedPackages|count == 1}paket{else}paket{/if}:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} i version {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Följande paket {else}Följande paket{/if} tillåter inte {if $action == 'install'}paket installation{else}paket uppdatering{/if} av paketet &quot;{$packageName}&quot; i version {$packageVersion} på grund av oförenligheter:]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} i version {$excludingPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Följande paket är{else}Följande paket är{/if} oförenligt med paket &quot;{$packageName}&quot; i version {$packageVersion}. Om du fortsätter installationen {if $excludingPackages|count == 1}kommer paketet{else}kommer paketen{/if} förmodligen inte att fungera längre.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="färg: grön"{else}{if !$package.file|isset} style="färg: röd"{/if}{/if}>{$package.name} ({if $package.open == 0}Installerade{else}{if $package.file|isset}ligger i detta paket{else}Inte tillgängligt{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Är du säker på att du vill avbryta installationen av det här paketet?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Följande paket kan uppdateras med detta paket]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Välj ett av följande paket, för att uppdatera din version. Om du vill installera paketet igen, klicka på &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Det finns redan en kopia av detta paket installerat. Om du fortsätter, kommer ytterligare en kopia av detta paket att installeras. Om du vill uppdatera en tillgänglig kopia av det här paketet kan du välja kopiera från följande lista.]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[Paket Version:]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[Installation datum]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Vid uppackning av filer i paketet inträffade följande fel :]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[Följande filer kunde inte packas upp utan problem. Kontrollera om målmappen är skrivbar.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Motstridiga Tabeller]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Skriv inte över dessa tabeller och fråga mig inte igen om den här installationen.]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Skriv över de befintliga tabellerna och fråga mig inte igen om den här installationen.]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Krävs förändringar]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Tabeller påverkas]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Befintliga databas tabeller i konflikt med de tabeller som skall installeras av detta paket. Välj om att skriva över dessa tabeller.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[Installerade paket]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[Författare]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[Totalt {#$items} paket installerade]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[Datum]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[Namn]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Plugin]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Fristående program]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[Version]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[Installera valfria paket]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[De valda paketet har följande alternativ med. Välj dem som du vill installera.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Detta paket är redan installerat.)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Kraven på det här paketet har inte uppfyllts.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[Installations mapp]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Ett annat program är redan installerat i mappen.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[Denna mapp är ogiltig.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Denna mapp är inte skrivbar.]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Denna mapp används redan av WoltLab Community Framework. Välj en annan plats.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Fyll i installationsmappen här.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Denna applikation är tillgängliga via följande webbadress efter installationen i denna mapp:]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[Välj beroenden]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Det nuvarande paketet kräver ett annat paket som är installerat flera gånger. Välj den instans som skall krävas.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[Rulla tillbaka paket installationsåtgärden]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Version {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[Installera nya paket]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Det valda paketet har ingen giltig installations rutin.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[Arkivet ni har angett är inte ett giltigt paket.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[Paketet &quot;{$package->getName()}&quot; kunde inte uppdateras från ditt levereras arkiv.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Inga filer hittades inom den angivna katalogen.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Ditt valda paketet är redan installerat. Paket kan inte installeras mer än en gång.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[Uppladdning av ditt valda arkiv har misslyckats.]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Välj paketkälla]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Skriv in sökvägen till det paket som finns på din Server]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Ange här en direkt sökväg till paket-filen. En Internet-adress kan användas eller alternativt att ta vägen till paket filen med hjälp av serverns filsystem.]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Ladda upp paketet från din lokala dator]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Ange här paket filen som ska laddas upp från din dator.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Uppdatera Paket &quot;{$package->getName()}&quot;]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Installera meny uppgifterna för Administration Kontrollpanelen ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Installera mall sökvägar för Administration Kontroll Panel ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Installera mallar för Administration Kontrollpanelen ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Installera händelse åhörare ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Uppacka paketfiler ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Installera användargrupp alternativ ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Installera paket språk ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Installera paketet alternativ ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Verkställ särskilda skript ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Installera databas poster...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Installera mall sökvägar ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Installera paket mallar ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Installera användarprofil fält ...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Kontrollerar eventuella konflikter ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Exekvera paket plugins ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Installeringen är klar]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[Installera valfria paket ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Registrerings paket ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Installera paket plugins ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Förälder paket fördelning görs ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Kontrollera beroenden ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[Paket <b>{$packageName|encodeJS}</b>: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Ta bort menyalternativ från Administration Kontrollpanelen ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Ta bort mall sökvägen i Administration Kontroll Panel ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Borttagning av mallar från Administration Kontroll Panel ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Ta bort händelse åhörare ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Borttagning av paket filer ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Ta bort användargrupp alternativ ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Ta bort paket språk ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Ta bort paketet alternativ ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Ta bort databas poster...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Ta bort mall sökvägar ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Ta bort paket mallar ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Ta bort användar profil fälten ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Exekvera paket plugins ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Paket avlägsnande färdiga]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[Ta bort valfria paket ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Ta bort paket plugins ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Ta bort paket krav ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Uppdatering av menyalternativ i Administration Kontrollpanelen ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Updating template patches in the Administration Control Panel ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Uppdaterar mallar i Administrations Kontroll Panel ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Uppdatera händelse åhörare ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Uppackning paketfiler ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Uppdatera användargrupp alternativ ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Uppdatera paket språk ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Uppdatera paketet alternativ ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Verkställ särskilda skript ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Uppdatera databas poster ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Uppdatera mall sökvägar ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Uppdatera paket mallar ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Uppdatera användarprofil fält ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Checking possible conflicts ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Exekvera paket plugins ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Paket uppdatering färdig]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[Uppdatering valfria paket ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Uppdatering paket ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Uppdatering paket plugins ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Förälder paket fördelning görs ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Kontrollera beroenden ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[Sökvägen som detta paket försöker tillämpa har misslyckats eftersom denna sökväg är inte kompatibel med sin mål fil. Därför kan inte detta paketet installeras. Klicka här &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; knapp.]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Repatching av följande mallar har misslyckats:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Ursprungligen patchad av: {$failure.packageName})<br />{/foreach}Det ursprungliga Korrigeringspaketet som tidigare tillämpats fungerar inte längre. Du ska fortsätta med den här uppdateringen genom att klicka på &quot;{lang}wcf.global.button.next{/lang}&quot; knapp.]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[Sökvägen som detta paket försöker ta bort har misslyckats eftersom dess mål fil har externt ändrats. Därför kan inte detta paketet tas bort. Klicka på &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; knapp.]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[Paketet avlägsnat]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Avbryt paket-avlägsnande]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Det går inte att avinstallera detta paket, eftersom det finns minst ett beroende paket, som inte kan avinstalleras.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Efter slutlig bekräftelse {if $dependentPackages|count == 1}detta paket{else}dessa paket{/if} kommer att tas bort utan ytterligare övertalning.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[Paket uppdatering]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[Date of update]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[Författare:]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Gå till Administration Kontroll Panelen]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Ta bort paket]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Ta bort alla paket]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Är du säker på att du vill ta bort det här paketet?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Uppdatera paket]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[Datum:]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[Beroende paket]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Detta paket har ett krav från {if $dependentPackages|count == 1}ett andra paket.{else}{#$dependentPackages|count} andra paket.{/if}]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Det här paketet krävs av ett annat paket{else}{#$dependentPackages|count} Paketet är direkt eller indirekt beroende av detta paket{/if}.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[Installations mapp:]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Identifiera:]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Installerade exempel:]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[Förälder paket:]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[Egenskaper]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Kräver paket]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Detta paket har ett krav på {if $requiredPackages|count == 1}ett andra paket.{else}{#$requiredPackages|count} andra paket.{/if}]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[Hemsida:]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[Installerad version:]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[Uppdatera paket]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Autentisering med Update Server]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Anslutnings uppgifter]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Användarnamn och lösenord har inte godtagits.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Lösenord]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Ange ett lösenord som används för autentisering.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Ange ett användarnamn som används för autentisering.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Användarinloggning]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Server meddelande]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Server namn]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Spara användardata permanent]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Den angivna användarens uppgifter kommer att sparas permanent, så att du inte behöver mata in uppgifter senare igen.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adress]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Installerad version]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Ett fel uppstod: ]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[Hämtningen av paketet {$package} har misslyckats.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[En lista på paket kunde inte hittas.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[Följande {if $excludedPackages|count == 1}konflikt{else}konflikter{/if} inträffade:]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Det installerade paketet &quot;{$excludedPackage.existingPackageName}&quot; är oförenligt med paketet &quot;{$excludedPackage.packageName}&quot; i version {$excludedPackage.packageVersion}.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[Paketet &quot;{$excludedPackage.packageName}&quot; i version {$excludedPackage.packageVersion} är oförenligt med det installerade paketet &quot;{$excludedPackage.existingPackageName}&quot;.]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} är installerad]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Det finns inga uppdateringar tillgängliga.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Du har inte valt några uppdateringar.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Val]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Paketet är redan installerat och är unikt. Därför går det inte att installera en gång till.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Installera paket]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Installera ett annat paket exempel (paketet är redan installerat {#$package.instances} gånger{if $package.instances > 1}{/if})]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Uppdateta installerade paket {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} version {$updatableInstance.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Sök paket]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Författare]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Sök efter ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Dölj redan installerade unika paket]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Paket namn]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Paket namn och beskrivning]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Uppdatera server]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Sök alla uppdaterade server]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Typ av paket]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Andra paket]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Plugin för redan installerade paket]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Fristående program]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Välj alla paket]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion} är uppdaterad till {$package.toVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Ny version]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Följande paket uppdateringar och installationer bearbetas:]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[Åtgärder av den inloggade sessionen &quot;{$sessionLog->username}&quot;]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Det finns totalt {#$items} loggade åtgärder{if $items != 1}s{/if}]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[Åtgärder]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Class namn]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP adress]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Senaste åtgärd]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Metod]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Datum]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[Användar agent]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Loggad session]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Det finns totalt {#$items} loggade sessioner{if $items != 1}s{/if}]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[Lägg till server]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Server har tilllagts successfullt.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[Server data]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Radera server]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Servern har tagits bort successfullt.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Vill du verkligen ta bort denna server?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Inaktivera]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Redigera server]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Dina ändringar har sparats successfullt.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Aktivera]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Felmeddelanden]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Lösenord]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Ange ett lösenord som krävs för autentisering (frivilligt).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Ange ett användarnamn som krävs för autentisering (frivilligt).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Följande fel uppstod vid försök att ansluta sista gången:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} server tillgänglig]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Server id]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adress]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Ange URL till en paket server.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[Den angivna adressen är ogiltig.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[Status]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Senaste tillträde]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[Tillgängliga updateringar Server]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Det finns ingen uppdatering server tillgänglig.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[Lägg till en ny användare]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[Användar information]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[Den nya användaren har sparats successfullt.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Grupp tilldelning]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Tilldela följande användare den valda gruppen]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Användarna har framgångsrikt tilldelats till dina valda grupper.]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Grupp tilldelning]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[Exportera e-postadresser]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Skicka ett e-post]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[Radera användare]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[Inga användare kan raderas.]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}Användare har {else}{#$deletedUsers} användaren har{/if} blivit successfullt raderad.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Är du säker på att du vill ta bort den här användaren?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Är du säker på att du vill ta bort den valda Användaren?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[Redigera användare]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[Förändringarna för den här användaren har sparats successfullt.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Du redigerar för närvarande ditt eget användarkonto. Ändring av rättigheter för denna användargrupp kan leda till att du låser ute dig själv från  Administration Kontrollpanelen. Var försiktig!]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[Exportera e-postadresser]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Exportera filformat]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Exportalternativ]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Exportera e-postadresser från följande användare]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Skilj adresserna med ett]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Bifoga adresser med]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[Gruppmedlemskap]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Hitta användare som inte är medlemmar i valda användargrupper.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[Användare]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[Lista alla användare]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[Totalt {#$items} användare{if $items > 1}{/if}]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 användare vald" : this.count+" användare valda"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Bulk behandling av användare]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[Aktion]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Villkor]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Den valda åtgärden har genomförts framgångsrikt på {#$affectedUsers} users.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Bulk processorn kommer att utföra följande uppgifter <strong>utan extra säkerhets anmälan</strong>, på alla användare som matchar de villkor som fastställts. Bulk behandlingen kan vara mycket prestanda intensivt, så den bör endast utföras när forumet är offline. För att ha en korrekt visning av ditt innehåll bör du uppdatera räknarna. Bearbetningen kan inte hejdas, så du bör vara uppmärksam när du använder denna funktion.]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[Sök efter användare]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Sökkriterier]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Allmänna sökkriterier]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profil sökkriterier]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[Visa]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Kolumner]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Annan]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profil]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[Allmän]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Användare per sida]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sortering]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Ingen användare har hittats.]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[Din sökning producerade {if $items == 1}ett resultat{else}{#$items} resultat{/if}]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Sök inom resultat]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[Skicka ett e-postmeddelande]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-posta alla användare]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[Skicka e-post som HTML]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Avsändare]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Här kan du ange avsändarens e-postadress i följande format:</p>
+<p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Avsändarens namn &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>
+<p>Om du har fullständigt fyllt i avsnittet under System -> Inställningar -> E-post, då kommer detta fält automatiskt att fyllas i. Om du skickar e-post via SMTP, då måste avsändarens e-postadress också accepteras av Servern.</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[E-posta alla gruppmedlemmar]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Skicka ett e-post till medlemmarna i följande användargrupper:]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-post]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Skicka ett e-postmeddelande till följande användare]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Ämne]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Ange här e-post ämnet.]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Meddelande]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Ange här meddelandet du vill skicka till användare.]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[Välkommen {$this->user->username}.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Pågående process]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[Lämna detta fönster öppet tills processen är klar. Försök INTE att logga in med ett separat fönster på ditt administrations område då detta kan skada den pågående processen.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[Processen slutförts successfullt]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[Bearbetning ...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% komplett]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[Bearbetning ...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Tillbaka]]></item>
+               <item name="wcf.global.button.close"><![CDATA[Stäng]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[Radera]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Vill du verkligen ta bort denna post?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Ta bort helt]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[Redigera]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[Använd full redigerare]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[Välj]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Nästa &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[Förhandsgranska]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[Återställ]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[Skicka in]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[Avmarkera]]></item>
+               <item name="wcf.global.date.day"><![CDATA[Dag]]></item>
+               <item name="wcf.global.date.days"><![CDATA[Dagar]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[Timme]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[Timmar]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[Minut]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[Minuter]]></item>
+               <item name="wcf.global.date.month"><![CDATA[Månad]]></item>
+               <item name="wcf.global.date.months"><![CDATA[Månader]]></item>
+               <item name="wcf.global.date.second"><![CDATA[Sekund]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[Sekunder]]></item>
+               <item name="wcf.global.date.week"><![CDATA[Vecka]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[Veckor]]></item>
+               <item name="wcf.global.date.year"><![CDATA[År]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Specificera år är frivilligt.]]></item>
+               <item name="wcf.global.date.years"><![CDATA[Years]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Idag</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Igår, %H:%M]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[Standard]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[Tillbaka till sista sidan]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[Ange den information som krävs för detta område.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[Filen kunde inte hittas.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[Länken du försöker nå är inte längre tillgänglig eller är ogiltig.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Du har inte rätt att skriva på den här sidan. Du har inte behörighet att gå in på denna sida.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Du har inte behörighet att gå in på denna sida.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[Felmeddelande]]></item>
+               <item name="wcf.global.form.error"><![CDATA[De data som du har angett är ogiltigt. Kontrollera den information du har angett i det markerade området.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arabiska]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosniska]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Tjeckiska]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danska]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Tyska]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Tyska (informella)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grekiska]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Engelska]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Spanska]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persiska (farsi)]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finska]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Franska]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hebreiska]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Kroatiska]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Ungerska]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Italienska]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japanska]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Koreanska]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Holländska]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norska]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polska]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugisiska]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugisiska (Brasilien)]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Rumänska]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Ryska]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovakiska]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Serbiska]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Svenska]]></item>
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turkiska]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Kinesiska (förenklad)]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Kinesiska (traditionell)]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[sv_SE]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[swedish]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[Flera objekt kan väljas genom att hålla &quot;Ctrl/Shift&quot; nyckel (Windows) eller &quot;Kommando&quot; (Mac OS) tangenten och klicka på de punkter som krävs.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[Gå till följande webbplats]]></item>
+               <item name="wcf.global.page.next"><![CDATA[Nästa sida]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[Föregående sida]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[Omdirigering]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[Klicka här om automatisk omdirigering inte fungerar!]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[Gå till början av sidan]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Exakt matchning]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e. %B %Y, %H:%M]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[Skip navigation]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[stigande]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[fallande]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Image " + (this.currentIndex + 1) + " of " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[Stäng]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Visa endast denna bild (avsluta bildvisningsprogrammet)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[Nästa bild]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[Stoppa bildspel]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[Starta bildspel (changes the image every 5 seconds)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[Föregående bild]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Casablanca, Dublin, Edinburgh, Canary Islands, Lisbon, London, Monrovia, Ouagadougou, Reykjav&iacute;k]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brussels, Madrid, Paris, Prague, Rome, Sarajevo, Stockholm, Tunis, Warsaw, Vienna]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Athens, Beirut, Bucharest, Helsinki, Istanbul, Jerusalem, Cairo, Cape Town, Khartoum, Kiev, Minsk, Sofia]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Ababa, Antananarivo, Baghdad, Dodoma, Kampala, Kuwait City, Mogadishu, Moscow, Nairobi, Riyadh]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Tehran]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Baku, Dubai, Yerevan, Muscat, R&eacute;union, Tbilisi]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabul]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Ashgabat, Bishkek, Dushanbe, Islamabad, Yekaterinburg, Karachi, Maldive Islands, Tashkent]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kolkata, Mumbai, New Delhi]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaty, Astana, Dhaka, Novosibirsk]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Islands, Yangon]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangkok, Hanoi, Jakarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Beijing, Perth, Singapore, Taipei, Ulaanbaatar]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Western Australia)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seoul, Tokyo]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darwin]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sydney, Vladivostok]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Island (Australia)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, New Caledonia, Solomon Islands]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolk Island]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, South Tarawa, Fiji, Kamchatka, Marshall Islands, Wellington]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Islands (New Zealand)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenix Islands]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Islands, Christmas Island]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azores, Cape Verde Islands]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Mid-Atlantic]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Greenland, Montevideo]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Newfoundland]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantic Time (Canada), Asunci&oacute;n, La Paz, Port-of-Spain, Santiago]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Eastern Time (US &amp; Canada), Bogot&aacute;, Lima, San Francisco de Quito]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Central Time (US &amp; Canada), Central America, Mexico City]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Time (US &amp; Canada), Chihuahua, Mazatlan]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pacific Time (US &amp; Canada), Tijuana]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) French Polynesia]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cook Islands, Hawaii]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midway Islands, Samoa]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[Sida {#$pageNo}]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[Bekräfta e-postadress]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[Bekräfta lösenord]]></item>
+               <item name="wcf.user.email"><![CDATA[E-postadress]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Den angivna e-postadressen och den bekräftade e-postadressen är inte samma.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Det angivna lösenordet och det bekräfta lösenordet inte är samma.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[E-postadressen du har angett har redan använts av en annan användare.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[E-postadressen du har angett är ogiltigt.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[Lösenord är felaktigt.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[Användarnamnet &quot;{$username}&quot; kunde inte hittas.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Användarnamnet du har angett har redan tagits.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[Användarnamnet du har angett är ogiltigt.]]></item>
+               <item name="wcf.user.language"><![CDATA[Språk]]></item>
+               <item name="wcf.user.language.description"><![CDATA[Välj användargränssnittets språk som skall visas i!]]></item>
+               <item name="wcf.user.logout"><![CDATA[Logga ut]]></item>
+               <item name="wcf.user.password"><![CDATA[Lösenord]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[Datum för registrering]]></item>
+               <item name="wcf.user.userID"><![CDATA[Användare ID]]></item>
+               <item name="wcf.user.username"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[Visa innehållet i följande språk]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Välj här innehålls språket som skall visas.]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Den information du har angett är ogiltigt.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/tr.xml b/wcfsetup/install/lang/tr.xml
new file mode 100644 (file)
index 0000000..0c6a38e
--- /dev/null
@@ -0,0 +1,812 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="tr">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[Yönetim Gözden Geçirme]]></item>
+               <item name="wcf.acp.help"><![CDATA[Yardım]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[Tüm Yardım]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[Çevrimiçi Yardımı Etkisizleştir]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[Etkileşimli Yardım]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[Paket Değiştir]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[Gelişmiş Arama ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[Site Haritası]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[Belleği boşalt]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[Bellek başarıyla boşaltıldı.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[Belleği tamamen boşaltmak istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[Ayarlar]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[Dosyalar]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[Boyut]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[Kaynak]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[Sürüm]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[Bellek]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[Son güncelleme]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[İsim]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[İzinler]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[Boyut]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[Yeni kullanıcı grubu ekle]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[İzinler]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[Kullanıcı grubu başarıyla eklendi.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[Yöneticiler]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[Genel grup bilgisi]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[Bu kullanıcı grubunu sil]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[{if $deletedGroups == 1}Bu kullanıcı grubu{else}{#$deletedGroups} Bu kullanıcı grupları{/if} başarıyla silindi.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[Bu kullanıcı grubunu kaldırmak istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[Bu kullanıcı grubunu düzenle]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[Kullanıcı grubu değişiklikleriniz başarıyla kaydedildi.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[Şu an bu kullanıcı grubunun bir üyesisiniz. Bu kullanıcı grubunun izinlerini değiştirmek sizi yönetim dışında bırakabilir. Lütfen dikkatli olunuz!]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Herkes]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[Grup kimliği]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[Bu kullanıcı grubunun adı]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[Buraya bu grup için kullanılacak bir isim giriniz.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[Misafirler]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[Kullanıcı grupları]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[Toplam {#$items} kullanıcı grubu]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[Üye Sayısı]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[Moderatörler]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[Yönetim Gözden Geçirmesine girebilir]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[Bu seçeneğin etkinleştirilmesi bu kullanıcı grubunun üyelerinin Yönetim Gözden Geçirmesine girmesini sağlayacak ve bu üyelere verilen izinlere bağlı olarak bu alanlarda gerekli değişiklikleri yapmalarını sağlayacaktır.]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[Özel kullanıcı seçeneklerini görebilir]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[Bu kullanıcı grubunun üyeleri özel kullanıcı seçeneklerini görebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[Sistem seçeneklerini değiştirebilir]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[Bu seçeneği etkinleştirmek bu kullanıcı grubu üyelerine sistem seçeneklerini görüntüleme ve değiştirme yetkisi verecektir - Örn: Forum etkin/etkisiz.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[Kayıtları görebilir]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[Bu kullanıcı grubunun üyeleri sistem kaytılarını görebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[Güncelleme Sunucularını düzenleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[Bu kullanıcı grubunun üyeleri Güncelleme Sunucularını düzenleyebilir ve ilave Güncelleme Sunucuları ekleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[Yeni paketler yükleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[Bu kullanıcı grubunun üyeleri ilave paketler yükleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[Varolan paketleri kaldırabilir]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan paketleri kaldırabilir.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[Varolan paketleri güncelleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan paketleri güncelleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[Erişilebilir Kullanıcı Grupları]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[Bu kullanıcı grubunun üyeleri belirtilen gruplara erişim hakkına sahiptir. Örneğin, burada kullanıcı gruplarının kendilerini düzenleyip düzenlememe izinlerini ayarlayabilirsiniz.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[Yeni kullanıcı grupları ekleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[Bu kullanıcı grubunun üyeleri yeni kullanıcı grupları ekleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[Yeni kullanıcılar ekleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[Bu kullanıcı grubunun üyeleri yeni kullanıcılar ekleyebilir. Eğer yeni kullanıcı oluşturma kısmındaki &quot;Erişilebilir Kullanıcı Grupları&quot; seçeneği etkinleştirilmişse, aynı zamanda uygun kullanıcı grupları atanabilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[Varolan kullanıcı gruplarını silebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan kullanıcı gruplarını silebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[Varolan kullanıcıları silebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan kullanıcıları silebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[Varolan kullanıcı gruplarını düzenleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan kullanıcı gruplarını düzenleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[Kullanıcı e-posta adreslerini düzenleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[Bu kullanıcı grubunun üyeleri kullanıcı e-posta adreslerini düzenleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[Kullanıcı şifrelerini düzenleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[Bu kullanıcı grubunun üyeleri kullanıcı şifrelerini düzenleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[Varolan kullanıcıları düzenleyebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan kullanıcıları düzenleyebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[Kullanıcılara e-posta gönderebilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[Bu kullanıcı grubunun üyeleri diğer üyelerin e-posta adreslerini görebilir ve onlara e-posta gönderebilir.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[Üye arayabilir]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[Bu kullanıcı grubunun üyeleri varolan üyeleri ve bu üyeleri profil bilgilerine göre arayabilir.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[Yönetici İzinleri]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[İçerik]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[Tasarım]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[Genel Yönetim İzinleri]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[Bakım]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[Sistem İşlevleri]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[Paket Yönetimi]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[Kullanıcı İşlevleri]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[Grup Yönetimi]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[Kullanıcı Yönetimi]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[Moderatör İzinleri]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[Genel İzinler]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Girdiğiniz bilgi geçersiz.]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[Bu kullanıcı grubunun üyelerini göster]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[Süper Moderatörler]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[Kayıtlı Kullanıcılar]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[Giriş]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[Giriş ayrıntıları]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[Ana Şifre]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[Ana şifreyi doğrula]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[Ana şifre gerekli]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[Bu sayfa ya da işlem güvenlik nedenlerinden dolayı ana şifreyi girmenizi gerektirmektedir. Bu işlemi bir oturumda sadece bir defa yapmanız gerekmektedir. Eğer ana şifreyi hatırlayamıyorsanız <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em> dosyasını silerek ana şifreyi sıfırlayabilirsiniz.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA[Ana şifre doğru değil.Eğer hatırlamıyorsanız <em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em> dosyasını silerek ana şifreyi sıfırlayabilirsiniz.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[Girilen şifreler aynı değil.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[Şifre güvenli değil. En az sekiz karakter, küçük ve büyük latin harfleri ile birlikte numara ve özel karakterlerde içermelidir. Ayrıca bu sitenin yöneticilerinin şifreleri ile de aynı olmamalıdır.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[Şifre önerisi]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[Şifre önerisini kullan]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[Ana şifreyi ayarla]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA[Ana şifre güvenlikle ilişkili olan işlevler ve işlemler için ilave bir korumadır. Yönetici şifrenizle aynı olmayan, diğerleri tarafından bilinmeyen ve diğer sitelerde kullanılmayan çok güçlü bir şifre kullanmalısınız.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[Otomatik güncelleme]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[İçerik]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[Tasarım]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[Kullanıcı Grupları]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[Yeni kullanıcı grubu ekle]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[Tüm grup üyelerine e-posta]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[Grup gözden geçirme]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[Sistem Kayıtları]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[Bellek]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Oturum]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[Bakım]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[Seçenekler]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[İçeri &amp; dışarı aktarım]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[Paketler]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[Paketleri ara]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[Yeni paket yükle]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[Yeni sunucu ekle]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[Sunucu gözden geçirme]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[Yüklenmiş paketleri listele]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[Sistem]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[Kullanıcı]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[Kullanıcı ekle]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[Kullanıcıları listele]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[Tüm kullanıcılara e-posta]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[Kullanıcılar]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[Kullanıcılar için toplu işlem]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[Kullanıcılarda ara]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[Sunucu adlarını engelle]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[Bu siteye erişmesini istemediğiniz, hariç tutmak, dışarıda tutmak istediğiniz sunucu adlarını her satıra bir tane gelecek şekilde yazın.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[IP adreslerini engelle]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[Bu siteye erişmesini istemediğiniz, hariç tutmak, dışarıda tutmak istediğiniz IP adreslerini her satıra bir tane gelecek şekilde yazın.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[Kullanıcı aracını engelle]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Bu siteye erişmesini istemediğiniz, hariç tutmak, dışarıda tutmak istediğiniz kullanıcı araçlarını (tarayıcı, arama motoru robotu gibi) her satıra bir tane gelecek şekilde yazın.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache sunucusu]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[Memcache sunucusunun adresini giriniz! Her satıra bir sunucu girebilirsiniz.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Kalıcı bağlantılar kullan]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[Bu seçeneğin etkinleştirilmesi ise memcache sunucusuna bağlanmak için kalıcı ve sürekli bağlantılar kullanılacaktır.]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[Bellek türü]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Lütfen kullanmak istediğiniz bellek türünü seçiniz! Bazı türler sunucu sistemleri için özel gereksinimlere sahiptir ve sizin donanımınızla kullanılamayabilir.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[Dosya sistemi (öntanımlı)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (deneysel)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[Genel]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[Bellek]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[Genel]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache sıklıkla kullanılan verileri bellekte tutar. Bu durum veritabanı yükünü büyük ölçüde azaltır. Memcache hakkında daha fazla bilgiye aşağıdaki siteden ulaşabilirsiniz:
+<ul>
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[Tarih ve zaman]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Çerezler]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[Vekil Sunucu]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[Dış sunuculara yapılan bağlantılar için dilerseniz vekil sunucu yapılandırabilirsiniz.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-posta]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[Genel]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[İletim]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[Forumu geçici olarak etkisizleştir]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[Modüller etkin / etkisiz]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[İçerik]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[Görünüm]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[Sistem]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[Kullanıcı]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[Güvenlik]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[Güvenlik kodu]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[Robotlar ve yazılımlar tarafından internet sayfalarına sık sık saldırılar düzenlenmektedir. Otomatik olarak yüzlerce kullanıcı hesabı oluşturmak mümkündür. Kendinizi bu tür zararlılara karşı <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">güvenlik kodu resmi</a> yardımıyla web formlarının kullanıcı tarafından onaylandığı ya da gönderildiği heryerde koruyabilirsiniz. Kayıtlı olmayan kullanıcılar formu göndermeden önce bu güvenlik kodunu doğrulamalıdırlar. Robotlar bu kodu okuyamazlar. Hatırlayın güvenlik kodu resimleri kör ya da görme kusuru olan kimseler tarafından okunamayabilir.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[Kara liste]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[Sansür]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[Genel]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Oturumlar]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[Kullanıcılar]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Çerez alan adı]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Buraya çerezin hangi alan adı için kullanılacağını giriniz. Bu seçenek isteğinize bağlı olup çoğu durumda çerez alan adını belirtmenize gerek yoktur.]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Çerez yolu]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Çerez yolu sitenizin belge kök dizini ile uyumludur - örneğin [url]http://www.woltlab.com/forum[/url] için &quot;/forum&quot;.]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Çerez öneki]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[Buraya çerez adı için kullanılacak öneki giriniz.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[Otomatik Yaz/Kış Saati Uygulaması Etkin]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[Kış ve yaz zamanına göre saat otomatik olarak değiştirilsin mi?]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[Oturum verisi için bellek yöntemi kullan]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[Oturum verisini kaydetmek için seçilen bellek yöntemi kullanılmalı mı?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[Girdiğiniz bilgi geçersiz.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[Seçenekleri dışarı aktar]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[Dışarı aktarılan seçenekleri indir]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[Dışarı aktarılan seçenekleri bir yedekleme dosyası olarak yerel makinanıza indirir.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[Content-Type application/xhtml+xml etkin]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[Bu seçeneğin etkinleştirilmesi ile sayfalarınızın Content-Type application/xhtml+xml kullanılarak görüntülenmesiniz sağlarsınız.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[Gzip Sıkıştırması Etkin]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[Bu seçeneğin etkinleştirilmesi ile sunucudaki içeriğin sıkıştırılmasına neden olacaktır ve bu sıkıştırılmış veriler istemcilere gönderilecektir. Bu seçenek sitedeki trafiği düşürmektedir.]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[Tarayıcılarda sayfaların belleğe alınmasını etkisizleştir]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[Bu seçeneğin etkinleştirilmesi tarayıcıların sayfaları belleklerine almalarını engelleyecektir.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[Sıkıştırma Seviyesi]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[1 ile 9 arasında bir değer girmeniz gerekmektedir. İdeal sıkıştırma ve forum performansı için biz 1 değerini öneriyoruz.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[Seçenekleri içeri aktar]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[Seçenekler başarıyla içeri aktarıldı.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[Seçenekleri yükle]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[İçeri aktarılacak seçenekleri yerel makinanızdan yükler.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[Seçenekleri içeri &amp; dışarı aktarma]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[Yönetici E-Posta Adresi]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[Buraya yöneticilerin e-posta adreslerini giriniz.]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Hata ayıklama kayıt dosyasının yolu]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[Buraya kayıt dosyasının yolunu giriniz.]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[Gönderenin E-Posta Adresi]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[Buraya otomatik e-postalarda kullanılacak gönderenin e-posta adresini giriniz.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[Gönderenin Adı]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[Buraya otomatik e-postalarda kullanılacak gönderenin adını giriniz.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-Posta Yöntemi]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Hata Ayıkla]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[Bir e-posta iletme yöntemi seçiniz.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[Gönderenin İmzası]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[Buraya sistem e-postaları ile birlikte gönderilecek bir imza giriniz.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP Sunucusu]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[Buraya SMTP Sunucu adını giriniz.]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP Şifresi]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[Buraya SMTP kullanıcı adlarının şifresini giriniz.]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP Portu]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[Buraya SMTP sunucu portunu giriniz.]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP Kullanıcı Adı]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[Buraya SMTP kullanıcı adını giriniz.]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[&quot;-f&quot; parametresi etkin]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[Bazı sunucular e-posta gönderirken &quot;-f&quot; parametresine gerek duyarlar. Eğer kullanıcılarınızın e-posta alamaması gibi bir sorun yaşıyorsanız, bu seçeneği etkinleştirmeyi deneyiniz.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[Biçimlendirilmiş e-posta adresleri kullan]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[Alıcı ve gönderen adresleri &quot;İsim &lt;email@domain.tld&gt;&quot; şeklinde biçimlendirilmiştir. Bu seçenek tüm e-posta sunucularınca desteklenmemektedir ve herhangi bir sorunla karşılaşılırsa kapatılmalıdır.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[Ana şifreyi etkinleştir]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA[Yönetici panelinde bulunan ve güvenlik ile ilgili olan sayfalar ve formlar ilave bir ana şifre ile korunabilir.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[Vekil Sunucu (FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[FTP bağlantıları için vekil sunucu]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[Vekil Sunucu (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[HTTP bağlantıları için vekil sunucu]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Oturum Zaman Aşımı]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[Buraya bir oturumun ne kadar süre geçerli kalacağını giriniz [Saniye].]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[Oturumun IP adresini kontrol et]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[Bir IP adresinin oturum verisini okurken kontrol edilecek blok sayısı. Yüksek bir sayı IP adresi değiştirmeyi kullanan kullanıcıları hariç tutacaktır.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[Oturumun kullanıcı aracını kontrol et]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[Otutum verisi okunurken kullanıcı aracı kontrol edilmeli mi?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[Seçenek değişiklikleriniz başarıyla kaydedildi.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[Zaman Dilimi]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[Siteniz için standart zaman dilimini seçin.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[Çevrimiçi Kullanıcı Zaman Aşımı]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[Buraya kullanıcılar etkisiz olduktan sonra ne kadar süre içerisinde halen çevrimiçi olarak işaretleneceklerini giriniz [Saniye].]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[Paket Yüklemesini İptal Et]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[Description]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[FTP erişim ayrıntılarını buraya girin]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[FTP Erişim ayrıntıları]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[Sunucunuzda PHP Güvenli Modu etkinse paketin FTP işlevi yardımıyla yüklenmesine gerek vardır. Lütfen bu sunucu için FTP kullanıcı adı ve şifresini giriniz. Girdiğiniz bilgi kaydedilmeyecek ya da herhangi bir yere yönlendirilmeyecektir. Sadece bu paketin yüklenmesi için kullanılacaktır. Bu nedenden dolayı, yükleme işlemi süresince FTP ayrıntılarınızı tekrar girmeniz gerekebilir.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[Girdiğiniz FTP ayrıntıları ile herhangi bir FTP bağlantısı sağlanamadı.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[Verilen FTP sunucusu ile bir bağlantı kurulamadı.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[Verilen FTP sunucusuna, doğru bir giriş yapılamadı.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[Bilgisayar Adı]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[Şifre]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[Kullanıcı Adı]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[Paket Yüklemesi]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[Yüklemeyi iptal et]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[Bu yüklemeyi iptal etmek istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[Bu paket için gerekli olan paket gereksinimleri karşılanamadı.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[&quot;{$packageName}&quot; adlı ve {$packageVersion} sürümlü {if $action == 'install'}paket yüklemesi{else}paket güncellemesi{/if} belirtilen {if $excludedPackages|count == 1}paketle{else}paketlerle{/if} olan uyumsuzluktan dolayı gerçekleştirilemedi:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} sürüm {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[{if $excludingPackages|count == 1}Belirtilen paket{else}Belirtilen paketler{/if} &quot;{$packageName}&quot; adlı ve {$packageVersion} sürümlü {if $action == 'install'}paket yüklemesine{else}paket güncellemesine{/if} uyumsuzluklardan dolayı izin vermiyor:]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} sürüm {$excludingPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[{if $excludingPackages|count == 1}Belirtilen paket{else}Belirtilen paketler{/if} &quot;{$packageName}&quot; adlı ve {$packageVersion} sürümlü paket ile uyumsuz. Eğer yüklemeye devam ederseniz {if $excludingPackages|count == 1}paket{else}paketler{/if} muhtemelen artık çalışmayacak.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}Installed{else}{if $package.file|isset}bu paket içerisinde bulunmakta{else}erişilebilir değil{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[Bu paketin yüklenmesini iptal etmek istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[Belirtilen paketler bu paket ile birlikte güncellenebilir]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[Belirtilen paketlerden birini sürümünü yükseltmek için seçiniz. Eğer paketi tekrar yüklemek isterseniz, lütfen tıklayınız &quot;{lang}wcf.global.button.next{/lang}&quot;.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[Bu paketin bir kopyası zaten yüklenmiş durumda. Eğer devam ederseniz bu paketin bir ileri sürümü yüklenecektir. Eğer bu paketin sürümünü güncellemek isterseniz, belirtilen listeden kopyalamayı seçiniz.]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[Paket Sürümü:]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[Yükleme tarihi]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[Bu paketin dosyalarını çıkartırken belirtilen hatalar gözlendi:]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[Belirtilen dosyalar başarıyla çıkartılamadı. Lütfen hedef klasörün yazılabilir olduğunu kontrol ediniz.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[Çakışan Tablolar]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[Bu paketlerin üzerine yazma ve bu yükleme esnasında bana tekrar sorma.]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[Varolan tabloların üzerine yaz ve bu yükleme esnasında bana tekrar sorma.]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[Gereken değişiklikler]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[Etkilenen tablolar]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[Varolan veritabanı tabloları, bu paket tarafından yüklenmesi gereken tablolar ile çakışmaktadır. Lütfen bu tabloların üzerine yazmak isteyip istemediğinizi seçiniz.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[Yüklenmiş Paketler]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[Yazar]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[Toplam {#$items} paket yüklenmiş]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[Tarih]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[Kimlik]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[İsim]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[Eklenti]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[Tek Uygulama]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[Sürüm]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[İsteğe bağlı paketleri yükle]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[Seçilen paket, aşağıdaki isteğe bağlı yüklenebilir paketleri de içermektedir. Lütfen hangisini yüklemek istediğinizi seçin.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[ (Paket zaten yüklenmiş.)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[ (Bu paketin gereksinimleri karşılanamadı.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[Yükleme klasörü]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[Bu klasörde zaten başka bir uygulama yüklemiş olarak bulunmaktadır.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[This folder is invalid.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[Bu klasör yazılabilir değil.]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[Bu klasör zaten WoltLab Community Framework tarafından kullanılmaktadır. Lütfen başka bir konum seçiniz.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[Lütfen buraya yükleme klasörünü giriniz.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[Bu uygulama bu klasördeki yüklemeden sonra belirtilen URL ile ulaşılabilir:]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[Gereklilikleri seçin]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[Şu anki paket daha önce pek çok defa yüklenmiş olan başka bir pakete gereksinim duymaktadır. Lütfen gerekli olan paketi seçiniz.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[Paket Yüklemesini Geri Al]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[Sürüm {$packageVersion} - {@$packageDate|date} - Telif Hakkı &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[Yeni Paket Yükle]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[Seçilen paket geçerli yükleme yöntemine sahip değil.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[Verdiğiniz arşiv geçerli bir paket değil.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[&quot;{$package->getName()}&quot; paketi sizin verdiğiniz arşivden güncellenemez.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[Verdiğiniz dizinde herhangi bir dosya bulunamadı.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[Seçtiğiniz paket zaten yüklenmiş durumda. Paketler birden fazla sayıda yüklenemez.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[Seçtiğiniz arşivin gönderilmesinde hata oluştu.]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[Paket kaynağını seç]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[Sunucunuzda bulunan paketin yolunu girin]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[Paket dosyasının yolunu doğrudan buraya girin. Alternatif olarak sunucu dosya sistemini kullanan paket dosyasının yolu bir internet adresi girilerek de belirlenebilir.]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[Bilgisayarınızdan paket yükleyin]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[Buraya bilgisayarınızdan yüklenecek paket dosyasını girin.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[Paket Güncelle &quot;{$package->getName()}&quot;]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[Yönetim Gözden Geçirme menü girişleri yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Yönetim kontrol paneli için şablon yamaları yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[Yönetim Gözden Geçirme şablonları yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[Olay dinleyicisi yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[Paket dosyaları çıkartılıyor ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[Kullanıcı grup seçenekleri yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[Paket dilleri yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[Paket seçenekleri yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[Özel betikler çalıştırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[Veritabanı girişleri yükleniyor...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[Şablon yamaları yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[Paket şablonları yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[Kullanıcı profil alanları yükleniyor...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[Olası çakışmalar kontrol ediliyor ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[Paket eklentileri çalıştırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[Yükleme tamamlandı]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[İsteğe bağlı paketler yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[Paket kaydediliyor ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[Paket eklentileri yükleniyor ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[Üst paket hesaplaması yapıldı ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[Gereksinimler kontrol ediliyor ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[Paket <b>{$packageName|encodeJS}</b>: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[Yönetim Gözden Geçirme menü öğeleri kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Yönetim Kontrol Panelinin şablon yamaları kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[Yönetim Gözden Geçirme şablonları kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[Olay dinleyicisi kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[Paket dosyaları kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[Kullanıcı grupları seçenekleri kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[Paket dilleri kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[Paket seçenekleri kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[Veritabanı girişleri kaldırılıyor...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[Şablon yamaları kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[Paket şablonları kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[Kullanıcı profil alanları kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[Paket eklentileri çalıştırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[Paket kaldırılması tamamlandı]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[İsteğe bağlı paketler kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[Paket eklentileri kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[Paket gereksinimleri kaldırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[Yönetim Gözden Geçirme menü öğeleri güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[Yönetim kontrol panelindeki şablon yamaları güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[Yönetim Gözden Geçirme şablonları güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[Olay dinleyicisi güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[Paket dosyaları çıkartılıyor ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[Kullanıcı grubu seçenekleri güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[Paket dilleri güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[Paket seçenekleri güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[Özel betikler çalıştırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[Veritabanı girişleri güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[Şablon yamaları güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[Paket şablonları güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[Kullanıcı profil alanları güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[Olası çakışmalar kontrol ediliyor ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[Paket eklentileri çalıştırılıyor ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[Paket güncellemesi tamamlandı]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[İsteğe bağlı paketler güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[Paket Güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[Paket eklentileri güncelleniyor ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[Üst paket hesaplaması yapıldı ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[Gereksinimler kontrol ediliyor ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[Bu paketin uygulamaya çalıştığı yama başarısız oldu çünkü bu yama hedef dosya ile uyumlu değil. Bu nedenle bu paket yüklenemez. Lütfen &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; düğmesine tıklayınız.]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[Belirtilen şablonların tekrar yamalanma işlemi başarısız oldu:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Orijinal olarak yamalayan: {$failure.packageName})<br />{/foreach}Daha önce uygulanan orijinal yama büyük bir ihtimalle artık çalışmayacak. &quot;{lang}wcf.global.button.next{/lang}&quot; düğmesine tıklayarak bu güncellemeye devam etmelisiniz.]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[Bu paketin kaldırmaya çalıştığı yama başarısız oldu çünkü hedef dosyası değiştirilmiş. Bu nedenle bu paket kaldırılamaz. Lütfen &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; düğmesine tıklayınız.]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[Paket Kaldırma İşlemi]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[Paket kaldırma işlemini iptal et]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[Bu paketler kaldırılamaz çünkü en azından kaldırılamaz özellikte olan bir adet bağımlı paket bulunmakta.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[Son doğrulama üzerine {if $dependentPackages|count == 1}bu Paket{else}bu Paketler{/if} başka bir bildiri olmaksızın kaldırılacaktır.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[Paket Güncelleme]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[Güncelleme tarihi]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[Yazar:]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[Yönetim Gözden Geçirme bölümüne git]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[Paket Kaldır]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[Tüm Paketleri Kaldır]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[Bu paketi kaldırmak istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[Paketi Güncelle]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[Tarih:]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[İlişkili Paketler]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[Bu paket {if $dependentPackages|count == 1}diğer bir pakete{else}{#$dependentPackages|count} adet pakete daha{/if} gereksinim duymaktadır.]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[{if $dependentPackages|count == 1}Bu paket diğer bir paket için gereklidir{else}{#$dependentPackages|count} Paketler doğrudan ya da dolaylı olarak bu pakete bağımlıdır{/if}.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[Yükleme klasörü:]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[Kimlik:]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[Yüklenmiş örnek:]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[Üst Paket:]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[Özellikler]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[Gerekli Paketler]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[Bu paket {if $requiredPackages|count == 1}diğer bir pakete{else}{#$requiredPackages|count} pakete{/if} gereksinim duymaktadır.]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[Ana Sayfa:]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[Yüklenmiş sürüm:]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[Güncelleme paketleri]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[Güncelleme sunucusu ile kimlik doğrulama]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[Bağlantı verisi]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[Kullanıcı adı ve şifre kabul edilmedi.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[Şifre]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[Lütfen kimlik doğrulama için gerekli olan bir şifre giriniz.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[Kullanıcı adı]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[Lütfen kimlik doğrulama için gerekli olan bir kullanıcı adı giriniz.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[Kullanıcı girişi]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[Sunucu mesajı]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[Sunucu adı]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[Kullanıcı verisini kalıcı olarak kaydet]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[Girilen kullanıcı verisi kalıcı olarak kaydedilecek, böylece daha sonra aynı veriyi tekrar girmenize gerek kalmayacak.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[Adres]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[Yüklenmiş sürüm]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[Bir hata oluştu: ]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[{$package} paketinin indirimi başarısız oldu.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[Paket listesi indirilmeye çalışılırken bir hata gözlendi.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[Belirtilen {if $excludedPackages|count == 1}çakışma{else}çakışmalar{/if} gözlendi:]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[Yüklenmiş &quot;{$excludedPackage.existingPackageName}&quot; paketi &quot;{$excludedPackage.packageName}&quot; adlı ve {$excludedPackage.packageVersion} sürümlü paketle uyumlu değil.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[&quot;{$excludedPackage.packageName}&quot; adlı ve {$excludedPackage.packageVersion} sürümlü paket yüklenmiş olan &quot;{$excludedPackage.existingPackageName}&quot; adlı paketle uyumlu değil.]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} yüklendi]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[Şu anda herhangi bir güncelleme bulunmuyor.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[Herhangi bir güncelleme seçmediniz.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[Seçenekler]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[Paket yüklenmiş ve benzeri yok. Bu nedenle başka bir zaman tekrar yüklenemez.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[Paket yükle]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[Başka bir paket yükle (paket zaten {#$package.instances} defa{if $package.instances > 1}{/if} yüklenmiş)]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[Yüklenmiş paketi güncelle {$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} sürüm {$updatableInstance.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[Paketleri ara]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[Yazar]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[Bunu ara ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[Benzeri olmayan yüklenmiş paketleri gizle]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[Paket adı]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[Paket adı ve tanımı]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[Güncelleme sunucusu]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[Tüm güncelleme sunucularını ara]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[Paket türü]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[Diğer paketler]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[Yüklenmiş paketler için eklenti]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[Tek uygulama]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[Tüm paketleri seç]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} {$package.fromversion}, {$package.toVersion} paketine güncellendi]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[Yeni sürüm]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[Belirtilen güncelleme paketleri ve yükleme işlemleri gerçekleştirildi:]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[&quot;{$sessionLog->username}&quot; giriş yapılmış oturumunun işlemleri]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[Toplam{#$items} girişli işlem{if $items != 1}{/if}]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[İşlemler]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[Sınıf adı]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP adresi]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[Son işlem]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[Paket]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[Yöntem]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[Kimlik]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[Kimlik]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[Tarih]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[Kullanıcı aracı]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[Giriş yapılan oturumlar]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[Toplam {#$items} girişli oturum{if $items != 1}{/if}]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[Sunucu ekle]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[Sunucu başarıyla eklendi.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[Sunucu verisi]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[Sunucuyu sil]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[Sunucu başarıyla silindi.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[Bu sunucuyu silmeyi gerçekten istiyor musunuz?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[Etkisizleştir]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[Sunucu düzenle]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[Değişiklikleriniz başarıyla kaydedildi.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[Etkinleştir]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[Hata mesajları]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[Şifre]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[Lütfen kimlik doğrulaması için gerekli olan şifreyi giriniz (isteğe bağlı).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[Kullanıcı adı]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[Lütfen kimlik doğrulaması için kullanılacak olan bir kullanıcı adı giriniz (isteğe bağlı).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[Son defa bağlanılmaya çalışılırken belirtilen hata oluştu:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[{#$items} sunucu uygun]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[Sunucu kimligi]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[Paketler]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[Adres]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[Lütfen bir paket sunucusu adresi giriniz.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[Girilen adres geçersiz.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[Durum]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[Son erişim]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[Uygun güncelleme sunucusu]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[Uygun güncelleme sunucusu bulunmamakta.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[Yeni kullanıcı ekle]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[Kullanıcı ayrıntıları]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[Yeni kullanıcı başarıyla kaydedildi.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[Grup ataması]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[Belirtilen kullanıcıları seçilen gruplara ata]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[Kullanıcılar seçtiğiniz gruplara başarıyla atandı.]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[Grup ataması]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[E-posta adreslerini dışarı aktar]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[Bir e-posta gönder]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[Kullanıcıyı sil]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[Herhangi bir kullanıcı silinmedi.]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[{if $deletedUsers == 1}Kullanıcı {else}{#$deletedUsers} Kullanıcılar{/if} başarıyla silindi.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[Bu kullanıcıyı silmek istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[Seçilen kullanıcıları silmek istediğinizden emin misiniz?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[Kullanıcıyı düzenle]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[Bu kullanıcı için yapılan değişiklikler başarıyla kaydedildi.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[Şu anda kendi kullanıcı hesabınızı düzenliyorsunuz. Bu kullanıcı grubunun erişim haklarını değiştirmek sizi Yönetim Kontrol Paneli dışında bırakabilir. Lütfen dikkatli olunuz!]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[E-posta adreslerini dışarı aktar]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[Dışarı aktarılacak dosya biçimi]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV (<em>Character Separated Values</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML (<em>Extensible Markup Language</em>)]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[Dışarı aktarma seçenekleri]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[Belirtilen kullanıcıların e-posta adreslerini dışarı aktar]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[Adresleri belirtilen öğeyle ayırarak ]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Adresleri belirtilen öğeyle çevreleyerek ]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[Grup üyeliği]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[Seçilen kullanıcı gruplarına üye olmayan kullanıcıları bul.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[Kullanıcılar]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[Tüm kullanıcılar]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[Toplam {#$items} kullanıcı{if $items > 1}{/if}]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 kullanıcı seçildi" : this.count+" kullanıcı seçildi"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[Kullanıcıların toplu işlemi]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[İşlem]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[Durum]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[Seçilen işlem {#$affectedUsers} kullanıcılar üzerinde başarıyla gerçekleştirildi.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[Toplu işlem belirtilen görevleri <strong>ilave bir güvenlik bildirimi olmadan</strong> aynı duruma sahip tüm kullanıcılara uygulayacaktır. Toplu işlem çok performans duyarlı olabilir bu nedenle bu işlem forum çevrimdışıyken uygulanmalıdır. İçeriğinizin doğru görüntülenmesi için sayaçları da güncellemelisiniz. İşlemler geri alınamaz bu nedenle bu işlevi kullanırken çok dikkatli olunuz.]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[Kullanıcı ara]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[Arama ölçütü]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[Genel arama ölçütü]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profil arama ölçütü]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[Görünüm]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[Sütun]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[Diğer]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[Profil]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[Genel]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[Sayfa başına kullanıcılar]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[Sıralama]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[Hiçbir kullanıcı bulunamadı.]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[Aramanız {if $items == 1}bir sonuç verdi{else}{#$items} sonuç verdi{/if}.]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[Sonuçlar içinde ara]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[Bir e-posta gönder]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[Tüm kullanıcılara e-posta]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[E-postayı HTML olarak gönder]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[Gönderen]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>Buraya gönderenin e-posta adresini belirtilen biçimde girebilirsiniz:</p>
+<p style="text-align: center; line-height: 2em;"><code>{if MAIL_USE_FORMATTED_ADDRESS}Gönderenin adı &lt;email@sender.tld&gt;{else}email@sender.tld{/if}</code></p>
+<p>Eğer Sistem -> Seçenekler -> E-posta altındaki bölümü tamamen doldurduysanız bu alan otomatik olarak doldurulacaktır. Eğer e-postaları SMTP kullanarak gönderiyorsanız aynı zamanda gönderenin e-posta adresi de sunucu tarafından kabul edilmiş olmalıdır.</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[Tüm grup üyelerine e-posta gönder]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[Belirtilen kullanıcı gruplarının üyelerine e-posta gönder:]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-posta]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[Belirtilen kullanıcılara e-posta gönder:]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[Konu]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[Bu bölüme e-postanın konusunu giriniz.]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[Mesaj]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[Bu bölüme kullanıcılarınıza göndermek istediğiniz mesajı yazınız.]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[Hoş Geldiniz {$this->user->username}.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[Geçerli İşlem]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[Lütfen işlem başarıyla tamamlanana kadar bu tarayıcı penceresini açık bırakın. Başka bir tarayıcı penceresi kullanarak yönetici alanınıza girmeye ÇALIŞMAYIN bunu yapmak o anki işleminize zarar verebilir.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[İşlem başarıyla tamamlandı]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[İşlem gerçekleştiriliyor ...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% tamamlandı]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[İşlem gerçekleştiriliyor ...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; Geri]]></item>
+               <item name="wcf.global.button.close"><![CDATA[Kapat]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[Sil]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[Bu öğeyi gerçekten silmek istiyor musunuz?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[Tamamen sil]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[Düzenle]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[Editör]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[Seç]]></item>
+               <item name="wcf.global.button.next"><![CDATA[İleri &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[Önizleme]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[Sıfırla]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[Onayla]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[Seçimi Kaldır]]></item>
+               <item name="wcf.global.date.day"><![CDATA[Gün]]></item>
+               <item name="wcf.global.date.days"><![CDATA[Gün]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[Saat]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[Saat]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[Dakika]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[Dakika]]></item>
+               <item name="wcf.global.date.month"><![CDATA[Ay]]></item>
+               <item name="wcf.global.date.months"><![CDATA[Ay]]></item>
+               <item name="wcf.global.date.second"><![CDATA[Saniye]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[Saniye]]></item>
+               <item name="wcf.global.date.week"><![CDATA[Hafta]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[Hafta]]></item>
+               <item name="wcf.global.date.year"><![CDATA[Yıl]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[Yıl belirtmek isteğe bağlıdır.]]></item>
+               <item name="wcf.global.date.years"><![CDATA[Yıl]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>\B\u\g\ü\n</b>, g:ia]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[\D\ü\n, g:ia]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[day-month-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[Varsayılan]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[Son sayfaya geri dön]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[Lütfen bu alan için gerekli olan bilgiyi girin.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[Dosya bulunamadı.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[Erişmeye çalıştığınız bağlantı artık ulaşılabilir değil ya da geçersiz.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[Bu sayfaya girmenize izin verilmemektedir. Bu sayfaya girmek için gerekli erişim haklarınız bulunmamaktadır.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[Bu sayfaya giriş izniniz bulunmamaktadır.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[Hata mesajı]]></item>
+               <item name="wcf.global.form.error"><![CDATA[Girdiğiniz veri geçersiz. Lütfen işaretlenen alanlarda bulunan verdiğiniz bilgileri tekrar kontrol ediniz.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arapça]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosnaca]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Çekçe]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danimarkaca]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Almanca]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Almanca (Gayri resmi)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Yunanca]]></item>
+               <item name="wcf.global.language.en"><![CDATA[İngilizce]]></item>
+               <item name="wcf.global.language.es"><![CDATA[İspanyolca]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Farsça]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Fince]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Fransızca]]></item>
+               <item name="wcf.global.language.he"><![CDATA[İbranice]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Hırvatça]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Macarca]]></item>
+               <item name="wcf.global.language.it"><![CDATA[İtalyanca]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japonca]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Korece]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Felemenkçe]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norveççe]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Lehçe]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portekizce]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portekizce (Brezilya)]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Romence]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Rusça]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovakça]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Sırpça]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[İsveççe]]></item>
+               <item name="wcf.global.language.th"><![CDATA[Thai]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Türkçe]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Çince (Basitleştirilmiş)]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Çince (Geleneksel)]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[en_US]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[english]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[Çoklu öğeler &quot;Ctrl/Shift&quot; (Windows) ya da &quot;Command&quot; (Mac OS) anahtarlarına basılı tutulup, gerekli öğeler tıklanarak seçilebilir.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[Sonraki sayfaya git]]></item>
+               <item name="wcf.global.page.next"><![CDATA[Sonraki sayfa]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[Önceki sayfa]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab&reg; Community Framework&trade;]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[Yönlendirme]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[Eğer otomatik yönlendirme çalışmıyorsa lütfen buraya tıklayın!]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[Sayfanın en üstüne git]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[Tam eşleşme]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[M jS Y, g:ia]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[Gezintiyi geç]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[artan]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[azalan]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Resim " + (this.currentIndex + 1) + "  " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[Kapat]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[Sadece bu resmi göster (resim göstericisinden çıkar)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[Sonraki resim]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[Slayt gösterisini durdur]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[Slayt gösterisi başlat (her beş saniyede resim değiştirir)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[Önceki resim]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(UTC) Belfast, Kazablanka, Dublin, Edinburgh, Kanarya Adaları, Lizbon, Londra, Monrovia, Ouagadougou, Reykjavik]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(UTC+01:00) Amsterdam, Berlin, Bern, Brüksel, Copenhagen, Madrid, Paris, Prag, Roma, Saraybosna, Stockholm, Tunus, Varşova, Viyana]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(UTC+02:00) Atina, Beyrut, Bükreş, Helsinki, İstanbul, Kudüs, Kahire, Cape Town, Khartoum, Kiev, Minsk, Sofya]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(UTC+03:00) Addis Ababa, Antananarivo, Bağdat, Dodoma, Kampala, Kuveyt, Mogadishu, Moskova, Nairobi, Riyad]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(UTC+03:30) Tahran]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(UTC+04:00) Abu Dhabi, Bakü, Dubai, Erivan, Muscat, Reunion, Tiflis]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(UTC+04:30) Kabil]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(UTC+05:00) Aşgabat, Bishkek, Duşanbe, İslamabad, Yekaterinburg, Karaçi, Maldiv Adaları, Taşkent]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(UTC+05:30) Chennai, Colombo, Kalküta, Bombay,Yeni Delhi]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(UTC+05:45) Kathmandu]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(UTC+06:00) Almaata, Astana, Dhaka, Novosibirsk]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(UTC+06:30) Cocos (Keeling) Adaları, Yangon]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(UTC+07:00) Bangok, Hanoi, Jakarta, Phnom Penh, Krasnoyarsk, Vientiane]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(UTC+08:00) Hong Kong, Irkutsk, Kuala Lumpur, Manila, Pekin, Perth, Singapur, Taipei, Ulan Batur]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(UTC+08:45) Eucla (Batı Avustralya)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(UTC+09:00) Dili, Yakutsk, Osaka, Pyongyang, Sapporo, Seul, Tokyo]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(UTC+09:30) Adelaide, Darvin]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(UTC+10:00) Brisbane, Canberra, Guam, Hobart, Melbourne, Port Moresby, Sidney, Vladivostok]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(UTC+10:30) Lord Howe Adası (Avustralya)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(UTC+11:00) Magadan, Yeni Kaledonya, Solomon Adaları]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(UTC+11:30) Norfolk Adası]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(UTC+12:00) Auckland, Güney Tarawa, Fiji, Kamçatka, Marshall Adaları, Wellington]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(UTC+12:45) Chatham Adaları (Yeni Zelanda)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(UTC+13:00) Nuku'alofa, Phoenix Adaları]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(UTC+14:00) Line Adaları, Christmas Adası]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(UTC-01:00) Azores, Cape Verde Adaları]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(UTC-02:00) Orta Atlantik]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(UTC-03:00) Bras&iacute;lia, Buenos Aires, Cayenne, Georgetown, Greenland, Montevideo]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(UTC-03:30) Newfoundland]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(UTC-04:00) Atlantik Zamanı (Kanada), Asunci&oacute;n, La Paz, Port-of-Spain, Santiago]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(UTC-04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(UTC-05:00) Doğu Zamanı (ABD &amp; Kanada), Bogot&aacute;, Lima, San Francisco de Quito]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(UTC-06:00) Merkez Zamanı (ABD &amp; Kanada), Orta Amerika, Mexico City]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(UTC-07:00) Mountain Zamanı (ABD &amp; Kanada), Chihuahua, Mazatlan]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(UTC-08:00) Pasifik Zamanı (ABD &amp; Kanada), Tijuana]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(UTC-09:00) Anchorage (Alaska)]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(UTC-09:30) French Polynesia]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(UTC-10:00) Cook Adaları, Havayi]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(UTC-11:00) Midway Adaları, Samoa]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(UTC-12:00) Enewetak, Kwajalein]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[Sayfa {#$pageNo}]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[E-posta Adresi Doğrulama]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[Şifre Doğrulama]]></item>
+               <item name="wcf.user.email"><![CDATA[E-posta adresi]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[Girilen e-posta adresi ve doğrulama e-posta adresi aynı değil.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[Girilen şifre ve doğrulama şifresi aynı değil.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[Girdiğiniz e-posta adresi başka bir kullanıcı tarafından kullanılmakta.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[Girdiğiniz e-posta adresi geçersiz.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[Şifre doğru değil.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[&quot;{$username}&quot; kullanıcı adı bulunamadı.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[Girdiğiniz kullanıcı adı daha önce başkası tarafından alınmış.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[Girdiğiniz kullanıcı adı geçersiz.]]></item>
+               <item name="wcf.user.language"><![CDATA[Dil]]></item>
+               <item name="wcf.user.language.description"><![CDATA[Lütfen kullanıcı arayüz dilini seçiniz!]]></item>
+               <item name="wcf.user.logout"><![CDATA[Çıkış]]></item>
+               <item name="wcf.user.password"><![CDATA[Şifre]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[Kayıt tarihi]]></item>
+               <item name="wcf.user.userID"><![CDATA[Kullanıcı Kimliği]]></item>
+               <item name="wcf.user.username"><![CDATA[Kullanıcı Adı]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[Belirtilen dillerde içeriği göster.]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[Görüntülenmesini isteğiniz içerik dillerini bu bölümde seçiniz.]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[Girdiğiniz bilgi geçersiz.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/zh-CN.xml b/wcfsetup/install/lang/zh-CN.xml
new file mode 100644 (file)
index 0000000..298f14c
--- /dev/null
@@ -0,0 +1,813 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="zh-CN">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[系统设置]]></item>
+               <item name="wcf.acp.help"><![CDATA[帮助]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[显示所有帮助信息]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[隐藏所有帮助信息]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[交互式帮助]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[更改模块]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[高级搜索 ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[网站地图]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[清空缓存]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[缓存已成功清空.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[你确认要清空缓存?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[缓存数据]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[文件]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[大小]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[源]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[版本]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[缓存]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[最后更新]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[文件名]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[文件权限]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[文件大小]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[添加用户组]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[权限]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[用户组添加成功.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[管理员]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[常规设置]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[删除用户组]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[用户组删除成功.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[你确认删除用户组?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[编辑用户组]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[编辑保存成功.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[你当前是系统管理组的成员, 更改该用户组成员权限可能导致你无法正常使用系统设置功能, 请小心操作!]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Everyone]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[编号]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[用户组名]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[输入该用户组的名称.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[游客]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[用户组]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[{#$items} 个用户组]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[会员数]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[版主]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[进入系统设置?]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[启用该选项可以赋予该用户组成员进入系统设置的权限, 进入系统设置后台后, 根据权限不同, 该组成员可以进行不同的管理操作.]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[查看用户私有选项]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[该组成员是否可以查看用户私有选项.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[修改系统设置?]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[启用该选项, 该用户组成员可以修改系统设置, 例如: 开启/关闭论坛.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[查看系统日志]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[该组成员是否可以查看系统日志.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[编辑升级服务器]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[该用户组成员是否可以编辑升级服务器.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[安装模块]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[该用户组成员是否可以安装模块.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[删除模块]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[该用户组成员是否可以删除模块.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[升级模块]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[该用户组成员是否可以升级模块.]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[编辑用户组权限]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[该组成员可以编辑下列用户组的权限. 例如, 你可以在此设置该组成员是否有权限编辑自身数据.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[添加用户组]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[该用户组成员是否可以添加用户组.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[添加用户]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[该组成员是否可以添加新用户. 如果 "编辑用户组权限" 启用, 则当添加用户的时候, "编辑用户组权限" 的选项也可以被赋值.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[删除用户组]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[该用户组成员是否可以删除用户组.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[删除用户]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[该用户组成员是否可以删除用户.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[编辑用户组]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[该用户组成员是否可以编辑用户组.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[编辑用户E-Mail]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[该用户组成员是否可以编辑用户E-Mail.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[编辑用户密码]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[该用户组成员是否可以编辑用户密码.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[编辑用户]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[该用户组成员是否可以编辑用户.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[给用户发 E-Mails]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[该用户组成员是否可以查看其他会员的 E-Mail 并给他们发邮件.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[搜索用户]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[该用户组成员是否可以搜索用户和用户资料.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[管理权限]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[内容]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[设计]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[常规管理选项]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[论坛维护]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[系统设置]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[模块管理]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[用户功能]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[用户组管理]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[用户等级]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[版主权限]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[常规权限]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[你输入的信息无效.]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[管理团队]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[超级版主]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[注册用户]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[登录]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[登录数据]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[后台操作密码]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[再次确认后台操作密码]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[后才操作密码确认]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[出于安全原因,该页面或操作需要验证你的 "后台操作密码".每次session生效只需要验证一次.如果你忘记了"系统操作密码",你可以通过删除<em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>的方式重新设置.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA["后台操作密码" 不正确. 如果你忘记了"系统操作密码",你可以通过删除<em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>的方式重新设置.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[两次输入的密码不一致.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[密码不安全."后台操作密码"至少8位,且必须包含大小写拉丁字符、数字和特殊符合.并且不能和管理员密码相同.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[建议]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[使用建议]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[设置后台操作密码]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA["后台操作密码"是对系统操作安全保护的附加程序.你可以使用一个不同于管理员帐户密码的复杂密码,用于验证系统操作.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[自动更新]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[内容]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[设计]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[用户组]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[添加用户组]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[发邮件至用户组]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[用户组概览]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[日志和统计]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[缓存]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[论坛维护]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[选项]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[系统设置导入&amp;导出]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[论坛模块]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[检查更新]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[安装模块]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[添加模块升级服务器]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[模块升级服务器概览]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[已安装模块]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[系统]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[用户]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[添加用户]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[用户概览]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-Mail通知所有用户]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[用户]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[批量操作用户]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[搜索用户]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[屏蔽的主机名]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[输入你想要屏蔽的主机名,每行一个.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[屏蔽的IP地址]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[输入你想要屏蔽的IP地址,每行一个.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[屏蔽的 User Agents]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[输入你想要屏蔽的 User Agents, 每行一个.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache 服务器]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[输入 Memcache 服务器地址! 每行一个.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[使用持久链接]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[勾选此项则系统与 Memcache 服务器将使用持久连接.]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[缓存类型]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[请选择你想要使用的缓存类型. 有些需要特定的环境支持, 不一定能在你的服务器环境中使用.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[文件系统(默认的)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (试验性的)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[常规选项]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[缓存]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[缓存选项]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache 将经常访问到的数据在内存中管理. 这将显著的节约数据加载时间. 你可以通过这里了解更多有关Memcache 的信息:
+<ul>
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li>
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[日期时间]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[代理服务器]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[你可以为系统设置多个连接外部的代理服务器.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[邮件选项]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[传送选项]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[临时关闭论坛]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[模块开启/关闭]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[内容模块]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[显示]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[系统模块]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[用户模块]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[安全设置]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[验证码设置]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[面向公共网络的页面经常会被恶意程序或机器人波坏, 比如在很短的时间内注册大量的用户和发帖等. 你可以使用 随机验证码 的办法来对付垃圾程序. 你可以在这里了解更多有关随机验证码的信息: <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">captcha image</a> 不过你也需要注意, 盲人和视力受损的人也难以识别 随机验证码.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[屏蔽设置]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[词语屏蔽选项]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[安全设置]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessions]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[用户]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookie 作用域]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Cookie 所影响的域名。修改此选项默认值最常见的原因是,你的论坛有两个不同的网址,例如 standme.com 和 forum.standme.com. 要使用户在以两个不同的域名访问论坛时,都能保持登录状态,你需要将此选项设置为 .standme.com (注意域名需要以点开头).<br /><strong>注意:若你不能肯定,最好将此处留空。输入错误的设置会导致你无法登录论坛。</strong>]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookie 路径]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Cookie 保存的路径。如果你在同一个域名下运行了多个论坛, 便需要将它设置为每个论坛所在的目录名. 否则, 填写 / 便可以了. 请注意,此处必须以斜杠结尾, 比如“/forums/”、“/wbb3/”等. <br /><strong>注意:输入错误的设置会导致你无法登录论坛.</strong>]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Cookie 前缀]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[你可以设置你的论坛 Cookie 使用特定的前缀.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[启用夏令时]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[系统始终是否自动调整夏令/冬令时?]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[使用缓存模式储存 Session 数据]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[你确认要使用缓存模式来存储 Session 数据?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[你输入的信息无效.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[导出系统设置]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[下载导出的系统设置]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[将系统设置下载到你的计算机作为备份.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[启用媒体类型标记]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[启用该选项则允许论坛向浏览器的发送的HTTP头部请求标记文档的媒体类型为 application/xhtml+xml.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[启用 Gzip 压缩]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[选择“是”将使用 GZIP HTML 压缩输出给用户页面,这会减少带宽要求。这项功能要求客户端浏览器的支持,以及 HTTP 1.1 兼容。它会产生服务器额外的性能开销。<br />这项功能要求 ZLIB 库支持。<br />如果你已经在服务器上使用了mod_gzip,请不要打开这个选项。]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[禁用浏览器页面缓存]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[启用这个选项将限制浏览器对页面进行缓存.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[压缩等级]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[设置 GZIP 在输出时的压缩级别: 0=无压缩, 9=最大压缩比. 我们强烈推荐你使用级别 1.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[导入系统设置]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[系统设置导入成功.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[上传系统设置]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[从你的计算机上传系统设置.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[导入 &amp; 导出系统设置]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[管理员 E-Mail]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[输入你的管理员E-mail.]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Debug 日志文件路径]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[在这里输入Debug 日志文件的路径]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[发送E-Mail]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[输入用于发送邮件的 E-Mails.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[邮件作者]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[输入一个名字, 以便你的用户知道是谁给他发的邮件, 可以直接填写论坛名称.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-Mail 方式]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[选择一个邮件发送方式.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[发送签名]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[在这里可以输入一段话, 他将作为邮件签名显示在底部.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP 主机]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[输入SMTP邮件主机名.]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP 密码]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[填写SMTP 用户的密码.]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP 端口]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[输入SMTP 邮件服务器的端口.]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP 用户名]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[输入SMTP 邮件服务器的用户名]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[启用 &quot;-f&quot; 参数]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[一些 Sendmail 服务器在 PHP 发送邮件时需要“-f”参数, 如果你遇到这样的问题, 用户收不到从论坛发出的邮件, 试试打开这个选项.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[使用格式化的Email地址]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[启用该选项, 发件人和收件人的邮件地址将被格式化为 &quot;Name &lt;email@domain.tld&gt;&quot;. 的格式. 但并非所有的邮件服务器都支持该选项, 当邮件发送出现问题的时候请关闭该选项.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[启用后台操作密码]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA["后台操作密码"是对系统操作安全保护的附加程序.你可以使用一个不同于管理员帐户密码的复杂密码,用于验证系统操作.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[代理服务器(FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[用于FTP连接的代理服务器]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[代理服务器 (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[用户HTTP连接的代理服务器]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Session 作用时间]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[在这里设置用户的Session 作用时间. 单位:秒.]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[检测IP地址位数]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[选择检测Session数据中IP地址的数据位数, 数字越大则可以排除用户更换IP登陆.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[从Session中检测用户Agent]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[是否从Session数据中检测用户的Agent?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[设置修改成功.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[时区设置]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[设置你网站所在地方的时区.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[在线列表统计时间]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[统计在线列表的时间范围, 超过这个时间没有任何活动, 其用户名会从在线用户列表中删除. 单位:秒.]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[取消模块安装]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[描述]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[输入 FTP 的登录信息]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[FTP 登录信息]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[如果你的服务器开启了PHP安全模式, 则论坛模块的安装需要FTP功能的支持. 请输入该服务器的FTP用户名和密码, 此次你输入的FTP用户名和密码仅用于此次论坛模块安装而不被记录, 因此, 你安装另外的论坛模块的时候还需要再次输入该信息.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[根据你输入的FTP信息, 无法建立FTP连接, 请检查你输入的信息.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[无法创建FTP连接.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[无法登录FTP服务器.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[主机名]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[密码]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[用户名]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[安装模块]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[取消安装]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[你确认要取消模块安装?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[该模块的模块需求无法满足.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[The  模块 &quot;{$packageName}({$packageVersion})&quot; 的 {if $action == 'install'}安装{else}升级{/if}因下列模块的冲突无法完成:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} 版本 {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[下列模块的 {if $action == 'install'}安装{else}升级{/if}: &quot;{$packageName}&quot; {$packageVersion} 因冲突无法完成.]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} ({$excludingPackage.packageVersion})]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[和以下冲突模块:  &quot;{$packageName}&quot; ({$packageVersion}). 如果你继续安装, 这些模块将无法正常工作.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}被安装{else}{if $package.file|isset}在该模块中{else}不可用{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[你确认取消该模块的安装?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[通过该模块下列模块可以更新]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[选择下列模块的一个来更新它的版本, 如果你想要再次安装该模块, 请点击 &quot;{lang}wcf.global.button.next{/lang}&quot; 按钮.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[该模块已经存在于已安装模块列表中. 如果你点继续则将再安装一个该模块的副本. 如果你想要更新一个该模块的可用拷贝, 请从下面列表中选择. ]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[模块版本:]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[安装日期]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[解压模块文件时发生如下错误:]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[下列文件无法解压,请检查文件夹的写入权限.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[冲突的数据表]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[不覆盖数据表(此次安装不需再次询问).]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[覆盖数据表(此次安装不需再次询问).]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[所需变化]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[影响表]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[安装该模块时与以下数据表冲突. 请选择是否覆盖这些数据表.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[已安装模块]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[作者]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[已安装 {#$items} 个模块]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[日期]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[名称]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[模块]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[插件]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[标准程序]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[版本]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[安装附加模块]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[该模块包含以下附加模块, 请选择你要安装的模块.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[(该模块已被安装.)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[(该模块需求不能完全满足.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[文件夹]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[已有其他程序被安装在该文件夹中.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[文件夹不可用.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[文件夹不可写.]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[该文件夹已被 WoltLab Community Framework 使用. 请选择另外的文件夹.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[输入安装目录.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[模块安装完成之后的URL:]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[选择所需模块]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[当前模块需要其他模块的支持, 请选择你所需的模块.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[取消安装]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[版本: {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[安装模块]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[所选模块不是有效的安装例行.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[你给出的文件不是一个有效的模块文件.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[模块 &quot;{$package->getName()}&quot; 无法通过你给出的文件来更新.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[你给出的文件夹内无文件.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[所选模块已被安装. 模块不可被安装多次.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[上传所选文件失败.]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[选择模块文件来源]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[来自服务器]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[请输入你服务器上的模块文件路径(相对路径), 支持远程文件(http://...).]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[来自你的计算机]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[请从你的计算机选择模块文件.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[更新 &quot;{$package->getName()}&quot; 模块]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[安装系统设置菜单选项 ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[安装系统设置模板补丁 ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[安装系统设置模板 ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[安装事件监听 ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[解压模块文件包 ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[安装用户组选项 ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[安装模块语言 ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[安装模块选项 ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[解压特殊脚本 ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[安装数据...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[安装模板补丁 ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[安装模板包 ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[安装用户资料项 ...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[检查可能的冲突 ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[解压模块插件 ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[安装完成]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[安装附加模块 ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[注册模块 ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[安装模块插件 ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[安装上级模块 ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[检查需求 ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[<b>{$packageName}</b> 模块: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[移除系统设置菜单 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[移除系统设置模板补丁 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[移除系统设置模板 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[卸载事件监听 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[删除模块文件 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[移除用户组选项 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[移除模块语言 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[移除模块选项 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[移除数据条目...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[移除模板补丁 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[移除模块模板 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[移除用户资料项 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[解压模块插件 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[模块卸载完成]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[卸载附加模块 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[卸载模块插件 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[卸载模块需求 ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[更新系统设置菜单 ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[更新系统设置模板补丁 ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[更新系统设置模板 ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[更新事件监听 ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[解压模块文件包 ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[更新用户组选项 ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[更新模块语言 ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[更新模块设置 ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[解压特殊脚本 ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[更新数据内容 ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[更新模板补丁 ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[更新模块模板 ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[更新用户资料项 ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[检查可能的冲突 ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[解压模块插件 ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[模块更新完成]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[更新附加模块 ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[更新模块 ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[更新模块插件 ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[更新上级模块 ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[检查需求 ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[该模块补丁安装失败因为该补丁和模块不匹配. 因此该模块无法被安装. 请点击 &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; 按钮.]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[为下列模板打补丁失败:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Originally patched by: {$failure.packageName})<br />{/foreach}预先安装的模块补丁似乎已经无效. 你应当点击 &quot;{lang}wcf.global.button.next{/lang}&quot; 按钮继续完成升级过程.]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[该模块补丁移除失败因为源文件已经更改. 因此该模块无法被移除. 请单击 &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; 按钮.]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[移除模块]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[取消移除]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[无法移除该模块, 因为该模块被不止一个其它模块需要.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[经过最后确认, 下列模块将被卸载.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[升级模块]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[升级日期]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[作者:]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[跳转至系统设置]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[移除模块]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[移除所有模块]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[你确认移除该模块?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[升级模块]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[发布日期:]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[支持模块]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[该模块被其他 {#$dependentPackages|count} 个模块所需求.]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[该模块被其他{#$dependentPackages|count} 个模块所需求.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[安装目录:]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[标识:]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[安装实例:]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[上级模块:]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[属性]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[所需模块]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[该模块需要 {#$requiredPackages|count} 个其他模块的支持.]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[主页:]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[当前版本:]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[升级模块]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[升级服务器验证]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[连接数据]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[所给的用户名和密码无效.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[密码]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[输入模块升级服务器所需的验证密码.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[用户名]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[输入模块升级服务器所需的用户名.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[用户登录]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[服务器信息]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[服务器名]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[保存用户数据]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[你输入的用户资料将被保存, 这样你就不用在以后再每次输入这些数据了.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[地址]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[当前版本]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[发生了一个错误: ]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[模块 {$package} 下载失败.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[没有找到以下模块.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[发生如下冲突:]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[模块&quot;{$excludedPackage.existingPackageName}&quot; 和如下模块冲突:&quot; {$excludedPackage.packageName}&quot;({$excludedPackage.packageVersion}).]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[模块 &quot;{$excludedPackage.packageName}&quot;({$excludedPackage.packageVersion})和如下模块冲突: &quot;{$excludedPackage.existingPackageName}&quot; .]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} 安装成功]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[当前无可用更新.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[你未选择任何更新.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[选项]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[模块已经被安装且是独一无二的. 因此不能被再次安装.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[安装模块]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[安装另一个模块实例(该模块已经被安装了 {#$package.instances} 次)]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[升级已安装模块{$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} 版本 {$updatableInstance.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[搜索模块]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[作者]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[搜索 ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[隐藏已安装的独立模块]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[模块名]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[模块名和模块描述]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[升级服务器]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[搜索所有升级服务器]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[模块类型]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[其他模块]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[已安装模块的插件]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[标准程序]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[选择所有模块]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} 从{$package.fromversion} 升级至{$package.toVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[新版本]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[下列模块正在更新/安装:]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[&quot;{$sessionLog->username}&quot; 的登陆操作记录]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[共有 {#$items} 条操作记录]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[操作]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[类文件]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP地址]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[最后活动]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[模块]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[请求]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[时间]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[用户Agent]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[系统登陆 Sessions]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[共有 {#$items} 条系统登陆 Session]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[添加服务器]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[服务器添加成功.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[服务器数据]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[删除服务器]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[服务器删除成功.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[你确认要删除该服务器?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[禁用]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[编辑服务器]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[设置更新成功.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[启用]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[错误信息]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[密码]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[输入密码如果需要身份验证(非必需).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[用户名]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[输入用户名如果需要身份验证(非必需).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[最后一次尝试连接时发生如下错误:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[共有 {#$items}  台升级服务器]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[模块]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[URL]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[输入升级服务器的URL.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[服务器URL输入无效.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[状态]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[最近更新]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[可用升级服务器]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[当前无可用升级服务器.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[添加用户]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[用户资料]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[新用户添加成功.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[所属用户组]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[将下列用户加入所选用户组]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[用户被成功加入所选用户组.]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[所属用户组]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[导出所有 E-Mail 地址]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[发送 E-Mail]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[删除用户]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[没有用户被删除.]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[用户删除成功.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[你确认删除该用户?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[你确认删除所选用户?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[编辑用户]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[用户编辑成功.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[你现在在编辑你自己的账户. 更改你的用户权限可能导致你无法进入后台系统设置进行操作, 请慎用此功能!]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[导出 E-Mail 地址]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[导出文件格式]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[导出选项]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[导出下列用户的E-Mail 地址]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[地址分隔符]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Email 地址结束分隔符]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[用户组]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[搜索非所选用户组的用户.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[用户]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[列出所有用户]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[共有 {#$items} 位用户]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 位用户被选定" : this.count+" 位用户被选定"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[批量操作用户]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[操作]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[条件]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[所选操作对如下用户操作成功: {#$affectedUsers}.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[批量操作将对所有符合条件的用户直接生效而<strong>不会有任何安全警告</strong>. 该操作时非常占用资源的, 所以最好在论坛关闭的状态下进行操作. 操作完成后请更新论坛统计. 另外, 该操作是不可恢复的, 所以请慎重.]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[搜索用户]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[搜索条件]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[一般搜索选项]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[用户资料搜索选项]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[结果显示]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[项目]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[其他]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[资料]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[设置]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[每页用户数]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[排序]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[没有找到用户.]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[共搜索到 {#$users|count} 位用户]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[在结果中搜索]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[发送 E-Mail]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-Mail 通知所有用户]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[邮件内容使用html语言格式.]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[发送者]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>你可以用这样的格式填写发送者信息:</p><p><strong>发送者名字 &lt;发送者Email&gt;</strong></p><p>如果你在后台系统设置里的 系统 -> 选项 -> 邮件已经设置好了邮件发送选项, 这里将会自动按照已经设置好的进行发送. 如果你选择通过SMTP方式发送邮件, 那么你在这里填写的发送者邮件地址也必须被SMTP服务器接受.</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[给用户组成员发邮件]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[给下列用户组成员发送邮件]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-Mail]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[给下列用户发送E-Mail]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[主题]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[输入E-mail主题.]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[消息]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[输入邮件内容.]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[{$this->user->username}, 你好.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[当前进度]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[操作完成之前请勿关闭浏览器. 请勿再开启新窗口进入后台系统设置, 那样将可能导致当前操作失败.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[操作成功]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[操作进行中 ...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% 完成]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[操作进行中 ...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; 后退]]></item>
+               <item name="wcf.global.button.close"><![CDATA[关闭]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[删除]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[你确认删除该条目?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[彻底删除]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[编辑]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[使用高级编辑器]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[选择]]></item>
+               <item name="wcf.global.button.next"><![CDATA[下一步 &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[预览]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[重置]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[提交]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[取消选择]]></item>
+               <item name="wcf.global.date.day"><![CDATA[天]]></item>
+               <item name="wcf.global.date.days"><![CDATA[天]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[小时]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[小时]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[分钟]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[分钟]]></item>
+               <item name="wcf.global.date.month"><![CDATA[月]]></item>
+               <item name="wcf.global.date.months"><![CDATA[月]]></item>
+               <item name="wcf.global.date.second"><![CDATA[秒]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[秒]]></item>
+               <item name="wcf.global.date.week"><![CDATA[星期]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[星期]]></item>
+               <item name="wcf.global.date.year"><![CDATA[年]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[你的生日]]></item>
+               <item name="wcf.global.date.years"><![CDATA[年]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>今天</b>, g:ia]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[昨天, g:ia]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[month-day-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[默认的]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[返回上页.]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[请填写必填信息.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[无法找到文件.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[该链接无效.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[无权查看, 你没有查看此页所需的权限.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[你无权查看此页.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[错误信息]]></item>
+               <item name="wcf.global.form.error"><![CDATA[资料填写错误. 请检查表单中有标记处的信息.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[阿拉伯语]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[波斯尼亚语]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[捷克语]]></item>
+               <item name="wcf.global.language.da"><![CDATA[丹麦语]]></item>
+               <item name="wcf.global.language.de"><![CDATA[德语]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[德语 (非正式的)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[希腊语]]></item>
+               <item name="wcf.global.language.en"><![CDATA[英语]]></item>
+               <item name="wcf.global.language.es"><![CDATA[西班牙语]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[波斯语]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[芬兰语]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[法语]]></item>
+               <item name="wcf.global.language.he"><![CDATA[希伯来语]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[克罗地亚语]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[匈牙利语]]></item>
+               <item name="wcf.global.language.it"><![CDATA[意大利语]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[日语]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[韩语]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[荷兰语]]></item>
+               <item name="wcf.global.language.no"><![CDATA[挪威语]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[波兰语]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[葡萄牙语]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[葡萄牙语]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[罗马尼亚语]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[俄语]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[斯洛伐克语]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[塞尔维亚语]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[瑞典语]]></item>
+               <item name="wcf.global.language.th"><![CDATA[泰文]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[土耳其语]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[简体中文]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[繁体中文]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[zh_CN]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[chinese-simplified]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[按下&quot;Ctrl/Shift&quot;(Windows)或是&quot;Command&quot; (Mac OS) 键可以选择多个项目.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[跳转到下一页]]></item>
+               <item name="wcf.global.page.next"><![CDATA[下一页]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[上一页]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab Community Framework]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[跳转至]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[如果页面没有自动跳转,请点击这里!]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[至页面顶部]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[精确匹配]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[M jS Y, g:ia]]></item>
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e. %B %Y, %H:%M]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[跳过导航]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[升序]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[降序]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Image " + (this.currentIndex + 1) + " of " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[关闭]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[显示该图片(退出幻灯片浏览)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[后一张]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[停止幻灯片播放]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[开始幻灯片播放(5秒每张)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[前一张]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(格林尼治标准时) 西欧时间、伦敦、卡萨布兰卡]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(标准时+1:00) 中欧时间、安哥拉、利比亚]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(标准时+2:00) 东欧时间、加里宁格勒、南非]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(标准时+3:00) 巴格达、科威特、利雅得、莫斯科]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(标准时+3:30) 德黑兰]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(标准时+4:00) 阿布扎比、马斯喀特、巴库]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(标准时+4:30) 喀布尔]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(标准时+5:00) 叶卡捷琳堡、伊斯兰堡、卡拉奇]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(标准时+5:30) 孟买、加尔各答、新德里]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(标准时+05:45) 加德满都]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(标准时+6:00) 科伦波、 达卡、新亚伯利亚]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(标准时+06:30) 基林群岛, 仰光]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(标准时+7:00) 曼谷、河内、雅加达]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(标准时+8:00) 北京、佩思、新加坡、香港]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(标准时+08:45) 尤克拉 (西澳大利亚)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(标准时+9:00) 东京、汉城、大阪、雅库茨克]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(标准时+9:30) 阿德莱德、达尔文]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(标准时+10:00) 澳大利亚东部、关岛]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(标准时+10:30) 豪勋爵岛 (澳大利亚)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(标准时+11:00) 马加丹、索罗门群岛]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(标准时+11:30) 诺福克岛]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(标准时+12:00) 奥克兰、惠灵顿、堪察加半岛]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(标准时+12:45) 查塔姆群岛 (新西兰东部)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(标准时+13:00) 阿洛, 风凰岛]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(标准时+14:00) 莱恩群岛, 圣诞岛]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(标准时-1:00) 亚速尔群岛、佛得角群岛]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(标准时-2:00) 中大西洋]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(标准时-3:00) 巴西、布宜诺斯艾利斯、乔治敦]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(标准时-3:30) 纽芬兰]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(标准时-4:00) 大西洋时间(加拿大)、加拉加斯]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(标准时-04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(标准时-5:00) 东部时间(美国和加拿大)、波哥大]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(标准时-6:00) 中部时间(美国和加拿大)、墨西哥城]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(标准时-7:00) 山地时间(美国和加拿大)]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(标准时-8:00) 美国西部标准时间(美国和加拿大)]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(标准时-9:00) 阿拉斯加]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(标准时-09:30) 法属波利尼西亚]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(标准时-10:00) 夏威夷]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(标准时-11:00) 中途岛、萨摩亚群岛]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(标准时-12:00) 艾尼威多克、夸贾林环礁]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[第 {#$pageNo} 页]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[确认E-Mail 地址]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[确认密码]]></item>
+               <item name="wcf.user.email"><![CDATA[E-Mail]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[E-Mail 验证不符.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[密码验证不符.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[该 E-Mail 已存在.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[E-Mail 输入无效.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[密码错误.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[用户 &quot;{$username}&quot; 找不到.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[你输入的用户名已存在.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[用户名输入无效.]]></item>
+               <item name="wcf.user.language"><![CDATA[语言]]></item>
+               <item name="wcf.user.language.description"><![CDATA[请选择一个论坛界面语言!]]></item>
+               <item name="wcf.user.logout"><![CDATA[注销]]></item>
+               <item name="wcf.user.password"><![CDATA[密码]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[注册日期]]></item>
+               <item name="wcf.user.userID"><![CDATA[UID]]></item>
+               <item name="wcf.user.username"><![CDATA[用户名]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[显示以下语言的帖子]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[请选择一个语言, 属于该语言的帖子将会被显示.]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[信息输入无效.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/install/lang/zh-TW.xml b/wcfsetup/install/lang/zh-TW.xml
new file mode 100644 (file)
index 0000000..2c2e542
--- /dev/null
@@ -0,0 +1,813 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="zh-TW">
+       <category name="wcf.acp">
+               <item name="wcf.acp"><![CDATA[系統設置]]></item>
+               <item name="wcf.acp.help"><![CDATA[説明]]></item>
+               <item name="wcf.acp.help.complete"><![CDATA[顯示所有幫助資訊]]></item>
+               <item name="wcf.acp.help.disable"><![CDATA[隱藏所有幫助資訊]]></item>
+               <item name="wcf.acp.help.interactive"><![CDATA[互動式説明]]></item>
+               <item name="wcf.acp.packageQuickAccess"><![CDATA[更改模組]]></item>
+               <item name="wcf.acp.search.extended"><![CDATA[高級搜索 ...]]></item>
+               <item name="wcf.acp.sitemap"><![CDATA[網站地圖]]></item>
+       </category>
+       <category name="wcf.acp.cache">
+               <item name="wcf.acp.cache.button.clear"><![CDATA[清空緩存]]></item>
+               <item name="wcf.acp.cache.clear.success"><![CDATA[緩存已成功清空.]]></item>
+               <item name="wcf.acp.cache.clear.sure"><![CDATA[你確認要清空緩存?]]></item>
+               <item name="wcf.acp.cache.data"><![CDATA[緩存數據]]></item>
+               <item name="wcf.acp.cache.data.files"><![CDATA[文件]]></item>
+               <item name="wcf.acp.cache.data.size"><![CDATA[大小]]></item>
+               <item name="wcf.acp.cache.data.source"><![CDATA[源]]></item>
+               <item name="wcf.acp.cache.data.version"><![CDATA[版本]]></item>
+               <item name="wcf.acp.cache.list"><![CDATA[緩存]]></item>
+               <item name="wcf.acp.cache.list.mtime"><![CDATA[最後更新]]></item>
+               <item name="wcf.acp.cache.list.name"><![CDATA[檔案名]]></item>
+               <item name="wcf.acp.cache.list.perm"><![CDATA[文件許可權]]></item>
+               <item name="wcf.acp.cache.list.size"><![CDATA[文件大小]]></item>
+       </category>
+       <category name="wcf.acp.group">
+               <item name="wcf.acp.group.add"><![CDATA[添加用戶組]]></item>
+               <item name="wcf.acp.group.add.permissions"><![CDATA[許可權]]></item>
+               <item name="wcf.acp.group.add.success"><![CDATA[用戶組添加成功.]]></item>
+               <item name="wcf.acp.group.administrators"><![CDATA[管理員]]></item>
+               <item name="wcf.acp.group.data"><![CDATA[常規設置]]></item>
+               <item name="wcf.acp.group.delete"><![CDATA[刪除用戶組]]></item>
+               <item name="wcf.acp.group.delete.success"><![CDATA[用戶組刪除成功.]]></item>
+               <item name="wcf.acp.group.delete.sure"><![CDATA[你確認刪除用戶組?]]></item>
+               <item name="wcf.acp.group.edit"><![CDATA[編輯用戶組]]></item>
+               <item name="wcf.acp.group.edit.success"><![CDATA[編輯保存成功.]]></item>
+               <item name="wcf.acp.group.edit.warning.selfIsMember"><![CDATA[你當前是系統管理組的成員, 更改該用戶組成員許可權可能導致你無法正常使用系統設置功能, 請小心操作!]]></item>
+               <item name="wcf.acp.group.everyone"><![CDATA[Everyone]]></item>
+               <item name="wcf.acp.group.groupID"><![CDATA[編號]]></item>
+               <item name="wcf.acp.group.groupName"><![CDATA[用戶組名]]></item>
+               <item name="wcf.acp.group.groupName.description"><![CDATA[輸入該用戶組的名稱.]]></item>
+               <item name="wcf.acp.group.guests"><![CDATA[遊客]]></item>
+               <item name="wcf.acp.group.list"><![CDATA[用戶組]]></item>
+               <item name="wcf.acp.group.list.data"><![CDATA[{#$items} 個用戶組]]></item>
+               <item name="wcf.acp.group.members"><![CDATA[會員數]]></item>
+               <item name="wcf.acp.group.moderators"><![CDATA[版主]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp"><![CDATA[進入系統設置?]]></item>
+               <item name="wcf.acp.group.option.admin.general.canUseAcp.description"><![CDATA[啟用該選項可以賦予該用戶組成員進入系統設置的許可權, 進入系統設置後臺後, 根據許可權不同, 該組成員可以進行不同的管理操作.]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions"><![CDATA[查看用戶私有選項]]></item>
+               <item name="wcf.acp.group.option.admin.general.canViewPrivateUserOptions.description"><![CDATA[該組成員是否可以查看用戶私有選項.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption"><![CDATA[修改系統設置?]]></item>
+               <item name="wcf.acp.group.option.admin.system.canEditOption.description"><![CDATA[啟用該選項, 該用戶組成員可以修改系統設置, 例如: 開啟/關閉論壇.]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog"><![CDATA[查看系統日誌]]></item>
+               <item name="wcf.acp.group.option.admin.system.canViewLog.description"><![CDATA[該組成員是否可以查看系統日誌.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer"><![CDATA[編輯升級伺服器]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canEditServer.description"><![CDATA[該用戶組成員是否可以編輯升級伺服器.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage"><![CDATA[安裝模組]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canInstallPackage.description"><![CDATA[該用戶組成員是否可以安裝模組.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage"><![CDATA[刪除模組]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUninstallPackage.description"><![CDATA[該用戶組成員是否可以刪除模組.]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage"><![CDATA[升級模組]]></item>
+               <item name="wcf.acp.group.option.admin.system.package.canUpdatePackage.description"><![CDATA[該用戶組成員是否可以升級模組.]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups"><![CDATA[編輯用戶組許可權]]></item>
+               <item name="wcf.acp.group.option.admin.user.accessibleGroups.description"><![CDATA[該組成員可以編輯下列用戶組的許可權. 例如, 你可以在此設置該組成員是否有許可權編輯自身資料.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup"><![CDATA[添加用戶組]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddGroup.description"><![CDATA[該用戶組成員是否可以添加用戶組.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser"><![CDATA[添加用戶]]></item>
+               <item name="wcf.acp.group.option.admin.user.canAddUser.description"><![CDATA[該組成員是否可以添加新用戶. 如果 "編輯用戶組許可權" 啟用, 則當添加用戶的時候, "編輯用戶組許可權" 的選項也可以被賦值.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup"><![CDATA[刪除用戶組]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteGroup.description"><![CDATA[該用戶組成員是否可以刪除用戶組.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser"><![CDATA[刪除用戶]]></item>
+               <item name="wcf.acp.group.option.admin.user.canDeleteUser.description"><![CDATA[該用戶組成員是否可以刪除用戶.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup"><![CDATA[編輯用戶組]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditGroup.description"><![CDATA[該用戶組成員是否可以編輯用戶組.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress"><![CDATA[編輯用戶E-Mail]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditMailAddress.description"><![CDATA[該用戶組成員是否可以編輯用戶E-Mail.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword"><![CDATA[編輯用戶密碼]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditPassword.description"><![CDATA[該用戶組成員是否可以編輯用戶密碼.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser"><![CDATA[編輯用戶]]></item>
+               <item name="wcf.acp.group.option.admin.user.canEditUser.description"><![CDATA[該用戶組成員是否可以編輯用戶.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser"><![CDATA[給用戶發 E-Mails]]></item>
+               <item name="wcf.acp.group.option.admin.user.canMailUser.description"><![CDATA[該用戶組成員是否可以查看其他會員的 E-Mail 並給他們發郵件.]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser"><![CDATA[搜索用戶]]></item>
+               <item name="wcf.acp.group.option.admin.user.canSearchUser.description"><![CDATA[該用戶組成員是否可以搜索用戶和用戶資料.]]></item>
+               <item name="wcf.acp.group.option.category.admin"><![CDATA[管理許可權]]></item>
+               <item name="wcf.acp.group.option.category.admin.content"><![CDATA[內容]]></item>
+               <item name="wcf.acp.group.option.category.admin.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.display"><![CDATA[設計]]></item>
+               <item name="wcf.acp.group.option.category.admin.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.general"><![CDATA[常規管理選項]]></item>
+               <item name="wcf.acp.group.option.category.admin.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance"><![CDATA[論壇維護]]></item>
+               <item name="wcf.acp.group.option.category.admin.maintenance.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system"><![CDATA[系統設置]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package"><![CDATA[模組管理]]></item>
+               <item name="wcf.acp.group.option.category.admin.system.package.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user"><![CDATA[用戶功能]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group"><![CDATA[用戶組管理]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.group.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user"><![CDATA[用戶等級]]></item>
+               <item name="wcf.acp.group.option.category.admin.user.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.mod"><![CDATA[版主許可權]]></item>
+               <item name="wcf.acp.group.option.category.mod.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.category.user"><![CDATA[常規許可權]]></item>
+               <item name="wcf.acp.group.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.group.option.error.validationFailed"><![CDATA[你輸入的資訊無效.]]></item>
+               <item name="wcf.acp.group.showMembers"><![CDATA[管理團隊]]></item>
+               <item name="wcf.acp.group.superModerators"><![CDATA[超級版主]]></item>
+               <item name="wcf.acp.group.users"><![CDATA[註冊用戶]]></item>
+       </category>
+       <category name="wcf.acp.login">
+               <item name="wcf.acp.login"><![CDATA[登錄]]></item>
+               <item name="wcf.acp.login.data"><![CDATA[登錄數據]]></item>
+       </category>
+       <category name="wcf.acp.masterPassword">
+               <item name="wcf.acp.masterPassword"><![CDATA[後臺操作密碼]]></item>
+               <item name="wcf.acp.masterPassword.confirm"><![CDATA[再次確認後臺操作密碼]]></item>
+               <item name="wcf.acp.masterPassword.enter"><![CDATA[後才操作密碼確認]]></item>
+               <item name="wcf.acp.masterPassword.enter.description"><![CDATA[出於安全原因,該頁面或操作需要驗證你的 "後臺操作密碼".每次session生效只需要驗證一次.如果你忘記了"系統操作密碼",你可以通過刪除<em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>的方式重新設置.]]></item>
+               <item name="wcf.acp.masterPassword.error.invalid"><![CDATA["後臺操作密碼" 不正確. 如果你忘記了"系統操作密碼",你可以通過刪除<em>{@RELATIVE_WCF_DIR}acp/masterPassword.inc.php</em>的方式重新設置.]]></item>
+               <item name="wcf.acp.masterPassword.error.notEqual"><![CDATA[兩次輸入的密碼不一致.]]></item>
+               <item name="wcf.acp.masterPassword.error.notSecure"><![CDATA[密碼不安全."後臺操作密碼"至少8位元,且必須包含大小寫拉丁字元、數位和特殊符合.並且不能和管理員密碼相同.]]></item>
+               <item name="wcf.acp.masterPassword.example"><![CDATA[建議]]></item>
+               <item name="wcf.acp.masterPassword.example.set"><![CDATA[使用建議]]></item>
+               <item name="wcf.acp.masterPassword.init"><![CDATA[設置後臺操作密碼]]></item>
+               <item name="wcf.acp.masterPassword.init.description"><![CDATA["後臺操作密碼"是對系統操作安全保護的附加程式.你可以使用一個不同于管理員帳戶密碼的複雜密碼,用於驗證系統操作.]]></item>
+       </category>
+       <category name="wcf.acp.menu">
+               <item name="wcf.acp.menu.link.autoupdate"><![CDATA[自動更新]]></item>
+               <item name="wcf.acp.menu.link.content"><![CDATA[內容]]></item>
+               <item name="wcf.acp.menu.link.display"><![CDATA[設計]]></item>
+               <item name="wcf.acp.menu.link.group"><![CDATA[用戶組]]></item>
+               <item name="wcf.acp.menu.link.group.add"><![CDATA[添加用戶組]]></item>
+               <item name="wcf.acp.menu.link.group.mail"><![CDATA[發郵件至用戶組]]></item>
+               <item name="wcf.acp.menu.link.group.view"><![CDATA[用戶組概覽]]></item>
+               <item name="wcf.acp.menu.link.log"><![CDATA[日誌和統計]]></item>
+               <item name="wcf.acp.menu.link.log.cache"><![CDATA[緩存]]></item>
+               <item name="wcf.acp.menu.link.log.session"><![CDATA[Session]]></item>
+               <item name="wcf.acp.menu.link.maintenance"><![CDATA[論壇維護]]></item>
+               <item name="wcf.acp.menu.link.option"><![CDATA[選項]]></item>
+               <item name="wcf.acp.menu.link.option.importAndExport"><![CDATA[系統設置導入&amp;導出]]></item>
+               <item name="wcf.acp.menu.link.package"><![CDATA[論壇模組]]></item>
+               <item name="wcf.acp.menu.link.package.database"><![CDATA[檢查更新]]></item>
+               <item name="wcf.acp.menu.link.package.install"><![CDATA[安裝模組]]></item>
+               <item name="wcf.acp.menu.link.package.server.add"><![CDATA[添加模組升級伺服器]]></item>
+               <item name="wcf.acp.menu.link.package.server.view"><![CDATA[模組升級伺服器概覽]]></item>
+               <item name="wcf.acp.menu.link.package.view"><![CDATA[已安裝模組]]></item>
+               <item name="wcf.acp.menu.link.system"><![CDATA[系統]]></item>
+               <item name="wcf.acp.menu.link.user"><![CDATA[用戶]]></item>
+               <item name="wcf.acp.menu.link.user.add"><![CDATA[添加用戶]]></item>
+               <item name="wcf.acp.menu.link.user.list"><![CDATA[用戶概覽]]></item>
+               <item name="wcf.acp.menu.link.user.mail"><![CDATA[E-Mail通知所有用戶]]></item>
+               <item name="wcf.acp.menu.link.user.management"><![CDATA[用戶]]></item>
+               <item name="wcf.acp.menu.link.user.massProcessing"><![CDATA[批量操作用戶]]></item>
+               <item name="wcf.acp.menu.link.user.search"><![CDATA[搜索用戶]]></item>
+       </category>
+       <category name="wcf.acp.option">
+               <item name="wcf.acp.option.blacklist_hostnames"><![CDATA[遮罩的主機名]]></item>
+               <item name="wcf.acp.option.blacklist_hostnames.description"><![CDATA[輸入你想要遮罩的主機名,每行一個.]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses"><![CDATA[遮罩的IP地址]]></item>
+               <item name="wcf.acp.option.blacklist_ip_addresses.description"><![CDATA[輸入你想要遮罩的IP位址,每行一個.]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents"><![CDATA[遮罩的 User Agents]]></item>
+               <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[輸入你想要遮罩的 User Agents, 每行一個.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache 伺服器]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[輸入 Memcache 伺服器位址! 每行一個.]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[使用持久鏈結]]></item>
+               <item name="wcf.acp.option.cache_source_memcache_use_pconnect.description"><![CDATA[勾選此項則系統與 Memcache 伺服器將使用持久連接.]]></item>
+               <item name="wcf.acp.option.cache_source_type"><![CDATA[緩存類型]]></item>
+               <item name="wcf.acp.option.cache_source_type.description"><![CDATA[請選擇你想要使用的緩存類型. 有些需要特定的環境支援, 不一定能在你的伺服器環境中使用.]]></item>
+               <item name="wcf.acp.option.cache_source_type.disk"><![CDATA[檔系統(默認的)]]></item>
+               <item name="wcf.acp.option.cache_source_type.memcache"><![CDATA[Memcache (試驗性的)]]></item>
+               <item name="wcf.acp.option.category.general"><![CDATA[常規選項]]></item>
+               <item name="wcf.acp.option.category.general.cache"><![CDATA[緩存]]></item>
+               <item name="wcf.acp.option.category.general.cache.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.general"><![CDATA[緩存選項]]></item>
+               <item name="wcf.acp.option.category.general.cache.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache"><![CDATA[Memcache]]></item>
+               <item name="wcf.acp.option.category.general.cache.memcache.description"><![CDATA[Memcache 將經常訪問到的資料在記憶體中管理. 這將顯著的節約資料載入時間. 你可以通過這裏瞭解更多有關Memcache 的資訊: 
+<ul> 
+       <li><a href="http://www.danga.com/memcached/">www.danga.com/memcached/</a></li> 
+</ul>]]></item>
+               <item name="wcf.acp.option.category.general.date"><![CDATA[日期時間]]></item>
+               <item name="wcf.acp.option.category.general.date.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie"><![CDATA[Cookies]]></item>
+               <item name="wcf.acp.option.category.general.http.cookie.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.http"><![CDATA[HTTP]]></item>
+               <item name="wcf.acp.option.category.general.http.http.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy"><![CDATA[代理伺服器]]></item>
+               <item name="wcf.acp.option.category.general.http.proxy.description"><![CDATA[你可以為系統設置多個連接外部的代理伺服器.]]></item>
+               <item name="wcf.acp.option.category.general.mail"><![CDATA[E-mails]]></item>
+               <item name="wcf.acp.option.category.general.mail.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.general"><![CDATA[郵件選項]]></item>
+               <item name="wcf.acp.option.category.general.mail.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.mail.send"><![CDATA[傳送選項]]></item>
+               <item name="wcf.acp.option.category.general.mail.send.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.general.offline"><![CDATA[臨時關閉論壇]]></item>
+               <item name="wcf.acp.option.category.general.offline.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module"><![CDATA[模組開啟/關閉]]></item>
+               <item name="wcf.acp.option.category.module.content"><![CDATA[內容模組]]></item>
+               <item name="wcf.acp.option.category.module.content.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.display"><![CDATA[顯示]]></item>
+               <item name="wcf.acp.option.category.module.display.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.system"><![CDATA[系統模組]]></item>
+               <item name="wcf.acp.option.category.module.system.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.module.user"><![CDATA[用戶模組]]></item>
+               <item name="wcf.acp.option.category.module.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security"><![CDATA[安全設置]]></item>
+               <item name="wcf.acp.option.category.security.antispam"><![CDATA[驗證碼設置]]></item>
+               <item name="wcf.acp.option.category.security.antispam.description"><![CDATA[面向公共網路的頁面經常會被惡意程式或機器人波壞, 比如在很短的時間內註冊大量的用戶和發帖等. 你可以使用 隨機驗證碼 的辦法來對付垃圾程式. 你可以在這裏瞭解更多有關隨機驗證碼的資訊: <a href="http://en.wikipedia.org/wiki/Captcha" class="externalURL">captcha image</a> 不過你也需要注意, 盲人和視力受損的人也難以識別 隨機驗證碼.]]></item>
+               <item name="wcf.acp.option.category.security.blacklist"><![CDATA[遮罩設置]]></item>
+               <item name="wcf.acp.option.category.security.blacklist.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.censorship"><![CDATA[詞語遮罩選項]]></item>
+               <item name="wcf.acp.option.category.security.censorship.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general"><![CDATA[安全設置]]></item>
+               <item name="wcf.acp.option.category.security.general.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.security.general.session"><![CDATA[Sessions]]></item>
+               <item name="wcf.acp.option.category.security.general.session.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.category.user"><![CDATA[用戶]]></item>
+               <item name="wcf.acp.option.category.user.description"><![CDATA[]]></item>
+               <item name="wcf.acp.option.cookie_domain"><![CDATA[Cookie 作用域]]></item>
+               <item name="wcf.acp.option.cookie_domain.description"><![CDATA[Cookie 所影響的功能變數名稱。修改此選項預設值最常見的原因是,你的論壇有兩個不同的網址,例如 standme.com 和 forum.standme.com. 要使用戶在以兩個不同的功能變數名稱訪問論壇時,都能保持登錄狀態,你需要將此選項設置為 .standme.com (注意功能變數名稱需要以點開頭).<br /><strong>注意:若你不能肯定,最好將此處留空。輸入錯誤的設置會導致你無法登錄論壇。</strong>]]></item>
+               <item name="wcf.acp.option.cookie_path"><![CDATA[Cookie 路徑]]></item>
+               <item name="wcf.acp.option.cookie_path.description"><![CDATA[Cookie 保存的路徑。如果你在同一個功能變數名稱下運行了多個論壇, 便需要將它設置為每個論壇所在的目錄名. 否則, 填寫 / 便可以了. 請注意,此處必須以斜杠結尾, 比如“/forums/”、“/wbb3/”等. <br /><strong>注意:輸入錯誤的設置會導致你無法登錄論壇.</strong>]]></item>
+               <item name="wcf.acp.option.cookie_prefix"><![CDATA[Cookie 首碼]]></item>
+               <item name="wcf.acp.option.cookie_prefix.description"><![CDATA[你可以設置你的論壇 Cookie 使用特定的首碼.]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time"><![CDATA[啟用夏令時]]></item>
+               <item name="wcf.acp.option.enable_daylight_saving_time.description"><![CDATA[系統始終是否自動調整夏令/冬令時?]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache"><![CDATA[使用緩存模式儲存 Session 資料]]></item>
+               <item name="wcf.acp.option.enable_session_data_cache.description"><![CDATA[你確認要使用緩存模式來存儲 Session 資料?]]></item>
+               <item name="wcf.acp.option.error.validationFailed"><![CDATA[你輸入的資訊無效.]]></item>
+               <item name="wcf.acp.option.export"><![CDATA[導出系統設置]]></item>
+               <item name="wcf.acp.option.export.download"><![CDATA[下載導出的系統設置]]></item>
+               <item name="wcf.acp.option.export.download.description"><![CDATA[將系統設置下載到你的電腦作為備份.]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml"><![CDATA[啟用媒體類型標記]]></item>
+               <item name="wcf.acp.option.http_content_type_xhtml.description"><![CDATA[啟用該選項則允許論壇向流覽器的發送的HTTP頭部請求標記文檔的媒體類型為 application/xhtml+xml.]]></item>
+               <item name="wcf.acp.option.http_enable_gzip"><![CDATA[啟用 Gzip 壓縮]]></item>
+               <item name="wcf.acp.option.http_enable_gzip.description"><![CDATA[選擇“是”將使用 GZIP HTML 壓縮輸出給用戶頁面,這會減少帶寬要求。這項功能要求用戶端流覽器的支持,以及 HTTP 1.1 相容。它會產生伺服器額外的性能開銷。<br />這項功能要求 ZLIB 庫支持。<br />如果你已經在伺服器上使用了mod_gzip,請不要打開這個選項。]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers"><![CDATA[禁用流覽器頁面緩存]]></item>
+               <item name="wcf.acp.option.http_enable_no_cache_headers.description"><![CDATA[啟用這個選項將限制流覽器對頁面進行緩存.]]></item>
+               <item name="wcf.acp.option.http_gzip_level"><![CDATA[壓縮等級]]></item>
+               <item name="wcf.acp.option.http_gzip_level.description"><![CDATA[設置 GZIP 在輸出時的壓縮級別: 0=無壓縮, 9=最大壓縮比. 我們強烈推薦你使用級別 1.]]></item>
+               <item name="wcf.acp.option.import"><![CDATA[導入系統設置]]></item>
+               <item name="wcf.acp.option.import.error.importFailed"><![CDATA[The import of the chosen file has failed.]]></item>
+               <item name="wcf.acp.option.import.success"><![CDATA[系統設置導入成功.]]></item>
+               <item name="wcf.acp.option.import.upload"><![CDATA[上傳系統設置]]></item>
+               <item name="wcf.acp.option.import.upload.description"><![CDATA[從你的電腦上傳系統設置.]]></item>
+               <item name="wcf.acp.option.importAndExport"><![CDATA[導入 &amp; 導出系統設置]]></item>
+               <item name="wcf.acp.option.mail_admin_address"><![CDATA[管理員 E-Mail]]></item>
+               <item name="wcf.acp.option.mail_admin_address.description"><![CDATA[輸入你的管理員E-mail.]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path"><![CDATA[Debug 日誌檔路徑]]></item>
+               <item name="wcf.acp.option.mail_debug_logfile_path.description"><![CDATA[在這裏輸入Debug 日誌檔的路徑]]></item>
+               <item name="wcf.acp.option.mail_from_address"><![CDATA[發送E-Mail]]></item>
+               <item name="wcf.acp.option.mail_from_address.description"><![CDATA[輸入用於發送郵件的 E-Mails.]]></item>
+               <item name="wcf.acp.option.mail_from_name"><![CDATA[郵件作者]]></item>
+               <item name="wcf.acp.option.mail_from_name.description"><![CDATA[輸入一個名字, 以便你的用戶知道是誰給他發的郵件, 可以直接填寫論壇名稱.]]></item>
+               <item name="wcf.acp.option.mail_send_method"><![CDATA[E-Mail 方式]]></item>
+               <item name="wcf.acp.option.mail_send_method.debug"><![CDATA[Debug]]></item>
+               <item name="wcf.acp.option.mail_send_method.description"><![CDATA[選擇一個郵件發送方式.]]></item>
+               <item name="wcf.acp.option.mail_send_method.php"><![CDATA[PHP]]></item>
+               <item name="wcf.acp.option.mail_send_method.smtp"><![CDATA[SMTP]]></item>
+               <item name="wcf.acp.option.mail_signature"><![CDATA[發送簽名]]></item>
+               <item name="wcf.acp.option.mail_signature.description"><![CDATA[在這裏可以輸入一段話, 他將作為郵件簽名顯示在底部.]]></item>
+               <item name="wcf.acp.option.mail_smtp_host"><![CDATA[SMTP 主機]]></item>
+               <item name="wcf.acp.option.mail_smtp_host.description"><![CDATA[輸入SMTP郵件主機名.]]></item>
+               <item name="wcf.acp.option.mail_smtp_password"><![CDATA[SMTP 密碼]]></item>
+               <item name="wcf.acp.option.mail_smtp_password.description"><![CDATA[填寫SMTP 用戶的密碼.]]></item>
+               <item name="wcf.acp.option.mail_smtp_port"><![CDATA[SMTP 埠]]></item>
+               <item name="wcf.acp.option.mail_smtp_port.description"><![CDATA[輸入SMTP 郵件伺服器的埠.]]></item>
+               <item name="wcf.acp.option.mail_smtp_user"><![CDATA[SMTP 用戶名]]></item>
+               <item name="wcf.acp.option.mail_smtp_user.description"><![CDATA[輸入SMTP 郵件伺服器的用戶名]]></item>
+               <item name="wcf.acp.option.mail_use_f_param"><![CDATA[啟用 &quot;-f&quot; 參數]]></item>
+               <item name="wcf.acp.option.mail_use_f_param.description"><![CDATA[一些 Sendmail 伺服器在 PHP 發送郵件時需要“-f”參數, 如果你遇到這樣的問題, 用戶收不到從論壇發出的郵件, 試試打開這個選項.]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address"><![CDATA[使用格式化的Email位址]]></item>
+               <item name="wcf.acp.option.mail_use_formatted_address.description"><![CDATA[啟用該選項, 發件人和收件人的郵件地址將被格式化為 &quot;Name &lt;email@domain.tld&gt;&quot;. 的格式. 但並非所有的郵件伺服器都支援該選項, 當郵件發送出現問題的時候請關閉該選項.]]></item>
+               <item name="wcf.acp.option.module_master_password"><![CDATA[啟用後臺操作密碼]]></item>
+               <item name="wcf.acp.option.module_master_password.description"><![CDATA["後臺操作密碼"是對系統操作安全保護的附加程式.你可以使用一個不同于管理員帳戶密碼的複雜密碼,用於驗證系統操作.]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp"><![CDATA[代理伺服器(FTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_ftp.description"><![CDATA[用於FTP連接的代理伺服器]]></item>
+               <item name="wcf.acp.option.proxy_server_http"><![CDATA[代理伺服器 (HTTP)]]></item>
+               <item name="wcf.acp.option.proxy_server_http.description"><![CDATA[用戶HTTP連接的代理伺服器]]></item>
+               <item name="wcf.acp.option.session_timeout"><![CDATA[Session 作用時間]]></item>
+               <item name="wcf.acp.option.session_timeout.description"><![CDATA[在這裏設置用戶的Session 作用時間. 單位:秒.]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address"><![CDATA[檢測IP地址位數]]></item>
+               <item name="wcf.acp.option.session_validate_ip_address.description"><![CDATA[選擇檢測Session資料中IP位址的資料位元數, 數位越大則可以排除用戶更換IP登陸.]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent"><![CDATA[從Session中檢測用戶Agent]]></item>
+               <item name="wcf.acp.option.session_validate_user_agent.description"><![CDATA[是否從Session資料中檢測用戶的Agent?]]></item>
+               <item name="wcf.acp.option.success"><![CDATA[設置修改成功.]]></item>
+               <item name="wcf.acp.option.timezone"><![CDATA[時區設置]]></item>
+               <item name="wcf.acp.option.timezone.description"><![CDATA[設置你網站所在地方的時區.]]></item>
+               <item name="wcf.acp.option.user_online_timeout"><![CDATA[線上列表統計時間]]></item>
+               <item name="wcf.acp.option.user_online_timeout.description"><![CDATA[統計線上列表的時間範圍, 超過這個時間沒有任何活動, 其用戶名會從線上用戶列表中刪除. 單位:秒.]]></item>
+       </category>
+       <category name="wcf.acp.package">
+               <item name="wcf.acp.package.cancel"><![CDATA[取消模組安裝]]></item>
+               <item name="wcf.acp.package.description"><![CDATA[描述]]></item>
+               <item name="wcf.acp.package.ftp"><![CDATA[輸入 FTP 的登錄資訊]]></item>
+               <item name="wcf.acp.package.ftp.accessData"><![CDATA[FTP 登錄信息]]></item>
+               <item name="wcf.acp.package.ftp.description"><![CDATA[如果你的伺服器開啟了PHP安全模式, 則論壇模組的安裝需要FTP功能的支援. 請輸入該伺服器的FTP用戶名和密碼, 此次你輸入的FTP用戶名和密碼僅用於此次論壇模組安裝而不被記錄, 因此, 你安裝另外的論壇模組的時候還需要再次輸入該資訊.]]></item>
+               <item name="wcf.acp.package.ftp.error"><![CDATA[根據你輸入的FTP資訊, 無法建立FTP連接, 請檢查你輸入的資訊.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotConnect"><![CDATA[無法創建FTP連接.]]></item>
+               <item name="wcf.acp.package.ftp.error.cannotLogin"><![CDATA[無法登錄FTP伺服器.]]></item>
+               <item name="wcf.acp.package.ftp.host"><![CDATA[主機名]]></item>
+               <item name="wcf.acp.package.ftp.password"><![CDATA[密碼]]></item>
+               <item name="wcf.acp.package.ftp.user"><![CDATA[用戶名]]></item>
+               <item name="wcf.acp.package.install"><![CDATA[安裝模組]]></item>
+               <item name="wcf.acp.package.install.cancel"><![CDATA[取消安裝]]></item>
+               <item name="wcf.acp.package.install.cancel.sure"><![CDATA[你確認要取消模組安裝?]]></item>
+               <item name="wcf.acp.package.install.error"><![CDATA[該模組的模組需求無法滿足.]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages"><![CDATA[The  模組 &quot;{$packageName}({$packageVersion})&quot; 的 {if $action == 'install'}安裝{else}升級{/if}因下列模組的衝突無法完成:]]></item>
+               <item name="wcf.acp.package.install.error.excludedPackages.excludedPackage"><![CDATA[{$excludedPackage.packageName}{if $excludedPackage.instanceNo > 1} (#{@$excludedPackage.instanceNo}){/if} 版本 {$excludedPackage.packageVersion}]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages"><![CDATA[下列模組的 {if $action == 'install'}安裝{else}升級{/if}: &quot;{$packageName}&quot; {$packageVersion} 因衝突無法完成.]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.excludingPackage"><![CDATA[{$excludingPackage.packageName}{if $excludingPackage.instanceNo > 1} (#{@$excludingPackage.instanceNo}){/if} ({$excludingPackage.packageVersion})]]></item>
+               <item name="wcf.acp.package.install.error.excludingPackages.warning"><![CDATA[和以下衝突模組:  &quot;{$packageName}&quot; ({$packageVersion}). 如果你繼續安裝, 這些模組將無法正常工作.]]></item>
+               <item name="wcf.acp.package.install.packageName"><![CDATA[<span{if $package.open == 0} style="color: green"{else}{if !$package.file|isset} style="color: red"{/if}{/if}>{$package.name} ({if $package.open == 0}被安裝{else}{if $package.file|isset}在該模組中{else}不可用{/if}{/if})</span>]]></item>
+               <item name="wcf.acp.package.install.rollback.sure"><![CDATA[你確認取消該模組的安裝?]]></item>
+               <item name="wcf.acp.package.install.updatableInstances"><![CDATA[通過該模組下列模組可以更新]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.description"><![CDATA[選擇下列模組的一個來更新它的版本, 如果你想要再次安裝該模組, 請點擊 &quot;{lang}wcf.global.button.next{/lang}&quot; 按鈕.]]></item>
+               <item name="wcf.acp.package.install.updatableInstances.warning"><![CDATA[該模組已經存在於已安裝模組列表中. 如果你點繼續則將再安裝一個該模組的副本. 如果你想要更新一個該模組的可用拷貝, 請從下面列表中選擇. ]]></item>
+               <item name="wcf.acp.package.install.version"><![CDATA[模組版本:]]></item>
+               <item name="wcf.acp.package.installDate"><![CDATA[安裝日期]]></item>
+               <item name="wcf.acp.package.installation.file.error.unknown"><![CDATA[解壓模組檔時發生如下錯誤:]]></item>
+               <item name="wcf.acp.package.installation.file.error.untarFailed"><![CDATA[下列檔無法解壓,請檢查檔夾的寫入許可權.]]></item>
+               <item name="wcf.acp.package.installation.tables.conflict"><![CDATA[衝突的資料表]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainKeep"><![CDATA[不覆蓋資料表(此次安裝不需再次詢問).]]></item>
+               <item name="wcf.acp.package.installation.tables.dontAskAgainOverride"><![CDATA[覆蓋資料表(此次安裝不需再次詢問).]]></item>
+               <item name="wcf.acp.package.installation.tables.solution"><![CDATA[所需變化]]></item>
+               <item name="wcf.acp.package.installation.tables.tableName"><![CDATA[影響表]]></item>
+               <item name="wcf.acp.package.installation.tables.warning"><![CDATA[安裝該模組時與以下資料表衝突. 請選擇是否覆蓋這些資料表.]]></item>
+               <item name="wcf.acp.package.list"><![CDATA[已安裝模組]]></item>
+               <item name="wcf.acp.package.list.author"><![CDATA[作者]]></item>
+               <item name="wcf.acp.package.list.count"><![CDATA[已安裝 {#$items} 個模組]]></item>
+               <item name="wcf.acp.package.list.date"><![CDATA[日期]]></item>
+               <item name="wcf.acp.package.list.id"><![CDATA[ID]]></item>
+               <item name="wcf.acp.package.list.name"><![CDATA[名稱]]></item>
+               <item name="wcf.acp.package.list.other"><![CDATA[模組]]></item>
+               <item name="wcf.acp.package.list.plugin"><![CDATA[插件]]></item>
+               <item name="wcf.acp.package.list.standalone"><![CDATA[標準程式]]></item>
+               <item name="wcf.acp.package.list.version"><![CDATA[版本]]></item>
+               <item name="wcf.acp.package.optionals"><![CDATA[安裝附加模組]]></item>
+               <item name="wcf.acp.package.optionals.description"><![CDATA[該模組包含以下附加模組, 請選擇你要安裝的模組.]]></item>
+               <item name="wcf.acp.package.optionals.installed"><![CDATA[(該模組已被安裝.)]]></item>
+               <item name="wcf.acp.package.optionals.openRequirements"><![CDATA[(該模組需求不能完全滿足.)]]></item>
+               <item name="wcf.acp.package.packageDir"><![CDATA[文件夾]]></item>
+               <item name="wcf.acp.package.packageDir.description"><![CDATA[]]></item>
+               <item name="wcf.acp.package.packageDir.error.alreadyInstalled"><![CDATA[已有其他程式被安裝在該檔夾中.]]></item>
+               <item name="wcf.acp.package.packageDir.error.invalid"><![CDATA[文件夾不可用.]]></item>
+               <item name="wcf.acp.package.packageDir.error.notWritable"><![CDATA[文件夾不可寫.]]></item>
+               <item name="wcf.acp.package.packageDir.error.wcfDirLocked"><![CDATA[該檔夾已被 WoltLab Community Framework 使用. 請選擇另外的檔夾.]]></item>
+               <item name="wcf.acp.package.packageDir.input"><![CDATA[輸入安裝目錄.]]></item>
+               <item name="wcf.acp.package.packageDir.url"><![CDATA[模組安裝完成之後的URL:]]></item>
+               <item name="wcf.acp.package.requirements"><![CDATA[選擇所需模組]]></item>
+               <item name="wcf.acp.package.requirements.description"><![CDATA[當前模組需要其他模組的支援, 請選擇你所需的模組.]]></item>
+               <item name="wcf.acp.package.rollback"><![CDATA[取消安裝]]></item>
+               <item name="wcf.acp.package.shortPackageInfo"><![CDATA[版本: {$packageVersion} - {@$packageDate|date} - Copyright &copy; {$packageAuthor}]]></item>
+               <item name="wcf.acp.package.startInstall"><![CDATA[安裝模組]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidInstall"><![CDATA[所選模組不是有效的安裝例行.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidPackage"><![CDATA[你給出的檔不是一個有效的模組檔.]]></item>
+               <item name="wcf.acp.package.startInstall.error.noValidUpdate"><![CDATA[模組 &quot;{$package->getName()}&quot; 無法通過你給出的檔來更新.]]></item>
+               <item name="wcf.acp.package.startInstall.error.notFound"><![CDATA[你給出的文件夾內無文件.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uniqueAlreadyInstalled"><![CDATA[所選模組已被安裝. 模組不可被安裝多次.]]></item>
+               <item name="wcf.acp.package.startInstall.error.uploadFailed"><![CDATA[上傳所選檔失敗.]]></item>
+               <item name="wcf.acp.package.startInstall.source"><![CDATA[選擇模組檔來源]]></item>
+               <item name="wcf.acp.package.startInstall.source.download"><![CDATA[來自伺服器]]></item>
+               <item name="wcf.acp.package.startInstall.source.download.description"><![CDATA[請輸入你伺服器上的模組檔路徑(相對路徑), 支援遠端檔(http://...).]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload"><![CDATA[來自你的電腦]]></item>
+               <item name="wcf.acp.package.startInstall.source.upload.description"><![CDATA[請從你的電腦選擇模組檔.]]></item>
+               <item name="wcf.acp.package.startUpdate"><![CDATA[更新 &quot;{$package->getName()}&quot; 模組]]></item>
+               <item name="wcf.acp.package.step.install.ACPMenuPackageInstallationPlugin"><![CDATA[安裝系統設置功能表選項 ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[安裝系統設置範本補丁 ...]]></item>
+               <item name="wcf.acp.package.step.install.ACPTemplatesPackageInstallationPlugin"><![CDATA[安裝系統設置範本 ...]]></item>
+               <item name="wcf.acp.package.step.install.EventListenerPackageInstallationPlugin"><![CDATA[安裝事件監聽 ...]]></item>
+               <item name="wcf.acp.package.step.install.FilesPackageInstallationPlugin"><![CDATA[解壓模組檔包 ...]]></item>
+               <item name="wcf.acp.package.step.install.GroupOptionsPackageInstallationPlugin"><![CDATA[安裝用戶組選項 ...]]></item>
+               <item name="wcf.acp.package.step.install.LanguagesPackageInstallationPlugin"><![CDATA[安裝模組語言 ...]]></item>
+               <item name="wcf.acp.package.step.install.OptionsPackageInstallationPlugin"><![CDATA[安裝模組選項 ...]]></item>
+               <item name="wcf.acp.package.step.install.ScriptPackageInstallationPlugin"><![CDATA[解壓特殊腳本 ...]]></item>
+               <item name="wcf.acp.package.step.install.SqlPackageInstallationPlugin"><![CDATA[安裝資料...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatePatchPackageInstallationPlugin"><![CDATA[安裝範本補丁 ...]]></item>
+               <item name="wcf.acp.package.step.install.TemplatesPackageInstallationPlugin"><![CDATA[安裝範本包 ...]]></item>
+               <item name="wcf.acp.package.step.install.UserOptionsPackageInstallationPlugin"><![CDATA[安裝用戶資料項 ...]]></item>
+               <item name="wcf.acp.package.step.install.exclusions"><![CDATA[檢查可能的衝突 ...]]></item>
+               <item name="wcf.acp.package.step.install.execPackageInstallationPlugins"><![CDATA[解壓模組插件 ...]]></item>
+               <item name="wcf.acp.package.step.install.finish"><![CDATA[安裝完成]]></item>
+               <item name="wcf.acp.package.step.install.optionals"><![CDATA[安裝附加模組 ...]]></item>
+               <item name="wcf.acp.package.step.install.package"><![CDATA[註冊模組 ...]]></item>
+               <item name="wcf.acp.package.step.install.packageInstallationPlugins"><![CDATA[安裝模組插件 ...]]></item>
+               <item name="wcf.acp.package.step.install.parent"><![CDATA[安裝上級模組 ...]]></item>
+               <item name="wcf.acp.package.step.install.requirements"><![CDATA[檢查需求 ...]]></item>
+               <item name="wcf.acp.package.step.title"><![CDATA[<b>{$packageName}</b> 模組: ]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPMenuPackageInstallationPlugin"><![CDATA[移除系統設置功能表 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[移除系統設置範本補丁 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.ACPTemplatesPackageInstallationPlugin"><![CDATA[移除系統設置範本 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.EventListenerPackageInstallationPlugin"><![CDATA[卸載事件監聽 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.FilesPackageInstallationPlugin"><![CDATA[刪除模組檔 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.GroupOptionsPackageInstallationPlugin"><![CDATA[移除用戶組選項 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.LanguagesPackageInstallationPlugin"><![CDATA[移除模組語言 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.OptionsPackageInstallationPlugin"><![CDATA[移除模組選項 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.SqlPackageInstallationPlugin"><![CDATA[移除數據條目...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatePatchPackageInstallationPlugin"><![CDATA[移除範本補丁 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.TemplatesPackageInstallationPlugin"><![CDATA[移除模組範本 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.UserOptionsPackageInstallationPlugin"><![CDATA[移除用戶資料項 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.execPackageInstallationPlugins"><![CDATA[解壓模組插件 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.finish"><![CDATA[模組卸載完成]]></item>
+               <item name="wcf.acp.package.step.uninstall.optionals"><![CDATA[卸載附加模組 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.packageInstallationPlugins"><![CDATA[卸載模組插件 ...]]></item>
+               <item name="wcf.acp.package.step.uninstall.requirements"><![CDATA[卸載模組需求 ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPMenuPackageInstallationPlugin"><![CDATA[更新系統設置功能表 ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatePatchPackageInstallationPlugin"><![CDATA[更新系統設置範本補丁 ...]]></item>
+               <item name="wcf.acp.package.step.update.ACPTemplatesPackageInstallationPlugin"><![CDATA[更新系統設置範本 ...]]></item>
+               <item name="wcf.acp.package.step.update.EventListenerPackageInstallationPlugin"><![CDATA[更新事件監聽 ...]]></item>
+               <item name="wcf.acp.package.step.update.FilesPackageInstallationPlugin"><![CDATA[解壓模組檔包 ...]]></item>
+               <item name="wcf.acp.package.step.update.GroupOptionsPackageInstallationPlugin"><![CDATA[更新用戶組選項 ...]]></item>
+               <item name="wcf.acp.package.step.update.LanguagesPackageInstallationPlugin"><![CDATA[更新模組語言 ...]]></item>
+               <item name="wcf.acp.package.step.update.OptionsPackageInstallationPlugin"><![CDATA[更新模組設置 ...]]></item>
+               <item name="wcf.acp.package.step.update.ScriptPackageInstallationPlugin"><![CDATA[解壓特殊腳本 ...]]></item>
+               <item name="wcf.acp.package.step.update.SqlPackageInstallationPlugin"><![CDATA[更新資料內容 ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatePatchPackageInstallationPlugin"><![CDATA[更新範本補丁 ...]]></item>
+               <item name="wcf.acp.package.step.update.TemplatesPackageInstallationPlugin"><![CDATA[更新模組範本 ...]]></item>
+               <item name="wcf.acp.package.step.update.UserOptionsPackageInstallationPlugin"><![CDATA[更新用戶資料項 ...]]></item>
+               <item name="wcf.acp.package.step.update.exclusions"><![CDATA[檢查可能的衝突 ...]]></item>
+               <item name="wcf.acp.package.step.update.execPackageInstallationPlugins"><![CDATA[解壓模組插件 ...]]></item>
+               <item name="wcf.acp.package.step.update.finish"><![CDATA[模組更新完成]]></item>
+               <item name="wcf.acp.package.step.update.optionals"><![CDATA[更新附加模組 ...]]></item>
+               <item name="wcf.acp.package.step.update.package"><![CDATA[更新模組 ...]]></item>
+               <item name="wcf.acp.package.step.update.packageInstallationPlugins"><![CDATA[更新模組插件 ...]]></item>
+               <item name="wcf.acp.package.step.update.parent"><![CDATA[更新上級模組 ...]]></item>
+               <item name="wcf.acp.package.step.update.requirements"><![CDATA[檢查需求 ...]]></item>
+               <item name="wcf.acp.package.templatePatch.install.failed"><![CDATA[該模組補丁安裝失敗因為該補丁和模組不匹配. 因此該模組無法被安裝. 請點擊 &quot;{lang}wcf.acp.package.install.cancel{/lang}&quot; 按鈕.]]></item>
+               <item name="wcf.acp.package.templatePatch.repatch.failed"><![CDATA[為下列範本打補丁失敗:<br />{foreach from=$failures item=$failure}{$failure.templateName} (Originally patched by: {$failure.packageName})<br />{/foreach}預先安裝的模組補丁似乎已經無效. 你應當點擊 &quot;{lang}wcf.global.button.next{/lang}&quot; 按鈕繼續完成升級過程.]]></item>
+               <item name="wcf.acp.package.templatePatch.uninstall.failed"><![CDATA[該模組補丁移除失敗因為原始檔案已經更改. 因此該模組無法被移除. 請單擊 &quot;{lang}wcf.acp.package.uninstall.cancel{/lang}&quot; 按鈕.]]></item>
+               <item name="wcf.acp.package.uninstall"><![CDATA[移除模組]]></item>
+               <item name="wcf.acp.package.uninstall.cancel"><![CDATA[取消移除]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.error"><![CDATA[無法移除該模組, 因為該模組被不止一個其他模組需要.]]></item>
+               <item name="wcf.acp.package.uninstall.dependentPackages.warning"><![CDATA[經過最後確認, 下列模組將被卸載.]]></item>
+               <item name="wcf.acp.package.update"><![CDATA[升級模組]]></item>
+               <item name="wcf.acp.package.updateDate"><![CDATA[升級日期]]></item>
+               <item name="wcf.acp.package.view.author"><![CDATA[作者:]]></item>
+               <item name="wcf.acp.package.view.button.makeActive"><![CDATA[跳轉至系統設置]]></item>
+               <item name="wcf.acp.package.view.button.uninstall"><![CDATA[移除模組]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.all"><![CDATA[移除所有模組]]></item>
+               <item name="wcf.acp.package.view.button.uninstall.sure"><![CDATA[你確認移除該模組?]]></item>
+               <item name="wcf.acp.package.view.button.update"><![CDATA[升級模組]]></item>
+               <item name="wcf.acp.package.view.date"><![CDATA[發佈日期:]]></item>
+               <item name="wcf.acp.package.view.dependentPackages"><![CDATA[支援模組]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.description"><![CDATA[該模組被其他 {#$dependentPackages|count} 個模組所需求.]]></item>
+               <item name="wcf.acp.package.view.dependentPackages.uninstall.description"><![CDATA[該模組被其他{#$dependentPackages|count} 個模組所需求.]]></item>
+               <item name="wcf.acp.package.view.dir"><![CDATA[安裝目錄:]]></item>
+               <item name="wcf.acp.package.view.identifier"><![CDATA[標識:]]></item>
+               <item name="wcf.acp.package.view.instanceNo"><![CDATA[安裝實例:]]></item>
+               <item name="wcf.acp.package.view.parent"><![CDATA[上級模組:]]></item>
+               <item name="wcf.acp.package.view.properties"><![CDATA[屬性]]></item>
+               <item name="wcf.acp.package.view.requiredPackages"><![CDATA[所需模組]]></item>
+               <item name="wcf.acp.package.view.requiredPackages.description"><![CDATA[該模組需要 {#$requiredPackages|count} 個其他模組的支援.]]></item>
+               <item name="wcf.acp.package.view.url"><![CDATA[主頁:]]></item>
+               <item name="wcf.acp.package.view.version"><![CDATA[當前版本:]]></item>
+       </category>
+       <category name="wcf.acp.packageUpdate">
+               <item name="wcf.acp.packageUpdate"><![CDATA[升級模組]]></item>
+               <item name="wcf.acp.packageUpdate.auth"><![CDATA[升級伺服器驗證]]></item>
+               <item name="wcf.acp.packageUpdate.auth.data"><![CDATA[連接資料]]></item>
+               <item name="wcf.acp.packageUpdate.auth.error"><![CDATA[所給的用戶名和密碼無效.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword"><![CDATA[密碼]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htPassword.description"><![CDATA[輸入模組升級伺服器所需的驗證密碼.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername"><![CDATA[用戶名]]></item>
+               <item name="wcf.acp.packageUpdate.auth.htUsername.description"><![CDATA[輸入模組升級伺服器所需的用戶名.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.input"><![CDATA[用戶登錄]]></item>
+               <item name="wcf.acp.packageUpdate.auth.message"><![CDATA[伺服器資訊]]></item>
+               <item name="wcf.acp.packageUpdate.auth.realm"><![CDATA[伺服器名]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save"><![CDATA[保存用戶資料]]></item>
+               <item name="wcf.acp.packageUpdate.auth.save.description"><![CDATA[你輸入的用戶資料將被保存, 這樣你就不用在以後再每次輸入這些資料了.]]></item>
+               <item name="wcf.acp.packageUpdate.auth.url"><![CDATA[地址]]></item>
+               <item name="wcf.acp.packageUpdate.currentVersion"><![CDATA[當前版本]]></item>
+               <item name="wcf.acp.packageUpdate.error"><![CDATA[發生了一個錯誤: ]]></item>
+               <item name="wcf.acp.packageUpdate.error.downloadFailed"><![CDATA[模組 {$package} 下載失敗.]]></item>
+               <item name="wcf.acp.packageUpdate.error.listNotFound"><![CDATA[沒有找到以下模組.]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages"><![CDATA[發生如下衝突:]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.existingPackageExcludesNewPackage"><![CDATA[模組&quot;{$excludedPackage.existingPackageName}&quot; 和如下模組衝突:&quot; {$excludedPackage.packageName}&quot;({$excludedPackage.packageVersion}).]]></item>
+               <item name="wcf.acp.packageUpdate.excludedPackages.newPackageExcludesExistingPackage"><![CDATA[模組 &quot;{$excludedPackage.packageName}&quot;({$excludedPackage.packageVersion})和如下模組衝突: &quot;{$excludedPackage.existingPackageName}&quot; .]]></item>
+               <item name="wcf.acp.packageUpdate.install"><![CDATA[{$package.packageName} {$package.packageVersion} 安裝成功]]></item>
+               <item name="wcf.acp.packageUpdate.noneAvailable"><![CDATA[當前無可用更新.]]></item>
+               <item name="wcf.acp.packageUpdate.noneSelected"><![CDATA[你未選擇任何更新.]]></item>
+               <item name="wcf.acp.packageUpdate.options"><![CDATA[選項]]></item>
+               <item name="wcf.acp.packageUpdate.options.alreadyInstalledUnique"><![CDATA[模組已經被安裝且是獨一無二的. 因此不能被再次安裝.]]></item>
+               <item name="wcf.acp.packageUpdate.options.install"><![CDATA[安裝模組]]></item>
+               <item name="wcf.acp.packageUpdate.options.installAlreadyInstalled"><![CDATA[安裝另一個模組實例(該模組已經被安裝了 {#$package.instances} 次)]]></item>
+               <item name="wcf.acp.packageUpdate.options.update"><![CDATA[升級已安裝模組{$updatableInstance.packageName}{if $updatableInstance.instanceNo > 1} (#{$updatableInstance.instanceNo}){/if} 版本 {$updatableInstance.packageVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.search"><![CDATA[搜索模組]]></item>
+               <item name="wcf.acp.packageUpdate.search.author"><![CDATA[作者]]></item>
+               <item name="wcf.acp.packageUpdate.search.conditions"><![CDATA[搜索 ...]]></item>
+               <item name="wcf.acp.packageUpdate.search.ignoreUniques"><![CDATA[隱藏已安裝的獨立模組]]></item>
+               <item name="wcf.acp.packageUpdate.search.packageName"><![CDATA[模組名]]></item>
+               <item name="wcf.acp.packageUpdate.search.searchDescription"><![CDATA[模組名和模組描述]]></item>
+               <item name="wcf.acp.packageUpdate.search.server"><![CDATA[升級伺服器]]></item>
+               <item name="wcf.acp.packageUpdate.search.server.all"><![CDATA[搜索所有升級伺服器]]></item>
+               <item name="wcf.acp.packageUpdate.search.type"><![CDATA[模組類型]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.other"><![CDATA[其他模組]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.plugin"><![CDATA[已安裝模組的插件]]></item>
+               <item name="wcf.acp.packageUpdate.search.type.standalone"><![CDATA[標準程式]]></item>
+               <item name="wcf.acp.packageUpdate.selectAll"><![CDATA[選擇所有模組]]></item>
+               <item name="wcf.acp.packageUpdate.update"><![CDATA[{$package.packageName}{if $package.instanceNo > 1} (#{#$package.instanceNo}){/if} 從{$package.fromversion} 升級至{$package.toVersion}]]></item>
+               <item name="wcf.acp.packageUpdate.updateVersion"><![CDATA[新版本]]></item>
+               <item name="wcf.acp.packageUpdate.updates"><![CDATA[下列模組正在更新/安裝:]]></item>
+       </category>
+       <category name="wcf.acp.sessionLog">
+               <item name="wcf.acp.sessionLog.access.view"><![CDATA[&quot;{$sessionLog->username}&quot; 的登陸操作記錄]]></item>
+               <item name="wcf.acp.sessionLog.access.view.count"><![CDATA[共有 {#$items} 條操作記錄]]></item>
+               <item name="wcf.acp.sessionLog.accesses"><![CDATA[操作]]></item>
+               <item name="wcf.acp.sessionLog.className"><![CDATA[類文件]]></item>
+               <item name="wcf.acp.sessionLog.ipAddress"><![CDATA[IP地址]]></item>
+               <item name="wcf.acp.sessionLog.lastActivityTime"><![CDATA[最後活動]]></item>
+               <item name="wcf.acp.sessionLog.packageName"><![CDATA[模組]]></item>
+               <item name="wcf.acp.sessionLog.requestMethod"><![CDATA[請求]]></item>
+               <item name="wcf.acp.sessionLog.requestURI"><![CDATA[URI]]></item>
+               <item name="wcf.acp.sessionLog.sessionAccessLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.sessionLogID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.sessionLog.time"><![CDATA[時間]]></item>
+               <item name="wcf.acp.sessionLog.userAgent"><![CDATA[用戶Agent]]></item>
+               <item name="wcf.acp.sessionLog.view"><![CDATA[系統登陸 Sessions]]></item>
+               <item name="wcf.acp.sessionLog.view.count"><![CDATA[共有 {#$items} 條系統登陸 Session]]></item>
+       </category>
+       <category name="wcf.acp.updateServer">
+               <item name="wcf.acp.updateServer.add"><![CDATA[添加伺服器]]></item>
+               <item name="wcf.acp.updateServer.add.success"><![CDATA[伺服器添加成功.]]></item>
+               <item name="wcf.acp.updateServer.data"><![CDATA[伺服器資料]]></item>
+               <item name="wcf.acp.updateServer.delete"><![CDATA[刪除伺服器]]></item>
+               <item name="wcf.acp.updateServer.delete.success"><![CDATA[伺服器刪除成功.]]></item>
+               <item name="wcf.acp.updateServer.delete.sure"><![CDATA[你確認要刪除該伺服器?]]></item>
+               <item name="wcf.acp.updateServer.disable"><![CDATA[禁用]]></item>
+               <item name="wcf.acp.updateServer.edit"><![CDATA[編輯伺服器]]></item>
+               <item name="wcf.acp.updateServer.edit.success"><![CDATA[設置更新成功.]]></item>
+               <item name="wcf.acp.updateServer.enable"><![CDATA[啟用]]></item>
+               <item name="wcf.acp.updateServer.errorText"><![CDATA[錯誤資訊]]></item>
+               <item name="wcf.acp.updateServer.htPassword"><![CDATA[密碼]]></item>
+               <item name="wcf.acp.updateServer.htPassword.description"><![CDATA[輸入密碼如果需要身份驗證(非必需).]]></item>
+               <item name="wcf.acp.updateServer.htUsername"><![CDATA[用戶名]]></item>
+               <item name="wcf.acp.updateServer.htUsername.description"><![CDATA[輸入用戶名如果需要身份驗證(非必需).]]></item>
+               <item name="wcf.acp.updateServer.lastErrorText"><![CDATA[最後一次嘗試連接時發生如下錯誤:]]></item>
+               <item name="wcf.acp.updateServer.list.available"><![CDATA[共有 {#$items}  台升級伺服器]]></item>
+               <item name="wcf.acp.updateServer.packageUpdateServerID"><![CDATA[ID]]></item>
+               <item name="wcf.acp.updateServer.packages"><![CDATA[模組]]></item>
+               <item name="wcf.acp.updateServer.server"><![CDATA[URL]]></item>
+               <item name="wcf.acp.updateServer.server.description"><![CDATA[輸入升級伺服器的URL.]]></item>
+               <item name="wcf.acp.updateServer.server.error.notValid"><![CDATA[伺服器URL輸入無效.]]></item>
+               <item name="wcf.acp.updateServer.status"><![CDATA[狀態]]></item>
+               <item name="wcf.acp.updateServer.timestamp"><![CDATA[最近更新]]></item>
+               <item name="wcf.acp.updateServer.view"><![CDATA[可用升級伺服器]]></item>
+               <item name="wcf.acp.updateServer.view.noneAvailable"><![CDATA[當前無可用升級伺服器.]]></item>
+       </category>
+       <category name="wcf.acp.user">
+               <item name="wcf.acp.user.add"><![CDATA[添加用戶]]></item>
+               <item name="wcf.acp.user.add.data"><![CDATA[用戶資料]]></item>
+               <item name="wcf.acp.user.add.success"><![CDATA[新用戶添加成功.]]></item>
+               <item name="wcf.acp.user.assignToGroup"><![CDATA[所屬用戶組]]></item>
+               <item name="wcf.acp.user.assignToGroup.markedUsers"><![CDATA[將下列用戶加入所選用戶組]]></item>
+               <item name="wcf.acp.user.assignToGroup.success"><![CDATA[用戶被成功加入所選用戶組.]]></item>
+               <item name="wcf.acp.user.button.assignGroup"><![CDATA[所屬用戶組]]></item>
+               <item name="wcf.acp.user.button.exportMail"><![CDATA[導出所有 E-Mail 地址]]></item>
+               <item name="wcf.acp.user.button.sendMail"><![CDATA[發送 E-Mail]]></item>
+               <item name="wcf.acp.user.delete"><![CDATA[刪除用戶]]></item>
+               <item name="wcf.acp.user.delete.error"><![CDATA[沒有用戶被刪除.]]></item>
+               <item name="wcf.acp.user.delete.success"><![CDATA[用戶刪除成功.]]></item>
+               <item name="wcf.acp.user.delete.sure"><![CDATA[你確認刪除該用戶?]]></item>
+               <item name="wcf.acp.user.deleteMarked.sure"><![CDATA[你確認刪除所選用戶?]]></item>
+               <item name="wcf.acp.user.edit"><![CDATA[編輯用戶]]></item>
+               <item name="wcf.acp.user.edit.success"><![CDATA[用戶編輯成功.]]></item>
+               <item name="wcf.acp.user.edit.warning.selfEdit"><![CDATA[你現在在編輯你自己的帳戶. 更改你的用戶許可權可能導致你無法進入後臺系統設置進行操作, 請慎用此功能!]]></item>
+               <item name="wcf.acp.user.exportEmailAddress"><![CDATA[導出 E-Mail 地址]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType"><![CDATA[導出檔格式]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.csv"><![CDATA[CSV]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.fileType.xml"><![CDATA[XML]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.format"><![CDATA[導出選項]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.markedUsers"><![CDATA[導出下列用戶的E-Mail 地址]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.separator"><![CDATA[地址分隔符號]]></item>
+               <item name="wcf.acp.user.exportEmailAddress.textSeparator"><![CDATA[Email 地址結束分隔符號]]></item>
+               <item name="wcf.acp.user.groups"><![CDATA[用戶組]]></item>
+               <item name="wcf.acp.user.groups.invertSearch"><![CDATA[搜索非所選用戶組的用戶.]]></item>
+               <item name="wcf.acp.user.list"><![CDATA[用戶]]></item>
+               <item name="wcf.acp.user.list.all"><![CDATA[列出所有用戶]]></item>
+               <item name="wcf.acp.user.list.count"><![CDATA[共有 {#$items} 位用戶]]></item>
+               <item name="wcf.acp.user.markedUsers"><![CDATA[this.count == 1 ? "1 位用戶被選定" : this.count+" 位用戶被選定"]]></item>
+               <item name="wcf.acp.user.massProcessing"><![CDATA[批量操作用戶]]></item>
+               <item name="wcf.acp.user.massProcessing.action"><![CDATA[操作]]></item>
+               <item name="wcf.acp.user.massProcessing.conditions"><![CDATA[條件]]></item>
+               <item name="wcf.acp.user.massProcessing.success"><![CDATA[所選操作對如下用戶操作成功: {#$affectedUsers}.]]></item>
+               <item name="wcf.acp.user.massProcessing.warning"><![CDATA[批量操作將對所有符合條件的用戶直接生效而<strong>不會有任何安全警告</strong>. 該操作時非常佔用資源的, 所以最好在論壇關閉的狀態下進行操作. 操作完成後請更新論壇統計. 另外, 該操作是不可恢復的, 所以請慎重.]]></item>
+               <item name="wcf.acp.user.search"><![CDATA[搜索用戶]]></item>
+               <item name="wcf.acp.user.search.conditions"><![CDATA[搜索條件]]></item>
+               <item name="wcf.acp.user.search.conditions.general"><![CDATA[一般搜索選項]]></item>
+               <item name="wcf.acp.user.search.conditions.profile"><![CDATA[用戶資料搜索選項]]></item>
+               <item name="wcf.acp.user.search.display"><![CDATA[結果顯示]]></item>
+               <item name="wcf.acp.user.search.display.columns"><![CDATA[項目]]></item>
+               <item name="wcf.acp.user.search.display.columns.other"><![CDATA[其他]]></item>
+               <item name="wcf.acp.user.search.display.columns.profile"><![CDATA[資料]]></item>
+               <item name="wcf.acp.user.search.display.general"><![CDATA[設置]]></item>
+               <item name="wcf.acp.user.search.display.itemsPerPage"><![CDATA[每頁用戶數]]></item>
+               <item name="wcf.acp.user.search.display.sort"><![CDATA[排序]]></item>
+               <item name="wcf.acp.user.search.error.noMatches"><![CDATA[沒有找到用戶.]]></item>
+               <item name="wcf.acp.user.search.matches"><![CDATA[共搜索到 {#$users|count} 位用戶]]></item>
+               <item name="wcf.acp.user.search.withinResults"><![CDATA[在結果中搜索]]></item>
+               <item name="wcf.acp.user.sendMail"><![CDATA[發送 E-Mail]]></item>
+               <item name="wcf.acp.user.sendMail.all"><![CDATA[E-Mail 通知所有用戶]]></item>
+               <item name="wcf.acp.user.sendMail.enableHTML"><![CDATA[郵件內容使用html語言格式.]]></item>
+               <item name="wcf.acp.user.sendMail.from"><![CDATA[發送者]]></item>
+               <item name="wcf.acp.user.sendMail.from.description"><![CDATA[<p>你可以用這樣的格式填寫發送者資訊:</p><p><strong>發送者名字 &lt;發送者Email&gt;</strong></p><p>如果你在後臺系統設置裏的 系統 -> 選項 -> 郵件已經設置好了郵件發送選項, 這裏將會自動按照已經設置好的進行發送. 如果你選擇通過SMTP方式發送郵件, 那麼你在這裏填寫的發送者郵件地址也必須被SMTP伺服器接受.</p>]]></item>
+               <item name="wcf.acp.user.sendMail.group"><![CDATA[給用戶組成員發郵件]]></item>
+               <item name="wcf.acp.user.sendMail.groups"><![CDATA[給下列用戶組成員發送郵件]]></item>
+               <item name="wcf.acp.user.sendMail.mail"><![CDATA[E-Mail]]></item>
+               <item name="wcf.acp.user.sendMail.markedUsers"><![CDATA[給下列用戶發送E-Mail]]></item>
+               <item name="wcf.acp.user.sendMail.subject"><![CDATA[主題]]></item>
+               <item name="wcf.acp.user.sendMail.subject.description"><![CDATA[輸入E-mail主題.]]></item>
+               <item name="wcf.acp.user.sendMail.text"><![CDATA[消息]]></item>
+               <item name="wcf.acp.user.sendMail.text.description"><![CDATA[輸入郵件內容.]]></item>
+               <item name="wcf.acp.user.userNote"><![CDATA[{$this->user->username}, 你好.]]></item>
+       </category>
+       <category name="wcf.acp.worker">
+               <item name="wcf.acp.worker.currentStep"><![CDATA[當前進度]]></item>
+               <item name="wcf.acp.worker.description"><![CDATA[操作完成之前請勿關閉流覽器. 請勿再開啟新視窗進入後臺系統設置, 那樣將可能導致當前操作失敗.]]></item>
+               <item name="wcf.acp.worker.progress.finish"><![CDATA[操作成功]]></item>
+               <item name="wcf.acp.worker.progress.working"><![CDATA[操作進行中 ...]]></item>
+               <item name="wcf.acp.worker.progressBar"><![CDATA[{@$progress}% 完成]]></item>
+               <item name="wcf.acp.worker.title"><![CDATA[操作進行中 ...]]></item>
+       </category>
+       <category name="wcf.global">
+               <item name="wcf.global.button.back"><![CDATA[&laquo; 後退]]></item>
+               <item name="wcf.global.button.close"><![CDATA[關閉]]></item>
+               <item name="wcf.global.button.collapse"><![CDATA[Collapse]]></item>
+               <item name="wcf.global.button.collapsible"><![CDATA[Expand or collapse]]></item>
+               <item name="wcf.global.button.delete"><![CDATA[刪除]]></item>
+               <item name="wcf.global.button.delete.confirm"><![CDATA[你確認刪除該條目?]]></item>
+               <item name="wcf.global.button.deleteCompletely"><![CDATA[徹底刪除]]></item>
+               <item name="wcf.global.button.edit"><![CDATA[編輯]]></item>
+               <item name="wcf.global.button.editor.jump"><![CDATA[使用高級編輯器]]></item>
+               <item name="wcf.global.button.expand"><![CDATA[Expand]]></item>
+               <item name="wcf.global.button.mark"><![CDATA[選擇]]></item>
+               <item name="wcf.global.button.next"><![CDATA[下一步 &raquo;]]></item>
+               <item name="wcf.global.button.preview"><![CDATA[預覽]]></item>
+               <item name="wcf.global.button.reset"><![CDATA[重置]]></item>
+               <item name="wcf.global.button.submit"><![CDATA[提交]]></item>
+               <item name="wcf.global.button.unmark"><![CDATA[取消選擇]]></item>
+               <item name="wcf.global.date.day"><![CDATA[天]]></item>
+               <item name="wcf.global.date.days"><![CDATA[天]]></item>
+               <item name="wcf.global.date.hour"><![CDATA[小時]]></item>
+               <item name="wcf.global.date.hours"><![CDATA[小時]]></item>
+               <item name="wcf.global.date.minute"><![CDATA[分鐘]]></item>
+               <item name="wcf.global.date.minutes"><![CDATA[分鐘]]></item>
+               <item name="wcf.global.date.month"><![CDATA[月]]></item>
+               <item name="wcf.global.date.months"><![CDATA[月]]></item>
+               <item name="wcf.global.date.second"><![CDATA[秒]]></item>
+               <item name="wcf.global.date.seconds"><![CDATA[秒]]></item>
+               <item name="wcf.global.date.week"><![CDATA[星期]]></item>
+               <item name="wcf.global.date.weeks"><![CDATA[星期]]></item>
+               <item name="wcf.global.date.year"><![CDATA[年]]></item>
+               <item name="wcf.global.date.year.notRequired"><![CDATA[你的生日]]></item>
+               <item name="wcf.global.date.years"><![CDATA[年]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>今天</b>, g:ia]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[昨天, g:ia]]></item>
+               <item name="wcf.global.dateInputOrder"><![CDATA[month-day-year]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.defaultValue"><![CDATA[默認的]]></item>
+               <item name="wcf.global.error.backward"><![CDATA[返回上頁.]]></item>
+               <item name="wcf.global.error.empty"><![CDATA[請填寫必填資訊.]]></item>
+               <item name="wcf.global.error.file.notFound"><![CDATA[無法找到文件.]]></item>
+               <item name="wcf.global.error.illegalLink"><![CDATA[該鏈結無效.]]></item>
+               <item name="wcf.global.error.permissionDenied"><![CDATA[無權查看, 你沒有查看此頁所需的許可權.]]></item>
+               <item name="wcf.global.error.permissionDenied.title"><![CDATA[你無權查看此頁.]]></item>
+               <item name="wcf.global.error.title"><![CDATA[錯誤資訊]]></item>
+               <item name="wcf.global.form.error"><![CDATA[資料填寫錯誤. 請檢查表單中有標記處的資訊.]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[阿拉伯語]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[波士尼亞語]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[捷克語]]></item>
+               <item name="wcf.global.language.da"><![CDATA[丹麥語]]></item>
+               <item name="wcf.global.language.de"><![CDATA[德語]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[德語 (非正式的)]]></item>
+               <item name="wcf.global.language.el"><![CDATA[希臘語]]></item>
+               <item name="wcf.global.language.en"><![CDATA[英語]]></item>
+               <item name="wcf.global.language.es"><![CDATA[西班牙語]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[波斯語]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[芬蘭語]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[法語]]></item>
+               <item name="wcf.global.language.he"><![CDATA[希伯來語]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[克羅地亞語]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[匈牙利語]]></item>
+               <item name="wcf.global.language.it"><![CDATA[義大利語]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[日語]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[韓語]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[荷蘭語]]></item>
+               <item name="wcf.global.language.no"><![CDATA[挪威語]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[波蘭語]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[葡萄牙語]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[葡萄牙語]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[羅馬尼亞語]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[俄語]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[斯洛伐克語]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[塞爾維亞語]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[瑞典語]]></item>
+               <item name="wcf.global.language.th"><![CDATA[泰文]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[土耳其語]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[簡體中文]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[繁體中文]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[zh_TW]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[chinese-traditional]]></item>
+               <item name="wcf.global.multiSelect"><![CDATA[按下&quot;Ctrl/Shift&quot;(Windows)或是&quot;Command&quot; (Mac OS) 鍵可以選擇多個項目.]]></item>
+               <item name="wcf.global.page.input"><![CDATA[跳轉到下一頁]]></item>
+               <item name="wcf.global.page.next"><![CDATA[下一頁]]></item>
+               <item name="wcf.global.page.previous"><![CDATA[上一頁]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.pageTitle"><![CDATA[WoltLab Community Framework]]></item>
+               <item name="wcf.global.redirect.title"><![CDATA[跳轉至]]></item>
+               <item name="wcf.global.redirect.url"><![CDATA[如果頁面沒有自動跳轉,請點擊這裏!]]></item>
+               <item name="wcf.global.scrollUp"><![CDATA[至頁面頂部]]></item>
+               <item name="wcf.global.search.matchesExactly"><![CDATA[精確匹配]]></item>
+               <item name="wcf.global.shortTimeFormat"><![CDATA[M jS Y, g:ia]]></item>
+               <item name="wcf.global.shortTimeFormatLocalized"><![CDATA[%e. %B %Y, %H:%M]]></item>
+               <item name="wcf.global.skipToContent"><![CDATA[跳過導航]]></item>
+               <item name="wcf.global.sortOrder.ascending"><![CDATA[昇冪]]></item>
+               <item name="wcf.global.sortOrder.descending"><![CDATA[降冪]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>
+       </category>
+       <category name="wcf.imageViewer">
+               <item name="wcf.imageViewer.caption"><![CDATA[this.links.length > 1 ? "Image " + (this.currentIndex + 1) + " of " + this.links.length + (this.currentLink.title ? (" - " + this.currentLink.title) : "") : (this.currentLink.title ? this.currentLink.title : "")]]></item>
+               <item name="wcf.imageViewer.close"><![CDATA[關閉]]></item>
+               <item name="wcf.imageViewer.enlarge"><![CDATA[顯示該圖片(退出幻燈片流覽)]]></item>
+               <item name="wcf.imageViewer.next"><![CDATA[後一張]]></item>
+               <item name="wcf.imageViewer.pause"><![CDATA[停止幻燈片播放]]></item>
+               <item name="wcf.imageViewer.play"><![CDATA[開始幻燈片播放(5秒每張)]]></item>
+               <item name="wcf.imageViewer.previous"><![CDATA[前一張]]></item>
+       </category>
+       <category name="wcf.option">
+               <item name="wcf.option.timezone.utc"><![CDATA[(格林尼治標準時) 西歐時間、倫敦、卡薩布蘭卡]]></item>
+               <item name="wcf.option.timezone.utc+01:00"><![CDATA[(標準時+1:00) 中歐時間、安哥拉、利比亞]]></item>
+               <item name="wcf.option.timezone.utc+02:00"><![CDATA[(標準時+2:00) 東歐時間、加里寧格勒、南非]]></item>
+               <item name="wcf.option.timezone.utc+03:00"><![CDATA[(標準時+3:00) 巴格達、科威特、利雅得、莫斯科]]></item>
+               <item name="wcf.option.timezone.utc+03:30"><![CDATA[(標準時+3:30) 德黑蘭]]></item>
+               <item name="wcf.option.timezone.utc+04:00"><![CDATA[(標準時+4:00) 阿布扎比、馬斯喀特、巴庫]]></item>
+               <item name="wcf.option.timezone.utc+04:30"><![CDATA[(標準時+4:30) 喀布爾]]></item>
+               <item name="wcf.option.timezone.utc+05:00"><![CDATA[(標準時+5:00) 葉卡捷琳堡、伊斯蘭堡、卡拉奇]]></item>
+               <item name="wcf.option.timezone.utc+05:30"><![CDATA[(標準時+5:30) 孟買、加爾各答、新德里]]></item>
+               <item name="wcf.option.timezone.utc+05:45"><![CDATA[(標準時+05:45) 加德滿都]]></item>
+               <item name="wcf.option.timezone.utc+06:00"><![CDATA[(標準時+6:00) 科倫波、 達卡、新亞伯利亞]]></item>
+               <item name="wcf.option.timezone.utc+06:30"><![CDATA[(標準時+06:30) 基林群島, 仰光]]></item>
+               <item name="wcf.option.timezone.utc+07:00"><![CDATA[(標準時+7:00) 曼谷、河內、雅加達]]></item>
+               <item name="wcf.option.timezone.utc+08:00"><![CDATA[(標準時+8:00) 北京、佩思、新加坡、香港]]></item>
+               <item name="wcf.option.timezone.utc+08:45"><![CDATA[(標準時+08:45) 尤克拉 (西澳大利亞)]]></item>
+               <item name="wcf.option.timezone.utc+09:00"><![CDATA[(標準時+9:00) 東京、漢城、大阪、亞庫次克]]></item>
+               <item name="wcf.option.timezone.utc+09:30"><![CDATA[(標準時+9:30) 阿德萊德、達爾文]]></item>
+               <item name="wcf.option.timezone.utc+10:00"><![CDATA[(標準時+10:00) 澳大利亞東部、關島]]></item>
+               <item name="wcf.option.timezone.utc+10:30"><![CDATA[(標準時+10:30) 豪勳爵島 (澳大利亞)]]></item>
+               <item name="wcf.option.timezone.utc+11:00"><![CDATA[(標準時+11:00) 馬加丹、索羅門群島]]></item>
+               <item name="wcf.option.timezone.utc+11:30"><![CDATA[(標準時+11:30) 諾福克島]]></item>
+               <item name="wcf.option.timezone.utc+12:00"><![CDATA[(標準時+12:00) 奧克蘭、惠靈頓、堪察加半島]]></item>
+               <item name="wcf.option.timezone.utc+12:45"><![CDATA[(標準時+12:45) 查塔姆群島 (新西蘭東部)]]></item>
+               <item name="wcf.option.timezone.utc+13:00"><![CDATA[(標準時+13:00) 阿洛, 風凰島]]></item>
+               <item name="wcf.option.timezone.utc+14:00"><![CDATA[(標準時+14:00) 萊恩群島, 聖誕島]]></item>
+               <item name="wcf.option.timezone.utc-01:00"><![CDATA[(標準時-1:00) 亞速爾群島、佛德角群島]]></item>
+               <item name="wcf.option.timezone.utc-02:00"><![CDATA[(標準時-2:00) 中大西洋]]></item>
+               <item name="wcf.option.timezone.utc-03:00"><![CDATA[(標準時-3:00) 巴西、布宜諾賽勒斯、喬治敦]]></item>
+               <item name="wcf.option.timezone.utc-03:30"><![CDATA[(標準時-3:30) 紐芬蘭]]></item>
+               <item name="wcf.option.timezone.utc-04:00"><![CDATA[(標準時-4:00) 大西洋時間(加拿大)、加拉加斯]]></item>
+               <item name="wcf.option.timezone.utc-04:30"><![CDATA[(標準時-04:30) Caracas]]></item>
+               <item name="wcf.option.timezone.utc-05:00"><![CDATA[(標準時-5:00) 東部時間(美國和加拿大)、波哥大]]></item>
+               <item name="wcf.option.timezone.utc-06:00"><![CDATA[(標準時-6:00) 中部時間(美國和加拿大)、墨西哥城]]></item>
+               <item name="wcf.option.timezone.utc-07:00"><![CDATA[(標準時-7:00) 山地時間(美國和加拿大)]]></item>
+               <item name="wcf.option.timezone.utc-08:00"><![CDATA[(標準時-8:00) 美國西部標準時間(美國和加拿大)]]></item>
+               <item name="wcf.option.timezone.utc-09:00"><![CDATA[(標準時-9:00) 阿拉斯加]]></item>
+               <item name="wcf.option.timezone.utc-09:30"><![CDATA[(標準時-09:30) 法屬波利尼西亞]]></item>
+               <item name="wcf.option.timezone.utc-10:00"><![CDATA[(標準時-10:00) 夏威夷]]></item>
+               <item name="wcf.option.timezone.utc-11:00"><![CDATA[(標準時-11:00) 中途島、薩摩亞群島]]></item>
+               <item name="wcf.option.timezone.utc-12:00"><![CDATA[(標準時-12:00) 艾尼威多克、誇賈林環礁]]></item>
+       </category>
+       <category name="wcf.page">
+               <item name="wcf.page.pageNo"><![CDATA[第 {#$pageNo} 頁]]></item>
+       </category>
+       <category name="wcf.user">
+               <item name="wcf.user.confirmEmail"><![CDATA[確認E-Mail 地址]]></item>
+               <item name="wcf.user.confirmPassword"><![CDATA[確認密碼]]></item>
+               <item name="wcf.user.email"><![CDATA[E-Mail]]></item>
+               <item name="wcf.user.error.confirmEmail.notEqual"><![CDATA[E-Mail 驗證不符.]]></item>
+               <item name="wcf.user.error.confirmPassword.notEqual"><![CDATA[密碼驗證不符.]]></item>
+               <item name="wcf.user.error.email.notUnique"><![CDATA[該 E-Mail 已存在.]]></item>
+               <item name="wcf.user.error.email.notValid"><![CDATA[E-Mail 輸入無效.]]></item>
+               <item name="wcf.user.error.password.false"><![CDATA[密碼錯誤.]]></item>
+               <item name="wcf.user.error.username.notFound"><![CDATA[用戶 &quot;{$username}&quot; 找不到.]]></item>
+               <item name="wcf.user.error.username.notUnique"><![CDATA[你輸入的用戶名已存在.]]></item>
+               <item name="wcf.user.error.username.notValid"><![CDATA[用戶名輸入無效.]]></item>
+               <item name="wcf.user.language"><![CDATA[語言]]></item>
+               <item name="wcf.user.language.description"><![CDATA[請選擇一個論壇介面語言!]]></item>
+               <item name="wcf.user.logout"><![CDATA[註銷]]></item>
+               <item name="wcf.user.password"><![CDATA[密碼]]></item>
+               <item name="wcf.user.registrationDate"><![CDATA[註冊日期]]></item>
+               <item name="wcf.user.userID"><![CDATA[UID]]></item>
+               <item name="wcf.user.username"><![CDATA[用戶名]]></item>
+               <item name="wcf.user.visibleLanguages"><![CDATA[顯示以下語言的帖子]]></item>
+               <item name="wcf.user.visibleLanguages.description"><![CDATA[請選擇一個語言, 屬於該語言的帖子將會被顯示.]]></item>
+       </category>
+       <category name="wcf.user.option">
+               <item name="wcf.user.option.error.validationFailed"><![CDATA[資訊輸入無效.]]></item>
+       </category>
+</language>
\ No newline at end of file
diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql
new file mode 100644 (file)
index 0000000..536cb53
--- /dev/null
@@ -0,0 +1,827 @@
+/**** tables ****/\r
+DROP TABLE IF EXISTS wcf1_acp_menu_item;\r
+CREATE TABLE wcf1_acp_menu_item (\r
+       menuItemID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       menuItem VARCHAR(255) NOT NULL DEFAULT '',\r
+       parentMenuItem VARCHAR(255) NOT NULL DEFAULT '',\r
+       menuItemLink VARCHAR(255) NOT NULL DEFAULT '',\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       UNIQUE KEY menuItem (menuItem, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_acp_session;\r
+CREATE TABLE wcf1_acp_session (\r
+       sessionID CHAR(40) NOT NULL PRIMARY KEY,\r
+       packageID INT(10),\r
+       userID INT(10),\r
+       ipAddress VARCHAR(39) NOT NULL DEFAULT '',\r
+       userAgent VARCHAR(255) NOT NULL DEFAULT '',\r
+       lastActivityTime INT(10) NOT NULL DEFAULT 0,\r
+       requestURI VARCHAR(255) NOT NULL DEFAULT '',\r
+       requestMethod VARCHAR(4) NOT NULL DEFAULT '',\r
+       username VARCHAR(255) NOT NULL DEFAULT '',\r
+       KEY sessionID (sessionID, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_acp_session_data;\r
+CREATE TABLE wcf1_acp_session_data (\r
+       sessionID CHAR(40) NOT NULL PRIMARY KEY,\r
+       sessionVariables MEDIUMTEXT\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_acp_session_access_log;\r
+CREATE TABLE wcf1_acp_session_access_log (\r
+       sessionAccessLogID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       sessionLogID INT(10) NOT NULL,\r
+       packageID INT(10),\r
+       ipAddress VARCHAR(39) NOT NULL DEFAULT '',\r
+       time INT(10) NOT NULL DEFAULT 0,\r
+       requestURI VARCHAR(255) NOT NULL DEFAULT '',\r
+       requestMethod VARCHAR(4) NOT NULL DEFAULT '',\r
+       className VARCHAR(255) NOT NULL DEFAULT '',\r
+       KEY sessionLogID (sessionLogID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_acp_session_log;\r
+CREATE TABLE wcf1_acp_session_log (\r
+       sessionLogID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       sessionID CHAR(40) NOT NULL DEFAULT '',\r
+       userID INT(10),\r
+       ipAddress VARCHAR(39) NOT NULL DEFAULT '',\r
+       hostname VARCHAR(255) NOT NULL DEFAULT '',\r
+       userAgent VARCHAR(255) NOT NULL DEFAULT '',\r
+       time INT(10) NOT NULL DEFAULT 0,\r
+       lastActivityTime INT(10) NOT NULL DEFAULT 0,\r
+       KEY sessionID (sessionID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_acp_template;\r
+CREATE TABLE wcf1_acp_template (\r
+       templateID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10),\r
+       templateName VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY (packageID, templateName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_application;\r
+CREATE TABLE wcf1_application (\r
+       packageID INT(10) NOT NULL PRIMARY KEY,\r
+       domainName VARCHAR(255) NOT NULL,\r
+       domainPath VARCHAR(255) NOT NULL DEFAULT '/',\r
+       groupID INT(10),\r
+       isPrimary TINYINT(1) NOT NULL DEFAULT 0\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_application_group;\r
+CREATE TABLE wcf1_application_group (\r
+       groupID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       groupName VARCHAR(255) NOT NULL\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_cache_resource;\r
+CREATE TABLE wcf1_cache_resource (\r
+       cacheResource VARCHAR(255) NOT NULL PRIMARY KEY\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_cleanup_listener;\r
+CREATE TABLE wcf1_cleanup_listener (\r
+       listenerID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       className VARCHAR(255) NOT NULL DEFAULT '',\r
+       objectType VARCHAR(255) NOT NULL DEFAULT '',\r
+       lastUpdateTime INT(10) NOT NULL DEFAULT 0,\r
+       UNIQUE KEY (className, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_cleanup_log;\r
+CREATE TABLE wcf1_cleanup_log (\r
+       packageID INT(10) NOT NULL DEFAULT 0,\r
+       objectType VARCHAR(255) NOT NULL DEFAULT '',\r
+       objectID INT(10) NOT NULL DEFAULT 0,\r
+       deleteTime INT(10) NOT NULL DEFAULT 0,\r
+       KEY objectType (objectType)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_core_object;\r
+CREATE TABLE wcf1_core_object (\r
+       objectID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       objectName VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY object (packageID, objectName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_cronjob;\r
+CREATE TABLE wcf1_cronjob (\r
+       cronjobID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       className varchar(255) NOT NULL DEFAULT '',\r
+       packageID INT(10) NOT NULL,\r
+       description varchar(255) NOT NULL DEFAULT '',\r
+       startMinute varchar(255) NOT NULL DEFAULT '*',\r
+       startHour varchar(255) NOT NULL DEFAULT '*',\r
+       startDom varchar(255) NOT NULL DEFAULT '*',\r
+       startMonth varchar(255) NOT NULL DEFAULT '*',\r
+       startDow varchar(255) NOT NULL DEFAULT '*',\r
+       lastExec INT(10) NOT NULL DEFAULT 0,\r
+       nextExec INT(10) NOT NULL DEFAULT 0,\r
+       afterNextExec INT(10) NOT NULL DEFAULT 0,\r
+       active TINYINT NOT NULL DEFAULT 1,\r
+       canBeEdited TINYINT NOT NULL DEFAULT 1,\r
+       canBeDisabled TINYINT NOT NULL DEFAULT 1,\r
+       state TINYINT(1) NOT NULL DEFAULT 1,\r
+       failCount TINYINT(1) NOT NULL DEFAULT 0\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_cronjob_log;\r
+CREATE TABLE wcf1_cronjob_log (\r
+       cronjobLogID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       cronjobID INT(10) NOT NULL,\r
+       execTime INT(10) NOT NULL DEFAULT 0,\r
+       success TINYINT NOT NULL DEFAULT 0,\r
+       error TEXT\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_event_listener;\r
+CREATE TABLE wcf1_event_listener (\r
+       listenerID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       eventClassName VARCHAR(80) NOT NULL DEFAULT '',\r
+       eventName VARCHAR(50) NOT NULL DEFAULT '',\r
+       listenerClassName VARCHAR(200) NOT NULL DEFAULT '',\r
+       inherit TINYINT(1) NOT NULL DEFAULT 0,\r
+       niceValue TINYINT(3) NOT NULL DEFAULT 0,\r
+       UNIQUE KEY packageID (packageID, eventClassName, eventName, listenerClassName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_language;\r
+CREATE TABLE wcf1_language (\r
+       languageID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       languageCode VARCHAR(20) NOT NULL DEFAULT '',\r
+       isDefault TINYINT(1) NOT NULL DEFAULT 0,\r
+       hasContent TINYINT(1) NOT NULL DEFAULT 0,\r
+       UNIQUE KEY languageCode (languageCode)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_language_category;\r
+CREATE TABLE wcf1_language_category (\r
+       languageCategoryID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       languageCategory VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY languageCategory (languageCategory)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_language_item;\r
+CREATE TABLE wcf1_language_item (\r
+       languageItemID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       languageID INT(10) NOT NULL,\r
+       languageItem VARCHAR(255) NOT NULL DEFAULT '',\r
+       languageItemValue MEDIUMTEXT NOT NULL,\r
+       languageCustomItemValue MEDIUMTEXT,\r
+       languageUseCustomValue TINYINT(1) NOT NULL DEFAULT 0,\r
+       languageItemOriginIsSystem TINYINT(1) NOT NULL DEFAULT 1,\r
+       languageCategoryID INT(10) NOT NULL,\r
+       packageID INT(10),\r
+       UNIQUE KEY languageItem (languageItem, packageID, languageID),\r
+       KEY languageItemOriginIsSystem (languageItemOriginIsSystem)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_language_server;\r
+CREATE TABLE wcf1_language_server (\r
+       languageServerID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       serverURL VARCHAR(255) NOT NULL DEFAULT '',\r
+       disabled TINYINT(1) NOT NULL DEFAULT 0\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_language_to_package;\r
+CREATE TABLE wcf1_language_to_package (\r
+       languageID INT(10) NOT NULL,\r
+       packageID INT(10),\r
+       UNIQUE KEY languageID (languageID, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_option;\r
+CREATE TABLE wcf1_option (\r
+       optionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       optionName VARCHAR(255) NOT NULL DEFAULT '',\r
+       categoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       optionType VARCHAR(255) NOT NULL DEFAULT '',\r
+       optionValue MEDIUMTEXT,\r
+       validationPattern TEXT,\r
+       selectOptions MEDIUMTEXT,\r
+       enableOptions MEDIUMTEXT,\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       hidden TINYINT(1) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       additionalData MEDIUMTEXT,\r
+       UNIQUE KEY optionName (optionName, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_option_category;\r
+CREATE TABLE wcf1_option_category (\r
+       categoryID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       categoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       parentCategoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       UNIQUE KEY categoryName (categoryName, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package;\r
+CREATE TABLE wcf1_package (\r
+       packageID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       package VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageDir VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageName VARCHAR(255) NOT NULL DEFAULT '',\r
+       instanceName VARCHAR(255) NOT NULL DEFAULT '',\r
+       instanceNo INT(10) NOT NULL DEFAULT 1,\r
+       packageDescription VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageVersion VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageDate INT(10) NOT NULL DEFAULT 0,\r
+       installDate INT(10) NOT NULL DEFAULT 0,\r
+       updateDate INT(10) NOT NULL DEFAULT 0,\r
+       packageURL VARCHAR(255) NOT NULL DEFAULT '',\r
+       parentPackageID INT(10) NOT NULL DEFAULT 0,\r
+       isUnique TINYINT(1) NOT NULL DEFAULT 0,\r
+       standalone TINYINT(1) NOT NULL DEFAULT 0,\r
+       author VARCHAR(255) NOT NULL DEFAULT '',\r
+       authorURL VARCHAR(255) NOT NULL DEFAULT '',\r
+       KEY package (package)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_dependency;\r
+CREATE TABLE wcf1_package_dependency (\r
+       packageID INT(10) NOT NULL,\r
+       dependency INT(10) NOT NULL,\r
+       priority INT(10) NOT NULL DEFAULT 0,\r
+       UNIQUE KEY packageID (packageID, dependency)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_exclusion;\r
+CREATE TABLE wcf1_package_exclusion (\r
+       packageID INT(10) NOT NULL,\r
+       excludedPackage VARCHAR(255) NOT NULL DEFAULT '',\r
+       excludedPackageVersion VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageID (packageID, excludedPackage)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_installation_file_log;\r
+CREATE TABLE wcf1_package_installation_file_log (\r
+       packageID INT(10),\r
+       filename VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageID (packageID, filename)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_installation_form;\r
+CREATE TABLE wcf1_package_installation_form (\r
+       queueID INT(10) NOT NULL,\r
+       formName VARCHAR(80) NOT NULL DEFAULT '',\r
+       document TEXT NOT NULL,\r
+       UNIQUE KEY formDocument (queueID, formName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_installation_node;\r
+CREATE TABLE wcf1_package_installation_node (\r
+       queueID INT(10) NOT NULL,\r
+       processNo INT(10) NOT NULL DEFAULT 0,\r
+       sequenceNo SMALLINT(4) NOT NULL DEFAULT 0,\r
+       node CHAR(8) NOT NULL DEFAULT '',\r
+       parentNode CHAR(8) NOT NULL DEFAULT '',\r
+       nodeType ENUM('package', 'pip') NOT NULL DEFAULT 'package',\r
+       nodeData TEXT NOT NULL,\r
+       done TINYINT(1) NOT NULL DEFAULT 0\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_installation_plugin;\r
+CREATE TABLE wcf1_package_installation_plugin (\r
+       pluginName VARCHAR(255) NOT NULL PRIMARY KEY,\r
+       packageID INT(10),\r
+       priority TINYINT(1) NOT NULL DEFAULT 0,\r
+       className VARCHAR(255) NOT NULL\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_installation_queue;\r
+CREATE TABLE wcf1_package_installation_queue (\r
+       queueID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       parentQueueID INT(10) NOT NULL DEFAULT 0,\r
+       processNo INT(10) NOT NULL DEFAULT 0,\r
+       userID INT(10) NOT NULL,\r
+       package VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageName VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageID INT(10),\r
+       archive VARCHAR(255) NOT NULL DEFAULT '',\r
+       action ENUM('install', 'update', 'uninstall', 'rollback') NOT NULL DEFAULT 'install',\r
+       cancelable TINYINT(1) NOT NULL DEFAULT 1,\r
+       done TINYINT(1) NOT NULL DEFAULT 0,\r
+       confirmInstallation TINYINT(1) NOT NULL DEFAULT 0,\r
+       packageType ENUM('default', 'requirement', 'optional') NOT NULL DEFAULT 'default'\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_installation_sql_log;\r
+CREATE TABLE wcf1_package_installation_sql_log ( \r
+       packageID INT(10), \r
+       sqlTable VARCHAR(100) NOT NULL DEFAULT '', \r
+       sqlColumn VARCHAR(100) NOT NULL DEFAULT '', \r
+       sqlIndex VARCHAR(100) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageID (packageID, sqlTable, sqlColumn, sqlIndex) \r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_requirement;\r
+CREATE TABLE wcf1_package_requirement (\r
+       packageID INT(10) NOT NULL,\r
+       requirement INT(10) NOT NULL,\r
+       UNIQUE KEY packageID (packageID, requirement)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_requirement_map;\r
+CREATE TABLE wcf1_package_requirement_map (\r
+       packageID INT(10) NOT NULL,\r
+       requirement INT(10) NOT NULL,\r
+       level INT(10) NOT NULL DEFAULT 0,\r
+       UNIQUE KEY packageID (packageID, requirement)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_update;\r
+CREATE TABLE wcf1_package_update (\r
+       packageUpdateID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageUpdateServerID INT(10) NOT NULL,\r
+       package VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageName VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageDescription VARCHAR(255) NOT NULL DEFAULT '',\r
+       author VARCHAR(255) NOT NULL DEFAULT '',\r
+       authorURL VARCHAR(255) NOT NULL DEFAULT '',\r
+       standalone TINYINT(1) NOT NULL DEFAULT 0,\r
+       plugin VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageUpdateServerID (packageUpdateServerID, package)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_update_exclusion;\r
+CREATE TABLE wcf1_package_update_exclusion (\r
+       packageUpdateVersionID INT(10) NOT NULL,\r
+       excludedPackage VARCHAR(255) NOT NULL DEFAULT '',\r
+       excludedPackageVersion VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageUpdateVersionID (packageUpdateVersionID, excludedPackage)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_update_fromversion;\r
+CREATE TABLE wcf1_package_update_fromversion (\r
+       packageUpdateVersionID INT(10) NOT NULL DEFAULT 0,\r
+       fromversion VARCHAR(50) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageUpdateVersionID (packageUpdateVersionID, fromversion)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_update_requirement;\r
+CREATE TABLE wcf1_package_update_requirement (\r
+       packageUpdateVersionID INT(10) NOT NULL,\r
+       package VARCHAR(255) NOT NULL DEFAULT '',\r
+       minversion VARCHAR(50) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageUpdateVersionID (packageUpdateVersionID, package)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_update_server;\r
+CREATE TABLE wcf1_package_update_server (\r
+       packageUpdateServerID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       serverURL VARCHAR(255) NOT NULL DEFAULT '',\r
+       loginUsername VARCHAR(255) NOT NULL DEFAULT '',\r
+       loginPassword VARCHAR(255) NOT NULL DEFAULT '',\r
+       disabled TINYINT(1) NOT NULL DEFAULT 0,\r
+       lastUpdateTime INT(10) NOT NULL DEFAULT 0,\r
+       status ENUM('online', 'offline') NOT NULL DEFAULT 'online',\r
+       errorMessage TEXT\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_package_update_version;\r
+CREATE TABLE wcf1_package_update_version (\r
+       packageUpdateVersionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageUpdateID INT(10) NOT NULL,\r
+       packageVersion VARCHAR(50) NOT NULL DEFAULT '',\r
+       updateType VARCHAR(10) NOT NULL DEFAULT '',\r
+       packageDate INT(10) NOT NULL DEFAULT 0,\r
+       filename VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY packageUpdateID (packageUpdateID, packageVersion)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_page_location;\r
+CREATE TABLE wcf1_page_location (\r
+       locationID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       locationPattern VARCHAR(255) NOT NULL DEFAULT '',\r
+       locationName VARCHAR(255) NOT NULL DEFAULT '',\r
+       packageID INT(10) NOT NULL,\r
+       className varchar(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY (packageID, locationName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_page_menu_item;\r
+CREATE TABLE wcf1_page_menu_item (\r
+       menuItemID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       menuItem VARCHAR(255) NOT NULL DEFAULT '',\r
+       parentMenuItem VARCHAR(255) NOT NULL DEFAULT '',\r
+       menuItemLink VARCHAR(255) NOT NULL DEFAULT '',\r
+       menuPosition ENUM('header', 'footer') NOT NULL DEFAULT 'header',\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       permissions TEXT NULL,\r
+       options TEXT NULL,\r
+       isDisabled TINYINT(1) NOT NULL DEFAULT 0,\r
+       className VARCHAR(255) NOT NULL DEFAULT '',\r
+       UNIQUE KEY (packageID, menuItem)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_search;\r
+CREATE TABLE wcf1_search (\r
+       searchID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       userID INT(10),\r
+       searchData MEDIUMTEXT NOT NULL,\r
+       searchTime INT(10) NOT NULL DEFAULT 0,\r
+       searchType VARCHAR(255) NOT NULL DEFAULT '',\r
+       searchHash CHAR(40) NOT NULL DEFAULT '',\r
+       KEY searchHash (searchHash)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_session;\r
+CREATE TABLE wcf1_session (\r
+       sessionID CHAR(40) NOT NULL PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       userID INT(10),\r
+       ipAddress VARCHAR(39) NOT NULL DEFAULT '',\r
+       userAgent VARCHAR(255) NOT NULL DEFAULT '',\r
+       lastActivityTime INT(10) NOT NULL DEFAULT 0,\r
+       requestURI VARCHAR(255) NOT NULL DEFAULT '',\r
+       requestMethod VARCHAR(4) NOT NULL DEFAULT '',\r
+       username VARCHAR(255) NOT NULL DEFAULT '',\r
+       spiderID INT(10) NOT NULL DEFAULT 0,\r
+       KEY packageID (packageID, lastActivityTime, spiderID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_session_data;\r
+CREATE TABLE wcf1_session_data (\r
+       sessionID CHAR(40) NOT NULL PRIMARY KEY,\r
+       sessionVariables MEDIUMTEXT\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_spider;\r
+CREATE TABLE wcf1_spider (\r
+       spiderID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       spiderIdentifier VARCHAR(255) DEFAULT '',\r
+       spiderName VARCHAR(255) DEFAULT '',\r
+       spiderURL VARCHAR(255) DEFAULT '',\r
+       UNIQUE KEY spiderIdentifier (spiderIdentifier)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_style;\r
+CREATE TABLE wcf1_style (\r
+       styleID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       styleName VARCHAR(255) NOT NULL DEFAULT '',\r
+       templateGroupID INT(10) NOT NULL DEFAULT 0,\r
+       isDefault TINYINT(1) NOT NULL DEFAULT 0,\r
+       disabled TINYINT(1) NOT NULL DEFAULT 0,\r
+       styleDescription TEXT,\r
+       styleVersion VARCHAR(255) NOT NULL DEFAULT '',\r
+       styleDate CHAR(10) NOT NULL DEFAULT '0000-00-00',\r
+       image VARCHAR(255) NOT NULL DEFAULT '',\r
+       copyright VARCHAR(255) NOT NULL DEFAULT '',\r
+       license VARCHAR(255) NOT NULL DEFAULT '',\r
+       authorName VARCHAR(255) NOT NULL DEFAULT '',\r
+       authorURL VARCHAR(255) NOT NULL DEFAULT ''\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_style_to_package;\r
+CREATE TABLE wcf1_style_to_package (\r
+       styleID INT(10) NOT NULL,\r
+       packageID INT(10) NOT NULL,\r
+       isDefault TINYINT(1) NOT NULL DEFAULT 0,\r
+       disabled TINYINT(1) NOT NULL DEFAULT 0,\r
+       UNIQUE KEY (styleID, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_style_variable;\r
+CREATE TABLE wcf1_style_variable (\r
+       styleID INT(10) NOT NULL,\r
+       variableName VARCHAR(50) NOT NULL DEFAULT '',\r
+       variableValue MEDIUMTEXT,\r
+       UNIQUE KEY (styleID, variableName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_style_variable_to_attribute;\r
+CREATE TABLE wcf1_style_variable_to_attribute (\r
+       packageID INT(10) NOT NULL,\r
+       cssSelector VARCHAR(200) NOT NULL DEFAULT '',\r
+       attributeName VARCHAR(50) NOT NULL DEFAULT '',\r
+       variableName VARCHAR(50) NOT NULL DEFAULT '',\r
+       UNIQUE KEY (packageID, cssSelector, attributeName, variableName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_template;\r
+CREATE TABLE wcf1_template (\r
+       templateID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       templateName VARCHAR(255) NOT NULL DEFAULT '',\r
+       templateGroupID INT(10),\r
+       obsolete TINYINT(1) NOT NULL DEFAULT 0,\r
+       KEY packageID (packageID, templateName),\r
+       KEY templateGroupID (packageID, templateGroupID, templateName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_template_group;\r
+CREATE TABLE wcf1_template_group (\r
+       templateGroupID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       parentTemplateGroupID INT(10) NOT NULL DEFAULT 0,\r
+       templateGroupName VARCHAR(255) NOT NULL DEFAULT '',\r
+       templateGroupFolderName VARCHAR(255) NOT NULL DEFAULT ''\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user;\r
+CREATE TABLE wcf1_user (\r
+       userID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       username VARCHAR(255) NOT NULL DEFAULT '',\r
+       email VARCHAR(255) NOT NULL DEFAULT '',\r
+       password VARCHAR(40) NOT NULL DEFAULT '',\r
+       salt VARCHAR(40) NOT NULL DEFAULT '',\r
+       languageID INT(10) NOT NULL DEFAULT 0,\r
+       registrationDate INT(10) NOT NULL DEFAULT 0,\r
+       styleID INT(10) NOT NULL DEFAULT 0,\r
+       \r
+       KEY username (username),\r
+       KEY registrationDate (registrationDate),\r
+       KEY styleID (styleID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_group;\r
+CREATE TABLE wcf1_user_group (\r
+       groupID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       groupName VARCHAR(255) NOT NULL DEFAULT '',\r
+       groupType TINYINT(1) NOT NULL DEFAULT 0\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_group_option;\r
+CREATE TABLE wcf1_user_group_option  (\r
+       optionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10),\r
+       optionName VARCHAR(255) NOT NULL DEFAULT '',\r
+       categoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       optionType VARCHAR(255) NOT NULL DEFAULT '',\r
+       defaultValue MEDIUMTEXT,\r
+       adminDefaultValue MEDIUMTEXT,\r
+       validationPattern TEXT,\r
+       enableOptions MEDIUMTEXT,\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       additionalData MEDIUMTEXT,\r
+       UNIQUE KEY optionName (optionName, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_group_option_category;\r
+CREATE TABLE wcf1_user_group_option_category (\r
+       categoryID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       categoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       parentCategoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       UNIQUE KEY categoryName (categoryName, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_group_option_value;\r
+CREATE TABLE wcf1_user_group_option_value  (\r
+       groupID INT(10) NOT NULL,\r
+       optionID INT(10) NOT NULL,\r
+       optionValue MEDIUMTEXT NOT NULL,\r
+       UNIQUE KEY groupID (groupID, optionID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_option;\r
+CREATE TABLE wcf1_user_option (\r
+       optionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       optionName VARCHAR(255) NOT NULL DEFAULT '',\r
+       categoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       optionType VARCHAR(255) NOT NULL DEFAULT '',\r
+       defaultValue MEDIUMTEXT,\r
+       validationPattern TEXT,\r
+       selectOptions MEDIUMTEXT,\r
+       enableOptions MEDIUMTEXT,\r
+       required TINYINT(1) NOT NULL DEFAULT 0,\r
+       askDuringRegistration TINYINT(1) NOT NULL DEFAULT 0,\r
+       editable TINYINT(1) NOT NULL DEFAULT 0, \r
+       visible TINYINT(1) NOT NULL DEFAULT 0, \r
+       outputClass VARCHAR(255) NOT NULL DEFAULT '',\r
+       searchable TINYINT(1) NOT NULL DEFAULT 0,\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       disabled TINYINT(1) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       additionalData MEDIUMTEXT,\r
+       UNIQUE KEY optionName (optionName, packageID),\r
+       KEY categoryName (categoryName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_option_category;\r
+CREATE TABLE wcf1_user_option_category (\r
+       categoryID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       categoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       categoryIconS VARCHAR(255) NOT NULL DEFAULT '',\r
+       categoryIconM VARCHAR(255) NOT NULL DEFAULT '',\r
+       parentCategoryName VARCHAR(255) NOT NULL DEFAULT '',\r
+       showOrder INT(10) NOT NULL DEFAULT 0,\r
+       permissions TEXT,\r
+       options TEXT,\r
+       UNIQUE KEY categoryName (categoryName, packageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_option_value;\r
+CREATE TABLE wcf1_user_option_value (\r
+       userID INT(10) NOT NULL PRIMARY KEY\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_to_group;\r
+CREATE TABLE wcf1_user_to_group (\r
+       userID INT(10) NOT NULL,\r
+       groupID INT(10) NOT NULL,\r
+       UNIQUE KEY userID (userID, groupID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_user_to_language;\r
+CREATE TABLE wcf1_user_to_language (\r
+       userID INT(10) NOT NULL,\r
+       languageID INT(10) NOT NULL,\r
+       UNIQUE KEY userID (userID, languageID)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_template_listener;\r
+CREATE TABLE wcf1_template_listener (\r
+       listenerID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r
+       packageID INT(10) NOT NULL,\r
+       name VARCHAR(80) NOT NULL DEFAULT '',\r
+       environment ENUM('user','admin') NOT NULL DEFAULT 'user',\r
+       templateName VARCHAR(80) NOT NULL DEFAULT '',\r
+       eventName VARCHAR(50) NOT NULL DEFAULT '',\r
+       templateCode TEXT NOT NULL,\r
+       KEY templateName (environment, templateName)\r
+);\r
+\r
+DROP TABLE IF EXISTS wcf1_storage;\r
+CREATE TABLE wcf1_storage (\r
+       userID INT(10) NOT NULL,\r
+       field VARCHAR(80) NOT NULL DEFAULT '',\r
+       fieldValue TEXT,\r
+       packageID INT(10),\r
+       UNIQUE KEY storageData (userID, field, packageID)\r
+);\r
+\r
+/**** foreign keys ****/\r
+ALTER TABLE wcf1_acp_menu_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_acp_session ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_acp_session ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_acp_session_access_log ADD FOREIGN KEY (sessionLogID) REFERENCES wcf1_acp_session_log (sessionLogID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_acp_session_access_log ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE SET NULL;\r
+\r
+ALTER TABLE wcf1_acp_session_data ADD FOREIGN KEY (sessionID) REFERENCES wcf1_acp_session (sessionID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_acp_session_log ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE SET NULL;\r
+\r
+ALTER TABLE wcf1_acp_template ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_application ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_application ADD FOREIGN KEY (groupID) REFERENCES wcf1_application_group (groupID) ON DELETE SET NULL;\r
+\r
+ALTER TABLE wcf1_cleanup_listener ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_cleanup_log ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_core_object ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_cronjob ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_cronjob_log ADD FOREIGN KEY (cronjobID) REFERENCES wcf1_cronjob (cronjobID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_event_listener ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_language_item ADD FOREIGN KEY (languageID) REFERENCES wcf1_language (languageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_language_item ADD FOREIGN KEY (languageCategoryID) REFERENCES wcf1_language_category (languageCategoryID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_language_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_language_to_package ADD FOREIGN KEY (languageID) REFERENCES wcf1_language (languageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_language_to_package ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_option ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_option_category ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_dependency ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_package_dependency ADD FOREIGN KEY (dependency) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_exclusion ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_installation_file_log ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_installation_form ADD FOREIGN KEY (queueID) REFERENCES wcf1_package_installation_queue (queueID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_installation_node ADD FOREIGN KEY (queueID) REFERENCES wcf1_package_installation_queue (queueID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_installation_plugin ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_installation_queue ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_package_installation_queue ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE SET NULL;\r
+\r
+ALTER TABLE wcf1_package_installation_sql_log ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_requirement ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_package_requirement ADD FOREIGN KEY (requirement) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_requirement_map ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_package_requirement_map ADD FOREIGN KEY (requirement) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_update ADD FOREIGN KEY (packageUpdateServerID) REFERENCES wcf1_package_update_server (packageUpdateServerID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_update_exclusion ADD FOREIGN KEY (packageUpdateVersionID) REFERENCES wcf1_package_update_version (packageUpdateVersionID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_update_fromversion ADD FOREIGN KEY (packageUpdateVersionID) REFERENCES wcf1_package_update_version (packageUpdateVersionID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_update_requirement ADD FOREIGN KEY (packageUpdateVersionID) REFERENCES wcf1_package_update_version (packageUpdateVersionID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_package_update_version ADD FOREIGN KEY (packageUpdateID) REFERENCES wcf1_package_update (packageUpdateID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_page_location ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_page_menu_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_search ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_session ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_session ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_session_data ADD FOREIGN KEY (sessionID) REFERENCES wcf1_session (sessionID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_storage ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_storage ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_style ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_style_to_package ADD FOREIGN KEY (styleID) REFERENCES wcf1_style (styleID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_style_to_package ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_style_variable ADD FOREIGN KEY (styleID) REFERENCES wcf1_style (styleID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_style_variable_to_attribute ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_template ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_template ADD FOREIGN KEY (templateGroupID) REFERENCES wcf1_template_group (templateGroupID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_template_listener ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_group_option ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_group_option_category ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_group_option_value ADD FOREIGN KEY (groupID) REFERENCES wcf1_user_group (groupID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_user_group_option_value ADD FOREIGN KEY (optionID) REFERENCES wcf1_user_group_option (optionID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_option ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_option_category ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_option_value ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_to_group ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_user_to_group ADD FOREIGN KEY (groupID) REFERENCES wcf1_user_group (groupID) ON DELETE CASCADE;\r
+\r
+ALTER TABLE wcf1_user_to_language ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;\r
+ALTER TABLE wcf1_user_to_language ADD FOREIGN KEY (languageID) REFERENCES wcf1_language (languageID) ON DELETE CASCADE;\r
+\r
+/**** default inserts ****/\r
+-- default user groups\r
+INSERT INTO wcf1_user_group (groupName, groupType) VALUES ('Everyone', 1);\r
+INSERT INTO wcf1_user_group (groupName, groupType) VALUES ('Guests', 2);\r
+INSERT INTO wcf1_user_group (groupName, groupType) VALUES ('Users', 3);\r
+INSERT INTO wcf1_user_group (groupName, groupType) VALUES ('Administrators', 4);\r
+INSERT INTO wcf1_user_group (groupName, groupType) VALUES ('Moderators', 4);\r
+INSERT INTO wcf1_user_group (groupName, groupType) VALUES ('Super Moderators', 4);\r
+               \r
+-- default user group options\r
+INSERT INTO wcf1_user_group_option (optionName, categoryName, optionType, defaultValue, adminDefaultValue, showOrder) VALUES ('admin.general.canUseAcp', 'admin.general', 'boolean', '0', '1', 1);\r
+INSERT INTO wcf1_user_group_option (optionName, categoryName, optionType, defaultValue, adminDefaultValue, showOrder) VALUES ('admin.system.package.canInstallPackage', 'admin.system.package', 'boolean', '0', '1', 1);\r
+INSERT INTO wcf1_user_group_option (optionName, categoryName, optionType, defaultValue, adminDefaultValue, showOrder) VALUES ('admin.user.canEditGroup', 'admin.user.group', 'boolean', '0', '1', 1);\r
+\r
+-- default user group option values\r
+INSERT INTO wcf1_user_group_option_value (groupID, optionID, optionValue) VALUES (1, 1, '0');  -- Everyone\r
+INSERT INTO wcf1_user_group_option_value (groupID, optionID, optionValue) VALUES (1, 2, '0');  -- Everyone\r
+INSERT INTO wcf1_user_group_option_value (groupID, optionID, optionValue) VALUES (1, 3, '0');  -- Everyone\r
+INSERT INTO wcf1_user_group_option_value (groupID, optionID, optionValue) VALUES (4, 1, '1');  -- Administrators\r
+INSERT INTO wcf1_user_group_option_value (groupID, optionID, optionValue) VALUES (4, 2, '1');  -- Administrators\r
+INSERT INTO wcf1_user_group_option_value (groupID, optionID, optionValue) VALUES (4, 3, '1');  -- Administrators\r
+               \r
+-- default update servers\r
+INSERT INTO wcf1_package_update_server (serverURL, status, disabled, errorMessage, lastUpdateTime, loginUsername, loginPassword) VALUES ('http://update.woltlab.com/tempest/', 'online', 0, NULL, 0, '', '');\r
+INSERT INTO wcf1_package_update_server (serverURL, status, disabled, errorMessage, lastUpdateTime, loginUsername, loginPassword) VALUES ('http://update.woltlab.com/maelstrom/', 'online', 0, NULL, 0, '', '');\r
+INSERT INTO wcf1_package_update_server (serverURL, status, disabled, errorMessage, lastUpdateTime, loginUsername, loginPassword) VALUES ('http://store.woltlab.com/tempest/', 'online', 0, NULL, 0, '', '');\r
+INSERT INTO wcf1_package_update_server (serverURL, status, disabled, errorMessage, lastUpdateTime, loginUsername, loginPassword) VALUES ('http://store.woltlab.com/maelstrom/', 'online', 0, NULL, 0, '', '');\r
diff --git a/wcfsetup/setup/lang/setup_da.xml b/wcfsetup/setup/lang/setup_da.xml
new file mode 100644 (file)
index 0000000..75724d3
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="da">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Installation]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Installation]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.locale.unix"><![CDATA[da_DK]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.locale.win"><![CDATA[danish]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[.]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Næste &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% gennemført]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>I dag</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[I går, %H:%M]]></item>
+               <item name="wcf.global.welcome"><![CDATA[Tak for at du valgte {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[Denne installations-guide vil hjælpe dig gennem opsætningen af <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} og <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[Sprog]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Engelsk]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Tysk]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Tysk (Uformelt)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Fransk]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japansk]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Spansk]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Kinesisk (Traditionelt)]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Kinesisk (Forenklet)]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Italiensk]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Hollandsk]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Russisk]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Koreansk]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugisisk]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugisisk (Brasiliansk)]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Svensk]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polsk]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Dansk]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Tjekkisk]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Tyrkisk]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Ungarnsk]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arabisk]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hebraisk]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persisk]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norsk]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finsk]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Rumænsk]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosnisk]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Kroatisk]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Serbisk]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovakisk]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Græsk]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[Guidens nuværende sprog er sat til engelsk.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[Skift sprog]]></item>
+               <item name="wcf.global.license"><![CDATA[Licens aftale]]></item>
+               <item name="wcf.global.license.description"><![CDATA[Læs venligst følgende licens aftale. Benyt scrollbaren for at se hele dokumentet.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[Accepterer du licensaftalens bestemmelser og vilkår? Du må kun installere softwaren, hvis du accepterer licens aftalen.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[Du skal acceptere licens aftalen for at kunne fortsætte med denne installation.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[Tjekker system forudsætninger]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Dette er system forudsætningerne:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Nødvendige system komponenter]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Anbefalede system komponenter]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Nødvendige:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Fundet:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Anbefalede:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Installeret version script sproget &quot;PHP&quot;]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[Den installerede version af script sproget &quot;PHP&quot; er for gammelt til en stabil afvikling af denne software. For at fortsætte installeringen er det nødvendigt at foretage en versions opdatering.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Din PHP version er forældet. For at afvikle denne software stabilt, anbefaler vi eb PHP version på 5.0.5 eller større.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[&quot;MySQL&quot; database understøttelse]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[&quot;MySQL&quot; database understøttelse er nødvendig for at kunne installere denn software.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Maksimal størrelse for upload af filer]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[Den nuværende opsætning af den installerede &quot;PHP&quot; gør det helt umuligt at uploade filer. På grund af denne opsætning, vil visse af softwarens muligheder være begrænsede.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Installeret version af grafik biblioteket &quot;GDLib&quot;]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[Grafik biblioteket &quot;GDLib&quot; anvendes til dynamisk oprettelse af billeder. Uden dette vil visse af softwarens muligheder ikke være tilgængelige.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Multibyte tegnsæt bibliotek &quot;MBString&quot;]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Uden dette bibliotek kan softwaren alene anvendes med Vest Europæiske sprog.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Sikkerhedsvalgmuligheden &quot;safe mode&quot; i &quot;PHP&quot; script sproget]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[For at garantere funktionaliteten af denne software, anbefaler vi at slå safe mode indstillingen fra.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Dataoverførselsbiblioteket til FTP]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Med sikkerhedsmuligheden &quot;safe mode&quot; aktiveret benyttes data overførselsbiblioteket til de fleste fil transaktioner i denne software. Vi anbefaler kraftigt at aktivere dette bibliotek.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Aktiveret]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Ikke aktiveret]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[Vælg installationsmappen]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[Alle filer i <b>WoltLab Community Framework</b> vil blive udpakket til installations mappen.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[The installation assistant has found previous install of the <b>WoltLab Community Framework</b> in the "{$foundDirectory}" folder.<br />If you would like to install a new copy of the <b>WoltLab Community Framework</b>, then please enter an alternative installation folder.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Installationsmappe]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Indtast venligst installations mappen til <b>WoltLab Community Framework</b>.]]></item>
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[Efter installation i den angivne mmappe, kan du få adgang til <b>WoltLab Community Framework</b> via følgende URL:]]></item>
+               <item name="wcf.global.wcfDir.error.invalid"><![CDATA[Den angivne mappe er ikke gyldig.]]></item>
+               <item name="wcf.global.ftp"><![CDATA[FTP adgangs information]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[Med PHP-SafeMode sikkerhedsmuligheden akiveret, kan WoltLab Community Framework kun installeres med hjælp af FTP funktionaliteten. Indtast venligst her FTP Brugernavn og Kodeord for denne server. Den indtastede information vil ikke blive gemt og er kun nødvendig for at kunne installere denne pakke. Af denne grund alene, vil du senere blive anmodet om at oplyse FTP brugernavn og kodeord.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[FTP adgangsinformation]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[Værtsnavn]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[Brugernavn]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[Kodeord]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[Der kunne ikke oprettes forbindelse til den anførte FTP server.]]></item>
+               <item name="wcf.global.next"><![CDATA[Indlæser næste trin ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[Installationen indlæser næste trin, vent venligst.]]></item>
+               <item name="wcf.global.languages"><![CDATA[Vælg de sprog, der skal installeres]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[Denne software kan understøtte flere sprog. Vælg venligst de sprog, som du vil installere.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[Tegnsætskodning]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[Tegnsætskodningen, også kendt som bare tegnsæt eller kodningssiden bestemmer  måden at gemme på og afspejler de installerede sprog på dette system. Vær venligst opmærksom på, at du ikke kan ændre din tegnsætskodning, efter systemet er blevet installeret.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 is required if you wish to install Western European languages only.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 is required if you wish to install Western European or any Non-Western European langauges, now or at a later date.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Vest Europæisk]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Central Europæisk]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Græsk]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebraisk]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Tyrkisk]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japansk]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japansk]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Kinesisk (Traditionelt)]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Kinesisk (Forenklet)]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Kinesisk (Forenklet)]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Kyrillisk]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Kyrillisk]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Koreansk]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[Sprog]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[Vælg venligst mindst et sproge!]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Sproget du har valgt modsvarer ikke den anførte tegnsætskodning, du tidligere har valgt. Tilret venligst dit valg af sprog.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[Opsæt databaseadgangen]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[Dataene i denne software skal gemmes i en MySQL database. Indtast venligst din database adgangsinformation!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Database adgangsinformation]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[Værtsnavn]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[Brugernavn]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[Kodeord]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[Databasenavn]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[Installationsnummer]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[Der er opstået en fejl under forsøget på at oprette forbindelse til din database:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />Yderligere information kan findes i WoltLabs fejlreference:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[Følgende tabel{if $conflictedTables|count > 1}ler{/if} findes allerede{if $conflictedTables|count == 1}s{/if} i din &quot;{$dbName}&quot; database:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />To solve this problem, please do one of the following:<br />1. Enable the &quot;Overwrite&quot; option below to overwrite {if $conflictedTables|count > 1}these tables{else}this table{/if} and continue the installation with the &quot;Next&quot; Button or<br />2. You re-enter the Database access information, but to a different Database and continue the installation with the &quot;Next&quot; Button or<br />3. You enter a new Installations number, not forgetting to continue the installation with the &quot;Next&quot; Button.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Overskriv de(n) ovenfor oplistede tabel{if $conflictedTables|count > 1}ler{/if}?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[Opret en administrator]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[Installationen vil nu oprette en administratorkonto til dig. Indtast venligst et brugernavn, e-mailadresse og et kodeord.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[Brugerinformation]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[Brugernavn]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[E-mail adresse]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[Bekræft e-mailadressen]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[Kodedord]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Bekræft kodeord]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[Der opstod fejl under registreringen aaf brugekontoen. Undersøg venligst de markerede felter for fejl.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Dette felt kan ikke forblive tomt.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[Det anførte brugernavn er ugyldigt. Et gyldigt brugernavn skal bestå af mellem 3 og 20 bogstaver.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[Den anførte e-mailadresse er ugyldig. EN gyldig e-mailadresse skal være i formatet navn@domæne .tld]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[De anførte e-mailadresser er ikke ens. Af sikkerhedsmæssigee årsager skal du forsikre dig om, at begge email adressefelter er blevet udfyldt og er identiske.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[De kodeord du har anført er ikke ens. Af sikkerhedsmæssigee årsager skal du forsikre dig om, at begge kodeordsfelter er blevet udfyldt og er identiske.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[Der er opstået en fejl i forbindelse med udpakningen af de nødvendige filer:
+               <br /><b>{$exception->getMessage()}</b><br />
+               Undersøg venligst om destinationsmappen eksisterer og at der kan skrives til den.
+               <br /><br />Yderligere information kan findes i WoltLabs fejlreference:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_de-informal.xml b/wcfsetup/setup/lang/setup_de-informal.xml
new file mode 100644 (file)
index 0000000..29692a6
--- /dev/null
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="de-informal">\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Installation]]></item>\r
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Installation]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[de_DE]]></item>\r
+               <item name="wcf.global.locale.win"><![CDATA[deu_deu]]></item>\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Weiter &raquo;]]></item>\r
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% fertiggestellt]]></item>\r
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>\r
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>\r
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Heute</b>, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Gestern, %H:%M]]></item>\r
+               <item name="wcf.global.welcome"><![CDATA[Vielen Dank, dass du dich für {$setupPackageName} entschieden hast]]></item>\r
+               <item name="wcf.global.welcome.description"><![CDATA[Dieser Installationsassistent hilft dir bei der Einrichtung von <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} und von <b>{$setupPackageName}</b>{/if}.]]></item>\r
+               <item name="wcf.global.welcome.language"><![CDATA[Sprache]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Englisch]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Deutsch]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Deutsch (Anrede &raquo;Du&laquo;)]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Französisch]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spanisch]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinesisch (traditionell)]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italienisch]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Niederländisch]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russisch]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Koreanisch]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portugiesisch]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugiesisch (Brasilien)]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Schwedisch]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polnisch]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Dänisch]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Tschechisch]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Türkisch]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungarisch]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabisch]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebräisch]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persisch]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norwegisch]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finnisch]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumänisch]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnisch]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Kroatisch]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbisch]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slowakisch]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Griechisch]]></item>\r
+               <item name="wcf.global.welcome.language.description"><![CDATA[Die Sprache dieses Assistenten ist zur Zeit Deutsch.]]></item>\r
+               <item name="wcf.global.welcome.language.change"><![CDATA[Sprache wechseln]]></item>\r
+               <item name="wcf.global.license"><![CDATA[Lizenzbestimmungen]]></item>\r
+               <item name="wcf.global.license.description"><![CDATA[Bitte lies die folgenden Lizenzbestimmungen. Verwende die Bildlaufleiste, um das gesamte Dokument anzuzeigen.]]></item>\r
+               <item name="wcf.global.license.accept.description"><![CDATA[Akzeptierst du sämtliche Bedingungen der Lizenzbestimmungen? Du kannst die Software nur installieren, wenn du die Lizenzbestimmungen akzeptierst.]]></item>\r
+               <item name="wcf.global.license.missingAcception"><![CDATA[Um mit der Installation fortfahren zu können, musst du die Lizenzbestimmungen akzeptieren.]]></item>\r
+               <item name="wcf.global.systemRequirements"><![CDATA[Überprüfung der Systemvoraussetzungen]]></item>\r
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Dies sind die Systemvoraussetzungen:]]></item>\r
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Benötigte Systemvoraussetzungen]]></item>\r
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Empfohlene Systemvoraussetzungen]]></item>\r
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Benötigt:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Gefunden:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Empfohlen:]]></item>\r
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Installierte Version der Skriptsprache &raquo;PHP&laquo;]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[Die installierte Version der Skriptsprache &raquo;PHP&laquo; ist für einen stabilen Betrieb dieser Software zu alt. Veranlasse eine Aktualisierung der installierten Version bevor du mit der Installation fortfährst.]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Deine PHP Version ist stark veraltet. Für einen einwandfreien Betrieb empfehlen wir PHP Version 5.0.5 oder höher.]]></item>\r
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[Unterstützung der &raquo;MySQL&laquo; Datenbank]]></item>\r
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[Ohne die Unterstützung der &raquo;MySQL&laquo; Datenbank kann diese Software nicht installiert werden.]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Maximale Größe für das Hochladen von Dateien]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[Die derzeitige Konfiguration der Skriptsprache &raquo;PHP&laquo; macht das Hochladen von Dateien unmöglich. Einige Funktionalitäten werden durch diese Konfiguration nur eingeschränkt funktionieren.]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Installierte Version der Grafikbearbeitungs-Bibliothek &raquo;gdlib&laquo;]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[Grafikbearbeitungs-Bibliothek &raquo;gdlib&laquo; ist für die dynamische Generierung von Bildern zuständig. Ohne sie werden einige Funktionalitäten der Software nicht funktionieren.]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Bibliothek für Zeichen mit mehreren Bytes (&raquo;multibyte string&laquo;)]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Ohne diese Bibliothek ist auschließlich der Betrieb von westeuropäischen Sprachen möglich.]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Sicherheitseinstellung &raquo;safe mode&laquo; in Skriptsprache &raquo;PHP&laquo;]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Es wird empfohlen diese Einstellung zu deaktivieren, da ansonsten ein einwandfreier Betrieb der Software nicht garantiert werden kann.]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Bibliothek für Datenübertragungen per FTP]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Bei der aktivierten Sicherheitseinstellung &raquo;safe mode&laquo; wird diese Bibliothek für einen Großteil der Dateioperationen der Software benutzt. Es wird dringend empfohlen, diese Bibliothek zu aktivieren.]]></item>\r
+               <item name="wcf.global.systemRequirements.active"><![CDATA[aktiviert]]></item>\r
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[nicht aktiviert]]></item>\r
+               <item name="wcf.global.wcfDir"><![CDATA[Installationsverzeichnis wählen]]></item>\r
+               <item name="wcf.global.wcfDir.description"><![CDATA[In das Installationsverzeichnis werden alle Dateien von <b>WoltLab Community Framework</b> entpackt.]]></item>\r
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[Die Installation vermutet eine bereits vorhandene Installation von <b>WoltLab Community Framework</b> im Ordner "{$foundDirectory}".<br />Überprüfe diese Angabe bzw. definiere ein anderes Installationsverzeichnis, wenn du eine neue Kopie von <b>WoltLab Community Framework</b> installieren möchtest.]]></item>\r
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Installationsverzeichnis]]></item>\r
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Gib hier das Installationsverzeichnis für <b>WoltLab Community Framework</b> an.]]></item>\r
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[Nach einer Installation in das angegebene Installationsverzeichnis ist <b>WoltLab Community Framework</b> über folgende Adresse (URL) erreichbar:]]></item>\r
+               <item name="wcf.global.wcfDir.error.invalid"><![CDATA[Das eingegebene Verzeichnis ist ungültig.]]></item>\r
+               <item name="wcf.global.ftp"><![CDATA[Eingabe der Zugangsdaten für FTP]]></item>\r
+               <item name="wcf.global.ftp.description"><![CDATA[Da auf deinem Server der PHP-SafeMode aktiviert ist, muss WoltLab Community Framework über die FTP-Funktionen installiert werden. Gib Benutzernamen und Kennwort für den FTP-Zugang zu diesem Server an. Die Daten werden nicht gespeichert oder weitergeleitet, sondern lediglich zur Installation dieses Paketes verwendet. Aus diesem Grunde musst du die FTP-Zugangsdaten evtl. auch mehrfach während dieser Installation angeben.]]></item>\r
+               <item name="wcf.global.ftp.accessData"><![CDATA[Zugangsdaten für FTP]]></item>\r
+               <item name="wcf.global.ftp.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.ftp.user"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.global.ftp.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.global.ftp.error"><![CDATA[Mit den angegebenen Zugangsdaten konnte keine Verbindung zu einem FTP-Server hergestellt werden.]]></item>\r
+               <item name="wcf.global.next"><![CDATA[Lade nächsten Schritt ...]]></item>\r
+               <item name="wcf.global.next.description"><![CDATA[Die Installation lädt im Moment den nächsten Schritt. Habe einen Augenblick Geduld.]]></item>\r
+               <item name="wcf.global.languages"><![CDATA[Sprachen wählen]]></item>\r
+               <item name="wcf.global.languages.description"><![CDATA[Du kannst diese Software mehrsprachig betreiben. Wähle aus, welche Sprachen du installieren möchtest.]]></item>\r
+               <item name="wcf.global.languages.charset"><![CDATA[Zeichenkodierung]]></item>\r
+               <item name="wcf.global.languages.charset.description"><![CDATA[Über die Zeichenkodierung wird die technische Speicherung und Darstellung von Sprachen beeinflusst. Beachte, dass die Zeichenkodierung zu einem späteren Zeitpunkt nicht mehr gewechselt werden kann.]]></item>\r
+               \r
+               <!-- <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Die Verwendung von ISO-8859-1 wird empfohlen, wenn du ausschließlich westeuropäische Sprachen installieren möchtest.]]></item>\r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 wird für den Betrieb von nicht westeuropäischen Sprachen benötigt. Wenn du jetzt oder zu einem späteren Zeitpunkt eine nicht westeuropäischen Sprache installieren möchtest, musst du hier UTF-8 auswählen.]]></item>-->\r
+               \r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Westeuropäisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Mitteleuropäisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Griechisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebräisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Türkisch]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Chinesisch (traditionell)]]></item>\r
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Kyrillisch]]></item>\r
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Kyrillisch]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Koreanisch]]></item>\r
+               \r
+               <item name="wcf.global.languages.languages"><![CDATA[Sprachen]]></item>\r
+               <item name="wcf.global.languages.error.empty"><![CDATA[Wähle mindestens eine Sprache aus!]]></item>\r
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Du hast Sprachen ausgewählt, die in der gleichzeitig ausgewählten Zeichencodierung nicht zur Verfügung stehen. Korrigiere deine Auswahl.]]></item>\r
+               <item name="wcf.global.configureDB"><![CDATA[Datenbankzugang konfigurieren]]></item>\r
+               <item name="wcf.global.configureDB.description"><![CDATA[Die Daten der Software werden in einer MySQL Datenbank gespeichert. Gib die Zugangsdaten für diese Datenbank an!]]></item>\r
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Datenbankzugangsdaten]]></item>\r
+               <item name="wcf.global.configureDB.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.configureDB.user"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.global.configureDB.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.global.configureDB.database"><![CDATA[Datenbankname]]></item>\r
+               <item name="wcf.global.configureDB.number"><![CDATA[Installationsnummer]]></item>\r
+               <item name="wcf.global.configureDB.error"><![CDATA[Beim Verbindungsversuch mit der Datenbank ist folgender Fehler aufgetreten:\r
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>\r
+               <br />Weitere Informationen zu diesem Problem erhältst du im Nachschlagewerk von WoltLab:\r
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[Folgende Tabelle{if $conflictedTables|count > 1}n{/if} existier{if $conflictedTables|count > 1}en{else}t{/if} schon in der Datenbank &raquo;{$dbName}&laquo;:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Um dieses Problem zu beheben, kannst du:<br />1. diese Tabelle{if $conflictedTables|count > 1}n{/if} überschreiben, indem du die &raquo;Überschreiben&laquo; Option aktivierst und die &raquo;Weiter&laquo; Schaltfläche betätigst, oder<br />2. Du gibst die Daten einer anderen Datenbank ein und betätigst die &raquo;Weiter&laquo; Schaltfläche, oder<br />3. Du gibst eine von &raquo;{$dbNumber}&laquo; unterschiedliche Installationsnummer an und betätigst die &raquo;Weiter&laquo; Schaltfläche.]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Oben genannte Tabelle{if $conflictedTables|count > 1}n{/if} überschreiben]]></item>\r
+               <item name="wcf.global.createUser"><![CDATA[Administrator erstellen]]></item>\r
+               <item name="wcf.global.createUser.description"><![CDATA[Der Installationsassistent erstellt nun ein Administrator-Konto für dich. Gib dazu einen Benutzernamen, eine E-Mail-Adresse und ein Kennwort ein.]]></item>\r
+               <item name="wcf.global.createUser.data"><![CDATA[Benutzerdaten]]></item>\r
+               <item name="wcf.global.createUser.username"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.global.createUser.email"><![CDATA[E-Mail-Adresse]]></item>\r
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[E-Mail-Adresse wiederholen]]></item>\r
+               <item name="wcf.global.createUser.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Kennwort wiederholen]]></item>\r
+               <item name="wcf.global.createUser.error"><![CDATA[Es sind Fehler bei deiner Registrierung aufgetreten. Überprüfe die markierten Felder.]]></item>\r
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Füll dieses Eingabefeld aus.]]></item>\r
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[Der eingegebene Benutzername ist ungültig. Ein gültiger Benutzername muss mindestens 3 und maximal 20 Zeichen lang sein.]]></item>\r
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[Die eingegebene E-Mail-Adresse ist ungültig. Eine gültige E-Mail-Adresse muss dem Format name@domain.tld entsprechen.]]></item>\r
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Die eingegebenen E-Mail-Adressen sind nicht identisch. Trage zur Sicherheit in beide Eingabefelder die selbe E-Mail-Adresse ein.]]></item>\r
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[Die eingegebenen Kennwörter sind nicht identisch. Trage zur Sicherheit in beide Eingabefelder das selbe Kennwort ein.]]></item>\r
+               <item name="wcf.global.wcfDir.error"><![CDATA[Beim Versuch die Dateien zu entpacken, ist folgender Fehler aufgetreten:\r
+               <br /><b>{$exception->getMessage()}</b><br />\r
+               Kontrolliere bitte, ob das Zielverzeichnis existiert und beschreibbar ist.\r
+               <br /><br />Weitere Informationen zu diesem Problem erhältst du im Nachschlagewerk von WoltLab:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+       </category>\r
+</language>\r
diff --git a/wcfsetup/setup/lang/setup_de.xml b/wcfsetup/setup/lang/setup_de.xml
new file mode 100644 (file)
index 0000000..5532018
--- /dev/null
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="de">\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Installation]]></item>\r
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Installation]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>\r
+               <item name="wcf.global.locale.unix"><![CDATA[de_DE]]></item>\r
+               <item name="wcf.global.locale.win"><![CDATA[deu_deu]]></item>\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Weiter &raquo;]]></item>\r
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% fertiggestellt]]></item>\r
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>\r
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>\r
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Heute</b>, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Gestern, %H:%M]]></item>\r
+               <item name="wcf.global.welcome"><![CDATA[Vielen Dank, dass Sie sich für {$setupPackageName} entschieden haben]]></item>\r
+               <item name="wcf.global.welcome.description"><![CDATA[Dieser Installationsassistent hilft Ihnen bei der Einrichtung von <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} und von <b>{$setupPackageName}</b>{/if}.]]></item>\r
+               <item name="wcf.global.welcome.language"><![CDATA[Sprache]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Englisch]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Deutsch]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Deutsch (Anrede &raquo;Du&laquo;)]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Französisch]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spanisch]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinesisch (traditionell)]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italienisch]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Niederländisch]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russisch]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Koreanisch]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portugiesisch]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugiesisch (Brasilien)]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Schwedisch]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polnisch]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Dänisch]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Tschechisch]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Türkisch]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungarisch]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabisch]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebräisch]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persisch]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norwegisch]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finnisch]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumänisch]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnisch]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Kroatisch]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbisch]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slowakisch]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Griechisch]]></item>\r
+               <item name="wcf.global.welcome.language.description"><![CDATA[Die Sprache dieses Assistenten ist zur Zeit Deutsch.]]></item>\r
+               <item name="wcf.global.welcome.language.change"><![CDATA[Sprache wechseln]]></item>\r
+               <item name="wcf.global.license"><![CDATA[Lizenzbestimmungen]]></item>\r
+               <item name="wcf.global.license.description"><![CDATA[Bitte lesen Sie die folgenden Lizenzbestimmungen. Verwenden Sie die Bildlaufleiste, um das gesamte Dokument anzuzeigen.]]></item>\r
+               <item name="wcf.global.license.accept.description"><![CDATA[Akzeptieren Sie sämtliche Bedingungen der Lizenzbestimmungen? Sie können die Software nur installieren, wenn Sie die Lizenzbestimmungen akzeptieren.]]></item>\r
+               <item name="wcf.global.license.missingAcception"><![CDATA[Um mit der Installation fortfahren zu können, müssen Sie die Lizenzbestimmungen akzeptieren.]]></item>\r
+               <item name="wcf.global.systemRequirements"><![CDATA[Überprüfung der Systemvoraussetzungen]]></item>\r
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Dies sind die Systemvoraussetzungen:]]></item>\r
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Benötigte Systemvoraussetzungen]]></item>\r
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Empfohlene Systemvoraussetzungen]]></item>\r
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Benötigt:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Gefunden:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Empfohlen:]]></item>\r
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Installierte Version der Skriptsprache &raquo;PHP&laquo;]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[Die installierte Version der Skriptsprache &raquo;PHP&laquo; ist für einen stabilen Betrieb dieser Software zu alt. Bitte veranlassen Sie eine Aktualisierung der installierten Version bevor Sie mit der Installation fortfahren.]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Ihre PHP Version ist stark veraltet. Für einen einwandfreien Betrieb empfehlen wir PHP Version 5.0.5 oder höher.]]></item>\r
+               <item name="wcf.global.systemRequirements.sql"><![CDATA[Datenbank-Unterstützung]]></item>\r
+               <item name="wcf.global.systemRequirements.sql.notFound"><![CDATA[nicht gefunden]]></item>\r
+               <item name="wcf.global.systemRequirements.sql.description"><![CDATA[Ohne die Unterstützung einer kompatiblen Datenbank kann diese Software nicht installiert werden.]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Maximale Größe für das Hochladen von Dateien]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[Die derzeitige Konfiguration der Skriptsprache &raquo;PHP&laquo; macht das Hochladen von Dateien unmöglich. Einige Funktionalitäten werden durch diese Konfiguration nur eingeschränkt funktionieren.]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Installierte Version der Grafikbearbeitungs-Bibliothek &raquo;gdlib&laquo;]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[Grafikbearbeitungs-Bibliothek &raquo;gdlib&laquo; ist für die dynamische Generierung von Bildern zuständig. Ohne sie werden einige Funktionalitäten der Software nicht funktionieren.]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Bibliothek für Zeichen mit mehreren Bytes (&raquo;multibyte string&laquo;)]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Ohne diese Bibliothek ist auschließlich der Betrieb von westeuropäischen Sprachen möglich.]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Sicherheitseinstellung &raquo;safe mode&laquo; in Skriptsprache &raquo;PHP&laquo;]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Es wird empfohlen diese Einstellung zu deaktivieren, da ansonsten ein einwandfreier Betrieb der Software nicht garantiert werden kann.]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Bibliothek für Datenübertragungen per FTP]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Bei der aktivierten Sicherheitseinstellung &raquo;safe mode&laquo; wird diese Bibliothek für einen Großteil der Dateioperationen der Software benutzt. Es wird dringend empfohlen, diese Bibliothek zu aktivieren.]]></item>\r
+               <item name="wcf.global.systemRequirements.active"><![CDATA[aktiviert]]></item>\r
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[nicht aktiviert]]></item>\r
+               <item name="wcf.global.wcfDir"><![CDATA[Installationsverzeichnis wählen]]></item>\r
+               <item name="wcf.global.wcfDir.description"><![CDATA[In das Installationsverzeichnis werden alle Dateien von <b>WoltLab Community Framework</b> entpackt.]]></item>\r
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[Die Installation vermutet eine bereits vorhandene Installation von <b>WoltLab Community Framework</b> im Ordner "{$foundDirectory}".<br />Bitte überprüfen Sie diese Angabe bzw. definieren Sie ein anderes Installationsverzeichnis, wenn Sie eine neue Kopie von <b>WoltLab Community Framework</b> installieren möchten.]]></item>\r
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Installationsverzeichnis]]></item>\r
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Bitte geben Sie hier das Installationsverzeichnis für <b>WoltLab Community Framework</b> an.]]></item>\r
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[Nach einer Installation in das angegebene Installationsverzeichnis ist <b>WoltLab Community Framework</b> über folgende Adresse (URL) erreichbar:]]></item>\r
+               <item name="wcf.global.wcfDir.error.invalid"><![CDATA[Das eingegebene Verzeichnis ist ungültig.]]></item>\r
+               <item name="wcf.global.ftp"><![CDATA[Eingabe der Zugangsdaten für FTP]]></item>\r
+               <item name="wcf.global.ftp.description"><![CDATA[Da auf Ihrem Server der PHP-SafeMode aktiviert ist, muss WoltLab Community Framework über die FTP-Funktionen installiert werden. Bitte geben Sie Benutzernamen und Kennwort für den FTP-Zugang zu diesem Server an. Die Daten werden nicht gespeichert oder weitergeleitet, sondern lediglich zur Installation dieses Paketes verwendet. Möglicherweise müssen Sie diese FTP-Zugangsdaten während dieser Installation mehrfach angeben.]]></item>\r
+               <item name="wcf.global.ftp.accessData"><![CDATA[Zugangsdaten für FTP]]></item>\r
+               <item name="wcf.global.ftp.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.ftp.user"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.global.ftp.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.global.ftp.error"><![CDATA[Mit den angegebenen Zugangsdaten konnte keine Verbindung zu einem FTP-Server hergestellt werden.]]></item>\r
+               <item name="wcf.global.next"><![CDATA[Lade nächsten Schritt ...]]></item>\r
+               <item name="wcf.global.next.description"><![CDATA[Die Installation lädt im Moment den nächsten Schritt. Bitte haben Sie einen Augenblick Geduld.]]></item>\r
+               <item name="wcf.global.languages"><![CDATA[Sprachen wählen]]></item>\r
+               <item name="wcf.global.languages.description"><![CDATA[Sie können diese Software mehrsprachig betreiben. Bitte wählen Sie aus, welche Sprachen Sie installieren möchten.]]></item>\r
+               <item name="wcf.global.languages.charset"><![CDATA[Zeichenkodierung]]></item>\r
+               <item name="wcf.global.languages.charset.description"><![CDATA[Über die Zeichenkodierung wird die technische Speicherung und Darstellung von Sprachen beeinflusst. Bitte beachten Sie, dass die Zeichenkodierung zu einem späteren Zeitpunkt nicht mehr gewechselt werden kann.]]></item>\r
+               \r
+               <!-- <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Die Verwendung von ISO-8859-1 wird empfohlen, wenn Sie ausschließlich westeuropäische Sprachen installieren möchten.]]></item>\r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 wird für den Betrieb von nicht westeuropäischen Sprachen benötigt. Wenn Sie jetzt oder zu einem späteren Zeitpunkt eine nicht westeuropäischen Sprache installieren möchten, müssen Sie hier UTF-8 auswählen.]]></item>-->\r
+               \r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Westeuropäisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Mitteleuropäisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Griechisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebräisch]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Türkisch]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japanisch]]></item>\r
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Chinesisch (traditionell)]]></item>\r
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Chinesisch (vereinfacht)]]></item>\r
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Kyrillisch]]></item>\r
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Kyrillisch]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Koreanisch]]></item>\r
+               \r
+               <item name="wcf.global.languages.languages"><![CDATA[Sprachen]]></item>\r
+               <item name="wcf.global.languages.error.empty"><![CDATA[Bitte wählen Sie mindestens eine Sprache aus!]]></item>\r
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Sie haben Sprachen ausgewählt, die in der gleichzeitig ausgewählten Zeichencodierung nicht zur Verfügung stehen. Bitte korrigieren Sie Ihre Auswahl.]]></item>\r
+               <item name="wcf.global.configureDB"><![CDATA[Datenbankzugang konfigurieren]]></item>\r
+               <item name="wcf.global.configureDB.description"><![CDATA[Die Daten der Software werden in einer SQL Datenbank gespeichert. Bitte geben Sie die Zugangsdaten für diese Datenbank an!]]></item>\r
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Datenbankzugangsdaten]]></item>\r
+               <item name="wcf.global.configureDB.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.configureDB.user"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.global.configureDB.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.global.configureDB.database"><![CDATA[Datenbankname]]></item>\r
+               <item name="wcf.global.configureDB.number"><![CDATA[Installationsnummer]]></item>\r
+               <item name="wcf.global.configureDB.error"><![CDATA[Beim Verbindungsversuch mit der Datenbank ist folgender Fehler aufgetreten:\r
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>\r
+               <br />Weitere Informationen zu diesem Problem erhalten Sie im Nachschlagewerk von WoltLab:\r
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[Folgende Tabelle{if $conflictedTables|count > 1}n{/if} existier{if $conflictedTables|count > 1}en{else}t{/if} schon in der Datenbank &raquo;{$dbName}&laquo;:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Um dieses Problem zu beheben, können Sie:<br />1. diese Tabelle{if $conflictedTables|count > 1}n{/if} überschreiben, indem Sie die &raquo;Überschreiben&laquo; Option aktivieren und die &raquo;Weiter&laquo; Schaltfläche betätigen, oder<br />2. Sie geben die Daten einer anderen Datenbank ein und betätigen die &raquo;Weiter&laquo; Schaltfläche, oder<br />3. Sie geben eine von &raquo;{$dbNumber}&laquo; unterschiedliche Installationsnummer an und betätigen die &raquo;Weiter&laquo; Schaltfläche.]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Oben genannte Tabelle{if $conflictedTables|count > 1}n{/if} überschreiben]]></item>\r
+               <item name="wcf.global.configureDB.class"><![CDATA[Datenbank-Typ]]></item>\r
+               <item name="wcf.global.configureDB.class.MSSQLDatabase"><![CDATA[Microsoft SQL Server 2008+]]></item>\r
+               <item name="wcf.global.configureDB.class.MySQLDatabase"><![CDATA[MySQL 5.1+]]></item>\r
+               <item name="wcf.global.configureDB.class.PostgreSQLDatabase"><![CDATA[PostgreSQL 8.2+]]></item>\r
+               <item name="wcf.global.createUser"><![CDATA[Administrator erstellen]]></item>\r
+               <item name="wcf.global.createUser.description"><![CDATA[Der Installationsassistent erstellt nun ein Administrator-Konto für Sie. Bitte geben Sie dazu einen Benutzernamen, eine E-Mail-Adresse und ein Kennwort ein.]]></item>\r
+               <item name="wcf.global.createUser.data"><![CDATA[Benutzerdaten]]></item>\r
+               <item name="wcf.global.createUser.username"><![CDATA[Benutzername]]></item>\r
+               <item name="wcf.global.createUser.email"><![CDATA[E-Mail-Adresse]]></item>\r
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[E-Mail-Adresse wiederholen]]></item>\r
+               <item name="wcf.global.createUser.password"><![CDATA[Kennwort]]></item>\r
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Kennwort wiederholen]]></item>\r
+               <item name="wcf.global.createUser.error"><![CDATA[Es sind Fehler bei Ihrer Registrierung aufgetreten. Bitte überprüfen Sie die markierten Felder.]]></item>\r
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Bitte füllen Sie dieses Eingabefeld aus.]]></item>\r
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[Der eingegebene Benutzername ist ungültig. Ein gültiger Benutzername muss mindestens 3 und maximal 20 Zeichen lang sein.]]></item>\r
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[Die eingegebene E-Mail-Adresse ist ungültig. Eine gültige E-Mail-Adresse muss dem Format name@domain.tld entsprechen.]]></item>\r
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Die eingegebenen E-Mail-Adressen sind nicht identisch. Bitte tragen Sie zur Sicherheit in beide Eingabefelder die selbe E-Mail-Adresse ein.]]></item>\r
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[Die eingegebenen Kennwörter sind nicht identisch. Bitte tragen Sie zur Sicherheit in beide Eingabefelder das selbe Kennwort ein.]]></item>\r
+               <item name="wcf.global.wcfDir.error"><![CDATA[Beim Versuch die Dateien zu entpacken, ist folgender Fehler aufgetreten:\r
+               <br /><b>{$exception->getMessage()}</b><br />\r
+               Bitte kontrollieren Sie, ob das Zielverzeichnis existiert und beschreibbar ist.\r
+               <br /><br />Weitere Informationen zu diesem Problem erhalten Sie im Nachschlagewerk von WoltLab:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+       </category>\r
+</language>\r
diff --git a/wcfsetup/setup/lang/setup_en.xml b/wcfsetup/setup/lang/setup_en.xml
new file mode 100644 (file)
index 0000000..2c36169
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="en">\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Installation]]></item>\r
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Installation]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.locale.unix"><![CDATA[en_US]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.locale.win"><![CDATA[english]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Next &raquo;]]></item>\r
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% complete]]></item>\r
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item> <!-- system variable; do not translate -->\r
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>\r
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>\T\o\d\a\y</b>, g:ia]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[\Y\e\s\t\e\r\d\a\y, g:ia]]></item>\r
+               <item name="wcf.global.welcome"><![CDATA[Thank you for choosing {$setupPackageName}]]></item>\r
+               <item name="wcf.global.welcome.description"><![CDATA[This installations-assistant will help you to setup <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} and <b>{$setupPackageName}</b>{/if}.]]></item>\r
+               <item name="wcf.global.welcome.language"><![CDATA[Language]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[English]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[German]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[German (Informal)]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[French]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Japanese]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spanish]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinese (Traditional)]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinese (Simplified)]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italian]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Dutch]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russian]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Korean]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portuguese]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portuguese (Brazil)]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Swedish]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polish]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Danish]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Czech]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Turkish]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Hungarian]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabic]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Hebrew]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persian]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norwegian]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finnish]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Romanian]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosnian]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Croatian]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbian]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slovak]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Greek]]></item>\r
+               <item name="wcf.global.welcome.language.description"><![CDATA[The assistants language is currently set to English.]]></item>\r
+               <item name="wcf.global.welcome.language.change"><![CDATA[Change language]]></item>\r
+               <item name="wcf.global.license"><![CDATA[License Agreement]]></item>\r
+               <item name="wcf.global.license.description"><![CDATA[Please read the following License Agreement. Use the scrollbar to view the whole document.]]></item>\r
+               <item name="wcf.global.license.accept.description"><![CDATA[Do you accept the terms and conditions of the License Agreement? You may only install this software upon acceptance of the License Agreement.]]></item>\r
+               <item name="wcf.global.license.missingAcception"><![CDATA[You must accept the License Agreement to continue this installation.]]></item>\r
+               <item name="wcf.global.systemRequirements"><![CDATA[Checking System Requirements]]></item>\r
+               <item name="wcf.global.systemRequirements.description"><![CDATA[These are the System Requirements:]]></item>\r
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Required System component]]></item>\r
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Recommended System component]]></item>\r
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Required:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Found:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Recommended:]]></item>\r
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Installed version of the Script language &quot;PHP&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[The installed version of the Script language &quot;PHP&quot; is too old for a stable operation of this Software. To proceed with the installation, a version update is necessary.]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Your PHP Version is obsolete. For a stable operation of this Software, we recommend a PHP version of 5.0.5 or greater.]]></item>\r
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[&quot;MySQL&quot; Database support]]></item>\r
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[&quot;MySQL&quot; Database support is required to install this Software.]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Maximum size for file uploads]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[The current configuration of the installed &quot;PHP&quot; makes it impossible to upload any files. Due to this configuration, some features of this Software will be restricted.]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Installed version of the graphics library &quot;GDLib&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[The graphics library &quot;GDLib&quot; is needed for the Dynamic Generation of Images. Without this, some features of this Software will not be available.]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[The multibyte character library &quot;MBString&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Without this library, the Software can only be used with Western European languages.]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Security option of &quot;safe mode&quot; in the &quot;PHP&quot; Script language]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[To quarantee the operation of this Software, we recommend to disable the safe mode setting.]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[The data transfer library for FTP]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[With the security option of &quot;safe mode&quot; being enabled, the data transfer library is needed for most of the file operations within this Software. We strongly recommend to enable this library.]]></item>\r
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Enabled]]></item>\r
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Not enabled]]></item>\r
+               <item name="wcf.global.wcfDir"><![CDATA[Choose the installation folder]]></item>\r
+               <item name="wcf.global.wcfDir.description"><![CDATA[All files of <b>WoltLab Community Framework</b> will be extracted into the installation folder.]]></item>\r
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[The installation assistant has found a previous installation of <b>WoltLab Community Framework</b> in the "{$foundDirectory}" folder.<br />If you would like to install a new copy of the <b>WoltLab Community Framework</b>, then please enter an alternative installation folder.]]></item>\r
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Installation folder]]></item>\r
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Please enter the installation folder for <b>WoltLab Community Framework</b>.]]></item>\r
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[After installation into the given folder you can access <b>WoltLab Community Framework</b> through the following URL:]]></item>\r
+               <item name="wcf.global.wcfDir.error.invalid"><![CDATA[The given folder is not valid.]]></item>\r
+               <item name="wcf.global.ftp"><![CDATA[FTP access information]]></item>\r
+               <item name="wcf.global.ftp.description"><![CDATA[With the PHP-SafeMode security option being enabled, WoltLab Community Framework can only be installed using FTP functionality. Please enter here the FTP Username and Password for this Server. The information given will not be saved and is only required for the installation of this Package. For this reason alone, further FTP Username and Password requests will be needed.]]></item>\r
+               <item name="wcf.global.ftp.accessData"><![CDATA[FTP access information]]></item>\r
+               <item name="wcf.global.ftp.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.ftp.user"><![CDATA[Username]]></item>\r
+               <item name="wcf.global.ftp.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.global.ftp.error"><![CDATA[A connection to the given FTP server could not be made.]]></item>\r
+               <item name="wcf.global.next"><![CDATA[Loading next step ...]]></item>\r
+               <item name="wcf.global.next.description"><![CDATA[The installation is currently loading the next step, please wait.]]></item>\r
+               <item name="wcf.global.languages"><![CDATA[Choose languages to install]]></item>\r
+               <item name="wcf.global.languages.description"><![CDATA[This Software can support multiple languages. Please choose the languages you would like to install.]]></item>\r
+               <item name="wcf.global.languages.charset"><![CDATA[Character Encoding]]></item>\r
+               <item name="wcf.global.languages.charset.description"><![CDATA[The Character Encoding, also known as the Character Set or the Code page determines the storage type and the representation of the installed languages of this System. Please be aware that once you have set your chosen Character Encoding, this can not be changed afterwards.]]></item>\r
+               \r
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 is required if you wish to install Western European languages only.]]></item>\r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 is required if you wish to install Western European or any Non-Western European langauges, now or at a later date.]]></item>-->\r
+               \r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Western European]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Central European]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Greek]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebrew]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Turkish]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japanese]]></item>\r
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japanese]]></item>\r
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Chinese (Traditional)]]></item>\r
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Chinese (Simplified)]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Chinese (Simplified)]]></item>\r
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Cyrillic]]></item>\r
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Cyrillic]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Korean]]></item>\r
+               \r
+               <item name="wcf.global.languages.languages"><![CDATA[Languages]]></item>\r
+               <item name="wcf.global.languages.error.empty"><![CDATA[Please choose at least one language!]]></item>\r
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[The languages you have chosen do not correspond to the given Character Encoding you made previously. Please amend your language choice.]]></item>\r
+               <item name="wcf.global.configureDB"><![CDATA[Configure Database access]]></item>\r
+               <item name="wcf.global.configureDB.description"><![CDATA[The Data for this Software needs to be stored in a MySQL Database. Please enter your Database access information!]]></item>\r
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Database access information]]></item>\r
+               <item name="wcf.global.configureDB.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.configureDB.user"><![CDATA[Username]]></item>\r
+               <item name="wcf.global.configureDB.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.global.configureDB.database"><![CDATA[Database name]]></item>\r
+               <item name="wcf.global.configureDB.number"><![CDATA[Installations number]]></item>\r
+               <item name="wcf.global.configureDB.error"><![CDATA[An Error has accured while trying to connect to your Database:\r
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>\r
+               <br />Additional information can be found in the WoltLab Error Reference:\r
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[The following table{if $conflictedTables|count > 1}s{/if} already exist{if $conflictedTables|count == 1}s{/if} within your &quot;{$dbName}&quot; Database:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />To solve this problem, please do one of the following:<br />1. Enable the &quot;Overwrite&quot; option below to overwrite {if $conflictedTables|count > 1}these tables{else}this table{/if} and continue the installation with the &quot;Next&quot; Button or<br />2. You re-enter the Database access information, but to a different Database and continue the installation with the &quot;Next&quot; Button or<br />3. You enter a new Installations number, not forgetting to continue the installation with the &quot;Next&quot; Button.]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Overwrite the above listed table{if $conflictedTables|count > 1}s{/if}?]]></item>\r
+               <item name="wcf.global.createUser"><![CDATA[Create an Administrator]]></item>\r
+               <item name="wcf.global.createUser.description"><![CDATA[The Installation will now generate an Administrator account for you. Please give a username, email address and password.]]></item>\r
+               <item name="wcf.global.createUser.data"><![CDATA[User information]]></item>\r
+               <item name="wcf.global.createUser.username"><![CDATA[Username]]></item>\r
+               <item name="wcf.global.createUser.email"><![CDATA[E-Mail Address]]></item>\r
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[Confirm E-Mail Address]]></item>\r
+               <item name="wcf.global.createUser.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Confirm Password]]></item>\r
+               <item name="wcf.global.createUser.error"><![CDATA[Errors have accured while registering the User account, please check the marked fields for errors.]]></item>\r
+               <item name="wcf.global.createUser.error.empty"><![CDATA[This field can not be left empty.]]></item>\r
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[The Username you have given is invalid. A valid Username must be between 3 and 20 characters long.]]></item>\r
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[The E-Mail Address you have given is invalid. A valid E-Mail Address must be in the format of name@domain.tld]]></item>\r
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[The E-Mail Addresses you have given are not identical. For security reasons, please make sure that both E-Mail Address fields have been filled in and are identical.]]></item>\r
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[The Passwords you have given are not identical. For security reasons, please make sure that both Password fields have been filled in and are identical.]]></item>\r
+               <item name="wcf.global.wcfDir.error"><![CDATA[An Error has accured while extracting the required files:\r
+               <br /><b>{$exception->getMessage()}</b><br />\r
+               Please make sure that the destination folder exists and can be written to.\r
+               <br /><br />Additional information can be found in the WoltLab Error Reference:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+       </category>\r
+</language>\r
diff --git a/wcfsetup/setup/lang/setup_fr.xml b/wcfsetup/setup/lang/setup_fr.xml
new file mode 100644 (file)
index 0000000..7350168
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="fr">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[Installation de {$setupPackageName}]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Installation]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[fr_FR]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[french]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Suivant &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% achevé]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d. %m. %Y, %H:%M]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Aujourd’hui</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Hier, %H:%M]]></item>
+               <item name="wcf.global.welcome"><![CDATA[Merci d’avoir choisi {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[Cet assistant d’installation vous guidera dans la configuration de<br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} et de <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[Langue]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Anglais]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Allemand]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Allemand (Informel)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Français]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japonais]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Espagnol]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinois (traditionnel)]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinois (Simplifié)]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Italien]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Néerlandais]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Russe]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Coréen]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugais]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portuguese (Brazil)]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Suédois]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polonais]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danois]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Tchéque]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turque]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Hongrois]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arabe]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hébreu]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persan]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norvégien]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finnois]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Roumain]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosnien]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Croate]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Serbe]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovaque]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grec]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[La langue de l’assistant est actuellement le français.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[Changer de langue]]></item>
+               <item name="wcf.global.license"><![CDATA[Contrat de licence]]></item>
+               <item name="wcf.global.license.description"><![CDATA[Veuillez lire le contrat de licence suivant. Utilisez la barre de défillement pour visualiser le document dans son ensemble.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[Acceptez vous les termes et conditions du contrat de licence ? Vous ne pouvez installer ce logiciel qu’après avoir accepté le contrat de licence.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[Vous devez accepter le contrat de licence pour continuer cette installation.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[Contrôle des spécifications requises]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Configuration requise :]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Configuration système requise]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Configuration système recommandée]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Requis :]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Trouvé :]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Recommandé :]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Version du langage script &quot;PHP&quot; installé]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[La version du langage script &quot;PHP&quot; présente est trop ancienne pour un fonctionnement normal de ce logiciel. Pour procéder à l’installation, une mise à jour est nécessaire.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Votre version PHP est obsolète. Pour une utilisation normale de ce logiciel, il est recommandé d’utiliser la version 5.0.5 de PHP, ou supérieur.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[Support de base de données &quot;MySQL&quot; ]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[Le support de base de données &quot;MySQL&quot; est nécessaire à l’installation de ce logiciel.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Taille maximale pour l’envoie de fichiers]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[La configuration actuelle du &quot;PHP&quot; installé rend impossible l’envoi de fichiers. En raison de cette configuration, certaines fonctionnalités de ce logiciel seront limitées.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Version de la librairie graphique &quot;GDLib&quot; installée]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[La librairie graphique &quot;GDLib&quot; est nécessaire pour la génération dynamique des images. Sans cette librairie, certaines fonctionnalités de ce logiciel ne seront pas disponibles.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Librairie de caractères multi-octets &quot;MBString&quot;]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Sans cette librairie, le logiciel ne peut être utilisé qu’avec les langues européennes occidentales.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Option de sécurité du &quot;Safe Mode&quot; dans le langage &quot;PHP&quot;]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Pour garantir un bon fonctionnement de ce logiciel, nous vous conseillons de désactiver les paramètres &quot;Safe Mode&quot;]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Librairie de transfert de données FTP]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Si vous avez activé l’option de sécurité &quot;Safe Mode&quot;, la librairie de transfert de donnée est nécessaire pour la plupart des opérations sur des fichiers. Nous vous conseillons fortement d’activer cette librairie.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Activé]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Non activé]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[Choix du répertoire d’installation]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[Tous les fichiers de <b>WoltLab Community Framework</b> seront extraits dans le répertoire d’installation.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[L’assistant d’installation a trouvé une installation du <b>WoltLab Community Framework</b> dans le répertoire  "{$foundDirectory}" .<br />Si vous voulez installer une nouvelle copie de <b>WoltLab Community Framework</b>, veuillez spécifier un autre répertoire d’installation.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Répertoire d’installation]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Veuillez indiquer le répertoire où vous voulez installer le <b>WoltLab Community Framework</b>.]]></item>
+               <item name="wcf.global.ftp"><![CDATA[Informations d’accès FTP]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[Si vous avez activé l’option de sécurité PHP &quot;Safe Mode&quot;, le WoltLab Community Framework ne peut être installé que par l’intermédiaire des fonctionnalités FTP. Veuillez entrer les identifiants et mots de passe FTP pour ce serveur. Les informations données ne seront pas enregistrées et sont seulement nécessaires à l’installation de ce paquet. Pour cette raison, il vous sera nécessaire de donner à nouveau vos identifiants FTP pour la suite de l’installation.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[Information d’accès FTP]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[Nom d’hôte]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[Identifiant]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[Impossible de se connecter au serveur FTP indiqué.]]></item>
+               <item name="wcf.global.next"><![CDATA[Chargement de la prochaine étape ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[Chargement de la prochaine étape d’installation. Veuillez patienter.]]></item>
+               <item name="wcf.global.languages"><![CDATA[Choix des langues à installer]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[Ce logiciel peut prendre en charge plusieurs langues. Veuillez choisir les langues que vous voulez installer.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[Encodage de caractères]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[L’encodage de caractères détermine le type de stockage et la représentation des langues installées sur ce système. Veuillez prendre en compte le fait que vous ne pourrez plus changer de type d’encodage de caractères une fois que vous aurez fait votre choix.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 est requis seulement si vous voulez installer les langues européennes occidentales.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 est requis si vous voulez installer les langues européennes occidentales ou n’importe quelle langue qui ne soit pas européenne occidentale, maintenant où plus tard.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Européenne occidentale]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Européenne centrale]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Grec]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebreu]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Turque]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japonais]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japonais]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Chinois (traditionnel)]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Chinois (simplifié)]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Chinois (simplifié)]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Cyrillique]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Cyrillique]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Coréen]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[Langues]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[Veuillez choisir au moins une langue !]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[La langue que vous avez choisi ne correspond pas à l’encodage de caractères que vous avez sélectionné précédemment. Veuillez modifier votre choix de langues.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[Configuration de l’accès à la base de données]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[Les données de ce logiciel seront stockés dans une base de données MySQL. Veuillez entrer vos informations d’accès à la base de donnée !]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Informations d’accès à la base de donnée]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[Nom d’hôte]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[Identifiant]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[Nom de la base de donnée]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[Numéro d’installation]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[Une erreur s’est produite lors de la tentative de connexion à votre base de données :
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />Vous pouvez obtenir des informations complémentaires dans la WoltLab Error Reference :
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[{if $conflictedTables|count > 1}Les tables suivantes existent {else} La table suivante existe {/if}déjà dans votre table de données &quot;{$dbName}&quot; :<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Pour résoudre ce problème, veuillez procéder à une des actions suivantes : <br />1. Autoriser l’option d’&quot;écrasement&quot; présente ci-dessous pour écraser {if $conflictedTables|count > 1}ces tables{else}cette table{/if} et continuer l’installation en cliquant sur le bouton &quot;Suivant&quot; ou<br />2. Entrer à nouveau les informations d’accès à la base de donnée, mais en utilisant une base de donnée différente et continuer l’installation en cliquant sur le bouton &quot;Suivant&quot; ou<br />3. Entrer un nouveau numéro d’installation, en n’oubliant pas de continuer l’installation en cliquant sur le bouton &quot;Suivant&quot;.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Écraser {if $conflictedTables|count > 1}les tables listées{else}la table listée{/if} ci-dessous ?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[Création d’un administrateur]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[L’installation va maintenant générer vos droits d’administrateur. Veuillez indiquer un identifiant, une adresse e-mail et un mot de passe pour l’utilisateur administrateur.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[Information utilisateur]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[Identifiant]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[Adresse e-mail]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[Confirmation de l’adresse e-mail]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[Mot de passe]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Confirmation du mot de passe]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[Des erreurs sont survenues lors de l’enregistrement du compte utilisateur. Veuillez vérifier les champs mis en valeurs.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Ce champ doit être remplis.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[L’identifiant que vous avez entré n’est pas valide. Un identifiant valide doit contenir entre 3 et 20 caractères.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[L’adresse e-mail que vous avez entrée n’est pas valide. Une adresse e-mail valide doit être au format nom@domaine.dpn]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Les adresses e-mail que vous avez fournies ne sont pas identiques. Pour des raisons de sécurité, veuillez vous assurer que les deux champs d’adresse e-mail ont bien été remplis à l’identique.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[Les mots de passe que vous avez fournis ne sont pas identiques. Pour des raisons de sécurité, veuillez vous assurer que les deux champs de mot de passe ont bien été remplis à l’identique.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[Une erreur est survenue lors de l’extraction des fichiers suivants :
+               <br /><b>{$exception->getMessage()}</b><br />
+               Veuillez vous assurer que le répertoire de destination existe et possède les droits d’écriture.
+               <br /><br />Vous pouvez obtenir des informations complémentaires dans la WoltLab Error Reference :<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_hr.xml b/wcfsetup/setup/lang/setup_hr.xml
new file mode 100644 (file)
index 0000000..bb9d2fb
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="hr">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Instalacija]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Instalacije]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[hr_HR]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[hrvatski]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[&nbsp;]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Dalje &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% završen]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Danas</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Jučer, %H:%M]]></item>
+               <item name="wcf.global.welcome"><![CDATA[Hvala, što ste se odlučili za {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[Ovaj instalacijski asistent Vam pomaže kod instalacije <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} i kod <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[Jezik]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Engleski]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Njemački]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Njemački (neformalno)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Francuski]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japanski]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Španjolski]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Kineski (tradicionalni)]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Kineski (pojednostavljeni)]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Talijanski]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Nizozemski]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Ruski]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Korejski]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugalski]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugalski (Brazilski)]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Švedski]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Poljski]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danski]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Češki]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turski]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Mađarski]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arapski]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hebrejski]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Perzijski]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norveški]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finski]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Rumunjski]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosanski]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Hrvatski]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Srpski]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovački]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grčki]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[Jezik ovog asistenta je trenutno postavljen na Hrvatski jezik.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[Promijeni jezik]]></item>
+               <item name="wcf.global.license"><![CDATA[Licenca]]></item>
+               <item name="wcf.global.license.description"><![CDATA[Molimo Vas pročitajte slijedeću licencu. Koristite scrollbar kako bi vidjeli cijeli dokument.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[Prihvaćate li cijelu licencu? Možete iinstalirati software, tek onda kada prihvatite licencu.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[Kako bi nastavili sa instalacijom software-a, morate prihvatiti licencu.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[Provjera sistemskih zahtjeva]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Ovo su sistemski zahtjevi:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Potrebni sistemski zahtjevi]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Preporučeni sistemski zahtjevi]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Potebno:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Pronađeno:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Preporučeno:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Instalirana verzija jezika skripte &raquo;PHP&laquo;]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[Instalirana verzija skripte &raquo;PHP&laquo; je za stabilnu uporabu software-a prestara. Molimo Vas aktualizirajte instaliranu verziju prije nego što nastavite sa instalacijom.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Vaša PHP verzija je jako stara. Za besprijekornu uporabu preporučamo PHP verziju 5.0.5 ili više.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[Podržava &raquo;MySQL&laquo; bazu podataka]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[Bez podržane &raquo;MySQL&laquo; baze podataka ne možete instalirati ovaj software.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Maksimalna veličina za upload fajlova]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[Trenutnom konfiguracijom jezika skripte &raquo;PHP&laquo; je nemoguće uploadati fajlove. Nekoličina funkcija će pomoću tih postavki krivo funkcionirati ili biti sograničene.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Instalirana verzija &raquo;gdlib&laquo;]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[Biblioteka grafičkog uređivaća &raquo;gdlib&laquo; je za dinamički generirane slike odgovorna. Bez nje nekoličina funkcija će krivo funkcionirati ili biti ograničene.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Biblioteka za znakove sa više bajt-a (&raquo;multibyte string&laquo;)]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Bez ove biblioteke je samo moguće koristiti zapadno-europske jezike.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Sigurnosne postavke &raquo;safe mode&laquo; u jezičnoj skripti &raquo;PHP&laquo;]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Preporuča se deaktivacija ove postavke, zbog besprijekornog funkcioniranja software-a.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Biblioteka za prijenos podatak preko FTP-a]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Kod aktivirane sigurnosne postavke &raquo;safe mode&laquo; će se ova biblioteka za većinu podatkovnih operacija software-a koristiti. Preporuča se aktivacija ove biblioteke.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[aktivirano]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[nije aktivirano]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[Odaberite mjesto instalacije]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[U instalacijski folder će se sve datoteke od <b>WoltLab Community Framework</b> otpakirati.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[Instalacija sumnja na već postojeću instalaciju  <b>WoltLab Community Frameworks</b> u folderu "{$foundDirectory}".<br />Molim Vas provjerite, tj. odredite drugo mjesto za instalaciju, ako želite kopiju <b>WoltLab Community Frameworks</b> instalirati.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Instalacijski folder]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Molim Vas odredite instalacijsko mjesto kamo želite instalirati <b>WoltLab Community Framework</b>.]]></item>
+               <item name="wcf.global.ftp"><![CDATA[Upis pristupnih podataka za FTP]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[Pošto je na vašem serveru PHP-SafeMode aktiviran, morate WoltLab Community Framework preko FTP-Funkcije instalirati. Molim Vas upišite korisničko ime i šifru za pristup FTP-u na ovom serveru. Podaci se neće snimiti niti dalje prosljediti, nego će se samo za ovu instalaciju koristiti. Zbog tog razloga morat ćete više puta upisati pristupne podatke tijekom instalacije.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[Pristupni podaci za FTP]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[Naziv hosta]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[Korisničko ime]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[Šifra]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[Sa upisanim pristupnim podacima se nije mogla uspostaviti veza prema FTP serveru.]]></item>
+               <item name="wcf.global.next"><![CDATA[Učitavam idući korak ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[Instalacija trenutno učitava sljedeći korak. Molim Vas za strpljenje.]]></item>
+               <item name="wcf.global.languages"><![CDATA[Jezike odabrati]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[Možete ovaj software više jezično koristiti. Molim Vas, odaberite koje jezike želite instalirati.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[Znakovno kodiranje]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[Preko znakovnog kodiranja će se tehničko snimanje i prikazivanje koristiti. Molim Vas, obratite pažnju da se znakovno kodiranje naknadno više ne može promijeniti.]]></item>
+               
+               <!-- <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Korištenje ISO-8859-1 se preporuča, samo kada želite instalirati zapadno europske jezike.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 se koristi za ne-zapadno europske jezike. Kada sad ili možda kasnije želite instalirati ne-zapadno europski jezik, morato ovdje UTG-8 odabrati.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Zapadno europski]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Srednjo europski]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Grčki]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebrejski]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Turski]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japanski]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japanski]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Kineski (tradicionalni)]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Kineski (pojednostavljeni)]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Chinesisch (pojednostavljeni)]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Kirilski]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Kirilski]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Korejski]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[Jezici]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[Odaberite najmanje jedan jezik !]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Odabrali ste jezike, koji ne odgovaraju prijašnje odabranom znakovnom kodiranju. Molim Vas ispravite Vaš odabir.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[Konfiguracija pristupa bazu]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[Podaci software-a se snimaju u jednoj MySQL bazi podataka. Molim Vas upišite pristupne podatke baze!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Pristupni podaci baze]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[Naziv hosta]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[Korisničko ime]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[Šifra]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[Naziv baze podataka]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[Instalacijski broj]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[Kod pokušaja pristupa bazi podataka se sljedeća greška pojavila:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />Više informacija ovog problema možete dobiti kod proizvođaća software-a WoltLab:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[Sljedeća tablica{if $conflictedTables|count > 1}n{/if} postiji{if $conflictedTables|count > 1}e{else}t{/if} već u bazi podataka &raquo;{$dbName}&laquo;:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Kako bi riješili ovaj problem, možete:<br />1. ovu tablicu{if $conflictedTables|count > 1}n{/if} prepisati, tako što &raquo;Prepisati&laquo; opciju aktivirate i &raquo;Dalje&laquo; kliknete, ili<br />2. Upišete podatke druge baze podataka i potvrdite sa &raquo;Dalje&laquo;, ili<br />3. Upišete jedan od &raquo;{$dbNumber}&laquo; različitih instalacijskih brojeva i potvrdite sa &raquo;Dalje&laquo;.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Gore napomenutu tablica{if $conflictedTables|count > 1}e{/if} prepisati]]></item>
+               <item name="wcf.global.createUser"><![CDATA[Administratorski račun napraviti]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[Instalacijski asistent će kreirati administracijski račun za Vas. Molim Vas, upišite korisničko ime, jednu E-Mail adresu i šifru.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[Korisnički podaci]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[Benutzername]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[E-Mail Adresa]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[E-Mail Adresu ponoviti]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[Šifra]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Šifru ponoviti]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[Nastale su greško sa Vašom registracijom. Molim Vas provjerite označena polja.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Molim Vas ispunite ovo polje.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[Upisano korisničko ime je nevaljano. Jedno valjano korisničko ime mora sadržavati najmanje 3 i najviše 20 znakova.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[Upisana E-Mail adresa je nevaljana. Jedna valjana E-Mail adresa mora biti oblika: ime@domena.tld.]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Upisane E-Mail adrese nisu jednake. Molim Vas, radi sigurnosti upišite u oba polja istu E-Mail adresu.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[Upisane šifre nisu jednake. Molim Vas, radi sigurnosti upišite u oba polja istu šifru.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[Kod pokušaja otpakiravanja datoteka, je sljedeća greška nastala:
+               <br /><b>{$exception->getMessage()}</b><br />
+               Molim Vas, provjerite dali postoji instalacijski folder i dali se može upisivati u njega.
+               <br /><br />Više informacija o ovom problemu možete dobiti kod proizvođaća software-a WoltLab:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_it.xml b/wcfsetup/setup/lang/setup_it.xml
new file mode 100644 (file)
index 0000000..3494226
--- /dev/null
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="it">\r
+       <category name="wcf.global">\r
+               <item name="wcf.global.pageTitle"><![CDATA[Installazione {$setupPackageName}]]></item>\r
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />installazione]]></item>\r
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item> <!-- variabile di sistema; non tradurre!! -->\r
+               <item name="wcf.global.locale.unix"><![CDATA[it_IT]]></item> <!-- variabile di sistema; non tradurre!! -->\r
+               <item name="wcf.global.locale.win"><![CDATA[italiano]]></item>\r
+               <item name="wcf.global.decimalPoint"><![CDATA[,]]></item>\r
+               <item name="wcf.global.thousandsSeparator"><![CDATA[.]]></item>\r
+               <item name="wcf.global.button.next"><![CDATA[Avanti &raquo;]]></item>\r
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% completato]]></item>\r
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item> <!-- variabile di sistema; non tradurre!! -->\r
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>\r
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%A, %d %B %Y]]></item>\r
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Oggi</b>, %H:%M]]></item>\r
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Ieri,  %H:%M]]></item>\r
+        <item name="wcf.global.welcome"><![CDATA[Grazie per aver scelto {$setupPackageName}]]></item>\r
+               <item name="wcf.global.welcome.description"><![CDATA[questo assistente all'installazione vi aiuter nel processo riguardante l'installazione del <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} e della <b>{$setupPackageName}</b>{/if}.]]></item>\r
+               <item name="wcf.global.welcome.language"><![CDATA[Lingua]]></item>\r
+               <item name="wcf.global.language.ar"><![CDATA[Arabo]]></item>\r
+               <item name="wcf.global.language.bs"><![CDATA[Bosniaco]]></item>\r
+               <item name="wcf.global.language.cs"><![CDATA[Ceco]]></item>\r
+               <item name="wcf.global.language.da"><![CDATA[Danese]]></item>\r
+               <item name="wcf.global.language.de"><![CDATA[Tedesco]]></item>\r
+               <item name="wcf.global.language.de-informal"><![CDATA[Tedesco (Informale)]]></item>\r
+               <item name="wcf.global.language.en"><![CDATA[Inglese]]></item>\r
+               <item name="wcf.global.language.es"><![CDATA[Spagnolo]]></item>\r
+               <item name="wcf.global.language.fa"><![CDATA[Persiano]]></item>\r
+               <item name="wcf.global.language.fi"><![CDATA[Finlandese]]></item>\r
+               <item name="wcf.global.language.fr"><![CDATA[Francese]]></item>\r
+               <item name="wcf.global.language.he"><![CDATA[Ebraico]]></item>\r
+               <item name="wcf.global.language.hr"><![CDATA[Croato]]></item>\r
+               <item name="wcf.global.language.hu"><![CDATA[Ungherese]]></item>\r
+               <item name="wcf.global.language.it"><![CDATA[Italiano]]></item>\r
+               <item name="wcf.global.language.ja"><![CDATA[Giapponese]]></item>\r
+               <item name="wcf.global.language.ko"><![CDATA[Coreano]]></item>\r
+               <item name="wcf.global.language.nl"><![CDATA[Olandese]]></item>\r
+               <item name="wcf.global.language.no"><![CDATA[Norvegese]]></item>\r
+               <item name="wcf.global.language.pl"><![CDATA[Polacco]]></item>\r
+               <item name="wcf.global.language.pt"><![CDATA[Portoghese]]></item>\r
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portoghese (Brasile)]]></item>\r
+               <item name="wcf.global.language.ro"><![CDATA[Rumeno]]></item>\r
+               <item name="wcf.global.language.ru"><![CDATA[Russo]]></item>\r
+               <item name="wcf.global.language.sk"><![CDATA[Slovacco]]></item>\r
+               <item name="wcf.global.language.sr"><![CDATA[Serbo]]></item>\r
+               <item name="wcf.global.language.sv"><![CDATA[Svedese]]></item>\r
+               <item name="wcf.global.language.tr"><![CDATA[Turco]]></item>\r
+               <item name="wcf.global.language.zh-CN"><![CDATA[Cinese (Semplificato)]]></item>\r
+               <item name="wcf.global.language.zh-TW"><![CDATA[Cinese (Tradizionale)]]></item>\r
+               <item name="wcf.global.language.el"><![CDATA[Greco]]></item>\r
+               <item name="wcf.global.welcome.language.description"><![CDATA[La lingua dell'assistente risulta impostata sulla lingua Inglese.]]></item>\r
+               <item name="wcf.global.welcome.language.change"><![CDATA[Cambia Lingua]]></item>\r
+               <item name="wcf.global.license"><![CDATA[Licenza d'uso]]></item>\r
+               <item name="wcf.global.license.description"><![CDATA[Prego leggere la seguente Licenza d'uso. Utilizzare la barra di scorrimento per visualizzare l'intero documento.]]></item>\r
+               <item name="wcf.global.license.accept.description"><![CDATA[Accettate i Termini e Condizioni espresse nella Licenza d'uso? Potete installare questo software solo se accettate le condizioni e i termini  della Licenza d'uso.]]></item>\r
+               <item name="wcf.global.license.missingAcception"><![CDATA[Dovete accettare La licenza d'uso per continuare questa installazione.]]></item>\r
+               <item name="wcf.global.systemRequirements"><![CDATA[Controllo requisiti di sistema]]></item>\r
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Questi sono i requisiti di sistema:]]></item>\r
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Componenti di sistema richiesti]]></item>\r
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Componenti di sistema raccomandati]]></item>\r
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Richiesto:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Trovato:]]></item>\r
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Raccomandato:]]></item>\r
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Versione &quot;PHP&quot; installata:]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[La versione del &quot;PHP&quot;  installata sul Sistema è troppo vecchia per garantre una stabilità a questo Software. Per procedere con l'installazione è necessario aggiornare la versione del PHP.]]></item>\r
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[La vostra versione del PHP è obsoleta. Per una migliore stabilità nell'esecuzione delle operazioni del Software, raccomandiamo un aggiornamento alla versione 5.0.5 oo superiore del PHP.]]></item>\r
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[Supporto Database &quot;MySQL&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[Il supporto del Database &quot;MySQL&quot; è richiesto per installare questo Software.]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Peso massimo per l'upload dei file]]></item>\r
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[La corrente configurazione dell'installazione &quot;PHP&quot; rende impossibile l'upload dei files. A causa di questa configurazione, molte opzioni del Software verranno disabilitate.]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Versione installata della libreria grafica &quot;GDLib&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[La libreria grafica &quot;GDLib&quot; è richiesta per la generazione dinamica delle immagini. Senza questa, molte opzioni di questo Software non saranno disponibili.]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Multibyte character library &quot;MBString&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Senza questa libreria, può essere usato esclusivamente con le lingue dell'Europa Occidentale.]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Opzione sulla sicurezza nel &quot;safe mode&quot; nel &quot;PHP&quot;]]></item>\r
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Per garantire il corretto funzionamento di questo software, raccomandiamo di disabilitare l'opzione Safe mode.]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Libreria del Trasferimento Dati per FTP]]></item>\r
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Con l'opzione &quot;safe mode&quot; abilitata, opzione riguardante la sicurezza del server, la libreria riguardante il trasferimento dei dati è richiesta per molte operazioni riguardanti i file e usate su questo Software. Raccomandiamo di abilitare questa libreria.]]></item>\r
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Abilitata]]></item>\r
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Disabilitata]]></item>\r
+               <item name="wcf.global.wcfDir"><![CDATA[Seleziona la cartella di installazione]]></item>\r
+               <item name="wcf.global.wcfDir.description"><![CDATA[Tutti i file della <b>WoltLab Community Framework</b> verranno estratti nella cartella di installazione.]]></item>\r
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[L'assistente all'installazione ha rilevato un'ulteriore installazione della <b>WoltLab Community Framework</b> nella cartella "{$foundDirectory}".<br />Se desiderate installare una nuova copia della <b>WoltLab Community Framework</b>, inserite un nuovo percorso ad una cartella alternativa.]]></item>\r
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Cartella di installazione]]></item>\r
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Prego inserire la cartella di installazione per la <b>WoltLab Community Framework</b>.]]></item>\r
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[L'assistente all'installazione ha individuato una precedente versione della <b>WoltLab Community Framework</b> nella cartella "{$foundDirectory}".<br />Se volete installare una nuova copia del software <b>WoltLab Community Framework</b>, inserite un percorso differente.]]></item>\r
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Cartella installazione]]></item>\r
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Inserire il percorso alla cartella di installazione per la <b>WoltLab Community Framework</b>.]]></item>\r
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[Dopo aver installato il software nella cartella indicata potrai accedere al <b>WoltLab Community Framework</b> attraverso questo percorso:]]></item>\r
+               <item name="wcf.global.wcfDir.error.invalid"><![CDATA[La cartella indicata non è valida.]]></item>\r
+               <item name="wcf.global.ftp"><![CDATA[Informazioni accesso FTP]]></item>\r
+               <item name="wcf.global.ftp.description"><![CDATA[Con l'opzione PHP-SafeMode abilitata, opzione riguardante la sicurezza, la WoltLab Community Framework può essere installata usando esclusivamente la funzionalità FTP. Prego inserire i dati di accesso, username e password, per accedere al server via FTP. Le informazioni indicate non saranno salvate e sono state richieste esclusivamente per l'installazione di questo Pacchetto. Per questa ragione, in futuro potrebbe essere necessario reinserire tali dati.]]></item>\r
+               <item name="wcf.global.ftp.accessData"><![CDATA[Informazioni accesso FTP]]></item>\r
+               <item name="wcf.global.ftp.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.ftp.user"><![CDATA[Username]]></item>\r
+               <item name="wcf.global.ftp.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.global.ftp.error"><![CDATA[Impossibile stabilere una connessione FTP con il server indicato.]]></item>\r
+               <item name="wcf.global.next"><![CDATA[Caricamento fase sucessiva ...]]></item>\r
+               <item name="wcf.global.next.description"><![CDATA[L'installazione sta caricando la fase successiva, attendere prego.]]></item>\r
+               <item name="wcf.global.languages"><![CDATA[Selezionare la lingua da installare]]></item>\r
+               <item name="wcf.global.languages.description"><![CDATA[Questo software supporta l'uso di più lingue. Selezionare le lingue che si desidera installare.]]></item>\r
+               <item name="wcf.global.languages.charset"><![CDATA[Codifica caratteri]]></item>\r
+               <item name="wcf.global.languages.charset.description"><![CDATA[La Codifica dei caratteri, conosciuta anche set di caratteri o codice caratteri determina il tipo di caretteri da usare e la rappresentazione delle lingue del sistema installate. Fare attenzione poichè una volta scelto il tipo di codifica, non sarà più possibile cambiarlo.]]></item>\r
+               \r
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 è richiesto se volete installare esclusivamente lingue dell'europa Occidentale.]]></item>\r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 è richiesto se volete installare, adesso o in futuro, lingue dell'Europa Occidentale o altre lingue non appartenenti all'Europa Occidentale.]]></item>-->\r
+               \r
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Europa Occidentale]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Europa Centrale]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Greco]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Ebraico]]></item>\r
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Turco]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Giapponese]]></item>\r
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Giapponese]]></item>\r
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Cinese (Tradizionale)]]></item>\r
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Cinese (Semplificato)]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Cinese (Semplificato)]]></item>\r
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Cirillico]]></item>\r
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Cirillico]]></item>\r
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Coreano]]></item>\r
+               \r
+               <item name="wcf.global.languages.languages"><![CDATA[Lingue]]></item>\r
+               <item name="wcf.global.languages.error.empty"><![CDATA[Prego selezionare almeno un lingua!]]></item>\r
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Le lingue selezionate non corrispondono alla codifica dei caratteri scelta in precedenza. Prego ricordare la scelta della lingua.]]></item>\r
+               <item name="wcf.global.configureDB"><![CDATA[Configurazione accesso Database]]></item>\r
+               <item name="wcf.global.configureDB.description"><![CDATA[I dati di questo software necessitano di essere salvati in un Database MySQL. Prego inserire i vostri dati di accesso al Database!]]></item>\r
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Informazioni accesso Database]]></item>\r
+               <item name="wcf.global.configureDB.host"><![CDATA[Hostname]]></item>\r
+               <item name="wcf.global.configureDB.user"><![CDATA[Username]]></item>\r
+               <item name="wcf.global.configureDB.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.global.configureDB.database"><![CDATA[Nome Database]]></item>\r
+               <item name="wcf.global.configureDB.number"><![CDATA[Numero installazioni]]></item>\r
+               <item name="wcf.global.configureDB.error"><![CDATA[Si è verificato un errore nel tentativo di connessione al vostro Database:\r
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>\r
+               <br />Informazioni aggiuntive possono essere trovate presso la WoltLab Error Reference:\r
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[{if $conflictedTables|count > 1}Le Seguenti tabelle esistono{else}La seguente tabella esiste{/if} già nel tuo &quot;{$dbName}&quot; Database:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Per risolvere questo problema seguire uno dei seguente passi:<br />1. Abilitare la sottostante voce &quot;Sovrascrivi&quot; per sovrascrivere {if $conflictedTables|count > 1}queste tabelle{else}questa tabella{/if} e continuare l'installazione premento il pulsante &quot;Successivo&quot; o<br />2. Reinserisci le informazioni di accesso al database, indicando però un differente Database e continua l'installazione premendo il pulsante &quot;Successivo&quot; o<br />3. Inserisci un nuovo numero di installazione, senza dimenticare di continuare l'installazione premendo il pulsante &quot;sucessivo&quot;.]]></item>\r
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Sovrascrivi {if $conflictedTables|count > 1}le tabelle elencate{else}la tabella elencata{/if} qui di seguito?]]></item>\r
+               <item name="wcf.global.createUser"><![CDATA[Crea un Amministratore]]></item>\r
+               <item name="wcf.global.createUser.description"><![CDATA[L'installazione genererà un accesso con diritti di Amministratore per il vostro account. Prego indicare un Username, indirizzo E-Mail e Password che saranno usati per l'account dell'amministratore.]]></item>\r
+               <item name="wcf.global.createUser.data"><![CDATA[Informazioni Utente]]></item>\r
+               <item name="wcf.global.createUser.username"><![CDATA[Username]]></item>\r
+               <item name="wcf.global.createUser.email"><![CDATA[Indirizzo E-Mail]]></item>\r
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[Conferma Indirizzo E-Mail]]></item>\r
+               <item name="wcf.global.createUser.password"><![CDATA[Password]]></item>\r
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Conferma Password]]></item>\r
+               <item name="wcf.global.createUser.error"><![CDATA[Si sono verificati degli errori durante il tentativo di registrazione dell'account utente, prego controllare i campi indicati per eventuali errori.]]></item>\r
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Questo campo non può essere lasciato vuoto.]]></item>\r
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[L'Username inserito non è valido. Un Username valido deve contenere un minimo di 3 ed un massimo di 20 caratteri.]]></item>\r
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[L'indirizzo E-Mail indicato non è valido. Un indirizzo E-Mail valido deve essere nella forma name@domain.tld]]></item>\r
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Gli indirizzi E-Mail indicati non sono identici. Per ragioni di sicurezza, controllare che i campi relativi siano stati riempiti e che i due indirizzi siano identici.]]></item>\r
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[Le password inserite non sono identiche. Per ragioni di sicurezza, prego verificare che i campi relativi siano stati riempiti e che le password inserite siano identiche.]]></item>\r
+               <item name="wcf.global.wcfDir.error"><![CDATA[Si è verificato un errore durante l'estrazione dei seguenti files:\r
+               <br /><b>{$exception->getMessage()}</b><br />\r
+               Prego controllare l'effettiva esistenza della cartella di destinazione e che abbia i permessi di scrittura.\r
+               <br /><br />Maggiori informazioni possono essere reperite nella WoltLab Error Reference:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>\r
+       </category>\r
+</language>\r
diff --git a/wcfsetup/setup/lang/setup_pt-BR.xml b/wcfsetup/setup/lang/setup_pt-BR.xml
new file mode 100644 (file)
index 0000000..101c89d
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="pt-BR">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Instalação]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Instalação]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[pt_BR]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[brazil]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Próximo &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% completo]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%A, %d %B %Y]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Hoje</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Ontem, %H:%M]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %d %B %Y - %H:%M]]></item>
+               <item name="wcf.global.welcome"><![CDATA[Obrigado por escolher {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[Este assistente de instalação ajudará durante a instalação do <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} e <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[Idioma]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Inglês]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Alemão]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Alemão (Informal)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Francês]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japonês]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Espanhol]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Chinês (Tradicional)]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Chinês (Simplificado)]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Italiano]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Holandês]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Russo]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Coreano]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Português]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Português do Brasil]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Sueco]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polonês]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Dinamarquês]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Checo]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turco]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Húngaro]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Árabe]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hebraico]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persa]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norueguês]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finlandês]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Romeno]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bósnio]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Croata]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Sérvio]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Eslovaco]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grego]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[O assistente de idioma está definido para Português do Brasil.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[Mudar idiona]]></item>
+               <item name="wcf.global.license"><![CDATA[Contrato de Licença]]></item>
+               <item name="wcf.global.license.description"><![CDATA[Leia o Contrato de Licença a seguir. Use a barra de rolagem para exibir o documento inteiro.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[Você aceita os termos e condições do contrato de licença? Você só poderá instalar este software após a aceitar o contrato de licença.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[Você deve aceitar o contrato de licença para continuar esta instalação.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[Verificando os requisitos de sistema]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Esses são os requisitos do sistema:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Componente do sistema necessário]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Componente de sistema recomendado]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Necessário:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Encontrado:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Recomendado:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Versão da linguagem de script PHP instalado ]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[A versão instalada da linguagem de script PHP é muito antiga para uma operação estável deste software. Para continuar com a instalação é necessária uma atualização de versão.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Sua versão PHP é obsoleta. Para uma operação estável desse software, recomendamos uma versão PHP do 5.0.5 ou maior.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[Suporte à base de dados MySQL]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[Suporte à base de dados MySQL é necessária para instalar esse software.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Tamanho máximo para carregamentos de arquivo]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[A configuraçãoo atual do PHP instalado torna impossível carregar os arquivos. Devido a essa configuração, alguns recursos deste software estarão restritos.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Versão instalada da biblioteca de elementos gráficos GDLib]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[A biblioteca de elementos gráficos GDLib é necessária para a geração dinâmica de imagens. Sem isso, alguns recursos deste software não estarão disponíveis.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[A biblioteca de caracteres de vários bytes "MBString"]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Sem essa biblioteca, o software só pode ser usado com idiomas da europa ocidental.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Opção de segurança de Modo Seguro na linguagem de script PHP]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Para garantir a operação desse software, é recomendado desativar a configuração de modo seguro.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Transferência de dados biblioteca para FTP]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Com a opção de segurança de Modo Seguro sendo ativada, a biblioteca de transferência de dados é necessária para a maioria das operações de arquivo dentro este software. É altamente recomendável ativar essa biblioteca.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Ativado]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Desabilitado]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[Escolha a pasta de instalação]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[Todos os arquivos de <b>WoltLab Community Framework</b> serão extraídos para a pasta de instalação.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[O assistente de instalação encontrou uma instalação anterior do <b>WoltLab Community Framework</b> na pasta "{$foundDirectory}".<br />Se você gostaria de instalar uma nova cópia do <b>WoltLab Community Framework</b>, por favor, insira uma pasta de instalação alternativa.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Pasta da Instalação]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Digite a pasta de instalação para o <b>WoltLab Community Framework</b>.]]></item>
+               <item name="wcf.global.ftp"><![CDATA[Informações de acesso FTP]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[Com a opção de segurança PHP - Modo Seguro sendo ativado, o WoltLab Community Framework só pode ser instalado usando a funcionalidade de FTP. Digite aqui o nome de usuário de FTP e a senha para este servidor. As informações fornecidas não serão salvas e só é necessário para a instalação deste pacote. Por esse motivo, mais solicitações de nome de usuário e senha do FTP serão necessária.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[Informações de acesso FTP]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[Nome do Host]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[Nome de usuário]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[Senha]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[Não foi possível estabelecer uma conexão para o servidor FTP fornecido.]]></item>
+               <item name="wcf.global.next"><![CDATA[Carregando próxima etapa ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[No momento, a instalação está carregando a próxima etapa, aguarde.]]></item>
+               <item name="wcf.global.languages"><![CDATA[Escolha idiomas para instalar]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[Esse software pode oferecer suporte a vários idiomas. Escolha os idiomas que você gostaria de instalar.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[Codificação de caractere]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[A codificação de caracteres, também conhecido como o conjunto de caracteres ou a página de código determina o tipo de armazenamento e a representação dos idiomas instalados neste sistema. Esteja ciente que uma vez que você definiu a codificação de caracteres, isso não pode ser alterado posteriormente.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 is required if you wish to install Western European languages only.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 is required if you wish to install Western European or any Non-Western European langauges, now or at a later date.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Europa Ocidental]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Europa Central]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Grego]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebraico]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Turco]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japonês]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japonês]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Chinês (Tradicional)]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Chinês (Simplificado)]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Chinês (Simplificado)]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Cirílico]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Cirílico]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Coreano]]></item>
+               <item name="wcf.global.languages.languages"><![CDATA[Idiomas]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[Escolha por favor pelo menos uma língua!]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[As línguas que você escolheu não correspondem à codificação dada do caráter você fêz previamente. Emende por favor sua escolha de língua.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[Configurar o acesso do banco de dados]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[Os dados para este software precisa ser armazenado em um banco de dados MySQL. Digite as informações de acesso do banco de dados!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Informações de acesso do banco de dados]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[Nome do Host]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[Nome de Usuário]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[Senha]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[Nome do banco de dados]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[Número da instalação]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[Um erro tem ocorreu ao tentar se conectar ao seu banco de dados:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />Informações adicionais podem ser encontradas na referência de erro do WoltLab:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[A{if $conflictedTables|count > 1}s{/if} tabela{if $conflictedTables|count > 1}s{/if}a seguir já existe{if $conflictedTables|count == 1}m{/if} em seu &quot;{$dbName}&quot; banco de dados:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Para resolver esse problema, por favor, faça o seguinte:<br />1. Ativar a opção Substituir {if $conflictedTables|count > 1}essas tabelas{else}essa tabela{/if} e continue a instalação com o botão Avançar ou<br />2. Você reinserir as informações de acesso do banco de dados, mas para um banco de dados diferente e continuar a instalação com o botão 'Avançar' ou<br />3. Você digitar um novo número de instalação, Não esquecer continuar a instalação com o botão 'Avançar'.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Substituir a{if $conflictedTables|count > 1}s{/if} tabela{if $conflictedTables|count > 1}s{/if} listada acima{if $conflictedTables|count > 1}s{/if}?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[Criar um administrador]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[A instalação agora irá gerar uma conta de administrador para você. Forneça um nome de usuário, endereço de email e senha.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[Informação do Usuário]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[Nome de Usuário]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[Endereço de e-mail]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[Confirmar endereço de e-mail]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[Senha]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Confirmar senha]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[Ocorreu erros ao registrar a conta de usuário, verifique os campos marcados em busca de erros.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Este campo pode não ser deixado vazio.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[O nome de usuário que você digitou é inválido. Um nome de usuário válido deve ter entre 3 e 20 caracteres.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[O endereço de email que você forneceu é inválido. Um endereço de email válido deve estar no formato do nome@domínio.tld]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Os endereços de email que você forneceu não são idênticos. Por motivos de segurança, certifique-se que ambos os campos de endereço de email tiverem sido preenchidos e são idênticos.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[As senhas que você forneceu não são idênticas. Por motivos de segurança, certifique-se que ambos os campos de senha tenham sido preenchidos e são idênticos.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[Ocorreu um erro ao extrair os arquivos necessários:
+               <br /><b>{$exception->getMessage()}</b><br />
+               Por favor, certifique-se de que a pasta de destino existe e pode ser gravada.
+               <br /><br />Informações adicionais podem ser encontradas na referência de erro do WoltLab:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_sv.xml b/wcfsetup/setup/lang/setup_sv.xml
new file mode 100644 (file)
index 0000000..370c658
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="sv">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Installation]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Installation]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.locale.unix"><![CDATA[sv_SE]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.locale.win"><![CDATA[swedish]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.button.next"><![CDATA[Nästa &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% komplett]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[strftime]]></item> <!-- system variable; do not translate -->
+               <item name="wcf.global.dateFormat"><![CDATA[%d.%m.%Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[%d.%m.%Y, %H:%M]]></item>
+               <item name="wcf.global.dateFormatLocalized"><![CDATA[%e. %B %Y]]></item>
+               <item name="wcf.global.timeFormatLocalized"><![CDATA[%A, %e. %B %Y, %H:%M]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>Idag</b>, %H:%M]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[Igår, %H:%M]]></item>
+               <item name="wcf.global.welcome"><![CDATA[Tack för att du väljer {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[Denna installations-assistent hjälper dig att installera <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} och <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[Språk]]></item>
+               <item name="wcf.global.language.en"><![CDATA[Engelska]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Tyska]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Tyska (informella)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Franska]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japanska]]></item>
+               <item name="wcf.global.language.es"><![CDATA[Spanska]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Kinesiska (traditionell)]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Kinesiska (förenklad)]]></item>
+               <item name="wcf.global.language.it"><![CDATA[Italienska]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Holländska]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Ryska]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Koreanska]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portugisiska]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portugisiska (Brasilien)]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[Svenska]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Polska]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danska]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Tjeckiska]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Turkiska]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Ungerska]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arabiska]]></item>
+               <item name="wcf.global.language.he"><![CDATA[Hebreiska]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Persiska]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norska]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Finska]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Rumänska]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosniska]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Kroatiska]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Serbiska]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovakiska]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Grekiska]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[Assisterande språket är inställt på Engelska.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[Ändra språk]]></item>
+               <item name="wcf.global.license"><![CDATA[Licensavtal]]></item>
+               <item name="wcf.global.license.description"><![CDATA[Vänligen läs följande Licensavtal. Använd rullningslisten för att visa hela dokumentet.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[Accepterar du villkoren i Licensavtalet? Du kan bara installera det här programmet efter godkännande av Licensavtalet.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[Du måste acceptera Licensavtalet för att fortsätta denna installation.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[Kontrollerar Systemkraven]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Dessa är Systemkraven:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Obligatoriska System komponenter]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Rekommenderade System komponenter]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Nödvändig:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Hittade:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Rekommenderad:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Installerad version av Script språket &quot;PHP&quot;]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[Den installerade versionen av Script språket &quot;PHP&quot; är för gammal för en stabil drift av denna Mjukvara. För att fortsätta med installationen, är en version uppdatering nödvändig.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[Din PHP-version är föråldrad. För en stabil drift av denna Mjukvara rekommenderar vi en PHP version 5.0.5 eller högre.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[&quot;MySQL&quot; Databas support]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[&quot;MySQL&quot; Databas support krävs för att installera det här Mjukvaran.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Maximala storleken för fil uppladdning]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[Den nuvarande konfigurationen för det installerade &quot;PHP&quot; gör det omöjligt att ladda upp några filer. På grund av den här konfigurationen, kommer vissa funktioner i Mjukvaran att begränsas.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Installerad version av det grafiska biblioteket &quot;GDLib&quot;]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[Det grafiska biblioteket &quot;GDLib&quot; behövs för Dynamisk Generation av Bilder. Utan detta, kommer vissa funktioner i Mjukvaran inte att vara tillgängliga.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Det multibyte tecken biblioteket &quot;MBString&quot;]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Utan detta bibliotek, kan Mjukvaran endast användas med Väst Europeiska språk.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[Säkerhets möjlighet i &quot;felsäkert läge&quot; i &quot;PHP&quot; Script språk]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[För att garantera driften av denna Mjukvara, rekommenderar vi att inaktivera felsäkert läge inställningen.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[Dataöverförings bibliotek för FTP]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[Med säkerhets möjlighet i &quot;felsäkert läge&quot; möjliggör överföring av data bibliotek som behövs för de flesta av filernas verksamhet inom denna Mjukvara. Vi rekommenderar starkt att aktivera detta bibliotek.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Aktiverad]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Inte aktiverad]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[Välj installationsmappen]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[Alla filer i <b>WoltLab Community Framework</b> kommer att extraheras in i installationsmappen.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[Installations assistenten har funnit tidigare installation av <b>WoltLab Community Framework</b> i "{$foundDirectory}" mappen.<br />Om du vill installera en ny kopia av <b>WoltLab Community Framework</b>, i så fall ange en alternativ installationsmapp.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Installations mapp]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Vänligen ange installationsmappen för <b>WoltLab Community Framework</b>.]]></item>
+               <item name="wcf.global.ftp"><![CDATA[FTP access information]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[Med PHP-safemode säkerhets alternativet aktiverat, kan WoltLab Community Framework endast installeras med FTP-funktionalitet. Ange här FTP-användarnamn och lösenord på den här servern. De uppgifter som lämnas kommer inte att sparas och krävs endast för installation av detta paketet. På grund av detta skäl, kommer ytterligare FTP-användarnamn och lösenord att behövas.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[FTP access information]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[Värdnamn]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[Lösenord]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[En anslutning till den angivna FTP-servern kan inte göras.]]></item>
+               <item name="wcf.global.next"><![CDATA[Laddar nästa steg ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[Installationen laddar förnärvarande nästa steg, var god vänta.]]></item>
+               <item name="wcf.global.languages"><![CDATA[Välj språk att installera]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[Denna Mjukvara kan stödja flera språk. Vänligen välj det språk du vill installera.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[Teckenkodning]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[Teckenkodning, även känd som teckenuppsättning eller kod sida bestämmer lagrings typ och representation av de installerade språken i detta system. Tänk på att när du har ställt in din valda Teckenkodning, kan detta inte ändras i efterhand.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 is required if you wish to install Western European languages only.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 is required if you wish to install Western European or any Non-Western European langauges, now or at a later date.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[VästEuropeiska]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[CentralEuropa]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Grekiska]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[Hebreiska]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Turkiska]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japanska]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japanska]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Kinesiska (traditionell)]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Kinesiska (förenklad)]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Kinesiska (förenklad)]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Kyrilliska]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Kyrilliska]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Koreanska]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[Språk]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[Vänligen välj minst ett språk!]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Det språk du har valt motsvarar inte dn givna Teckenkodning du gjorde tidigare. Vänligen ändra ditt val av språk.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[Konfigurera Database tillgång]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[Uppgifterna för denna Mjukvara måste lagras i en MySQL-databas. Ange din databas tillgångs information!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Databas access information]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[Värdnamn]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[Lösenord]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[Databas namn]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[Installations nummer]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[Ett fel har uppstått vid försök att ansluta till din databas:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />Ytterligare information kan hittas i WoltLab Error Reference:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[De följande tabell{if $conflictedTables|count > 1}er{/if} finns redan{if $conflictedTables|count == 1}s{/if} inom din &quot;{$dbName}&quot; Databas:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />För att lösa detta problem kan du göra något av följande:<br />1. Aktivera &quot;Överskriv&quot; alternativ nedan för att skriva över {if $conflictedTables|count > 1}dessa tabeller{else}denna tabell{/if} och fortsätt installationen med &quot;Nästa&quot; Knappen eller<br />2. Du åter-anger Databasens access information, men till en annan Databas och fortsätter installationen med &quot;Nästa&quot; Knappen eller<br />3. Du anger ett nytt Installations nummer, och inte att förglömma att fortsätta installationen med &quot;Nästa&quot; Knappen.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Skriv över den ovan angivna tabellen{if $conflictedTables|count > 1}s{/if}?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[Skapa en Administratör]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[Installationen kommer nu att skapa ett administratörskonto för dig. Var god ange ett användarnamn, e-postadress och lösenord.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[Användar information]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[Användarnamn]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[E-postadress]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[Bekräfta E-postadress]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[Lösenord]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Bekräfta Lösenord]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[Fel har uppstått samtidigt som du registrerade Användarkontot, vänligen kontrollera markerade områden efter fel.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Detta fält får inte lämnas tomt.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[Användarnamnet som du har angett är ogiltigt. Ett giltigt Användarnamn måste vara mellan 3 och 20 tecken långt.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[E-postadressen som du har angett är ogiltig. En giltig E-Postadress måste vara i formatet name@domain.tld]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[De E-Postadresser du har angett är inte identiska. Av säkerhetsskäl bör du se till att båda E-Postadressernas fält har fyllts i och är identiska.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[De lösenord du har angett är inte identiska. Av säkerhetsskäl bör du se till att samma lösenord har fyllts i båda fälten och är identiska.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[Ett fel har uppstått samtidigt som du extraherade de nödvändiga filerna:
+               <br /><b>{$exception->getMessage()}</b><br />
+               Vänligen se till att målmappen existerar och kan skrivas till.
+               <br /><br />Ytterligare information kan hittas i WoltLab Error Reference:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_tr.xml b/wcfsetup/setup/lang/setup_tr.xml
new file mode 100644 (file)
index 0000000..f75f736
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="tr">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} Yükleme]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />Yükleme]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[en_US]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[english]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.button.next"><![CDATA[İleri &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% tamamlandı]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>\B\u\g\ü\n</b>, g:ia]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[\D\ü\n, g:ia]]></item>
+               <item name="wcf.global.welcome"><![CDATA[{$setupPackageName}’u seçtiğiniz için teşekkür ederiz.]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[Bu yükleme yardımcısı <br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} ve <b>{$setupPackageName}</b>{/if} yükleme işlemlerinde size yardımcı olacaktır.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[Dil]]></item>
+               <item name="wcf.global.language.en"><![CDATA[İngilizce]]></item>
+               <item name="wcf.global.language.de"><![CDATA[Almanca]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[Almanca (Gayri resmi)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[Fransızca]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[Japonca]]></item>
+               <item name="wcf.global.language.es"><![CDATA[İspanyolca]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[Çince (Geleneksel)]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[Çince (Basitleştirilmiş)]]></item>
+               <item name="wcf.global.language.it"><![CDATA[İtalyanca]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[Felemenkçe]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[Rusça]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[Korece]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[Portekizce]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[Portekizce (Brezilya)]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[İsveççe]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[Lehçe]]></item>
+               <item name="wcf.global.language.da"><![CDATA[Danimarkaca]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[Çekçe]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[Türkçe]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[Macarca]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[Arapça]]></item>
+               <item name="wcf.global.language.he"><![CDATA[İbranice]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[Farça]]></item>
+               <item name="wcf.global.language.no"><![CDATA[Norveççe]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[Fince]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[Romence]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[Bosnaca]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[Hırvatça]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[Sırpça]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[Slovakça]]></item>
+               <item name="wcf.global.language.el"><![CDATA[Yunanca]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[Yardımcı dil şu anda Türkçe olarak ayarlanmış durumdadır.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[Dili değiştir]]></item>
+               <item name="wcf.global.license"><![CDATA[Lisans Sözleşmesi]]></item>
+               <item name="wcf.global.license.description"><![CDATA[Lütfen belirtilen Lisans Sözleşmesini okuyunuz. Tüm belgeyi görüntüleyebilmek için kaydırma çubuğunu kullanınız.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[Lisans Sözleşmesinin şartlarını ve kurallarını kabul ediyor musunuz? Bu yazılımı yanlızca Lisans Sözleşmesinin kabul edilmesiyle yükleyebilirsiniz.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[Yüklemeye devam etmek için Lisans Sözleşmesini kabul etmeniz gerekmektedir.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[Sistem Gereksinimleri Kontrol Ediliyor]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[Sistem Gereksinimleri:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[Gerekli sistem bileşeni]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[Önerilen sistem bileşeni]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[Gereken:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[Bulunan:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[Önerilen:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[Yüklenmiş betik dili &quot;PHP&quot; sürümü]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[Yüklenmiş betik dili &quot;PHP&quot; sürümü bu yazılımın kararlı bir şekilde çalışabilmesi için çok eski. Yükleme işleminin devamı için sürüm güncellemesi gerekmektedir.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[PHP Sürümünüz eski. Bu yazılımın kararlı bir şekilde çalışması için, 5.0.5 ya da daha yukarı bir PHP sürümü kullanmanızı öneririz.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[&quot;MySQL&quot; Veritabanı desteği]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[Bu yazılımın yüklenmesi için &quot;MySQL&quot; Veritabanı desteği gerekmektedir.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[Dosya yüklemeleri için en büyük boyut]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[ Yüklenmiş &quot;PHP&quot; sürümünün şu anki yapılandırması herhangi bir dosyanın yüklenmesine imkan vermemektedir. Bu yapılandırmadan dolayı bu yazılımın bazı özellikleri sınırlandırılacaktır.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[Yüklenmiş grafik kütüphanesi &quot;GDLib&quot; sürümü]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[Grafik kütüphanesi &quot;GDLib&quot; resimlerin dinamik olarak oluşturulmasında gereklidir. Onsuz yazılımın bazı özelliklerine erişilemiyecektir.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[Çoklu karakter kütüphanesi &quot;MBString&quot;]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[Bu kütüphane olmadan yazılım sadece batı avrupa dilleri ile kullanılabilir.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[&quot;PHP&quot; Betik dilindeki &quot;güvenli modun&quot; güvenlik seçeneği]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[Bu yazılımın işlevseliğini garantiye almak için güvenli mod ayarlarını etkisizleştirmenizi öneririz.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[FTP için veri aktarım kütüphanesi]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[&quot;Güvenli mod&quot; güvenlik seçeneklerinin etkinleştirilmesi nedeniyle bu yazılımın kullanacağı çoğu dosya işleminde veri aktarım kütüphanesi gerekli olacaktır. Bu kütüphanesi etkinleştirmenizi öneririz.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[Etkin]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[Etkisiz]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[Yükleme klasörünü seçiniz]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[<b>WoltLab Community Framework</b>’ün tüm dosyaları yükleme klasörüne çıkartılacaktır.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[Yükleme yardımcıları "{$foundDirectory}" klasöründe <b>WoltLab Community Framework</b> yüklemesi buldu.<br />Eğer <b>WoltLab Community Framework</b>’ün yeni bir kopyasını yüklemek istiyorsanız, lütfen farklı bir yükleme klasörü seçiniz.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[Yükleme klasörü]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[Lütfen <b>WoltLab Community Framework</b> için yükleme klasörünü giriniz.]]></item>
+                               <item name="wcf.global.wcfDir.url.description"><![CDATA[Belirtilen klasöre yükleme yapıldıktan sonra <b>WoltLab Community Framework</b>'e bu URL'yi kullanarak ulaşabilirsiniz:]]></item>
+               <item name="wcf.global.wcfDir.error.invalid"><![CDATA[Verilen klasör geçerli değil.]]></item>
+               <item name="wcf.global.ftp"><![CDATA[FTP erişim bilgileri]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[PHP güvenli mod güvenlik seçeneğinin etkinleştirilmesiyle WoltLab Community Framework sadece FTP işlevleri kullanılarak yüklenebilir. Lütfen buraya bu sunucu için FTP Kullanıcı adı ve Şifre bilgilerini giriniz. Verilen bilgi kaydedilmeyecek ve sadece bu paketin yükleme işlemi için kullanılacaktır. Sadece bu nedenden için, ilerde FTP Kullanıcı adı ve Şifre bilgileri gerekebilecektir.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[FTP erişim bilgisi]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[Sunucu adı]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[Kullanıcı adı]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[Şifre]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[Verilen FTP sunucusu ile bir bağlantı sağlanamadı.]]></item>
+               <item name="wcf.global.next"><![CDATA[Sonraki aşama yükleniyor ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[Yükleme işlemi şu anda sonraki aşamayı yüklüyor, lütfen bekleyiniz.]]></item>
+               <item name="wcf.global.languages"><![CDATA[Yükleme için dil seçiniz]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[Bu yazılım çoklu dilleri desteklemektedir. Lütfen yüklemek istediğiniz dilleri seçiniz.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[Karakter Kodlaması]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[Karakter Kodlaması bilinen diğer adlarıyla Karakter Seti ya da Kod Sayfası depolama türünü ve bu sistemdeki yüklenmiş dillerin sunumunu belirler. Lütfen dikkatli olunuz, Karakter Kodlamasını seçtiğinizde daha sonra bu seçimi değiştiremezsiniz.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Eğer sadece Batı Avrupa dillerini yüklemek isterseniz ISO-8859-1 gereklidir.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Batı Avrupa ya da Batı Avrupa kaynaklı olmayan dilleri şimdi ya da daha sonraki bir tarihte yüklemek isterseniz UTF-8 gereklidir.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[Batı Avrupa]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[Orta Avrupa]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[Yunanca]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[İbranice]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[Türkçe]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[Japonca]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[Japonca]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[Çince (Geleneksel)]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[Çince (Basitleştirilmiş)]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[Çince (Basitleştirilmiş)]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[Kiril]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[Kiril]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[Korece]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[Diller]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[Lütfen en az bir dil seçiniz!]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[Seçtiğiniz dil önceden verdiğiniz Karekter Kodlamasına uymamaktadır. Lütfen dil seçiminizi değiştiriniz.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[Veritabanı erişim yapılandırması]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[Bu yazılımda veriler bir MySQL Veritabanında tutulmaktadır. Lütfen veritabanı erişim bilgilerini giriniz!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[Veritabanı erişim bilgisi]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[Sunucu adı]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[Kullanıcı adı]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[Şifre]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[Veritabanı adı]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[Yükleme sayısı]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[Veritabanınızla bağlantı kurulmaya çalışılırken bir hata oluştu:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />Daha fazla bilgi WoltLab Hata kaynağında bulunabilir:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[Belirtilen tablo{if $conflictedTables|count > 1}lar{/if} zaten bulunmakta{if $conflictedTables|count == 1}lar{/if} &quot;{$dbName}&quot; Veritabanı:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />Bu sorunu çözmek için lüften belirtilenlerden birini yapınız:<br />1. &quot;Üzerine yaz&quot; seçeneği ile {if $conflictedTables|count > 1}bu tabloların{else}bu tablonun{/if} üzerine yazınız ve &quot;İleri&quot; düğmesi ile yüklemeye devam ediniz ya da<br />2. Veritabanı erişim bilgilerini farklı bir veritabanı kullanarak tekrar girebilirsiniz ve daha sonra &quot;İleri&quot; düğmesi ile yüklemeye devam edebilirsiniz ya da<br />3. Yeni bir yükleme sayısı girebilirsiniz, bu durumda &quot;İleri&quot; düğmesine basarak yüklemeye devam etmeyi unutmayınız.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[Yukarda listelenen tablonun{if $conflictedTables|count > 1}{/if} üzerine yazılsın mı?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[Bir Yönetici oluştur]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[Yükleme işlemi şimdi sizin için bir yönetici erişimi oluşturacak. Lütfen bu erişim için kullanılacak Yönetici kullanıcı adını, e-posta adresini ve şifreyi giriniz.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[Kullanıcı bilgisi]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[Kullanıcı adı]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[E-posta adresi]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[E-posta adresi doğrulama]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[Şifre]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[Şifre doğrulama]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[Kullanıcı hesabı kaydedilirken hatalar oluştu, hatalar için lütfen işaretlenmiş alanları kontrol ediniz.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[Bu alan boş bırakılamaz.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[Girdiğiniz kullanıcı adı geçersiz. Geçerli bir kullanıcı adı en az 3 en fazla 20 karakter uzunluğunda olmalıdır.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[Girdiğiniz e-posta adresi geçersiz. Geçersiz e-posta adresi biçimi name@domain.tld gibi olmalıdır.]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[Girdiğiniz e-posta adresleri birbirini tutmamaktadır. Güvenlik nedenlerinden dolayı, lütfen iki e-posta adresi alanının da birbiri ile aynı verilerle doldurulduğundan emin olunuz.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[Girdiğiniz şifreler birbirini tutmamaktadır. Güvenlik nedenlerinden dolayı, lütfen iki şifre alanının da birbiri ile aynı verilerle doldurulduğundan emin olunuz.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[Gerekli dosyalar çıkartılırken bir hata oluştu:
+               <br /><b>{$exception->getMessage()}</b><br />
+               Lütfen hedef klasörün bulunduğundan ve yazılabilir olduğundan emin olunuz.
+               <br /><br />Daha fazla bilgi WoltLab Hata kaynağında bulunabilir:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_zh-CN.xml b/wcfsetup/setup/lang/setup_zh-CN.xml
new file mode 100644 (file)
index 0000000..af2a67a
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="zh-CN">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} 安装程序]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />安装程序]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[zh_CN]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[chinese-simplified]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.button.next"><![CDATA[下一步 &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% 完成]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>今天</b>, g:ia]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[昨天, g:ia]]></item>
+               <item name="wcf.global.welcome"><![CDATA[感谢您选择 {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[安装程序将帮您安装<br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} 和 <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[安装程序语言]]></item>
+               <item name="wcf.global.language.en"><![CDATA[英语]]></item>
+               <item name="wcf.global.language.de"><![CDATA[德语]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[德语 (非正式的)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[法语]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[日语]]></item>
+               <item name="wcf.global.language.es"><![CDATA[西班牙语]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[繁体中文]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[简体中文]]></item>
+               <item name="wcf.global.language.it"><![CDATA[意大利语]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[荷兰语]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[俄语]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[韩语]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[葡萄牙语]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[葡萄牙语]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[瑞典语]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[波兰语]]></item>
+               <item name="wcf.global.language.da"><![CDATA[丹麦语]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[捷克语]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[土耳其语]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[匈牙利语]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[阿拉伯语]]></item>
+               <item name="wcf.global.language.he"><![CDATA[希伯来语]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[波斯语]]></item>
+               <item name="wcf.global.language.no"><![CDATA[挪威语]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[芬兰语]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[罗马尼亚语]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[波斯尼亚语]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[克罗地亚语]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[塞尔维亚语]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[斯洛伐克语]]></item>
+               <item name="wcf.global.language.el"><![CDATA[希腊语]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[当前安装程序语言为简体中文.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[更改安装程序语言]]></item>
+               <item name="wcf.global.license"><![CDATA[许可协议]]></item>
+               <item name="wcf.global.license.description"><![CDATA[请认真阅读论坛系统的许可协议.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[您必须接受许可协议才能安装论坛软件.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[您必须接受许可协议才能继续安装.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[检测系统需求]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[系统需求:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[基本系统组件]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[推荐系统组件]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[需求:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[当前:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[推荐:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[PHP 版本]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[您服务器的PHP版本过低, 请升级您的PHP版本.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[您的PHP版本过低, 系统推荐使用PHP5.0.5以上版本.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[&quot;MySQL&quot; 数据库]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[&quot;MySQL&quot; 数据库支持是必须的.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[上传文件最大尺寸]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[当前的PHP配置不允许上传任何文件, 这将导致该软件的一些功能受限.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[GDLib图形库]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[如果没有GDLib图形库支持, 论坛的一些功能将受限.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[MBString宽字符库]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[如果没有该组件, 论坛则只能使用西欧语言.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[PHP安全模式]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[为了确保系统的正常运行, 我们希望您禁用安全模式.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[FTP 数据传输库]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[当前您的PHP设置启用了安全模式, 所以很多文件数据传输需要FTP的支持, 我们强烈建议您启用该库.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[启用]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[未启用]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[选择安装目录]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[<b>WoltLab Community Framework</b> 模块的所有文件将被安装在以下目录.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[安装程序检测到 "{$foundDirectory}" 中已安装有 <b>WoltLab Community Framework</b>.<br />如果您想要再安装一个新的 <b>WoltLab Community Framework</b>, 请再选择一个别的目录.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[安装目录]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[请设定 <b>WoltLab Community Framework</b> 的安装目录.]]></item>
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[安装完成后 <b>WoltLab Community Framework</b> 的访问 URL:]]></item>
+               <item name="wcf.global.ftp"><![CDATA[FTP 登录信息]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[如果您的服务器开启了PHP安全模式, 则论坛模块的安装需要FTP功能的支持. 请输入该服务器的FTP用户名和密码, 此次您输入的FTP用户名和密码仅用于此次论坛模块安装而不被记录, 因此, 您安装另外的论坛模块的时候还需要再次输入该信息.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[FTP 登录信息]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[主机]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[用户名]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[密码]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[无法创建FTP连接.]]></item>
+               <item name="wcf.global.next"><![CDATA[加载下一步骤 ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[安装程序正在加载下一步骤, 请稍候.]]></item>
+               <item name="wcf.global.languages"><![CDATA[选择系统语言]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[本论坛系统支持多语言, 请选择你想要安装的语言.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[字符编码]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[论坛的字符编码, 注意, 一旦选定将无法更改.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 is required if you wish to install Western European languages only.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 is required if you wish to install Western European or any Non-Western European langauges, now or at a later date.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode编码]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[西欧]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[中欧]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[希腊]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[希伯来]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[土耳其]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[日语]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[日语]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[繁体中文]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[简体中文]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[简体中文]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[西里尔]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[西里尔]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[韩语]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[论坛语言]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[请至少选择一种语言!]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[您选择的语言与您的字符编码设置不符, 请更改您的语言选择.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[设置数据库]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[该论坛软件数据需放置在Mysql数据库中, 请输入您的数据库信息!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[数据库信息]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[主机]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[用户名]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[密码]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[数据库]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[安装编号]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[试图连接数据库的时候发生如下错误:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />有关该错误的更多信息:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[下列数据表在您的数据库 &quot;{$dbName}&quot; 中已存在:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />您可以采取下列办法之一来解决这个问题:<br />1. 启用 &quot;覆盖&quot; 选项来覆盖数据表, 然后点击 &quot;下一步&quot;.<br />2. 返回上一步, 重新填写数据库信息, 设置另外一个数据库, 然后点击 &quot;下一步&quot;.<br />3. 返回上一步, 输入一个新的安装编号, 安装一个不同安装编号的WBB, 然后点击 &quot;下一步&quot;.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[覆盖上面数据表?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[创建管理员账户]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[安装程序将创建一个管理员账户, 请输入管理员用户名, 邮件地址以及密码.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[账户信息]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[用户名]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[E-Mail]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[确认E-Mail]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[密码]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[确认密码]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[创建账户时发生错误, 请检查被标记的表单项.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[该项不能为空.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[用户名无效, 用户名长度应该在3-20个字符之间.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[您输入了无效的 E-Mail.]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[两次输入的E-Mail地址不一致.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[两次输入的密码不一致.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[解压所需文件的时候发生如下错误:
+               <br /><b>{$exception->getMessage()}</b><br />
+               请确保目标文件夹可写.
+               <br /><br />有关该错误的更多信息:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/lang/setup_zh-TW.xml b/wcfsetup/setup/lang/setup_zh-TW.xml
new file mode 100644 (file)
index 0000000..bfb6428
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<language xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/language.xsd" languagecode="zh-TW">
+       <category name="wcf.global">
+               <item name="wcf.global.pageTitle"><![CDATA[{$setupPackageName} 安裝程式]]></item>
+               <item name="wcf.global.title"><![CDATA[<b>{$setupPackageName}</b><br />安裝程式]]></item>
+               <item name="wcf.global.pageDirection"><![CDATA[ltr]]></item>
+               <item name="wcf.global.locale.unix"><![CDATA[zh_TW]]></item>
+               <item name="wcf.global.locale.win"><![CDATA[chinese-traditional]]></item>
+               <item name="wcf.global.decimalPoint"><![CDATA[.]]></item>
+               <item name="wcf.global.thousandsSeparator"><![CDATA[,]]></item>
+               <item name="wcf.global.button.next"><![CDATA[下一步 &raquo;]]></item>
+               <item name="wcf.global.progressBar"><![CDATA[{@$progress}% 完成]]></item>
+               <item name="wcf.global.dateMethod"><![CDATA[date]]></item>
+               <item name="wcf.global.dateFormat"><![CDATA[M jS Y]]></item>
+               <item name="wcf.global.timeFormat"><![CDATA[l, F jS Y, g:ia]]></item>
+               <item name="wcf.global.dateFormatToday"><![CDATA[<b>今天</b>, g:ia]]></item>
+               <item name="wcf.global.dateFormatYesterday"><![CDATA[昨天, g:ia]]></item>
+               <item name="wcf.global.welcome"><![CDATA[感謝您選擇 {$setupPackageName}]]></item>
+               <item name="wcf.global.welcome.description"><![CDATA[安裝程式將幫您安裝<br /><b>WoltLab Community Framework</b>{if $setupPackageName != 'WoltLab Community Framework'} 和 <b>{$setupPackageName}</b>{/if}.]]></item>
+               <item name="wcf.global.welcome.language"><![CDATA[安裝程式語言]]></item>
+               <item name="wcf.global.language.en"><![CDATA[英語]]></item>
+               <item name="wcf.global.language.de"><![CDATA[德語]]></item>
+               <item name="wcf.global.language.de-informal"><![CDATA[德語 (非正式的)]]></item>
+               <item name="wcf.global.language.fr"><![CDATA[法語]]></item>
+               <item name="wcf.global.language.ja"><![CDATA[日語]]></item>
+               <item name="wcf.global.language.es"><![CDATA[西班牙語]]></item>
+               <item name="wcf.global.language.zh-TW"><![CDATA[繁體中文]]></item>
+               <item name="wcf.global.language.zh-CN"><![CDATA[簡體中文]]></item>
+               <item name="wcf.global.language.it"><![CDATA[義大利語]]></item>
+               <item name="wcf.global.language.nl"><![CDATA[荷蘭語]]></item>
+               <item name="wcf.global.language.ru"><![CDATA[俄語]]></item>
+               <item name="wcf.global.language.ko"><![CDATA[韓語]]></item>
+               <item name="wcf.global.language.pt"><![CDATA[葡萄牙語]]></item>
+               <item name="wcf.global.language.pt-BR"><![CDATA[葡萄牙語]]></item>
+               <item name="wcf.global.language.sv"><![CDATA[瑞典語]]></item>
+               <item name="wcf.global.language.pl"><![CDATA[波蘭語]]></item>
+               <item name="wcf.global.language.da"><![CDATA[丹麥語]]></item>
+               <item name="wcf.global.language.cs"><![CDATA[捷克語]]></item>
+               <item name="wcf.global.language.tr"><![CDATA[土耳其語]]></item>
+               <item name="wcf.global.language.hu"><![CDATA[匈牙利語]]></item>
+               <item name="wcf.global.language.ar"><![CDATA[阿拉伯語]]></item>
+               <item name="wcf.global.language.he"><![CDATA[希伯來語]]></item>
+               <item name="wcf.global.language.fa"><![CDATA[波斯語]]></item>
+               <item name="wcf.global.language.no"><![CDATA[挪威語]]></item>
+               <item name="wcf.global.language.fi"><![CDATA[芬蘭語]]></item>
+               <item name="wcf.global.language.ro"><![CDATA[羅馬尼亞語]]></item>
+               <item name="wcf.global.language.bs"><![CDATA[波士尼亞語]]></item>
+               <item name="wcf.global.language.hr"><![CDATA[克羅地亞語]]></item>
+               <item name="wcf.global.language.sr"><![CDATA[塞爾維亞語]]></item>
+               <item name="wcf.global.language.sk"><![CDATA[斯洛伐克語]]></item>
+               <item name="wcf.global.language.el"><![CDATA[希臘語]]></item>
+               <item name="wcf.global.welcome.language.description"><![CDATA[當前安裝程式語言為簡體中文.]]></item>
+               <item name="wcf.global.welcome.language.change"><![CDATA[更改安裝程式語言]]></item>
+               <item name="wcf.global.license"><![CDATA[許可協議]]></item>
+               <item name="wcf.global.license.description"><![CDATA[請認真閱讀論壇系統的許可協定.]]></item>
+               <item name="wcf.global.license.accept.description"><![CDATA[您必須接受許可協定才能安裝論壇軟體.]]></item>
+               <item name="wcf.global.license.missingAcception"><![CDATA[您必須接受許可協議才能繼續安裝.]]></item>
+               <item name="wcf.global.systemRequirements"><![CDATA[檢測系統需求]]></item>
+               <item name="wcf.global.systemRequirements.description"><![CDATA[系統需求:]]></item>
+               <item name="wcf.global.systemRequirements.required"><![CDATA[基本系統元件]]></item>
+               <item name="wcf.global.systemRequirements.recommended"><![CDATA[推薦系統元件]]></item>
+               <item name="wcf.global.systemRequirements.element.required"><![CDATA[需求:]]></item>
+               <item name="wcf.global.systemRequirements.element.yours"><![CDATA[當前:]]></item>
+               <item name="wcf.global.systemRequirements.element.recommended"><![CDATA[推薦:]]></item>
+               <item name="wcf.global.systemRequirements.php"><![CDATA[PHP 版本]]></item>
+               <item name="wcf.global.systemRequirements.php.description"><![CDATA[您伺服器的PHP版本過低, 請升級您的PHP版本.]]></item>
+               <item name="wcf.global.systemRequirements.php.description2"><![CDATA[您的PHP版本過低, 系統推薦使用PHP5.0.5以上版本.]]></item>
+               <item name="wcf.global.systemRequirements.mysql"><![CDATA[&quot;MySQL&quot; 資料庫]]></item>
+               <item name="wcf.global.systemRequirements.mysql.description"><![CDATA[&quot;MySQL&quot; 資料庫支援是必須的.]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize"><![CDATA[上傳文件最大尺寸]]></item>
+               <item name="wcf.global.systemRequirements.uploadMaxFilesize.description"><![CDATA[當前的PHP配置不允許上傳任何檔, 這將導致該軟體的一些功能受限.]]></item>
+               <item name="wcf.global.systemRequirements.gdLib"><![CDATA[GDLib圖形庫]]></item>
+               <item name="wcf.global.systemRequirements.gdLib.description"><![CDATA[如果沒有GDLib圖形庫支援, 論壇的一些功能將受限.]]></item>
+               <item name="wcf.global.systemRequirements.mbString"><![CDATA[MBString寬字元庫]]></item>
+               <item name="wcf.global.systemRequirements.mbString.description"><![CDATA[如果沒有該元件, 論壇則只能使用西歐語言.]]></item>
+               <item name="wcf.global.systemRequirements.safeMode"><![CDATA[PHP安全模式]]></item>
+               <item name="wcf.global.systemRequirements.safeMode.description"><![CDATA[為了確保系統的正常運行, 我們希望您禁用安全模式.]]></item>
+               <item name="wcf.global.systemRequirements.ftp"><![CDATA[FTP 資料傳輸庫]]></item>
+               <item name="wcf.global.systemRequirements.ftp.description"><![CDATA[當前您的PHP設置啟用了安全模式, 所以很多檔資料傳輸需要FTP的支援, 我們強烈建議您啟用該庫.]]></item>
+               <item name="wcf.global.systemRequirements.active"><![CDATA[啟用]]></item>
+               <item name="wcf.global.systemRequirements.notActive"><![CDATA[未啟用]]></item>
+               <item name="wcf.global.wcfDir"><![CDATA[選擇安裝目錄]]></item>
+               <item name="wcf.global.wcfDir.description"><![CDATA[<b>WoltLab Community Framework</b> 模組的所有檔將被安裝在以下目錄.]]></item>
+               <item name="wcf.global.wcfDir.foundDirectory"><![CDATA[安裝程式檢測到 "{$foundDirectory}" 中已安裝有 <b>WoltLab Community Framework</b>.<br />如果您想要再安裝一個新的 <b>WoltLab Community Framework</b>, 請再選擇一個別的目錄.]]></item>
+               <item name="wcf.global.wcfDir.dir"><![CDATA[安裝目錄]]></item>
+               <item name="wcf.global.wcfDir.dir.description"><![CDATA[請設定 <b>WoltLab Community Framework</b> 的安裝目錄.]]></item>
+               <item name="wcf.global.wcfDir.url.description"><![CDATA[安裝完成後 <b>WoltLab Community Framework</b> 的訪問 URL:]]></item>
+               <item name="wcf.global.ftp"><![CDATA[FTP 登錄信息]]></item>
+               <item name="wcf.global.ftp.description"><![CDATA[如果您的伺服器開啟了PHP安全模式, 則論壇模組的安裝需要FTP功能的支援. 請輸入該伺服器的FTP用戶名和密碼, 此次您輸入的FTP用戶名和密碼僅用於此次論壇模組安裝而不被記錄, 因此, 您安裝另外的論壇模組的時候還需要再次輸入該資訊.]]></item>
+               <item name="wcf.global.ftp.accessData"><![CDATA[FTP 登錄信息]]></item>
+               <item name="wcf.global.ftp.host"><![CDATA[主機]]></item>
+               <item name="wcf.global.ftp.user"><![CDATA[用戶名]]></item>
+               <item name="wcf.global.ftp.password"><![CDATA[密碼]]></item>
+               <item name="wcf.global.ftp.error"><![CDATA[無法創建FTP連接.]]></item>
+               <item name="wcf.global.next"><![CDATA[載入下一步驟 ...]]></item>
+               <item name="wcf.global.next.description"><![CDATA[安裝程式正在載入下一步驟, 請稍候.]]></item>
+               <item name="wcf.global.languages"><![CDATA[選擇系統語言]]></item>
+               <item name="wcf.global.languages.description"><![CDATA[本論壇系統支援多語言, 請選擇你想要安裝的語言.]]></item>
+               <item name="wcf.global.languages.charset"><![CDATA[字元編碼]]></item>
+               <item name="wcf.global.languages.charset.description"><![CDATA[論壇的字元編碼, 注意, 一旦選定將無法更改.]]></item>
+               
+               <!--<item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[ISO-8859-1 is required if you wish to install Western European languages only.]]></item>
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[UTF-8 is required if you wish to install Western European or any Non-Western European langauges, now or at a later date.]]></item>-->
+               
+               <item name="wcf.global.languages.charset.UTF-8"><![CDATA[Unicode編碼]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-1"><![CDATA[西歐]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-2"><![CDATA[中歐]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-7"><![CDATA[希臘]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-8"><![CDATA[希伯來]]></item>
+               <item name="wcf.global.languages.charset.ISO-8859-9"><![CDATA[土耳其]]></item>
+               <item name="wcf.global.languages.charset.EUC-JP"><![CDATA[日語]]></item>
+               <item name="wcf.global.languages.charset.SJIS"><![CDATA[日語]]></item>
+               <item name="wcf.global.languages.charset.BIG-5"><![CDATA[繁體中文]]></item>
+               <item name="wcf.global.languages.charset.CP936"><![CDATA[簡體中文]]></item>
+               <item name="wcf.global.languages.charset.EUC-CN"><![CDATA[簡體中文]]></item>
+               <item name="wcf.global.languages.charset.KOI8-R"><![CDATA[西瑞爾]]></item>
+               <item name="wcf.global.languages.charset.Windows-1251"><![CDATA[西瑞爾]]></item>
+               <item name="wcf.global.languages.charset.EUC-KR"><![CDATA[韓語]]></item>
+               
+               <item name="wcf.global.languages.languages"><![CDATA[論壇語言]]></item>
+               <item name="wcf.global.languages.error.empty"><![CDATA[請至少選擇一種語言!]]></item>
+               <item name="wcf.global.languages.error.notAvailable"><![CDATA[您選擇的語言與您的字元編碼設置不符, 請更改您的語言選擇.]]></item>
+               <item name="wcf.global.configureDB"><![CDATA[設置資料庫]]></item>
+               <item name="wcf.global.configureDB.description"><![CDATA[該論壇軟體資料需放置在Mysql資料庫中, 請輸入您的資料庫資訊!]]></item>
+               <item name="wcf.global.configureDB.accessData"><![CDATA[資料庫資訊]]></item>
+               <item name="wcf.global.configureDB.host"><![CDATA[主機]]></item>
+               <item name="wcf.global.configureDB.user"><![CDATA[用戶名]]></item>
+               <item name="wcf.global.configureDB.password"><![CDATA[密碼]]></item>
+               <item name="wcf.global.configureDB.database"><![CDATA[資料庫]]></item>
+               <item name="wcf.global.configureDB.number"><![CDATA[安裝編號]]></item>
+               <item name="wcf.global.configureDB.error"><![CDATA[試圖連接資料庫的時候發生如下錯誤:
+               <br /><b>{$exception->getMessage()}{if $exception|get_class == 'DatabaseException'}<br />{$exception->getErrorDesc()}{/if}</b>
+               <br />有關該錯誤的更多資訊:
+               <br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+               <item name="wcf.global.configureDB.conflictedTables"><![CDATA[下列資料表在您的資料庫 &quot;{$dbName}&quot; 中已存在:<br />{implode from=$conflictedTables item="table"}{$table}{/implode}.<br /><br />您可以採取下列辦法之一來解決這個問題:<br />1. 啟用 &quot;覆蓋&quot; 選項來覆蓋資料表, 然後點擊 &quot;下一步&quot;.<br />2. 返回上一步, 重新填寫資料庫資訊, 設置另外一個資料庫, 然後點擊 &quot;下一步&quot;.<br />3. 返回上一步, 輸入一個新的安裝編號, 安裝一個不同安裝編號的WBB, 然後點擊 &quot;下一步&quot;.]]></item>
+               <item name="wcf.global.configureDB.conflictedTables.overwrite"><![CDATA[覆蓋上面資料表?]]></item>
+               <item name="wcf.global.createUser"><![CDATA[創建管理員帳戶]]></item>
+               <item name="wcf.global.createUser.description"><![CDATA[安裝程式將創建一個管理員帳戶, 請輸入管理員用戶名, 郵件位址以及密碼.]]></item>
+               <item name="wcf.global.createUser.data"><![CDATA[帳戶信息]]></item>
+               <item name="wcf.global.createUser.username"><![CDATA[用戶名]]></item>
+               <item name="wcf.global.createUser.email"><![CDATA[E-Mail]]></item>
+               <item name="wcf.global.createUser.confirmEmail"><![CDATA[確認E-Mail]]></item>
+               <item name="wcf.global.createUser.password"><![CDATA[密碼]]></item>
+               <item name="wcf.global.createUser.confirmPassword"><![CDATA[確認密碼]]></item>
+               <item name="wcf.global.createUser.error"><![CDATA[創建帳戶時發生錯誤, 請檢查被標記的表單項.]]></item>
+               <item name="wcf.global.createUser.error.empty"><![CDATA[該項不能為空.]]></item>
+               <item name="wcf.global.createUser.error.username.notValid"><![CDATA[用戶名無效, 用戶名長度應該在3-20個字元之間.]]></item>
+               <item name="wcf.global.createUser.error.email.notValid"><![CDATA[您輸入了無效的 E-Mail.]]></item>
+               <item name="wcf.global.createUser.error.confirmEmail.notEqual"><![CDATA[兩次輸入的E-Mail位址不一致.]]></item>
+               <item name="wcf.global.createUser.error.confirmPassword.notEqual"><![CDATA[兩次輸入的密碼不一致.]]></item>
+               <item name="wcf.global.wcfDir.error"><![CDATA[解壓所需檔的時候發生如下錯誤:
+               <br /><b>{$exception->getMessage()}</b><br />
+               請確保目標檔夾可寫.
+               <br /><br />有關該錯誤的更多資訊:<br /><a href="http://www.woltlab.com/help/?code={@$exception->getCode()}">http://www.woltlab.com/help/?code={@$exception->getCode()}</a>]]></item>
+       </category>
+</language>
diff --git a/wcfsetup/setup/license/license_en.txt b/wcfsetup/setup/license/license_en.txt
new file mode 100644 (file)
index 0000000..b87303c
--- /dev/null
@@ -0,0 +1,165 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE\r
+                       Version 3, 29 June 2007\r
+\r
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+\r
+  This version of the GNU Lesser General Public License incorporates\r
+the terms and conditions of version 3 of the GNU General Public\r
+License, supplemented by the additional permissions listed below.\r
+\r
+  0. Additional Definitions. \r
+\r
+  As used herein, "this License" refers to version 3 of the GNU Lesser\r
+General Public License, and the "GNU GPL" refers to version 3 of the GNU\r
+General Public License.\r
+\r
+  "The Library" refers to a covered work governed by this License,\r
+other than an Application or a Combined Work as defined below.\r
+\r
+  An "Application" is any work that makes use of an interface provided\r
+by the Library, but which is not otherwise based on the Library.\r
+Defining a subclass of a class defined by the Library is deemed a mode\r
+of using an interface provided by the Library.\r
+\r
+  A "Combined Work" is a work produced by combining or linking an\r
+Application with the Library.  The particular version of the Library\r
+with which the Combined Work was made is also called the "Linked\r
+Version".\r
+\r
+  The "Minimal Corresponding Source" for a Combined Work means the\r
+Corresponding Source for the Combined Work, excluding any source code\r
+for portions of the Combined Work that, considered in isolation, are\r
+based on the Application, and not on the Linked Version.\r
+\r
+  The "Corresponding Application Code" for a Combined Work means the\r
+object code and/or source code for the Application, including any data\r
+and utility programs needed for reproducing the Combined Work from the\r
+Application, but excluding the System Libraries of the Combined Work.\r
+\r
+  1. Exception to Section 3 of the GNU GPL.\r
+\r
+  You may convey a covered work under sections 3 and 4 of this License\r
+without being bound by section 3 of the GNU GPL.\r
+\r
+  2. Conveying Modified Versions.\r
+\r
+  If you modify a copy of the Library, and, in your modifications, a\r
+facility refers to a function or data to be supplied by an Application\r
+that uses the facility (other than as an argument passed when the\r
+facility is invoked), then you may convey a copy of the modified\r
+version:\r
+\r
+   a) under this License, provided that you make a good faith effort to\r
+   ensure that, in the event an Application does not supply the\r
+   function or data, the facility still operates, and performs\r
+   whatever part of its purpose remains meaningful, or\r
+\r
+   b) under the GNU GPL, with none of the additional permissions of\r
+   this License applicable to that copy.\r
+\r
+  3. Object Code Incorporating Material from Library Header Files.\r
+\r
+  The object code form of an Application may incorporate material from\r
+a header file that is part of the Library.  You may convey such object\r
+code under terms of your choice, provided that, if the incorporated\r
+material is not limited to numerical parameters, data structure\r
+layouts and accessors, or small macros, inline functions and templates\r
+(ten or fewer lines in length), you do both of the following:\r
+\r
+   a) Give prominent notice with each copy of the object code that the\r
+   Library is used in it and that the Library and its use are\r
+   covered by this License.\r
+\r
+   b) Accompany the object code with a copy of the GNU GPL and this license\r
+   document.\r
+\r
+  4. Combined Works.\r
+\r
+  You may convey a Combined Work under terms of your choice that,\r
+taken together, effectively do not restrict modification of the\r
+portions of the Library contained in the Combined Work and reverse\r
+engineering for debugging such modifications, if you also do each of\r
+the following:\r
+\r
+   a) Give prominent notice with each copy of the Combined Work that\r
+   the Library is used in it and that the Library and its use are\r
+   covered by this License.\r
+\r
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license\r
+   document.\r
+\r
+   c) For a Combined Work that displays copyright notices during\r
+   execution, include the copyright notice for the Library among\r
+   these notices, as well as a reference directing the user to the\r
+   copies of the GNU GPL and this license document.\r
+\r
+   d) Do one of the following:\r
+\r
+       0) Convey the Minimal Corresponding Source under the terms of this\r
+       License, and the Corresponding Application Code in a form\r
+       suitable for, and under terms that permit, the user to\r
+       recombine or relink the Application with a modified version of\r
+       the Linked Version to produce a modified Combined Work, in the\r
+       manner specified by section 6 of the GNU GPL for conveying\r
+       Corresponding Source.\r
+\r
+       1) Use a suitable shared library mechanism for linking with the\r
+       Library.  A suitable mechanism is one that (a) uses at run time\r
+       a copy of the Library already present on the user's computer\r
+       system, and (b) will operate properly with a modified version\r
+       of the Library that is interface-compatible with the Linked\r
+       Version. \r
+\r
+   e) Provide Installation Information, but only if you would otherwise\r
+   be required to provide such information under section 6 of the\r
+   GNU GPL, and only to the extent that such information is\r
+   necessary to install and execute a modified version of the\r
+   Combined Work produced by recombining or relinking the\r
+   Application with a modified version of the Linked Version. (If\r
+   you use option 4d0, the Installation Information must accompany\r
+   the Minimal Corresponding Source and Corresponding Application\r
+   Code. If you use option 4d1, you must provide the Installation\r
+   Information in the manner specified by section 6 of the GNU GPL\r
+   for conveying Corresponding Source.)\r
+\r
+  5. Combined Libraries.\r
+\r
+  You may place library facilities that are a work based on the\r
+Library side by side in a single library together with other library\r
+facilities that are not Applications and are not covered by this\r
+License, and convey such a combined library under terms of your\r
+choice, if you do both of the following:\r
+\r
+   a) Accompany the combined library with a copy of the same work based\r
+   on the Library, uncombined with any other library facilities,\r
+   conveyed under the terms of this License.\r
+\r
+   b) Give prominent notice with the combined library that part of it\r
+   is a work based on the Library, and explaining where to find the\r
+   accompanying uncombined form of the same work.\r
+\r
+  6. Revised Versions of the GNU Lesser General Public License.\r
+\r
+  The Free Software Foundation may publish revised and/or new versions\r
+of the GNU Lesser General Public License from time to time. Such new\r
+versions will be similar in spirit to the present version, but may\r
+differ in detail to address new problems or concerns.\r
+\r
+  Each version is given a distinguishing version number. If the\r
+Library as you received it specifies that a certain numbered version\r
+of the GNU Lesser General Public License "or any later version"\r
+applies to it, you have the option of following the terms and\r
+conditions either of that published version or of any later version\r
+published by the Free Software Foundation. If the Library as you\r
+received it does not specify a version number of the GNU Lesser\r
+General Public License, you may choose any version of the GNU Lesser\r
+General Public License ever published by the Free Software Foundation.\r
+\r
+  If the Library as you received it specifies that a proxy can decide\r
+whether future versions of the GNU Lesser General Public License shall\r
+apply, that proxy's public statement of acceptance of any version is\r
+permanent authorization for you to choose that version for the\r
+Library.\r
diff --git a/wcfsetup/setup/template/footer.tpl b/wcfsetup/setup/template/footer.tpl
new file mode 100644 (file)
index 0000000..a857e15
--- /dev/null
@@ -0,0 +1,6 @@
+               <div class="copyright">\r
+                       <span>Copyright &copy; 2001-2011 WoltLab&reg; GmbH</span>\r
+               </div>\r
+       </div>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/wcfsetup/setup/template/header.tpl b/wcfsetup/setup/template/header.tpl
new file mode 100644 (file)
index 0000000..fe08d56
--- /dev/null
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" dir="{lang}wcf.global.pageDirection{/lang}" xml:lang="{@LANGUAGE_CODE}">\r
+       <head>\r
+               <title>{lang}wcf.global.progressBar{/lang} - {lang}wcf.global.pageTitle{/lang}</title>\r
+               <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+               <style type="text/css">\r
+                       /*<![CDATA[*/\r
+                       body {\r
+                               font-family: "Trebuchet MS", Tahoma, Verdana, Arial, Helvetica, sans-serif; \r
+                               color: #333;\r
+                               font-size: .82em;\r
+                               margin: 0;\r
+                               padding: 0;\r
+                               background-color: #eee;\r
+                               background-image: url({if 'RELATIVE_WCF_DIR'|defined}{@' '|str_replace:'%20':RELATIVE_WCF_DIR}acp/images/setupBackground-{@PAGE_DIRECTION}.png{else}install.php?showImage=setupBackground-{@PAGE_DIRECTION}.png&tmpFilePrefix={@$tmpFilePrefix}{/if});\r
+                               background-repeat: repeat-y;\r
+                               background-position: {if PAGE_DIRECTION == 'ltr'}left{else}right{/if};\r
+                       }\r
+                       \r
+                       .page {\r
+                               background-image: url({if 'RELATIVE_WCF_DIR'|defined}{@' '|str_replace:'%20':RELATIVE_WCF_DIR}acp/images/setupHeader-{@PAGE_DIRECTION}.jpg{else}install.php?showImage=setupHeader-{@PAGE_DIRECTION}.jpg&tmpFilePrefix={@$tmpFilePrefix}{/if});\r
+                               background-repeat: no-repeat;\r
+                               background-color: #fff;\r
+                               padding: 153px 40px 20px 40px;\r
+                               width: 720px;\r
+                       }\r
+                       \r
+                       .inner {\r
+                               padding: 10px 20px;\r
+                       }\r
+                       \r
+                       h1 {\r
+                               color: #164369;\r
+                               text-shadow: 0 2px 3px #bbb;\r
+                               font-size: 1.9em;\r
+                               font-weight: normal;\r
+                               margin: 5px 0;\r
+                               padding: 5px 0;\r
+                       }\r
+                       \r
+                       h2 {\r
+                               color: #164369;\r
+                               font-size: 1.4em;\r
+                               font-weight: bold;\r
+                               margin: 0;\r
+                               padding-top: 5px;\r
+                       }\r
+                       \r
+                       h3 {\r
+                               font-size: 1.3em;\r
+                               font-weight: bold;\r
+                               color: #666;\r
+                               margin: 0;\r
+                               padding: 2px 0 10px 0;\r
+                       }\r
+                       \r
+                       .info, .success, .warning, .error, .help {\r
+                               -webkit-border-radius: 5px;\r
+                               -moz-border-radius: 5px;\r
+                       }\r
+                       \r
+                       fieldset {\r
+                               font-size: .82em;\r
+                               border: 1px solid #8da4b7;\r
+                               margin-bottom: 10px;\r
+                               padding: 0;\r
+                               -webkit-border-radius: 5px;\r
+                               -moz-border-radius: 5px;\r
+                       }\r
+                       \r
+                       legend {\r
+                               color: #487397;\r
+                               font-size: 1em;\r
+                               margin: 0 10px;\r
+                               padding: 0 4px;\r
+                       }\r
+                       \r
+                       fieldset p, fieldset div {\r
+                               margin: 0;\r
+                               padding: 0 0 5px 0;\r
+                       }\r
+                                               \r
+                       fieldset ul {\r
+                               list-style: none;\r
+                               margin: 0;\r
+                               padding: 0;\r
+                       }\r
+                               \r
+                       fieldset ul li {\r
+                               padding-{if PAGE_DIRECTION == 'ltr'}right{else}left{/if}: 3%;\r
+                               float: {if PAGE_DIRECTION == 'ltr'}left{else}right{/if};\r
+                               width: 30%;\r
+                       }\r
+                       \r
+                       hr {\r
+                               color: #8da4b7;\r
+                               background-color: #8da4b7;\r
+                               border: 0;\r
+                               margin: 10px 0;\r
+                               padding: 0;\r
+                               height: 1px;\r
+                               width: 100%;\r
+                               position: relative;\r
+                               clear: {if PAGE_DIRECTION == 'ltr'}left{else}right{/if};\r
+                       }\r
+                       \r
+                       form {\r
+                               padding: 0;\r
+                               margin: 0;\r
+                       }\r
+                       \r
+                       textarea, select, input[type="text"], input[type="password"] {\r
+                               background-color: #fafafa;\r
+                               border-width: 1px;\r
+                               border-style: solid;\r
+                               border-color: #666 #999 #ccc #999;\r
+                               background-image: url({if 'RELATIVE_WCF_DIR'|defined}{@' '|str_replace:'%20':RELATIVE_WCF_DIR}acp/images/setupInputBackground.png{else}install.php?showImage=setupInputBackground.png&tmpFilePrefix={@$tmpFilePrefix}{/if});\r
+                               background-position: left top;\r
+                               background-repeat: repeat-x;\r
+                               min-height: 13px;\r
+                       }\r
+                       \r
+                       textarea, input[type="text"], input[type="password"] {\r
+                               width: 100%;\r
+                       }\r
+               \r
+                       textarea:focus, select:focus, input[type="text"]:focus, input[type="password"]:focus {\r
+                               background-color: #fff9f4;\r
+                               border: 1px solid #fa2;\r
+                               background-image: url({if 'RELATIVE_WCF_DIR'|defined}{@' '|str_replace:'%20':RELATIVE_WCF_DIR}acp/images/setupInputBackground.png{else}install.php?showImage=setupInputBackground.png&tmpFilePrefix={@$tmpFilePrefix}{/if});\r
+                               background-repeat: repeat-x;\r
+                               outline: 0;\r
+                       }\r
+                       \r
+                       textarea, select, input[type="text"], input[type="password"] {\r
+                               padding: 2px;\r
+                               -webkit-border-radius: 3px;\r
+                               -moz-border-radius: 3px;\r
+                       }\r
+                                               \r
+                       label {\r
+                               padding-bottom: 2px;\r
+                               display: block;\r
+                       }\r
+                       \r
+                       .setupIcon {\r
+                               margin-{if PAGE_DIRECTION == 'ltr'}right{else}left{/if}: 30px;\r
+                               float: {if PAGE_DIRECTION == 'ltr'}left{else}right{/if};\r
+                       }\r
+                       \r
+                       .nextButton {\r
+                               float: {if PAGE_DIRECTION == 'ltr'}right{else}left{/if};\r
+                       }\r
+                       \r
+                       .copyright {\r
+                               font-size: .8em;\r
+                       }\r
+                       \r
+                       .left {\r
+                               float: {if PAGE_DIRECTION == 'ltr'}left{else}right{/if};\r
+                       }\r
+                       \r
+                       .left, .right {\r
+                               font-weight: bold;\r
+                               display: block;\r
+                       }\r
+                       \r
+                       .right {\r
+                               margin-{if PAGE_DIRECTION == 'ltr'}left{else}right{/if}: 48%;\r
+                               width: 48%;\r
+                       }\r
+                       \r
+                       .disabled {\r
+                               color: #b2b2b2;\r
+                       }\r
+                       \r
+                       .error {\r
+                               color: #c00;\r
+                               border: 1px solid #c00;\r
+                               background-color: #fee;\r
+                               padding: 4px 10px;\r
+                       }\r
+                       \r
+                       .errorField {\r
+                               color: #c00;\r
+                       }\r
+                       \r
+                       .errorField .inputText, .errorField select, .errorField textarea {\r
+                               border: 1px solid #c00;\r
+                               background-color: #fee;\r
+                       }\r
+                       \r
+                       .progress {\r
+                               border: 1px solid #b2b2b2;\r
+                               margin: {if PAGE_DIRECTION == 'ltr'}0 0 25px 128px{else}0 128px 25px 0{/if};\r
+                               padding: 1px;\r
+                               width: 300px;\r
+                               height: 16px;\r
+                               -webkit-border-radius: 3px;\r
+                               -moz-border-radius: 3px;\r
+                       }\r
+                       \r
+                       .progressBar {\r
+                               background-color: #f1f1f1;\r
+                               border-bottom: 8px solid #ddd;\r
+                               height: 8px;\r
+                               font-size: 7px;\r
+                               -webkit-border-radius: 1px;\r
+                               -moz-border-radius: 1px;\r
+                       }\r
+                       \r
+                       .progressText {\r
+                               color: #333;\r
+                               text-shadow: 0 1px 1px #fff;\r
+                               font-size: .75em;\r
+                               text-align: center;\r
+                               margin-top: -15px;\r
+                       }\r
+                       \r
+                       #wcfUrl {\r
+                               text-decoration: underline;\r
+                               background: transparent;\r
+                               border: none;\r
+                               padding: 0;\r
+                       }\r
+                                               \r
+                       /*]]>*/\r
+               </style>\r
+               <!--[if lt IE 7]>\r
+                       <style type="text/css">\r
+                               .page {\r
+                                       width: 800px;\r
+                               }\r
+                               .progressText {\r
+                                       margin-top: -16px;\r
+                               }\r
+                       </style>\r
+               <![endif]-->\r
+               <!--[if IE]>\r
+                       <style type="text/css">\r
+                               hr {\r
+                                       margin: 0;\r
+                               }\r
+                               fieldset p, fieldset div {\r
+                                       min-height: 0;\r
+                               }\r
+                       </style>\r
+               <![endif]-->\r
+       </head>\r
+<body>\r
+       <div class="page">\r
+               <img class="setupIcon" src="{if 'RELATIVE_WCF_DIR'|defined}{@RELATIVE_WCF_DIR}acp/images/setupIconXL.jpg{else}install.php?showImage=setupIconXL.jpg&amp;tmpFilePrefix={@$tmpFilePrefix}{/if}" alt="" />\r
+               <h1>{lang}wcf.global.title{/lang}</h1>\r
+               <div class="progress">\r
+                       <div class="progressBar" style="width: {@300*$progress/100|round:0}px"></div>\r
+                       <div class="progressText">{lang}wcf.global.progressBar{/lang}</div>\r
+               </div>\r
+               <hr />\r
+       \r
+       
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepConfigureDB.tpl b/wcfsetup/setup/template/stepConfigureDB.tpl
new file mode 100644 (file)
index 0000000..7b386b5
--- /dev/null
@@ -0,0 +1,78 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.configureDB{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.configureDB.description{/lang}</p>\r
+\r
+{if $exception|isset}\r
+       <p class="error">{lang}wcf.global.configureDB.error{/lang}</p>\r
+{/if}\r
+\r
+{if $conflictedTables|isset}\r
+<p class="error">\r
+       {lang}wcf.global.configureDB.conflictedTables{/lang}\r
+</p>\r
+{/if}\r
+\r
+<form method="post" action="install.php">\r
+       <fieldset>\r
+               <legend>{lang}wcf.global.configureDB.accessData{/lang}</legend>\r
+               \r
+               <div class="inner">\r
+                       <div>\r
+                               <label for="dbClass">{lang}wcf.global.configureDB.class{/lang}</label>\r
+                               <select name="dbClass" id="dbClass">\r
+                                       {foreach from=$availableDBClasses key=dbClassName item=availableDBClass}\r
+                                               <option value="{@$availableDBClass.class}"{if $availableDBClass.class == $dbClass} selected="selected"{/if}>{lang}wcf.global.configureDB.class.{@$dbClassName}{/lang}</option>\r
+                                       {/foreach}\r
+                               </select>\r
+                       </div>\r
+\r
+                       <div>\r
+                               <label for="dbHost">{lang}wcf.global.configureDB.host{/lang}</label>\r
+                               <input type="text" class="inputText" id="dbHost" name="dbHost" value="{$dbHost}" style="width: 100%;" />\r
+                       </div>\r
+                       \r
+                       <div>\r
+                               <label for="dbUser">{lang}wcf.global.configureDB.user{/lang}</label>\r
+                               <input type="text" class="inputText" id="dbUser" name="dbUser" value="{$dbUser}" style="width: 100%;" />\r
+                       </div>\r
+                       \r
+                       <div>\r
+                               <label for="dbPassword">{lang}wcf.global.configureDB.password{/lang}</label>\r
+                               <input type="password" class="inputText" id="dbPassword" name="dbPassword" value="{$dbPassword}" style="width: 100%;" />\r
+                       </div>\r
+                       \r
+                       <div>\r
+                               <label for="dbName">{lang}wcf.global.configureDB.database{/lang}</label>\r
+                               <input type="text" class="inputText" id="dbName" name="dbName" value="{$dbName}" style="width: 100%;" />\r
+                       </div>\r
+                       \r
+                       <div>\r
+                               <label for="dbNumber">{lang}wcf.global.configureDB.number{/lang}</label>\r
+                               <input type="text" class="inputText" id="dbNumber" name="dbNumber" value="{$dbNumber}" style="width: 100%;" />\r
+                       </div>\r
+                       \r
+                       {if $conflictedTables|isset}\r
+                       <div>\r
+                               <label><input type="checkbox" name="overwriteTables" value="1" /> {lang}wcf.global.configureDB.conflictedTables.overwrite{/lang}</label>\r
+                       </div>\r
+                       {/if}\r
+               </div>\r
+       </fieldset>\r
+       \r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="send" value="1" />\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="wcfDir" value="{$wcfDir}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+               {foreach from=$selectedLanguages item=language}\r
+                       <input type="hidden" name="selectedLanguages[]" value="{$language}" />\r
+               {/foreach}\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepCreateUser.tpl b/wcfsetup/setup/template/stepCreateUser.tpl
new file mode 100644 (file)
index 0000000..068757a
--- /dev/null
@@ -0,0 +1,82 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.createUser{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.createUser.description{/lang}</p>\r
+\r
+{if $errorField}\r
+<p class="error">{lang}wcf.global.createUser.error{/lang}</p>\r
+{/if}\r
+\r
+<form method="post" action="install.php">\r
+       <fieldset>\r
+               <legend>{lang}wcf.global.createUser.data{/lang}</legend>\r
+               \r
+               <div class="inner">\r
+                       <div{if $errorField == 'username'} class="errorField"{/if}>\r
+                               <label for="username">{lang}wcf.global.createUser.username{/lang}</label>\r
+                               <input type="text" class="inputText" id="username" name="username" value="{$username}" style="width: 100%;" />\r
+                               {if $errorField == 'username'}\r
+                                       <p>\r
+                                               {if $errorType == 'empty'}{lang}wcf.global.createUser.error.empty{/lang}{/if}\r
+                                               {if $errorType == 'notValid'}{lang}wcf.global.createUser.error.username.notValid{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+                       \r
+                       <div{if $errorField == 'email'} class="errorField"{/if}>\r
+                               <label for="email">{lang}wcf.global.createUser.email{/lang}</label>\r
+                               <input type="text" class="inputText" id="email" name="email" value="{$email}" style="width: 100%;" />\r
+                               {if $errorField == 'email'}\r
+                                       <p>\r
+                                               {if $errorType == 'empty'}{lang}wcf.global.createUser.error.empty{/lang}{/if}\r
+                                               {if $errorType == 'notValid'}{lang}wcf.global.createUser.error.email.notValid{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+                       \r
+                       <div{if $errorField == 'confirmEmail'} class="errorField"{/if}>\r
+                               <label for="confirmEmail">{lang}wcf.global.createUser.confirmEmail{/lang}</label>\r
+                               <input type="text" class="inputText" id="confirmEmail" name="confirmEmail" value="{$confirmEmail}" style="width: 100%;" />\r
+                               {if $errorField == 'confirmEmail'}\r
+                                       <p>\r
+                                               {if $errorType == 'notEqual'}{lang}wcf.global.createUser.error.confirmEmail.notEqual{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+                       \r
+                       <div{if $errorField == 'password'} class="errorField"{/if}>\r
+                               <label for="password">{lang}wcf.global.createUser.password{/lang}</label>\r
+                               <input type="password" class="inputText" id="password" name="password" value="{$password}" style="width: 100%;" />\r
+                               {if $errorField == 'password'}\r
+                                       <p>\r
+                                               {if $errorType == 'empty'}{lang}wcf.global.createUser.error.empty{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+                       \r
+                       <div{if $errorField == 'confirmPassword'} class="errorField"{/if}>\r
+                               <label for="confirmPassword">{lang}wcf.global.createUser.confirmPassword{/lang}</label>\r
+                               <input type="password" class="inputText" id="confirmPassword" name="confirmPassword" value="{$confirmPassword}" style="width: 100%;" />\r
+                               {if $errorField == 'confirmPassword'}\r
+                                       <p>\r
+                                               {if $errorType == 'notEqual'}{lang}wcf.global.createUser.error.confirmPassword.notEqual{/lang}{/if}\r
+                                       </p>\r
+                               {/if}\r
+                       </div>\r
+                       \r
+               </div>\r
+       </fieldset>\r
+       \r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="send" value="1" />\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="wcfDir" value="{$wcfDir}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepInstallPackages.tpl b/wcfsetup/setup/template/stepInstallPackages.tpl
new file mode 100644 (file)
index 0000000..2efe45e
--- /dev/null
@@ -0,0 +1,25 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.next{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.next.description{/lang}</p>\r
+\r
+<hr />\r
+\r
+<form method="get" action="{@RELATIVE_WCF_DIR}acp/index.php">\r
+       <div class="nextButton">\r
+               <input type="submit" name="nextButton" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               {@SID_INPUT_TAG}\r
+       </div>\r
+</form>\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       window.onload = function() {\r
+               document.forms[0].nextButton.disabled = true;\r
+               document.forms[0].submit();\r
+       }\r
+       //]]>\r
+</script>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepNext.tpl b/wcfsetup/setup/template/stepNext.tpl
new file mode 100644 (file)
index 0000000..5d3b88a
--- /dev/null
@@ -0,0 +1,32 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.next{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.next.description{/lang}</p>\r
+\r
+<hr />\r
+\r
+<form method="post" action="install.php?step={@$nextStep}">\r
+       <div class="nextButton">\r
+               <input type="submit" name="nextButton" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="wcfDir" value="{$wcfDir}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+               {foreach from=$selectedLanguages item=language}\r
+                       <input type="hidden" name="selectedLanguages[]" value="{$language}" />\r
+               {/foreach}\r
+       </div>\r
+</form>\r
+\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       window.onload = function() {\r
+               document.forms[0].nextButton.disabled = true;\r
+               document.forms[0].submit();\r
+       }\r
+       //]]>\r
+</script>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepSearchWcfDir.tpl b/wcfsetup/setup/template/stepSearchWcfDir.tpl
new file mode 100644 (file)
index 0000000..ce2a3ab
--- /dev/null
@@ -0,0 +1,117 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.wcfDir{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.wcfDir.description{/lang}</p>\r
+\r
+{if $foundDirectory}\r
+       <p>{lang}wcf.global.wcfDir.foundDirectory{/lang}</p>\r
+{/if}\r
+\r
+{if $exception|isset}\r
+       <p class="error">\r
+               {lang}wcf.global.wcfDir.error{/lang}\r
+       </p>\r
+{/if}\r
+\r
+<form method="post" action="install.php">\r
+       <fieldset>\r
+               <legend>{lang}wcf.global.wcfDir.dir{/lang}</legend>\r
+               \r
+               <div class="inner">\r
+                       <div>\r
+                               <label for="wcfDir">{lang}wcf.global.wcfDir.dir.description{/lang}</label>\r
+                               <input type="text" class="inputText" id="wcfDir" name="wcfDir" value="{$wcfDir}" style="width: 100%;" />\r
+                       </div>\r
+                       <div>\r
+                               <label for="wcfUrl">{lang}wcf.global.wcfDir.url.description{/lang}</label>\r
+                               <input type="text" class="inputText" id="wcfUrl" name="wcfUrl" value="" style="width: 100%;" readonly="readonly" />\r
+                       </div>\r
+               </div>\r
+       </fieldset>\r
+       \r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+       </div>\r
+</form>\r
+\r
+<script type="text/javascript">\r
+       //<![CDATA[\r
+       // data\r
+       var domainName = '{@$domainName|encodeJS}';\r
+       var installScriptDir = '{@$installScriptDir|encodeJS}';\r
+       var installScriptUrl = '{@$installScriptUrl|encodeJS}';\r
+       var invalidErrorMessage = '{lang}wcf.global.wcfDir.error.invalid{/lang}';\r
+       \r
+       // function\r
+       function refreshWcfUrl() {\r
+               // split paths\r
+               var installScriptDirs = installScriptDir.split('/');\r
+               var wcfDirs = document.getElementById('wcfDir').value.split('/');\r
+               var installScriptUrlDirs = installScriptUrl.split('/');\r
+               \r
+               // remove empty elements\r
+               for (var i = installScriptDirs.length; i >= 0; i--) if (installScriptDirs[i] == '' || installScriptDirs[i] == '.') installScriptDirs.splice(i, 1);\r
+               for (var i = wcfDirs.length; i >= 0; i--) if (wcfDirs[i] == '' || wcfDirs[i] == '.') wcfDirs.splice(i, 1);\r
+               for (var i = installScriptUrlDirs.length; i >= 0; i--) if (installScriptUrlDirs[i] == '') installScriptUrlDirs.splice(i, 1);\r
+               \r
+               // get relative path\r
+               var relativePathDirs = new Array();\r
+               var max = (wcfDirs.length > installScriptDirs.length ? wcfDirs.length : installScriptDirs.length);\r
+               for (var i = 0; i < max; i++) {\r
+                       if (i < installScriptDirs.length && i < wcfDirs.length) {\r
+                               if (installScriptDirs[i] != wcfDirs[i]) {\r
+                                       wcfDirs.splice(0, i);\r
+                                       for (var j = 0; j < installScriptDirs.length - i; j++) relativePathDirs.push('..');\r
+                                       relativePathDirs = relativePathDirs.concat(wcfDirs);\r
+                                       break;\r
+                               }\r
+                       }       \r
+                       // go up one level\r
+                       else if (i < installScriptDirs.length && i >= wcfDirs.length) {\r
+                               relativePathDirs.push('..');\r
+                       }\r
+                       else {\r
+                               relativePathDirs.push(wcfDirs[i]);\r
+                       }\r
+               }\r
+               \r
+               // loop dirs\r
+               for (var i = 0; i < relativePathDirs.length; i++) {\r
+                       if (relativePathDirs[i] == '..') {\r
+                               if (installScriptUrlDirs.length < 1) {\r
+                                       document.getElementById('wcfUrl').value = invalidErrorMessage;\r
+                                       return;\r
+                               }\r
+                               \r
+                               installScriptUrlDirs.pop();\r
+                       }\r
+                       else {\r
+                               installScriptUrlDirs.push(relativePathDirs[i]);\r
+                       }\r
+               }\r
+               \r
+               // implode and show result\r
+               var result = domainName;\r
+               for (var i = 0; i < installScriptUrlDirs.length; i++) result += '/' + installScriptUrlDirs[i];\r
+               document.getElementById('wcfUrl').value = result;\r
+       }\r
+       \r
+       window.onload = function() {\r
+               // set onchange listener\r
+               document.getElementById('wcfDir').onkeyup = function() { refreshWcfUrl(); };\r
+               \r
+               // set onblur listener\r
+               document.getElementById('wcfDir').onblur = function() { refreshWcfUrl(); };\r
+               \r
+               // set default value\r
+               refreshWcfUrl();\r
+       }\r
+       //]]>\r
+</script>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepSelectLanguages.tpl b/wcfsetup/setup/template/stepSelectLanguages.tpl
new file mode 100644 (file)
index 0000000..5b05423
--- /dev/null
@@ -0,0 +1,36 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.languages{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.languages.description{/lang}</p>\r
+\r
+{if $errorField}\r
+       <p class="error">{if $errorType == 'empty'}{lang}wcf.global.languages.error.empty{/lang}{/if}</p>\r
+{/if}\r
+\r
+<form method="post" action="install.php">\r
+       <fieldset>\r
+               <legend>{lang}wcf.global.languages.languages{/lang}</legend>\r
+               \r
+               <div class="inner">\r
+                       <ul class="languages">\r
+                               {foreach from=$languages key=language item=languageName}\r
+                                       <li><label><input type="checkbox" name="selectedLanguages[]" value="{@$language}" {if $language|in_array:$selectedLanguages}checked="checked" {/if}/> {@$languageName}</label></li>\r
+                               {/foreach}\r
+                       </ul>\r
+                       <br style="clear: both" />\r
+               </div>\r
+       </fieldset>\r
+       \r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="send" value="1" />\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="wcfDir" value="{$wcfDir}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepSelectSetupLanguage.tpl b/wcfsetup/setup/template/stepSelectSetupLanguage.tpl
new file mode 100644 (file)
index 0000000..0d96890
--- /dev/null
@@ -0,0 +1,36 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.welcome{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.welcome.description{/lang}</p>\r
+\r
+<form method="post" action="install.php">\r
+       <fieldset>\r
+               <legend>{lang}wcf.global.welcome.language{/lang}</legend>\r
+               \r
+               <div class="inner">\r
+                       <div>\r
+                               <label for="languageCode">{lang}wcf.global.welcome.language.description{/lang}</label>\r
+                               {htmlOptions name="languageCode" id="languageCode" options=$availableLanguages selected=$languageCode disableEncoding=true}\r
+                               \r
+                               <input type="submit" value="{lang}wcf.global.welcome.language.change{/lang}" />\r
+                               <input type="hidden" name="step" value="selectSetupLanguage" />\r
+                               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+                       </div>\r
+               \r
+               </div>\r
+               \r
+       </fieldset>\r
+</form>\r
+\r
+<form method="post" action="install.php">\r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepShowLicense.tpl b/wcfsetup/setup/template/stepShowLicense.tpl
new file mode 100644 (file)
index 0000000..974bc41
--- /dev/null
@@ -0,0 +1,29 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.license{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.license.description{/lang}</p>\r
+\r
+{if $missingAcception|isset}\r
+<p class="error">\r
+       {lang}wcf.global.license.missingAcception{/lang}\r
+</p>\r
+{/if}\r
+\r
+<form method="post" action="install.php">\r
+       <div>\r
+               <textarea rows="20" cols="40" style="width: 100%" readonly="readonly">{$license}</textarea>\r
+               <p><label{if $missingAcception|isset} class="errorField"{/if}><input type="checkbox" name="accepted" value="1" /> {lang}wcf.global.license.accept.description{/lang}</label></p>\r
+       </div>\r
+       <hr />\r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" />\r
+               <input type="hidden" name="send" value="1" />\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/setup/template/stepShowSystemRequirements.tpl b/wcfsetup/setup/template/stepShowSystemRequirements.tpl
new file mode 100644 (file)
index 0000000..7503acd
--- /dev/null
@@ -0,0 +1,80 @@
+{include file='header'}\r
+\r
+<h2>{lang}wcf.global.systemRequirements{/lang}</h2>\r
+\r
+<p>{lang}wcf.global.systemRequirements.description{/lang}</p>\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.global.systemRequirements.required{/lang}</legend>\r
+       <div class="inner">\r
+       \r
+               <div>\r
+                       <h3>{lang}wcf.global.systemRequirements.php{/lang}</h3>\r
+                       <span class="left">{lang}wcf.global.systemRequirements.element.required{/lang} 5.3.0</span>\r
+                       <span class="right" style="color: {if !$system.phpVersion.result}red{else}green{/if}">{lang}wcf.global.systemRequirements.element.yours{/lang} {$system.phpVersion.value}</span>\r
+                       {if !$system.phpVersion.result}<div>{lang}wcf.global.systemRequirements.php.description{/lang}</div>{/if}\r
+               </div>\r
+               <hr />\r
+               \r
+               <div>\r
+                       <h3>{lang}wcf.global.systemRequirements.sql{/lang}</h3>\r
+                       <span class="left">{lang}wcf.global.systemRequirements.element.required{/lang} {lang}wcf.global.systemRequirements.active{/lang}</span>\r
+                       <span class="right" style="color: {if !$system.sql.result}red{else}green{/if}">{lang}wcf.global.systemRequirements.element.yours{/lang} \r
+                       {if !$system.sql.result}{lang}wcf.global.systemRequirements.sql.notFound{/lang}{else}\r
+                               {implode from=$system.sql.value item=$sqlType glue=', '}{lang}wcf.global.configureDB.class.{@$sqlType}{/lang}{/implode}\r
+                       {/if}</span>\r
+                       {if !$system.sql.result}<div>{lang}wcf.global.systemRequirements.sql.description{/lang}</div>{/if}\r
+               </div>\r
+               <hr />\r
+               \r
+               <div>\r
+                       <h3>{lang}wcf.global.systemRequirements.mbString{/lang}</h3>\r
+                       <span class="left">{lang}wcf.global.systemRequirements.element.required{/lang} {lang}wcf.global.systemRequirements.active{/lang}</span>\r
+                       <span class="right" style="color: {if !$system.mbString.result}red{else}green{/if}">{lang}wcf.global.systemRequirements.element.yours{/lang} {if !$system.mbString.result}{lang}wcf.global.systemRequirements.notActive{/lang}{else}{lang}wcf.global.systemRequirements.active{/lang}{/if}</span>\r
+                       {if !$system.mbString.result}<div>{lang}wcf.global.systemRequirements.mbString.description{/lang}</div>{/if}\r
+               </div>\r
+               <hr />\r
+               \r
+               <div>\r
+                       <h3>{lang}wcf.global.systemRequirements.safeMode{/lang}</h3>\r
+                       <span class="left">{lang}wcf.global.systemRequirements.element.required{/lang} {lang}wcf.global.systemRequirements.notActive{/lang}</span>\r
+                       <span class="right" style="color: {if !$system.safeMode.result}red{else}green{/if}">{lang}wcf.global.systemRequirements.element.yours{/lang} {if !$system.safeMode.result}{lang}wcf.global.systemRequirements.active{/lang}{else}{lang}wcf.global.systemRequirements.notActive{/lang}{/if}</span>\r
+                       {if !$system.safeMode.result}<div>{lang}wcf.global.systemRequirements.safeMode.description{/lang}</div>{/if}\r
+               </div>\r
+               \r
+       </div>\r
+</fieldset>\r
+\r
+<fieldset>\r
+       <legend>{lang}wcf.global.systemRequirements.recommended{/lang}</legend>\r
+       <div class="inner">\r
+       \r
+               <div>\r
+                       <h3>{lang}wcf.global.systemRequirements.uploadMaxFilesize{/lang}</h3>\r
+                       <span class="left">{lang}wcf.global.systemRequirements.element.recommended{/lang} > 0</span>\r
+                       <span class="right" style="color: {if !$system.uploadMaxFilesize.result}orange{else}green{/if}">{lang}wcf.global.systemRequirements.element.yours{/lang} {$system.uploadMaxFilesize.value}</span>\r
+                       {if !$system.uploadMaxFilesize.result}<div>{lang}wcf.global.systemRequirements.uploadMaxFilesize.description{/lang}</div>{/if}\r
+               </div>\r
+               <hr />\r
+               \r
+               <div>\r
+                       <h3>{lang}wcf.global.systemRequirements.gdLib{/lang}</h3>\r
+                       <span class="left">{lang}wcf.global.systemRequirements.element.recommended{/lang} 2.0.0</span>\r
+                       <span class="right" style="color: {if !$system.gdLib.result}orange{else}green{/if}">{lang}wcf.global.systemRequirements.element.yours{/lang} {$system.gdLib.value}</span>\r
+                       {if !$system.gdLib.result}<div>{lang}wcf.global.systemRequirements.gdLib.description{/lang}</div>{/if}\r
+               </div>\r
+               \r
+       </div>\r
+</fieldset>\r
+\r
+<form method="post" action="install.php">      \r
+       <div class="nextButton">\r
+               <input type="submit" accesskey="s" value="{lang}wcf.global.button.next{/lang}" {if !$system.phpVersion.result || !$system.sql.result || !$system.mbString.result || !$system.safeMode.result} disabled="disabled"{/if}/>\r
+               <input type="hidden" name="step" value="{@$nextStep}" />\r
+               <input type="hidden" name="tmpFilePrefix" value="{@$tmpFilePrefix}" />\r
+               <input type="hidden" name="languageCode" value="{@$languageCode}" />\r
+               <input type="hidden" name="dev" value="{@$developerMode}" />\r
+       </div>\r
+</form>\r
+\r
+{include file='footer'}
\ No newline at end of file
diff --git a/wcfsetup/test.php b/wcfsetup/test.php
new file mode 100644 (file)
index 0000000..c95dded
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\r
+<html>\r
+<head>\r
+       <title>PHP5 Check</title>\r
+</head>\r
+<body>\r
+<?php\r
+/**\r
+ * Tests the support of php5.0.5 or greater.\r
+ * ><p><b>Support for PHP is missing.<br />PHP Unterst&uuml;tzung nicht gefunden</b></p> <!--\r
+ * \r
+ * @author     Marcel Werk\r
+ * @copyright  2001-2007 WoltLab GmbH\r
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>\r
+ */\r
+// check php version\r
+// php version\r
+$phpVersion = phpversion();\r
+$comparePhpVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $phpVersion);\r
+if (!(version_compare($comparePhpVersion, '5.2.0') >= 0)) {\r
+       ?>\r
+       <p>Your PHP version '<?php echo $phpVersion; ?>' is insufficient for installation of this software. PHP version 5.2.0 or greater is required.<br />\r
+       Ihre PHP Version '<?php echo $phpVersion; ?>' ist unzureichend f&uuml;r die Installation dieser Software. PHP Version 5.2.0 oder h&ouml;her wird ben&ouml;tigt.</p>\r
+       <?php\r
+}\r
+\r
+// check ze1_compatibility_mode\r
+else if (ini_get('zend.ze1_compatibility_mode')) {\r
+       ?>\r
+       <p>The option 'zend.ze1_compatibility_mode' is enabled. Please disable the option in your PHP configuration (php.ini) for a stable work of this software.<br />\r
+       Die Einstellung 'zend.ze1_compatibility_mode' ist aktiv. F&uuml;r einen einwandfreien Betrieb dieser Software muss die Einstellung in der PHP-Konfiguration (php.ini) deaktiviert werden.</p>\r
+       <?php\r
+}\r
+\r
+// check simplexml\r
+else if (!function_exists('simplexml_load_file')) {\r
+       ?>\r
+       <p>The 'simplexml' PHP extension is missing. Simplexml is required for a stable work of this software.<br />\r
+       Die 'simplexml' Erweiterung f&uuml;r PHP wurde nicht gefunden. Diese Erweiterung ist f&uuml;r den Betrieb der Software notwendig.</p>\r
+       <?php\r
+}\r
+\r
+// check zlib extension\r
+else if (!function_exists('gzopen')) {\r
+       ?>\r
+       <p>The 'zlib' PHP extension is missing. ZLib is required for a stable work of this software.<br />\r
+       Die 'zlib' Erweiterung f&uuml;r PHP wurde nicht gefunden. Diese Erweiterung ist f&uuml;r den Betrieb der Software notwendig.</p>\r
+       <?php\r
+}\r
+\r
+// \r
+else {\r
+       ?>\r
+       <p>PHP5 or greater is available. You can <a href="install.php">start</a> the installation now.<br />\r
+       PHP5 oder h&ouml;her wurde gefunden. Sie k&ouml;nnen mit der Installation <a href="install.php">beginnen</a>.</p>\r
+       <?php\r
+}\r
+?>\r
+</body>\r
+</html>
\ No newline at end of file