From dba70b917a6e560b3c84deefffd30c5b554f00b5 Mon Sep 17 00:00:00 2001 From: John Mertic Date: Tue, 7 Feb 2012 10:44:00 -0500 Subject: [PATCH] Release 6.4.0 --- .../PackageManager/PackageController.php | 199 +- .../PackageManager/PackageManager.php | 107 +- .../PackageManager/PackageManagerComm.php | 118 +- .../PackageManager/PackageManagerDisplay.php | 11 +- .../PackageManagerDownloader.php | 9 +- .../tpls/ModuleLoaderListView.tpl | 2 +- .../tpls/PackageManagerScripts.tpl | 37 +- XTemplate/xtpl.php | 22 +- Zend/Http/Response/Stream.php | 11 + Zend/Oauth/Provider.php | 2 +- cache/upload/index.html | 1 - cron.php | 20 +- custom/index.html | 2 +- data/BeanFactory.php | 10 +- data/Link.php | 8 +- data/Link2.php | 7 +- .../EmailAddressRelationship.php | 1 + data/Relationships/M2MRelationship.php | 9 +- data/Relationships/One2MBeanRelationship.php | 9 +- data/Relationships/One2MRelationship.php | 1 + .../Relationships/One2OneBeanRelationship.php | 4 + data/Relationships/One2OneRelationship.php | 4 + data/Relationships/RelationshipFactory.php | 6 +- data/Relationships/SugarRelationship.php | 5 +- data/SugarBean.php | 611 +- data/upload/index.html | 1 - download.php | 36 +- files.md5 | 1770 +-- include/Dashlets/Dashlet.php | 150 +- include/Dashlets/DashletGeneric.php | 18 +- include/Dashlets/DashletGenericChart.php | 108 +- include/Dashlets/DashletGenericConfigure.tpl | 4 +- include/Dashlets/DashletGenericDisplay.tpl | 57 +- include/Dashlets/DashletRssFeedTitle.php | 28 +- include/DetailView/DetailView.php | 153 +- include/DetailView/DetailView.tpl | 14 +- include/DetailView/DetailView2.php | 40 +- include/EditView/EditView.php | 24 +- include/EditView/EditView.tpl | 55 +- include/EditView/EditView2.php | 12 +- include/EditView/PopupQuickCreate.php | 8 +- include/EditView/QuickCreate.php | 20 +- include/EditView/SubpanelQuickCreate.php | 26 +- include/EditView/SubpanelQuickEdit.php | 24 +- include/EditView/SugarVCR.php | 65 +- include/JSON.php | 10 +- include/ListView/ListView.php | 114 +- include/ListView/ListViewDCMenu.tpl | 26 +- include/ListView/ListViewData.php | 93 +- include/ListView/ListViewDisplay.php | 80 +- include/ListView/ListViewGeneric.tpl | 36 +- include/ListView/ListViewNoMassUpdate.tpl | 25 +- include/ListView/ListViewPagination.tpl | 24 +- include/ListView/ListViewSmarty.php | 1 + include/ListView/ListViewXTPL.php | 38 +- include/Localization/Localization.php | 104 +- include/MVC/Controller/ControllerFactory.php | 19 +- include/MVC/Controller/SugarController.php | 9 +- include/MVC/Controller/action_view_map.php | 2 + include/MVC/SugarApplication.php | 18 +- include/MVC/SugarModule.php | 22 +- include/MVC/View/SugarView.php | 163 +- include/MVC/View/ViewFactory.php | 64 +- include/MVC/View/tpls/Importvcard.tpl | 2 +- include/MVC/View/tpls/gsdetail.tpl | 93 + include/MVC/View/views/view.gs.php | 205 + include/MVC/View/views/view.list.php | 18 +- .../MVC/View/views/view.modulelistmenu.php | 3 +- include/MVC/View/views/view.popup.php | 52 +- include/MVC/View/views/view.quickcreate.php | 24 +- include/MVC/View/views/view.quickedit.php | 27 +- include/MassUpdate.php | 45 +- .../MySugar/DashletsDialog/DashletsDialog.php | 9 +- include/MySugar/MySugar.php | 22 +- include/MySugar/tpls/MySugar.tpl | 30 +- include/MySugar/tpls/addDashletsDialog.tpl | 14 +- include/MySugar/tpls/retrievePage.tpl | 4 +- include/OutboundEmail/OutboundEmail.php | 76 +- include/Popups/PopupSmarty.php | 121 +- include/Popups/tpls/PopupGeneric.tpl | 98 +- include/Popups/tpls/header.tpl | 8 +- include/SearchForm/SearchForm.php | 69 +- include/SearchForm/SearchForm2.php | 1133 +- include/SearchForm/SugarSpot.php | 357 +- include/SearchForm/tpls/SearchFormGeneric.tpl | 6 +- .../tpls/SearchFormGenericAdvanced.tpl | 19 +- include/SearchForm/tpls/SugarSpot.tpl | 96 + include/SearchForm/tpls/footer.tpl | 6 +- .../plugins/function.overlib_includes.php | 2 +- .../plugins/function.sugar_evalcolumn.php | 26 +- .../plugins/function.sugar_getimage.php | 77 + .../plugins/function.sugar_getjspath.php | 11 +- .../Smarty/plugins/function.sugar_getlink.php | 76 + .../plugins/function.sugar_getscript.php | 44 +- .../Smarty/plugins/function.sugar_help.php | 7 +- include/SubPanel/SubPanel.php | 132 +- include/SubPanel/SubPanelDefinitions.php | 30 +- include/SubPanel/SubPanelTiles.js | 9 +- include/SubPanel/SubPanelTiles.php | 13 +- include/SubPanel/SubPanelTilesTabs.php | 6 +- include/SubPanel/SugarTab.php | 23 +- include/SubPanel/tpls/singletabmenu.tpl | 21 +- include/SugarCache/SugarCache.php | 38 +- include/SugarCache/SugarCacheAPC.php | 2 +- include/SugarCache/SugarCacheAbstract.php | 4 + include/SugarCache/SugarCacheFile.php | 20 +- include/SugarCache/SugarCacheMemcache.php | 2 +- include/SugarCache/SugarCacheRedis.php | 2 +- include/SugarCache/SugarCacheWincache.php | 2 +- include/SugarCache/SugarCacheZend.php | 2 +- include/SugarCache/SugarCachesMash.php | 2 +- include/SugarCharts/Jit/js/Jit/jit.js | 8 +- include/SugarCharts/JsChart.php | 41 +- include/SugarCharts/SugarChart.php | 484 +- include/SugarCharts/SugarChartFactory.php | 14 +- include/SugarDateTime.php | 115 +- .../SugarEmailAddress/SugarEmailAddress.js | 19 +- .../SugarEmailAddress/SugarEmailAddress.php | 32 +- .../templates/forEditView.tpl | 11 +- .../templates/forWideFormBodyView.tpl | 5 +- .../SugarFields/Fields/Address/EditView.tpl | 22 +- .../Fields/Address/en_us.EditView.tpl | 10 +- include/SugarFields/Fields/Base/EditView.tpl | 2 +- .../Fields/Base/SugarFieldBase.php | 17 +- .../SugarFields/Fields/Bool/SearchView.tpl | 2 +- .../Collection/CollectionDetailView.tpl | 2 +- .../Fields/Collection/CollectionEditView.tpl | 9 +- .../Collection/CollectionEditViewRow.tpl | 2 +- .../Fields/Collection/DetailView.tpl | 3 +- .../Collection/ViewSugarFieldCollection.php | 58 +- .../SugarFields/Fields/Datetime/EditView.tpl | 6 +- .../Fields/Datetime/SugarFieldDatetime.php | 6 +- .../Fields/Datetimecombo/Datetimecombo.js | 4 +- .../Fields/Datetimecombo/EditView.tpl | 16 +- .../Fields/Datetimecombo/RangeSearchForm.tpl | 14 +- .../Fields/Datetimecombo/SearchView.tpl | 22 +- .../Datetimecombo/SugarFieldDatetimecombo.php | 12 +- include/SugarFields/Fields/Enum/EditView.tpl | 4 +- .../SugarFields/Fields/File/DetailView.tpl | 2 +- include/SugarFields/Fields/File/EditView.tpl | 12 +- include/SugarFields/Fields/File/ListView.tpl | 2 +- .../Fields/Fullname/DetailView.tpl | 2 +- .../SugarFields/Fields/Iframe/DetailView.tpl | 2 +- .../SugarFields/Fields/Int/SugarFieldInt.php | 31 + .../SugarFields/Fields/Parent/SearchView.tpl | 14 +- .../SugarFields/Fields/Relate/EditView.tpl | 6 +- .../SugarFields/Fields/Relate/SearchView.tpl | 6 +- .../Fields/Relate/SugarFieldRelate.php | 115 +- .../SugarFields/Fields/Text/DetailView.tpl | 10 +- include/SugarFields/Parsers/MetaParser.php | 209 +- include/SugarFields/SugarFieldHandler.php | 43 +- include/SugarFolders/SugarFolders.php | 12 +- include/SugarLogger/LoggerManager.php | 40 +- include/SugarLogger/LoggerTemplate.php | 13 +- include/SugarLogger/SugarLogger.php | 60 +- include/SugarOAuthServer.php | 8 +- include/SugarOauth.php | 61 + include/SugarObjects/LanguageManager.php | 84 +- include/SugarObjects/SugarConfig.php | 12 +- include/SugarObjects/SugarRegistry.php | 4 + include/SugarObjects/SugarSession.php | 26 +- include/SugarObjects/VardefManager.php | 81 +- include/SugarObjects/forms/FormBase.php | 82 + include/SugarObjects/forms/PersonFormBase.php | 269 + include/SugarObjects/templates/file/File.php | 26 +- .../templates/file/metadata/editviewdefs.php | 6 +- .../file/metadata/quickcreatedefs.php | 12 +- .../SugarObjects/templates/person/Person.php | 31 +- include/SugarPHPMailer.php | 145 +- include/SugarSQLValidate.php | 246 + include/SugarTheme/SugarSprites.php | 81 + include/SugarTheme/SugarTheme.php | 388 +- include/SugarTheme/getImage.php | 20 +- include/Sugar_Smarty.php | 15 +- include/Sugarpdf/FontManager.php | 30 +- include/Sugarpdf/Sugarpdf.php | 112 +- include/Sugarpdf/SugarpdfFactory.php | 2 +- include/Sugarpdf/sugarpdf_default.php | 12 +- include/TemplateHandler/TemplateHandler.php | 14 +- include/TimeDate.php | 211 +- include/VarDefHandler/VarDefHandler.php | 102 +- include/VarDefHandler/listvardefoverride.php | 1 + include/connectors/ConnectorFactory.php | 14 +- include/connectors/component.php | 6 +- include/connectors/filters/FilterFactory.php | 20 +- include/connectors/filters/default/filter.php | 14 +- .../formatters/FormatterFactory.php | 20 +- .../formatters/default/formatter.php | 41 +- include/connectors/sources/SourceFactory.php | 9 +- include/connectors/sources/default/source.php | 4 +- include/connectors/sources/ext/eapm/eapm.php | 4 + include/connectors/sources/ext/rest/rest.php | 4 + include/connectors/sources/ext/soap/soap.php | 2 +- include/connectors/sources/loc/xml.php | 4 + include/connectors/utils/ConnectorUtils.php | 29 +- include/database/DBHelper.php | 1394 +-- include/database/DBManager.php | 4883 +++++--- include/database/DBManagerFactory.php | 253 +- include/database/FreeTDSHelper.php | 156 +- include/database/FreeTDSManager.php | 174 +- include/database/MssqlHelper.php | 754 +- include/database/MssqlManager.php | 1415 ++- include/database/MysqlHelper.php | 500 +- include/database/MysqlManager.php | 1751 ++- include/database/MysqliManager.php | 474 +- include/database/PearDatabase.php | 133 - include/database/SqlsrvHelper.php | 348 - include/database/SqlsrvManager.php | 633 +- include/dir_inc.php | 65 +- include/entryPoint.php | 6 +- include/export_utils.php | 19 +- include/externalAPI/Base/ExternalAPIBase.php | 34 +- .../externalAPI/Base/ExternalAPIPlugin.php | 4 + .../Base/ExternalOAuthAPIPlugin.php | 4 + include/externalAPI/Base/OAuthPluginBase.php | 4 + include/externalAPI/Base/WebDocument.php | 8 +- include/externalAPI/Base/WebFeed.php | 4 + include/externalAPI/Base/WebMeeting.php | 4 + include/externalAPI/ExternalAPIFactory.php | 31 +- include/generic/LayoutManager.php | 7 +- include/generic/Save2.php | 34 +- include/generic/SugarWidgets/SugarWidget.php | 20 +- .../generic/SugarWidgets/SugarWidgetField.php | 3 +- .../SugarWidgets/SugarWidgetFielddate.php | 409 +- .../SugarWidgetFielddatepicker.php | 11 +- .../SugarWidgets/SugarWidgetFielddatetime.php | 754 +- .../SugarWidgetFielddatetimecombo.php | 6 +- .../SugarWidgets/SugarWidgetFieldenum.php | 116 +- .../SugarWidgets/SugarWidgetFieldname.php | 132 +- .../SugarWidgets/SugarWidgetFieldtext.php | 53 +- .../SugarWidgets/SugarWidgetReportField.php | 420 +- .../SugarWidgetSubPanelCloseButton.php | 2 +- .../SugarWidgetSubPanelDeleteButton.php | 2 +- .../SugarWidgetSubPanelEditButton.php | 26 +- .../SugarWidgetSubPanelEditRoleButton.php | 3 +- .../SugarWidgetSubPanelEmailLink.php | 37 +- .../SugarWidgetSubPanelGetLatestButton.php | 3 +- .../SugarWidgets/SugarWidgetSubPanelIcon.php | 7 +- .../SugarWidgetSubPanelLoadSignedButton.php | 3 +- .../SugarWidgetSubPanelRemoveButton.php | 5 +- ...ugarWidgetSubPanelRemoveButtonMeetings.php | 5 +- ...ugarWidgetSubPanelRemoveButtonProjects.php | 5 +- ...garWidgetSubPanelTopComposeEmailButton.php | 21 +- ...garWidgetSubPanelTopScheduleCallButton.php | 4 +- ...WidgetSubPanelTopScheduleMeetingButton.php | 4 +- include/javascript/ajaxUI.js | 11 +- include/javascript/calendar.js | 10 +- include/javascript/importWizard.js | 4 +- include/javascript/javascript.php | 18 + include/javascript/jsAlerts.php | 76 +- include/javascript/overlibmws.js | 9 +- include/javascript/popup_helper.js | 22 +- include/javascript/quickCompose.js | 2 +- include/javascript/quicksearch.js | 2 +- include/javascript/report_additionals.js | 7 +- include/javascript/sugar_3.js | 41 +- include/javascript/sugar_grp1.js | 1391 --- include/javascript/sugar_grp1_yui.js | 9628 --------------- include/javascript/sugar_grp_emails.js | 10114 ---------------- include/javascript/sugar_grp_jsolait.js | 242 - include/javascript/sugar_grp_overlib.js | 307 - include/javascript/sugar_grp_quickcomp.js | 5701 --------- include/javascript/sugar_grp_yui2.js | 31 - include/javascript/sugar_grp_yui_widgets.css | 55 - include/javascript/sugar_grp_yui_widgets.js | 208 - include/javascript/yui/ygDDList.js | 1 - .../yui3/assets/dpSyntaxHighlighter.css | 190 - .../yui3/assets/dpSyntaxHighlighter.js | 168 +- include/language/en_us.lang.php | 324 +- include/modules.php | 4 +- include/php-sql-parser.php | 1970 +++ include/tcpdf/config/tcpdf_config.php | 76 +- include/tcpdf/tcpdf.php | 968 +- include/templates/TemplateDragDropChooser.php | 2 +- include/templates/TemplateGroupChooser.php | 17 +- include/upload_file.php | 531 +- include/utils.php | 300 +- include/utils/LogicHook.php | 1 + include/utils/activity_utils.php | 17 +- include/utils/db_utils.php | 82 +- include/utils/encryption_utils.php | 28 +- include/utils/file_utils.php | 33 +- include/utils/layout_utils.php | 146 +- include/utils/mvc_utils.php | 2 +- include/utils/php_zip_utils.php | 52 +- include/utils/security_utils.php | 3 +- include/utils/sugar_file_utils.php | 23 +- include/vCard.php | 11 +- install.php | 112 +- install/UserDemoData.php | 32 +- install/checkDBSettings.php | 471 +- install/confirmSettings.php | 50 +- install/dbConfig_a.php | 189 +- install/download_modules.php | 16 +- install/download_patches.php | 51 +- install/installDisabled.php | 4 +- install/installHelp.php | 2 +- install/installSystemCheck.php | 83 +- install/installType.php | 4 +- install/install_utils.php | 538 +- install/language/en_us.lang.php | 45 +- install/license.php | 8 +- install/licensePrint.php | 5 +- install/performSetup.php | 96 +- install/populateSeedData.php | 4 + install/ready.php | 16 +- install/register.php | 4 +- install/siteConfig_a.php | 33 +- install/siteConfig_b.php | 3 +- install/systemOptions.php | 52 +- install/welcome.php | 4 +- json_server.php | 4 +- jssource/JSGroupings.php | 10 +- jssource/minify.php | 101 +- jssource/minify_utils.php | 216 +- .../include/SubPanel/SubPanelTiles.js | 22 +- .../include/SugarCharts/Jit/js/Jit/jit.js | 51 +- .../SugarEmailAddress/SugarEmailAddress.js | 22 +- .../Fields/Datetimecombo/Datetimecombo.js | 43 +- .../src_files/include/javascript/ajaxUI.js | 38 +- .../src_files/include/javascript/calendar.js | 32 +- .../include/javascript/importWizard.js | 4 +- .../include/javascript/overlibmws.js | 22 +- .../include/javascript/popup_helper.js | 89 +- .../include/javascript/quickCompose.js | 4 +- .../include/javascript/quicksearch.js | 2 +- .../include/javascript/report_additionals.js | 409 +- .../src_files/include/javascript/sugar_3.js | 71 +- .../yui3/assets/dpSyntaxHighlighter.js | 807 +- jssource/src_files/modules/Calendar/Cal.js | 1394 +++ .../modules/Meetings/jsclass_scheduler.js | 68 +- .../src_files/modules/Users/DetailView.js | 37 +- jssource/src_files/modules/Users/User.js | 14 +- .../src_files/modules/Users/UserEditView.js | 346 + jssource/src_files/modules/Users/login.js | 4 +- log_file_restricted.html | 2 +- maintenance.php | 3 +- metadata/email_addressesMetaData.php | 7 +- metadata/emails_beansMetaData.php | 13 +- metadata/oauth_nonce.php | 4 +- metadata/schedulers_timesMetaData.php | 2 +- modules/ACL/ACLController.php | 4 +- modules/ACL/language/en_us.lang.php | 5 +- modules/ACLActions/ACLAction.php | 13 +- modules/ACLRoles/EditViewBody.tpl | 2 +- modules/ACLRoles/Popup_picker.html | 2 +- modules/ACLRoles/popup.tpl | 4 +- modules/Accounts/Account.php | 2 +- modules/Accounts/Popup_picker.html | 2 +- modules/Accounts/language/en_us.lang.php | 1 + modules/Accounts/views/view.detail.php | 4 +- modules/Activities/OpenListView.php | 328 + modules/Activities/Popup_picker.php | 21 +- modules/Activities/SubPanelView.php | 22 +- modules/Activities/language/en_us.lang.php | 6 +- .../Activities/views/view.modulelistmenu.php | 3 +- modules/Administration/Administration.php | 6 +- modules/Administration/Development.php | 4 +- modules/Administration/Diagnostic.php | 24 +- modules/Administration/Diagnostic.tpl | 16 +- modules/Administration/DiagnosticDelete.php | 12 +- modules/Administration/DiagnosticDownload.php | 2 +- modules/Administration/DiagnosticRun.php | 347 +- modules/Administration/DisplayWarnings.php | 14 +- modules/Administration/DstFix.php | 402 - modules/Administration/Locale.php | 35 +- modules/Administration/Locale.tpl | 17 +- modules/Administration/PasswordManager.php | 16 +- modules/Administration/PasswordManager.tpl | 68 +- .../Administration/QuickRepairAndRebuild.php | 27 +- modules/Administration/RebuildDashlets.php | 8 +- .../Administration/RebuildFulltextIndices.php | 14 +- modules/Administration/RebuildJSLang.php | 4 +- .../RebuildSprites.php} | 19 +- modules/Administration/RepairFieldCasing.php | 71 +- modules/Administration/RepairIndex.php | 34 +- modules/Administration/RepairSeedUsers.php | 10 +- modules/Administration/SugarSpriteBuilder.php | 641 + modules/Administration/SupportPortal.php | 2 + modules/Administration/SupportPortal.tpl | 4 +- modules/Administration/Upgrade.php | 56 +- modules/Administration/UpgradeAccess.php | 55 +- modules/Administration/UpgradeFields.php | 47 +- modules/Administration/UpgradeHistory.php | 2 +- modules/Administration/UpgradeWizard.php | 202 +- .../Administration/UpgradeWizardCommon.php | 45 +- .../Administration/UpgradeWizard_commit.php | 17 +- .../Administration/UpgradeWizard_prepare.php | 25 +- modules/Administration/clear_chart_cache.php | 8 +- modules/Administration/controller.php | 45 +- modules/Administration/expandDatabase.php | 20 +- modules/Administration/index.php | 4 +- .../Administration/language/en_us.lang.php | 35 +- .../metadata/adminpaneldefs.php | 1 - modules/Administration/repairUniSearch.php | 5 +- .../templates/ConfigureAjaxUI.tpl | 2 +- .../templates/ConfigureTabs.tpl | 2 +- .../templates/GlobalSearchSettings.tpl | 2 +- .../Administration/templates/Languages.tpl | 2 +- .../templates/RebuildSprites.tpl | 80 + .../Administration/templates/RepairXSS.tpl | 4 +- .../Administration/templates/ShortcutBar.tpl | 2 +- .../templates/themeSettings.tpl | 2 +- modules/Administration/updater_utils.php | 76 +- modules/Audit/Popup_picker.php | 2 +- modules/Calendar/Cal.css | 183 + modules/Calendar/Cal.js | 187 + modules/Calendar/Calendar.php | 869 +- modules/Calendar/CalendarActivity.php | 231 + modules/Calendar/CalendarDisplay.php | 450 + modules/Calendar/CalendarGrid.php | 408 + modules/Calendar/CalendarUtils.php | 124 + .../CalendarDashlet.en_us.lang.php} | 30 +- .../CalendarDashlet/CalendarDashlet.meta.php | 47 + .../CalendarDashlet/CalendarDashlet.php | 122 + .../CalendarDashletOptions.tpl | 72 + modules/Calendar/DateTimeUtil.php | 637 - modules/Calendar/Menu.php | 11 +- modules/Calendar/TasksListView.html | 61 - modules/Calendar/TasksListView.php | 144 - .../view.list.php => action_view_map.php} | 21 +- modules/Calendar/index.php | 103 +- modules/Calendar/language/en_us.lang.php | 253 +- .../templates/template_shared_calendar.php | 183 - .../Calendar/templates/templates_calendar.php | 876 -- modules/Calendar/tpls/empty.tpl | 37 + modules/Calendar/tpls/footer.tpl | 41 + .../Calendar/tpls/form.tpl | 82 +- modules/Calendar/tpls/header.tpl | 91 + modules/Calendar/tpls/main.tpl | 321 + modules/Calendar/tpls/settings.tpl | 115 + modules/Calendar/tpls/shared_users.tpl | 128 + modules/Calendar/views/view.getgr.php | 62 + modules/Calendar/views/view.getgrusers.php | 76 + modules/Calendar/views/view.quickedit.php | 125 + modules/Calendar/views/view.remove.php | 77 + modules/Calendar/views/view.reschedule.php | 84 + modules/Calendar/views/view.saveactivity.php | 558 + .../Calendar/views/view.savesettings.php | 84 +- modules/Calls/Call.php | 15 +- modules/Calls/CallFormBase.php | 14 +- .../MyCallsDashlet/MyCallsDashlet.php | 11 +- modules/Calls/metadata/editviewdefs.php | 38 +- modules/Calls/metadata/quickcreatedefs.php | 48 +- modules/Calls/tpls/QuickCreate.tpl | 6 +- modules/Calls/tpls/footer.tpl | 2 +- modules/CampaignLog/CampaignLog.php | 32 +- modules/CampaignLog/Popup_picker.html | 2 +- modules/CampaignTrackers/EditView.php | 2 +- .../CampaignTrackers/language/en_us.lang.php | 1 + modules/Campaigns/Campaign.php | 121 +- modules/Campaigns/CampaignDiagnostic.php | 52 +- modules/Campaigns/Charts1.php | 27 +- modules/Campaigns/Delete.php | 62 +- modules/Campaigns/GenerateWebToLeadForm.php | 12 +- modules/Campaigns/PopupCampaignRoi.php | 52 +- modules/Campaigns/Popup_picker.html | 15 +- modules/Campaigns/ProcessBouncedEmails.php | 8 +- modules/Campaigns/QueueCampaign.php | 61 +- modules/Campaigns/RemoveMe.php | 11 +- modules/Campaigns/RoiDetailView.php | 3 +- modules/Campaigns/Subscriptions.tpl | 4 +- modules/Campaigns/TrackDetailView.php | 73 +- modules/Campaigns/TrackDetailView.tpl | 3 +- modules/Campaigns/WebToLeadCapture.php | 9 +- modules/Campaigns/WebToLeadCreation.html | 40 +- modules/Campaigns/WebToLeadDownloadForm.html | 4 +- modules/Campaigns/WebToLeadForm.html | 24 +- modules/Campaigns/WebToLeadFormSave.php | 27 +- modules/Campaigns/WizardEmailSetup.html | 39 +- modules/Campaigns/WizardHome.php | 8 +- modules/Campaigns/WizardMarketing.html | 54 +- modules/Campaigns/WizardNewsletter.html | 6 +- modules/Campaigns/WizardNewsletter.php | 11 +- modules/Campaigns/language/en_us.lang.php | 8 + modules/Campaigns/metadata/listviewdefs.php | 4 +- .../Campaigns/tpls/WizardCampaignBudget.tpl | 34 +- .../Campaigns/tpls/WizardCampaignHeader.tpl | 36 +- .../tpls/WizardCampaignTargetList.tpl | 28 +- ...zardCampaignTargetListForNonNewsLetter.tpl | 21 +- .../Campaigns/tpls/WizardCampaignTracker.tpl | 15 +- modules/Campaigns/tpls/WizardHomeStart.tpl | 19 +- modules/Campaigns/tpls/WizardNewsletter.tpl | 10 +- modules/Campaigns/utils.php | 504 +- .../Campaigns/views/view.modulelistmenu.php | 3 +- modules/Cases/Case.php | 2 +- .../MyPipelineBySalesStageConfigure.tpl | 4 +- .../MyPipelineBySalesStageDashlet.php | 12 +- .../OutcomeByMonthConfigure.tpl | 4 +- .../OutcomeByMonthDashlet.php | 4 +- .../PipelineBySalesStageConfigure.tpl | 4 +- .../PipelineBySalesStageDashlet.php | 82 +- modules/Charts/DynamicAction.php | 7 +- .../code/Chart_lead_source_by_outcome.php | 15 +- .../code/Chart_my_pipeline_by_sales_stage.php | 19 +- .../Charts/code/Chart_outcome_by_month.php | 17 +- .../code/Chart_pipeline_by_lead_source.php | 15 +- .../code/Chart_pipeline_by_sales_stage.php | 19 +- modules/Configurator/Configurator.php | 2 +- modules/Configurator/UploadFileCheck.php | 38 +- modules/Configurator/controller.php | 34 +- modules/Configurator/language/en_us.lang.php | 8 + modules/Configurator/tpls/EditView.tpl | 25 +- .../Configurator/tpls/SugarpdfSettings.tpl | 12 +- modules/Configurator/tpls/addFontView.tpl | 8 +- modules/Configurator/tpls/adminwizard.tpl | 15 +- modules/Configurator/tpls/fontmanager.tpl | 4 +- .../Configurator/views/view.addfontresult.php | 20 +- .../Configurator/views/view.adminwizard.php | 4 +- .../views/view.sugarpdfsettings.php | 7 +- .../ext/rest/insideview/insideview.php | 5 - .../rest/insideview/language/en_us.lang.php | 22 +- .../ext/rest/insideview/tpls/InsideView.tpl | 70 +- .../sources/ext/rest/linkedin/config.php | 5 + .../ext/rest/linkedin/language/en_us.lang.php | 4 +- .../sources/ext/rest/linkedin/linkedin.php | 84 +- modules/Connectors/language/en_us.lang.php | 2 + .../Connectors/tpls/display_properties.tpl | 8 +- modules/Connectors/tpls/listview.tpl | 4 +- modules/Connectors/tpls/modify_display.tpl | 10 +- modules/Connectors/tpls/modify_mapping.tpl | 10 +- modules/Connectors/tpls/modify_properties.tpl | 10 +- modules/Connectors/tpls/modify_search.tpl | 10 +- modules/Contacts/Contact.php | 97 +- modules/Contacts/ContactFormBase.php | 197 +- modules/Contacts/Email_picker.html | 30 +- modules/Contacts/MailMergePicker.html | 24 +- modules/Contacts/Popup_picker.php | 9 - modules/Contacts/ShowDuplicates.php | 2 +- modules/Contacts/language/en_us.lang.php | 2 + modules/Contacts/tpls/QuickCreate.tpl | 2 +- modules/Contacts/vardefs.php | 2 +- modules/Contacts/views/view.edit.php | 20 +- modules/Currencies/EditView.tpl | 2 +- modules/Currencies/index.php | 6 +- modules/Currencies/language/en_us.lang.php | 1 + .../metadata/editviewdefs.php | 8 +- modules/Documents/Delete.php | 15 - modules/Documents/Document.php | 101 +- modules/Documents/DocumentSoap.php | 11 +- modules/Documents/Popup_picker.html | 4 +- modules/Documents/metadata/editviewdefs.php | 36 +- .../Documents/metadata/quickcreatedefs.php | 4 +- modules/Documents/metadata/subpaneldefs.php | 17 - modules/Documents/views/view.edit.php | 13 +- modules/DynamicFields/DynamicField.php | 69 +- modules/DynamicFields/language/en_us.lang.php | 4 +- .../templates/Fields/Forms/coreBottom.tpl | 6 +- .../templates/Fields/TemplateAddress.php | 3 +- .../templates/Fields/TemplateBoolean.php | 58 +- .../templates/Fields/TemplateCurrency.php | 42 +- .../templates/Fields/TemplateDate.php | 8 - .../Fields/TemplateDatetimecombo.php | 25 +- .../templates/Fields/TemplateDecimal.php | 41 +- .../templates/Fields/TemplateEnum.php | 13 +- .../templates/Fields/TemplateField.php | 84 +- .../templates/Fields/TemplateFloat.php | 45 +- .../templates/Fields/TemplateHTML.php | 1 + .../templates/Fields/TemplateInt.php | 19 +- .../templates/Fields/TemplateMultiEnum.php | 12 - .../templates/Fields/TemplatePhone.php | 1 + .../templates/Fields/TemplateRange.php | 149 +- .../templates/Fields/TemplateText.php | 1 + .../templates/Fields/TemplateTextArea.php | 24 +- .../templates/Fields/TemplateURL.php | 4 +- modules/EAPM/views/view.detail.php | 19 +- modules/EAPM/views/view.edit.php | 7 +- modules/EmailMan/EmailMan.php | 109 +- modules/EmailMan/EmailManDelivery.php | 18 +- modules/EmailMan/language/en_us.lang.php | 6 +- modules/EmailMan/tpls/campaignconfig.tpl | 2 +- modules/EmailMan/tpls/config.tpl | 4 +- modules/EmailMarketing/EditView.php | 38 +- modules/EmailMarketing/EmailMarketing.php | 59 +- modules/EmailMarketing/SubPanelView.php | 4 +- modules/EmailTemplates/AttachFiles.php | 12 +- modules/EmailTemplates/DetailView.php | 5 +- modules/EmailTemplates/EditView.html | 68 +- modules/EmailTemplates/EditView.php | 14 +- modules/EmailTemplates/EditViewMain.html | 74 +- modules/EmailTemplates/EmailTemplate.php | 3 + .../EmailTemplates/EmailTemplateFormBase.php | 67 +- .../PopupDocumentsCampaignTemplate.html | 4 +- .../EmailTemplates/language/en_us.lang.php | 3 + modules/EmailText/EmailText.php | 49 + modules/EmailText/vardefs.php | 47 + modules/Emails/Compose.php | 39 +- .../MyEmailsDashlet/MyEmailsDashlet.php | 18 +- modules/Emails/DetailView.html | 2 +- modules/Emails/DetailView.php | 9 +- modules/Emails/DetailViewSent.html | 2 +- modules/Emails/EditView.html | 433 - modules/Emails/EditView.php | 9 +- modules/Emails/EditViewArchive.html | 4 +- modules/Emails/Email.php | 329 +- modules/Emails/EmailUI.php | 74 +- modules/Emails/EmailUIAjax.php | 18 +- modules/Emails/ListViewDrafts.html | 2 +- modules/Emails/ListViewGroup.php | 8 +- modules/Emails/ListViewGroupInbox.html | 2 +- modules/Emails/ListViewHome.html | 2 +- modules/Emails/ListViewHome.php | 2 +- modules/Emails/ListViewMyInbox.html | 2 +- modules/Emails/ListViewSent.html | 2 +- modules/Emails/PopupDocuments.html | 4 +- modules/Emails/Popup_picker.html | 8 +- modules/Emails/Save.php | 18 +- modules/Emails/Status.php | 2 +- modules/Emails/SubPanelViewRecipients.php | 4 +- modules/Emails/javascript/Email.js | 10 +- modules/Emails/javascript/EmailUICompose.js | 30 +- modules/Emails/javascript/ajax.js | 22 +- .../Emails/javascript/composeEmailTemplate.js | 10 +- modules/Emails/javascript/grid.js | 2 +- modules/Emails/javascript/init.js | 4 + modules/Emails/language/en_us.lang.php | 22 +- modules/Emails/templates/_baseEmail.tpl | 23 +- modules/Emails/templates/_blank.html | 2 +- .../Emails/templates/_createGroupFolder.tpl | 32 +- modules/Emails/templates/addressSearch.tpl | 8 +- modules/Emails/templates/advancedSearch.tpl | 8 +- .../Emails/templates/editAccountDialogue.tpl | 2 +- modules/Emails/templates/emailDetailView.tpl | 3 +- .../Emails/templates/emailSettingsFolders.tpl | 2 +- .../Emails/templates/emailSettingsGeneral.tpl | 2 +- modules/Emails/views/view.modulelistmenu.php | 3 +- modules/Employees/Employee.php | 62 +- modules/Employees/EmployeesSearchForm.php | 83 + modules/Employees/EmployeesStudioModule.php | 57 + modules/Employees/Popup_picker.html | 2 +- modules/Employees/Save.php | 17 +- modules/Employees/WapAuthenticate.php | 150 +- modules/Employees/language/en_us.lang.php | 32 + modules/Employees/metadata/SearchFields.php | 6 +- modules/Employees/metadata/editviewdefs.php | 8 +- .../Employees/metadata/quickcreatedefs.php | 75 +- modules/Employees/metadata/searchdefs.php | 2 +- .../Employees/metadata/studio.php | 43 +- modules/Employees/vardefs.php | 8 + modules/Employees/views/view.detail.php | 20 +- modules/Employees/views/view.edit.php | 30 +- modules/Employees/views/view.list.php | 34 +- modules/Home/About.php | 21 +- .../Dashlets/ChartsDashlet/ChartsDashlet.php | 6 +- .../InvadersDashlet/InvadersDashlet.tpl | 2 +- .../SugarNewsDashlet/SugarNewsDashlet.php | 2 +- .../Dashlets/iFrameDashlet/iFrameDashlet.php | 7 +- modules/Home/Home.tpl | 10 +- modules/Home/TrainingPortal.tpl | 2 +- modules/Home/UnifiedSearchAdvanced.php | 327 +- modules/Home/UnifiedSearchAdvancedForm.tpl | 12 +- modules/Home/index.php | 5 +- modules/Home/language/en_us.lang.php | 9 +- modules/Home/quicksearchQuery.php | 7 +- modules/Home/views/view.modulelistmenu.php | 3 +- modules/Import/Forms.php | 6 +- modules/Import/ImportCacheFiles.php | 105 +- modules/Import/ImportDuplicateCheck.php | 30 +- modules/Import/Importer.php | 39 +- modules/Import/language/en_us.lang.php | 1 + modules/Import/maps/ImportMap.php | 10 +- .../sources/ExternalSourceEAPMAdapter.php | 7 +- modules/Import/sources/ImportFile.php | 46 +- modules/Import/tpls/confirm.tpl | 52 +- modules/Import/tpls/confirm_table.tpl | 4 +- modules/Import/tpls/dupcheck.tpl | 2 +- modules/Import/tpls/last.tpl | 2 +- modules/Import/tpls/listview.tpl | 2 +- modules/Import/tpls/listviewpaginator.tpl | 2 +- modules/Import/tpls/step1.tpl | 6 +- modules/Import/tpls/step2.tpl | 13 +- modules/Import/tpls/step3.tpl | 18 +- modules/Import/tpls/wizardWrapper.tpl | 3 +- modules/Import/views/ImportListView.php | 4 +- modules/Import/views/view.confirm.php | 2 +- modules/Import/views/view.dupcheck.php | 16 +- modules/Import/views/view.last.php | 42 +- modules/Import/views/view.step1.php | 39 +- modules/Import/views/view.step2.php | 36 +- modules/Import/views/view.step3.php | 34 +- modules/Import/views/view.step4.php | 17 +- modules/InboundEmail/Delete.php | 5 + modules/InboundEmail/EditGroupFolder.php | 7 +- modules/InboundEmail/EditView.html | 4 +- modules/InboundEmail/InboundEmail.php | 320 +- modules/InboundEmail/ListView.php | 4 +- modules/InboundEmail/Popup.php | 2 +- .../InboundEmail/ShowInboundFoldersList.php | 2 - modules/InboundEmail/language/en_us.lang.php | 4 +- modules/Leads/Capture.php | 4 +- modules/Leads/Lead.php | 2 +- modules/Leads/LeadFormBase.php | 263 +- modules/Leads/MyLeads.php | 2 +- modules/Leads/Popup_picker.html | 2 +- modules/Leads/SubPanelView.php | 2 +- modules/Leads/action_view_map.php | 1 + modules/Leads/language/en_us.lang.php | 9 +- modules/Leads/tpls/ConvertLeadFooter.tpl | 16 +- modules/Leads/tpls/EditConvertLead.tpl | 258 + modules/Leads/tpls/ShowDuplicates.tpl | 61 + modules/Leads/vardefs.php | 20 +- modules/Leads/views/view.convertlead.php | 1 + modules/Leads/views/view.list.php | 1 + modules/Leads/views/view.showduplicates.php | 195 + modules/MailMerge/Merge.html | 2 +- modules/MailMerge/Merge.php | 5 +- modules/MailMerge/Save.php | 20 +- modules/MailMerge/Step1.html | 4 +- modules/MailMerge/Step1.php | 51 +- modules/MailMerge/Step2.html | 4 +- modules/MailMerge/Step2.php | 9 +- modules/MailMerge/Step3.php | 4 +- modules/MailMerge/controller.php | 1 + modules/MailMerge/language/en_us.lang.php | 2 + .../MyMeetingsDashlet/MyMeetingsDashlet.php | 83 +- modules/Meetings/Meeting.php | 12 +- modules/Meetings/MeetingFormBase.php | 18 +- modules/Meetings/jsclass_scheduler.js | 27 +- modules/Meetings/metadata/editviewdefs.php | 44 +- modules/Meetings/metadata/quickcreatedefs.php | 72 +- modules/Meetings/tpls/QuickCreate.tpl | 6 +- modules/Meetings/tpls/footer.tpl | 2 +- modules/Meetings/vardefs.php | 4 + modules/MergeRecords/MergeField.html | 20 +- modules/MergeRecords/Step1.html | 4 +- modules/MergeRecords/Step1.php | 2 +- modules/MergeRecords/Step3.php | 23 +- modules/ModuleBuilder/Module/StudioModule.php | 2 +- modules/ModuleBuilder/controller.php | 49 +- modules/ModuleBuilder/language/en_us.lang.php | 13 +- .../parsers/parser.searchfields.php | 123 + .../relationships/AbstractRelationships.php | 6 +- .../relationships/DeployedRelationships.php | 9 +- .../ModuleBuilder/parsers/views/History.php | 13 +- .../views/ListLayoutMetaDataParser.php | 12 +- .../UndeployedMetaDataImplementation.php | 2 +- .../ModuleBuilder/tpls/MBModule/fields.tpl | 125 +- .../ModuleBuilder/tpls/MBPackage/deploy.tpl | 2 +- .../ModuleBuilder/tpls/MBPackage/package.tpl | 2 +- .../ModuleBuilder/tpls/Preview/layoutView.tpl | 4 +- .../ModuleBuilder/tpls/Preview/listView.tpl | 4 +- modules/ModuleBuilder/tpls/includes.tpl | 6 +- modules/ModuleBuilder/tpls/index.tpl | 2 +- modules/ModuleBuilder/tpls/layoutView.tpl | 21 +- modules/ModuleBuilder/tpls/listView.tpl | 4 +- modules/ModuleBuilder/views/view.dashlet.php | 14 +- .../views/view.displaydeployresult.php | 10 +- modules/ModuleBuilder/views/view.dropdown.php | 11 +- .../ModuleBuilder/views/view.dropdowns.php | 4 +- .../ModuleBuilder/views/view.layoutview.php | 2 +- modules/ModuleBuilder/views/view.listview.php | 13 +- .../ModuleBuilder/views/view.modulefield.php | 12 +- .../ModuleBuilder/views/view.modulefields.php | 78 +- .../ModuleBuilder/views/view.modulelabels.php | 1 + .../ModuleBuilder/views/view.popupview.php | 11 +- modules/ModuleBuilder/views/view.wizard.php | 4 +- modules/MySettings/LoadTabSubpanels.php | 5 +- modules/Notes/Note.php | 83 +- modules/Notes/NoteSoap.php | 66 +- modules/Notes/SubPanelView.php | 6 +- modules/Notes/language/en_us.lang.php | 4 + modules/Notes/metadata/editviewdefs.php | 2 +- modules/Notes/metadata/quickcreatedefs.php | 34 +- modules/Notes/vardefs.php | 7 +- modules/OAuthTokens/views/view.authorize.php | 3 + modules/Opportunities/ListViewTop.php | 2 +- modules/Opportunities/OpportunityFormBase.php | 4 +- modules/Opportunities/SubPanelView.php | 4 +- .../Opportunities/SubPanelViewProjects.php | 4 +- modules/Opportunities/language/en_us.lang.php | 3 +- modules/Opportunities/tpls/QuickCreate.tpl | 2 +- modules/Project/Project.php | 25 +- modules/Project/SubPanelView.php | 4 +- modules/Project/language/en_us.lang.php | 4 + modules/Project/tpls/QuickCreate.tpl | 4 +- modules/ProjectTask/Forms.html | 2 +- modules/ProjectTask/MyProjectTasks.php | 2 +- modules/ProjectTask/Popup_picker.html | 2 +- modules/ProjectTask/ProjectTask.php | 174 +- modules/ProjectTask/SubPanelView.php | 5 +- modules/ProjectTask/language/en_us.lang.php | 1 + modules/ProjectTask/views/view.list.php | 11 +- modules/ProspectLists/Popup_picker.html | 2 +- modules/ProspectLists/SubPanelView.php | 4 +- modules/ProspectLists/TargetListUpdate.php | 4 +- modules/ProspectLists/language/en_us.lang.php | 1 + modules/Prospects/Popup_picker.html | 2 +- modules/Prospects/Prospect.php | 28 +- modules/Prospects/ProspectFormBase.php | 9 +- modules/Relationships/Relationship.php | 115 +- modules/Releases/Popup_picker.html | 4 +- modules/Releases/index.php | 7 +- modules/Releases/language/en_us.lang.php | 3 +- modules/Roles/SubPanelViewUsers.php | 4 +- modules/SavedSearch/SavedSearch.php | 160 +- modules/Schedulers/Delete.php | 4 + modules/Schedulers/ListView.php | 2 +- modules/Schedulers/Scheduled.php | 2 +- modules/Schedulers/Scheduler.php | 18 +- modules/Schedulers/SchedulerDaemon.php | 27 +- modules/Schedulers/_AddJobsHere.php | 92 +- modules/SchedulersJobs/SchedulersJob.php | 6 +- modules/Studio/DropDowns/EditView.php | 10 +- modules/Studio/DropDowns/EditView.tpl | 63 +- modules/Studio/Forms.php | 14 +- modules/Studio/TabGroups/EditViewTabs.php | 16 +- modules/Studio/TabGroups/EditViewTabs.tpl | 70 +- modules/Studio/language/en_us.lang.php | 17 +- modules/Studio/parsers/StudioParser.php | 30 +- modules/Studio/wizards/RenameModules.php | 22 +- modules/Studio/wizards/RenameModules.tpl | 4 +- .../SugarFeedDashlet/SugarFeedDashlet.php | 19 +- .../SugarFeedDashlet/UserPostForm.tpl | 4 +- modules/SugarFeed/SugarFeed.php | 30 +- modules/SugarFeed/SugarFeedFlush.php | 2 +- modules/SugarFeed/language/en_us.lang.php | 8 + modules/SugarFeed/linkHandlers/Image.php | 2 +- modules/Tasks/MyTasks.php | 33 +- modules/Tasks/Task.php | 85 +- modules/Tasks/language/en_us.lang.php | 3 + modules/Tasks/tpls/QuickCreate.tpl | 10 +- modules/Trackers/store/DatabaseStore.php | 27 +- .../store/TrackerQueriesDatabaseStore.php | 43 +- .../store/TrackerSessionsDatabaseStore.php | 39 +- .../SugarMerge/EditViewMerge.php | 38 +- .../UpgradeWizard/SugarMerge/SugarMerge.php | 13 + modules/UpgradeWizard/cancel.php | 2 +- modules/UpgradeWizard/commit.php | 70 +- modules/UpgradeWizard/deleteCache.php | 15 +- modules/UpgradeWizard/end.php | 32 +- modules/UpgradeWizard/index.php | 81 +- modules/UpgradeWizard/language/en_us.lang.php | 14 +- modules/UpgradeWizard/preflight.php | 25 +- modules/UpgradeWizard/preflightJson.php | 26 +- modules/UpgradeWizard/silentUpgrade.php | 22 +- .../UpgradeWizard/silentUpgrade_dce_step1.php | 50 +- .../UpgradeWizard/silentUpgrade_dce_step2.php | 142 +- modules/UpgradeWizard/silentUpgrade_step1.php | 288 +- modules/UpgradeWizard/silentUpgrade_step2.php | 141 +- modules/UpgradeWizard/start.php | 5 +- modules/UpgradeWizard/systemCheck.php | 23 +- modules/UpgradeWizard/systemCheckJson.php | 33 +- modules/UpgradeWizard/tpls/layoutsMerge.tpl | 2 +- modules/UpgradeWizard/upgradeMetaHelper.php | 9 +- modules/UpgradeWizard/upload.php | 85 +- modules/UpgradeWizard/uw_ajax.php | 42 +- modules/UpgradeWizard/uw_main.tpl | 10 +- modules/UpgradeWizard/uw_utils.php | 1953 +-- modules/UserPreferences/UserPreference.php | 7 +- modules/Users/Authenticate.php | 25 +- modules/Users/Changenewpassword.php | 2 +- modules/Users/DetailView.js | 4 +- modules/Users/DetailView.php | 536 - modules/Users/EditView.php | 703 -- modules/Users/Forms.php | 169 +- modules/Users/GeneratePassword.php | 187 +- modules/Users/Login.php | 4 +- modules/Users/Popup_picker.html | 2 +- modules/Users/Save.php | 34 +- modules/Users/User.js | 1 - modules/Users/User.php | 273 +- modules/Users/UserEditView.js | 85 + modules/Users/UserViewHelper.php | 766 ++ .../AuthenticationController.php | 76 +- .../SAMLAuthenticate/SAMLAuthenticate.php | 18 +- .../SugarAuthenticate/SugarAuthenticate.php | 30 +- modules/Users/controller.php | 2 +- modules/Users/language/en_us.lang.php | 30 +- modules/Users/login.js | 4 +- modules/Users/login.tpl | 13 +- modules/Users/metadata/SearchFields.php | 2 +- .../Users/metadata/detailgroupviewdefs.php | 75 +- modules/Users/metadata/detailviewdefs.php | 73 + modules/Users/metadata/editgroupviewdefs.php | 66 + modules/Users/metadata/editviewdefs.php | 100 + modules/Users/metadata/quickcreatedefs.php | 107 + .../metadata/studio.php} | 49 +- modules/Users/reassignUserRecords.php | 6 +- .../DetailViewFooter.tpl} | 225 +- modules/Users/tpls/DetailViewHeader.tpl | 98 + .../{EditView.tpl => tpls/EditViewFooter.tpl} | 474 +- .../tpls/EditViewGroup.tpl} | 63 +- modules/Users/tpls/EditViewHeader.tpl | 146 + modules/Users/tpls/QuickEditFooter.tpl | 65 + modules/Users/tpls/wizard.tpl | 14 +- modules/Users/vardefs.php | 120 +- modules/Users/views/view.detail.php | 195 + modules/Users/views/view.edit.php | 209 + modules/Users/views/view.quickedit.php | 66 + modules/Users/views/view.wizard.php | 8 +- modules/vCals/vCal.php | 2 +- service/core/NusoapSoap.php | 2 +- service/core/PHP5Soap.php | 9 +- service/core/REST/SugarRest.php | 20 +- service/core/REST/SugarRestJSON.php | 11 +- service/core/REST/SugarRestRSS.php | 20 +- service/core/REST/SugarRestSerialize.php | 4 +- service/core/SoapHelperWebService.php | 69 +- service/core/SugarRestService.php | 6 +- service/core/SugarWebService.php | 5 +- service/core/SugarWebServiceImpl.php | 41 +- service/example/example.html | 2 +- service/v2_1/SugarWebServiceImplv2_1.php | 5 +- service/v3/SugarWebServiceImplv3.php | 165 +- service/v3/SugarWebServiceUtilv3.php | 5 +- service/v3_1/SugarWebServiceImplv3_1.php | 21 +- service/v4/SugarWebServiceImplv4.php | 31 +- service/v4/SugarWebServiceUtilv4.php | 73 +- soap/SoapData.php | 23 +- soap/SoapDeprecated.php | 7 +- soap/SoapHelperFunctions.php | 43 +- soap/SoapPortalHelper.php | 54 +- soap/SoapPortalUsers.php | 10 +- soap/SoapRelationshipHelper.php | 142 +- soap/SoapSugarUsers.php | 171 +- sugar_version.php | 8 +- sugarcrm.log | 0 tests/ModuleInstall/ExtTest.php | 1 + .../Util/TestDox/ResultPrinter/HTML.php | 2 +- tests/SugarTestAccountUtilities.php | 1 + tests/SugarTestContactUtilities.php | 18 +- tests/SugarTestHelper.php | 18 +- tests/SugarTestImportUtilities.php | 36 +- tests/SugarTestLeadUtilities.php | 17 +- tests/SugarTestProjectTaskUtilities.php | 11 + tests/SugarTestThemeUtilities.php | 78 +- tests/data/Bug49109Test.php | 8 +- .../Bug49281Test.php} | 63 +- tests/data/GetLinkedBeansTest.php | 115 + tests/data/SugarBeanTest.php | 61 +- tests/expressions/expression_engine_test.html | 6 +- tests/include/Bug43652.php | 4 +- tests/include/Bug45525Test.php | 4 + tests/include/Dashlets/Bug41013Test.php | 29 +- tests/include/EditView/Bug48570Test.php | 6 + tests/include/Localization/Bug41058Test.php | 315 + .../include/Localization/LocalizationTest.php | 26 - tests/include/MVC/SugarApplicationTest.php | 49 +- tests/include/MVC/View/views/Bug47572Test.php | 3 +- tests/include/OutboundEmail/Bug23140Test.php | 103 +- tests/include/SearchForm/Bug45709Test.php | 34 +- tests/include/SearchForm/Bug45966Test.php | 137 +- tests/include/SearchForm/Bug46713Test.php | 2 +- tests/include/SearchForm/Bug48846Test.php | 115 + tests/include/SearchForm/RangeSearchTest.php | 105 +- tests/include/SearchForm/SugarSpotTest.php | 10 +- tests/include/Smarty/plugins/Bug28321Test.php | 111 + tests/include/SubPanel/ITR27836Test.php | 141 + .../SugarEmailAddress/Bug41557Test.php | 4 +- .../SugarFields/Fields/Bug49691aTest.php} | 71 +- .../SugarFields/Fields/Bug49691bTest.php | 87 + .../Fields/Int/GetSearchWhereValueTest.php | 84 + tests/include/SugarFolders/Bug33404Test.php | 1 + tests/include/SugarObjects/Bug32797Test.php | 52 +- .../forms/ContactFormBaseTest.php | 116 + .../SugarObjects/forms/LeadFormBaseTest.php | 116 + tests/include/SugarTheme/Bug48571Test.php | 105 + tests/include/SugarTheme/SugarThemeTest.php | 198 +- tests/include/TimeDateTest.php | 1 + tests/include/ValidDBNameTest.php | 23 +- tests/include/database/Bug34547Test.php | 21 +- tests/include/database/Bug39635Test.php | 65 + tests/include/database/Bug42475Test.php | 9 +- tests/include/database/Bug43466Test.php | 83 +- tests/include/database/DBHelperTest.php | 129 +- .../include/database/DBManagerFactoryTest.php | 72 +- tests/include/database/DBManagerTest.php | 1688 ++- tests/include/database/MssqlManagerTest.php | 211 + tests/include/database/MysqlManagerTest.php | 224 + tests/include/database/TestBean.php | 52 + .../generic/SugarWidgets/Bug44272Test.php | 12 +- .../generic/SugarWidgets/Bug48616Test.php | 118 + .../generic/SugarWidgets/Bug49008Test.php | 78 + tests/include/utils/Bug49397Test.php | 71 + .../utils/CreateCacheDirectoryTest.php | 10 +- tests/include/utils/XssTest.php | 21 + tests/include/utils/ZipTest.php | 85 +- tests/install/Bug40129Test.php | 68 +- tests/modules/Administration/Bug46317Test.php | 11 + .../Administration/Bugs39819_39820.php | 4 +- .../Administration/SugarSpriteBuilderTest.php | 80 + tests/modules/Calendar/Bug37953Test.php | 1 + tests/modules/Calendar/Bug4236Test.php | 78 + tests/modules/Calendar/CalendarTest.php | 145 + tests/modules/CampaignLog/CampaignLogTest.php | 62 +- tests/modules/Configurator/Bug47845Test.php | 78 + tests/modules/Contacts/Bug36989Test.php | 4 +- tests/modules/DynamicFields/Bug43471Test.php | 17 +- .../Bug47553Test.php} | 92 +- tests/modules/DynamicFields/Bug49870Test.php | 62 + .../EmailAddresses/EmailAddressTest.php | 6 +- tests/modules/EmailMan/Bug44113Test.php | 50 +- tests/modules/EmailTemplates/Bug48800Test.php | 84 + tests/modules/Emails/Bug40911Test.php | 2 +- tests/modules/Emails/Bug45960Test.php | 4 +- tests/modules/Employees/Bug46923Test.php | 5 + tests/modules/Home/Bug43395Test.php | 36 +- tests/modules/Home/Bug43653Test.php | 6 + .../Home/UnifiedSearchAdvancedTest.php | 60 +- tests/modules/Import/Bug45963Test.php | 2 +- tests/modules/Import/Bug47737Test.php | 13 +- tests/modules/Import/ImportCacheFilesTest.php | 31 +- .../Import/ImportFieldSanitizeTest.php | 40 +- tests/modules/Import/ImportFileLimitTest.php | 8 +- .../modules/Import/ImportFileSplitterTest.php | 57 +- tests/modules/Import/ImportFileTest.php | 150 +- tests/modules/Import/ImporterTest.php | 2 +- tests/modules/Meetings/Bug45287Test.php | 28 +- tests/modules/Meetings/Bug45287_2Test.php | 31 +- .../modules/ModuleBuilder/MB/Bug39598Test.php | 6 +- .../ModuleBuilder/views/Bug44372Test.php | 2 +- .../ModuleBuilder/views/Bug47010Test.php | 5 +- tests/modules/Project/Bug37123Test.php | 15 +- .../{Bug46350Test.php => Bug49310Test.php} | 95 +- tests/modules/SavedSearch/Bug42378Test.php | 2 +- tests/modules/Schedulers/SchedulerTest.php | 8 +- tests/modules/Studio/RenameModulesTest.php | 50 +- tests/modules/Tasks/TasksTest.php | 5 +- tests/modules/UpgradeWizard/Bug36845Test.php | 124 +- tests/modules/UpgradeWizard/Bug37214Test.php | 76 +- tests/modules/UpgradeWizard/Bug39757Test.php | 2 +- tests/modules/UpgradeWizard/Bug40793Test.php | 21 +- tests/modules/UpgradeWizard/Bug44414Test.php | 99 - .../SilentUpgradeSessionVarsTest.php | 2 +- .../UpgradeWizard/SugarMerge/Bug36257Test.php | 133 - .../UpgradeWizard/SugarMerge/Bug36481Test.php | 102 - .../UpgradeWizard/SugarMerge/Bug37231Test.php | 280 - .../UpgradeWizard/SugarMerge/Bug37295Test.php | 166 - .../UpgradeWizard/SugarMerge/Bug37461Test.php | 174 - .../UpgradeWizard/SugarMerge/Bug37597Test.php | 174 - .../UpgradeWizard/SugarMerge/Bug37704Test.php | 153 - .../UpgradeWizard/SugarMerge/Bug37725Test.php | 155 - .../UpgradeWizard/SugarMerge/Bug37850Test.php | 101 - .../UpgradeWizard/SugarMerge/Bug37862Test.php | 162 - .../UpgradeWizard/SugarMerge/Bug37917Test.php | 83 - .../UpgradeWizard/SugarMerge/Bug39057Test.php | 92 - .../UpgradeWizard/SugarMerge/Bug49955Test.php | 148 + .../SugarMerge/LeadsMergeTest.php | 204 - .../UpgradeCustomTemplateMetaTest.php | 50 +- .../modules/Leads/metadata/detailviewdefs.php | 184 - .../modules/Leads/metadata/detailviewdefs.php | 230 - .../Quotes/metadata/detailviewdefs.php | 138 - .../Contacts/metadata/editviewdefs.php | 184 - .../Contacts/metadata/editviewdefs.php | 146 - .../modules/Contacts/metadata/searchdefs.php | 66 - .../modules/Leads/metadata/detailviewdefs.php | 220 - .../modules/Leads/metadata/editviewdefs.php | 155 - .../Documents/metadata/editviewdefs.php | 2 +- .../modules/Calls/metadata/editviewdefs.php | 2 +- .../Documents/metadata/editviewdefs.php | 2 +- .../Documents/metadata/quickcreatedefs.php | 2 +- .../610/modules/Notes/vardefs.php | 5 +- .../modules/Calls/metadata/editviewdefs.php | 2 +- .../Meetings/metadata/editviewdefs.php | 176 + .../Meetings/metadata/editviewdefs.php | 2 - .../modules/Notes/metadata/editviewdefs.php | 110 + .../Meetings/metadata/detailviewdefs.php | 107 - .../modules/Leads/metadata/detailviewdefs.php | 229 - .../Opportunities/metadata/listviewdefs.php | 110 - .../Accounts/metadata/detailviewdefs.php | 84 - .../Accounts/metadata/editviewdefs.php | 135 - .../Accounts/metadata/listviewdefs.php | 133 - .../Contacts/metadata/detailviewdefs.php | 171 - .../Contacts/metadata/editviewdefs.php | 145 - .../Opportunities/metadata/searchdefs.php | 63 - tests/modules/UpgradeWizard/UWUtilsTest.php | 59 +- .../UserPreferences/UserPreferenceTest.php | 98 + tests/modules/Users/Bug41527Test.php | 67 +- .../Bug44503Test.php} | 89 +- tests/modules/Users/Bug46473Test.php | 20 +- tests/modules/Users/Bug47735Test.php | 99 + tests/modules/Users/Bug49069Test.php | 125 + tests/modules/Users/Bug49175Test.php | 86 + tests/modules/Users/Bug49627Test.php | 149 + tests/phpunit.php | 2 +- tests/service/APIv3Helper.php | 30 +- tests/service/Bug22504Test.php | 8 +- tests/service/Bug31003Test.php | 6 +- tests/service/Bug36564Test.php | 4 +- tests/service/Bug39234Test.php | 1 + tests/service/Bug40250Test.php | 10 +- tests/service/Bug41296Test.php | 14 +- tests/service/Bug41985Test.php | 2 + tests/service/Bug42683Test.php | 18 +- tests/service/Bug43196Test.php | 1 + tests/service/Bug44280Test.php | 59 +- .../Bug47650Test.php} | 77 +- tests/service/Bug47683Test.php | 2 +- tests/service/Bug48748Test.php | 133 + tests/service/Bug48889Test.php | 78 + tests/service/Bug49898Test.php | 95 + .../NoBlankFieldUpdateOnFirstSyncTest.php | 241 + tests/service/OAuthTest.php | 4 +- tests/service/QuerySanitizeTest.php | 85 + tests/service/RESTAPI3Test.php | 97 +- tests/service/RESTAPI4Test.php | 84 +- tests/service/RESTAPIRSSTest.php | 1 + tests/service/RestTestCase.php | 153 + tests/service/SOAPAPI1Test.php | 35 +- tests/service/SOAPAPI2Test.php | 134 +- tests/service/SOAPAPI3Test.php | 158 +- tests/service/SOAPTestCase.php | 44 +- tests/service/SoapRelationshipHelperTest.php | 162 + .../service/core/SoapHelperWebServiceTest.php | 117 + tests/tests/SugarTestImportUtilitiesTest.php | 34 +- themes/Sugar5/css/style.css | 58 +- themes/Sugar5/tpls/_companyLogo.tpl | 6 +- themes/Sugar5/tpls/_globalLinks.tpl | 2 +- themes/Sugar5/tpls/_head.tpl | 3 +- themes/Sugar5/tpls/_headerSearch.tpl | 6 +- themes/Sugar5/tpls/header.tpl | 2 +- themes/default/css/wizard.css | 3 +- themes/default/images/icon_Employees_32.png | Bin 0 -> 2985 bytes upload/index.html | 1 + 1114 files changed, 44881 insertions(+), 64805 deletions(-) delete mode 100644 cache/upload/index.html delete mode 100644 data/upload/index.html create mode 100644 include/MVC/View/tpls/gsdetail.tpl create mode 100644 include/MVC/View/views/view.gs.php create mode 100644 include/SearchForm/tpls/SugarSpot.tpl create mode 100644 include/Smarty/plugins/function.sugar_getimage.php create mode 100644 include/Smarty/plugins/function.sugar_getlink.php rename tests/modules/UpgradeWizard/SugarMerge/metadata_files/551/modules/Notes/metadata/searchdefs.php => include/Smarty/plugins/function.sugar_getscript.php (75%) mode change 100755 => 100644 create mode 100644 include/SugarObjects/forms/FormBase.php create mode 100644 include/SugarObjects/forms/PersonFormBase.php create mode 100644 include/SugarSQLValidate.php create mode 100644 include/SugarTheme/SugarSprites.php delete mode 100644 include/database/PearDatabase.php delete mode 100644 include/database/SqlsrvHelper.php delete mode 100644 include/javascript/sugar_grp1.js delete mode 100644 include/javascript/sugar_grp1_yui.js delete mode 100644 include/javascript/sugar_grp_emails.js delete mode 100644 include/javascript/sugar_grp_jsolait.js delete mode 100644 include/javascript/sugar_grp_overlib.js delete mode 100644 include/javascript/sugar_grp_quickcomp.js delete mode 100644 include/javascript/sugar_grp_yui2.js delete mode 100644 include/javascript/sugar_grp_yui_widgets.css delete mode 100644 include/javascript/sugar_grp_yui_widgets.js create mode 100644 include/php-sql-parser.php create mode 100644 jssource/src_files/modules/Calendar/Cal.js create mode 100644 jssource/src_files/modules/Users/UserEditView.js create mode 100644 modules/Activities/OpenListView.php delete mode 100644 modules/Administration/DstFix.php rename modules/{Calendar/Forms.php => Administration/RebuildSprites.php} (84%) create mode 100644 modules/Administration/SugarSpriteBuilder.php create mode 100644 modules/Administration/templates/RebuildSprites.tpl create mode 100644 modules/Calendar/Cal.css create mode 100644 modules/Calendar/Cal.js create mode 100644 modules/Calendar/CalendarActivity.php create mode 100644 modules/Calendar/CalendarDisplay.php create mode 100644 modules/Calendar/CalendarGrid.php create mode 100644 modules/Calendar/CalendarUtils.php rename modules/Calendar/{small_month.php => Dashlets/CalendarDashlet/CalendarDashlet.en_us.lang.php} (77%) create mode 100644 modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.meta.php create mode 100644 modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.php create mode 100644 modules/Calendar/Dashlets/CalendarDashlet/CalendarDashletOptions.tpl delete mode 100644 modules/Calendar/DateTimeUtil.php delete mode 100644 modules/Calendar/TasksListView.html delete mode 100644 modules/Calendar/TasksListView.php rename modules/Calendar/{views/view.list.php => action_view_map.php} (86%) delete mode 100644 modules/Calendar/templates/template_shared_calendar.php delete mode 100644 modules/Calendar/templates/templates_calendar.php create mode 100644 modules/Calendar/tpls/empty.tpl create mode 100644 modules/Calendar/tpls/footer.tpl rename tests/modules/UpgradeWizard/SugarMerge/Bug37921Test.php => modules/Calendar/tpls/form.tpl (54%) mode change 100755 => 100644 create mode 100644 modules/Calendar/tpls/header.tpl create mode 100644 modules/Calendar/tpls/main.tpl create mode 100644 modules/Calendar/tpls/settings.tpl create mode 100644 modules/Calendar/tpls/shared_users.tpl create mode 100644 modules/Calendar/views/view.getgr.php create mode 100644 modules/Calendar/views/view.getgrusers.php create mode 100644 modules/Calendar/views/view.quickedit.php create mode 100644 modules/Calendar/views/view.remove.php create mode 100644 modules/Calendar/views/view.reschedule.php create mode 100644 modules/Calendar/views/view.saveactivity.php rename tests/modules/UpgradeWizard/Bug42643Test.php => modules/Calendar/views/view.savesettings.php (55%) mode change 100755 => 100644 create mode 100644 modules/EmailText/EmailText.php create mode 100644 modules/EmailText/vardefs.php delete mode 100644 modules/Emails/EditView.html create mode 100644 modules/Employees/EmployeesSearchForm.php create mode 100644 modules/Employees/EmployeesStudioModule.php rename tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Opportunities/metadata/detailviewdefs.php => modules/Employees/metadata/quickcreatedefs.php (51%) mode change 100755 => 100644 rename include/database/MysqliHelper.php => modules/Employees/metadata/studio.php (73%) create mode 100644 modules/Leads/tpls/EditConvertLead.tpl create mode 100644 modules/Leads/tpls/ShowDuplicates.tpl create mode 100644 modules/Leads/views/view.showduplicates.php create mode 100644 modules/ModuleBuilder/parsers/parser.searchfields.php delete mode 100644 modules/Users/DetailView.php delete mode 100644 modules/Users/EditView.php create mode 100644 modules/Users/UserEditView.js create mode 100644 modules/Users/UserViewHelper.php rename tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Opportunities/metadata/editviewdefs.php => modules/Users/metadata/detailgroupviewdefs.php (65%) mode change 100755 => 100644 create mode 100644 modules/Users/metadata/detailviewdefs.php create mode 100644 modules/Users/metadata/editgroupviewdefs.php create mode 100644 modules/Users/metadata/editviewdefs.php create mode 100644 modules/Users/metadata/quickcreatedefs.php rename modules/{Calendar/metadata/listviewdefs.php => Users/metadata/studio.php} (74%) rename modules/Users/{DetailView.tpl => tpls/DetailViewFooter.tpl} (54%) create mode 100644 modules/Users/tpls/DetailViewHeader.tpl rename modules/Users/{EditView.tpl => tpls/EditViewFooter.tpl} (51%) rename modules/{Calendar/SubPanelSharedCalendar.php => Users/tpls/EditViewGroup.tpl} (69%) create mode 100644 modules/Users/tpls/EditViewHeader.tpl create mode 100644 modules/Users/tpls/QuickEditFooter.tpl create mode 100644 modules/Users/views/view.detail.php create mode 100644 modules/Users/views/view.edit.php create mode 100644 modules/Users/views/view.quickedit.php create mode 100644 sugarcrm.log rename tests/{modules/Reports/Bug47271Test.php => data/Bug49281Test.php} (67%) create mode 100755 tests/data/GetLinkedBeansTest.php create mode 100755 tests/include/Localization/Bug41058Test.php create mode 100755 tests/include/SearchForm/Bug48846Test.php create mode 100755 tests/include/Smarty/plugins/Bug28321Test.php create mode 100755 tests/include/SubPanel/ITR27836Test.php rename tests/{modules/UpgradeWizard/SugarMerge/Bug39059Test.php => include/SugarFields/Fields/Bug49691aTest.php} (57%) create mode 100755 tests/include/SugarFields/Fields/Bug49691bTest.php create mode 100755 tests/include/SugarFields/Fields/Int/GetSearchWhereValueTest.php create mode 100755 tests/include/SugarObjects/forms/ContactFormBaseTest.php create mode 100755 tests/include/SugarObjects/forms/LeadFormBaseTest.php create mode 100755 tests/include/SugarTheme/Bug48571Test.php create mode 100755 tests/include/database/Bug39635Test.php create mode 100755 tests/include/database/MssqlManagerTest.php create mode 100755 tests/include/database/MysqlManagerTest.php create mode 100755 tests/include/database/TestBean.php create mode 100755 tests/include/generic/SugarWidgets/Bug48616Test.php create mode 100755 tests/include/generic/SugarWidgets/Bug49008Test.php create mode 100755 tests/include/utils/Bug49397Test.php create mode 100755 tests/modules/Administration/SugarSpriteBuilderTest.php create mode 100755 tests/modules/Calendar/Bug4236Test.php create mode 100755 tests/modules/Calendar/CalendarTest.php create mode 100755 tests/modules/Configurator/Bug47845Test.php rename tests/modules/{UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Accounts/metadata/searchdefs.php => DynamicFields/Bug47553Test.php} (50%) create mode 100755 tests/modules/DynamicFields/Bug49870Test.php create mode 100755 tests/modules/EmailTemplates/Bug48800Test.php rename tests/modules/ProjectTask/{Bug46350Test.php => Bug49310Test.php} (63%) delete mode 100755 tests/modules/UpgradeWizard/Bug44414Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug36257Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug36481Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37231Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37295Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37461Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37597Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37704Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37725Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37850Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37862Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug37917Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug39057Test.php create mode 100755 tests/modules/UpgradeWizard/SugarMerge/Bug49955Test.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/LeadsMergeTest.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/cit_metadata_files/554/modules/Leads/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/cit_metadata_files/custom/modules/Leads/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/520/modules/Quotes/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/550/modules/Contacts/metadata/editviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/551/modules/Contacts/metadata/editviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/551/modules/Contacts/metadata/searchdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/551/modules/Leads/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/551/modules/Leads/metadata/editviewdefs.php create mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/611/modules/Meetings/metadata/editviewdefs.php create mode 100755 tests/modules/UpgradeWizard/SugarMerge/metadata_files/custom/modules/Notes/metadata/editviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/od_metadata_files/551/modules/Meetings/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/od_metadata_files/554/modules/Leads/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/od_metadata_files/554/modules/Opportunities/metadata/listviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Accounts/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Accounts/metadata/editviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Accounts/metadata/listviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Contacts/metadata/detailviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Contacts/metadata/editviewdefs.php delete mode 100755 tests/modules/UpgradeWizard/SugarMerge/siupgrade_metadata_files/551/modules/Opportunities/metadata/searchdefs.php create mode 100755 tests/modules/UserPreferences/UserPreferenceTest.php rename tests/modules/{UpgradeWizard/Bug42622Test.php => Users/Bug44503Test.php} (53%) create mode 100755 tests/modules/Users/Bug47735Test.php create mode 100755 tests/modules/Users/Bug49069Test.php create mode 100755 tests/modules/Users/Bug49175Test.php create mode 100755 tests/modules/Users/Bug49627Test.php rename tests/{data/Bug47731Test.php => service/Bug47650Test.php} (57%) create mode 100755 tests/service/Bug48748Test.php create mode 100755 tests/service/Bug48889Test.php create mode 100755 tests/service/Bug49898Test.php create mode 100755 tests/service/NoBlankFieldUpdateOnFirstSyncTest.php create mode 100755 tests/service/QuerySanitizeTest.php create mode 100755 tests/service/RestTestCase.php create mode 100755 tests/service/SoapRelationshipHelperTest.php create mode 100755 tests/service/core/SoapHelperWebServiceTest.php create mode 100644 themes/default/images/icon_Employees_32.png create mode 100644 upload/index.html diff --git a/ModuleInstall/PackageManager/PackageController.php b/ModuleInstall/PackageManager/PackageController.php index 462bafb8..b036bb08 100644 --- a/ModuleInstall/PackageManager/PackageController.php +++ b/ModuleInstall/PackageManager/PackageController.php @@ -38,32 +38,32 @@ require_once('ModuleInstall/PackageManager/PackageManager.php'); class PackageController{ var $_pm; - + /** * Constructor: this class is called from the the ajax call and handles invoking the correct * functionality on the server. */ function PackageController(){ - $this->_pm = new PackageManager(); + $this->_pm = new PackageManager(); } - + function performBasicSearch(){ $json = getJSONobj(); $search_term = ''; $node_id = ''; if(isset($_REQUEST['search_term'])) { - $search_term = nl2br($_REQUEST['search_term']); - } + $search_term = nl2br($_REQUEST['search_term']); + } if(isset($_REQUEST['node_id'])) { - $node_id = nl2br($_REQUEST['node_id']); - } + $node_id = nl2br($_REQUEST['node_id']); + } $xml = PackageManager::getPackages($node_id); echo 'result = ' . $json->encode(array('packages' => $xml)); } - + /** * Retrieve a list of packages which belong to the corresponding category - * + * * @param category_id this is passed via POST and is the category id of packages * we wish to retrieve * @return packages xml string consisting of the packages and releases which belong to @@ -72,14 +72,14 @@ function getPackages(){ $json = getJSONobj(); $category_id = ''; - + if(isset($_REQUEST['category_id'])) { - $category_id = nl2br($_REQUEST['category_id']); - } + $category_id = nl2br($_REQUEST['category_id']); + } $xml = PackageManager::getPackages($category_id); echo 'result = ' . $json->encode(array('package_output' => $xml)); } - + /** * Obtain a list of releases from the server. This function is currently used for generating the patches/langpacks for upgrade wizard * as well as during installation @@ -90,16 +90,16 @@ $package_id = ''; $types = ''; if(isset($_REQUEST['category_id'])) { - $category_id = nl2br($_REQUEST['category_id']); - } + $category_id = nl2br($_REQUEST['category_id']); + } if(isset($_REQUEST['package_id'])) { - $package_id = nl2br($_REQUEST['package_id']); - } + $package_id = nl2br($_REQUEST['package_id']); + } if(isset($_REQUEST['types'])) { - $types = nl2br($_REQUEST['types']); - } + $types = nl2br($_REQUEST['types']); + } $types = explode(',', $types); - + $filter = array(); $count = count($types); $index = 1; @@ -110,35 +110,35 @@ $type_str .= ","; $index++; } - + $filter = array('type' => $type_str); - $filter = PackageManager::toNameValueList($filter); + $filter = PackageManager::toNameValueList($filter); $releases = PackageManager::getReleases($category_id, $package_id, $filter); $nodes = array(); $release_map = array(); foreach($releases['packages'] as $release){ $release = PackageManager::fromNameValueList($release); - $nodes[] = array('description' => $release['description'], 'version' => $release['version'], 'build_number' => $release['build_number'], 'id' => $release['id']); + $nodes[] = array('description' => $release['description'], 'version' => $release['version'], 'build_number' => $release['build_number'], 'id' => $release['id']); $release_map[$release['id']] = array('package_id' => $release['package_id'], 'category_id' => $release['category_id']); - } + } $_SESSION['ML_PATCHES'] = $release_map; echo 'result = ' . $json->encode(array('releases' => $nodes)); } - + /** * Obtain a promotion from the depot */ function getPromotion(){ $json = getJSONobj(); - + $header = PackageManager::getPromotion(); - + echo 'result = ' . $json->encode(array('promotion' => $header)); } - + /** * Download the given release - * + * * @param category_id this is passed via POST and is the category id of the release we wish to download * @param package_id this is passed via POST and is the package id of the release we wish to download * @param release_id this is passed via POST and is the release id of the release we wish to download @@ -151,29 +151,29 @@ $category_id = ''; $release_id = ''; if(isset($_REQUEST['package_id'])) { - $package_id = nl2br($_REQUEST['package_id']); - } + $package_id = nl2br($_REQUEST['package_id']); + } if(isset($_REQUEST['category_id'])) { - $category_id = nl2br($_REQUEST['category_id']); + $category_id = nl2br($_REQUEST['category_id']); } if(isset($_REQUEST['release_id'])) { - $release_id = nl2br($_REQUEST['release_id']); + $release_id = nl2br($_REQUEST['release_id']); } $GLOBALS['log']->debug("PACKAGE ID: ".$package_id); $GLOBALS['log']->debug("CATEGORY ID: ".$category_id); $GLOBALS['log']->debug("RELEASE ID: ".$release_id); - $result = $this->_pm->download($category_id, $package_id, $release_id, getcwd().'/'.$sugar_config['upload_dir']); + $result = $this->_pm->download($category_id, $package_id, $release_id); $GLOBALS['log']->debug("RESULT: ".print_r($result,true)); $success = 'false'; if($result != null){ $GLOBALS['log']->debug("Performing Setup"); $this->_pm->performSetup($result, 'module', false); $GLOBALS['log']->debug("Complete Setup"); - $success = 'true'; + $success = 'true'; } - echo 'result = ' . $json->encode(array('success' => $success)); - } - + echo 'result = ' . $json->encode(array('success' => $success)); + } + /** * Retrieve a list of categories that are subcategories to the selected category * @@ -184,25 +184,25 @@ $json = getJSONobj(); $node_id = ''; if(isset($_REQUEST['category_id'])) { - $node_id = nl2br($_REQUEST['category_id']); - } + $node_id = nl2br($_REQUEST['category_id']); + } $GLOBALS['log']->debug("NODE ID: ".$node_id); $nodes = PackageManager::getCategories($node_id); - echo 'result = ' . $json->encode(array('nodes' => $nodes)); + echo 'result = ' . $json->encode(array('nodes' => $nodes)); } - + function getNodes(){ $json = getJSONobj(); $category_id = ''; if(isset($_REQUEST['category_id'])) { - $category_id = nl2br($_REQUEST['category_id']); - } + $category_id = nl2br($_REQUEST['category_id']); + } $GLOBALS['log']->debug("CATEGORY ID: ".$category_id); $nodes = PackageManager::getModuleLoaderCategoryPackages($category_id); $GLOBALS['log']->debug(var_export($nodes, true)); - echo 'result = ' . $json->encode(array('nodes' => $nodes)); + echo 'result = ' . $json->encode(array('nodes' => $nodes)); } - + /** * Check the SugarDepot for updates for the given type as passed in via POST * @param type the type to check for @@ -212,8 +212,8 @@ $json = getJSONobj(); $type = ''; if(isset($_REQUEST['type'])) { - $type = nl2br($_REQUEST['type']); - } + $type = nl2br($_REQUEST['type']); + } $pm = new PackageManager(); $updates = $pm->checkForUpdates(); $nodes = array(); @@ -221,7 +221,7 @@ if(!empty($updates)){ foreach($updates as $update){ $update = PackageManager::fromNameValueList($update); - $nodes[] = array('label' => $update['name'], 'description' => $update['description'], 'version' => $update['version'], 'build_number' => $update['build_number'], 'id' => $update['id'], 'type' => $update['type']); + $nodes[] = array('label' => $update['name'], 'description' => $update['description'], 'version' => $update['version'], 'build_number' => $update['build_number'], 'id' => $update['id'], 'type' => $update['type']); $release_map[$update['id']] = array('package_id' => $update['package_id'], 'category_id' => $update['category_id'], 'type' => $update['type']); } } @@ -231,24 +231,24 @@ if(!empty($releases['packages'])){ foreach($releases['packages'] as $update){ $update = PackageManager::fromNameValueList($update); - $nodes[] = array('label' => $update['name'], 'description' => $update['description'], 'version' => $update['version'], 'build_number' => $update['build_number'], 'id' => $update['id'], 'type' => $update['type']); + $nodes[] = array('label' => $update['name'], 'description' => $update['description'], 'version' => $update['version'], 'build_number' => $update['build_number'], 'id' => $update['id'], 'type' => $update['type']); $release_map[$update['id']] = array('package_id' => $update['package_id'], 'category_id' => $update['category_id'], 'type' => $update['type']); } } $_SESSION['ML_PATCHES'] = $release_map; - echo 'result = ' . $json->encode(array('updates' => $nodes)); + echo 'result = ' . $json->encode(array('updates' => $nodes)); } - + function getLicenseText(){ $json = getJSONobj(); $file = ''; if(isset($_REQUEST['file'])) { - $file = hashToFile($_REQUEST['file']); - } - $GLOBALS['log']->debug("FILE : ".$file); - echo 'result = ' . $json->encode(array('license_display' => PackageManagerDisplay::buildLicenseOutput($file))); - } - + $file = hashToFile($_REQUEST['file']); + } + $GLOBALS['log']->debug("FILE : ".$file); + echo 'result = ' . $json->encode(array('license_display' => PackageManagerDisplay::buildLicenseOutput($file))); + } + /** * build the list of modules that are currently in the staging area waiting to be installed */ @@ -257,24 +257,24 @@ $json = getJSONobj(); echo 'result = ' . $json->encode(array('packages' => $packages)); - } - + } + /** * build the list of modules that are currently in the staging area waiting to be installed */ function performInstall(){ $file = ''; if(isset($_REQUEST['file'])) { - $file = hashToFile($_REQUEST['file']); - } - if(!empty($file)){ + $file = hashToFile($_REQUEST['file']); + } + if(!empty($file)){ $this->_pm->performInstall($file); } $json = getJSONobj(); echo 'result = ' . $json->encode(array('result' => 'success')); } - + function authenticate(){ $json = getJSONobj(); $username = ''; @@ -282,75 +282,92 @@ $servername = ''; $terms_checked = ''; if(isset($_REQUEST['username'])) { - $username = nl2br($_REQUEST['username']); - } + $username = nl2br($_REQUEST['username']); + } if(isset($_REQUEST['password'])) { - $password = nl2br($_REQUEST['password']); + $password = nl2br($_REQUEST['password']); } if(isset($_REQUEST['servername'])) { - $servername = $_REQUEST['servername']; + $servername = $_REQUEST['servername']; } if(isset($_REQUEST['terms_checked'])) { - $terms_checked = $_REQUEST['terms_checked']; + $terms_checked = $_REQUEST['terms_checked']; if($terms_checked == 'on') - $terms_checked = true; + $terms_checked = true; } if(!empty($username) && !empty($password)){ $password = md5($password); $result = PackageManager::authenticate($username, $password, $servername, $terms_checked); if(!is_array($result) && $result == true) - $status = 'success'; + $status = 'success'; else - $status = $result['faultstring']; + $status = $result['faultstring']; }else{ - $status = 'failed'; + $status = 'failed'; } - - echo 'result = ' . $json->encode(array('status' => $status)); + + echo 'result = ' . $json->encode(array('status' => $status)); } - + function getDocumentation(){ $json = getJSONobj(); $package_id = ''; $release_id = ''; - + if(isset($_REQUEST['package_id'])) { - $package_id = nl2br($_REQUEST['package_id']); + $package_id = nl2br($_REQUEST['package_id']); } if(isset($_REQUEST['release_id'])) { - $release_id = nl2br($_REQUEST['release_id']); - } - + $release_id = nl2br($_REQUEST['release_id']); + } + $documents = PackageManager::getDocumentation($package_id, $release_id); $GLOBALS['log']->debug("DOCUMENTS: ".var_export($documents, true)); echo 'result = ' . $json->encode(array('documents' => $documents)); } - + function downloadedDocumentation(){ $json = getJSONobj(); $document_id = ''; - + if(isset($_REQUEST['document_id'])) { - $document_id = nl2br($_REQUEST['document_id']); + $document_id = nl2br($_REQUEST['document_id']); } - $GLOBALS['log']->debug("Downloading Document: ".$document_id); + $GLOBALS['log']->debug("Downloading Document: ".$document_id); PackageManagerComm::downloadedDocumentation($document_id); - echo 'result = ' . $json->encode(array('result' => 'true')); + echo 'result = ' . $json->encode(array('result' => 'true')); + } + + /** + * Remove metadata files such as foo-manifest + * Enter description here ... + * @param unknown_type $file + * @param unknown_type $meta + */ + protected function rmMetaFile($file, $meta) + { + $metafile = pathinfo($file, PATHINFO_DIRNAME)."/". pathinfo($file, PATHINFO_FILENAME)."-$meta.php"; + if(file_exists($metafile)) { + unlink($metafile); + } } - + function remove(){ $json = getJSONobj(); $file = ''; - + if(isset($_REQUEST['file'])) { - $file = urldecode(hashToFile($_REQUEST['file'])); - } + $file = urldecode(hashToFile($_REQUEST['file'])); + } $GLOBALS['log']->debug("FILE TO REMOVE: ".$file); if(!empty($file)){ unlink($file); + foreach(array("manifest", "icon") as $meta) { + $this->rmMetaFile($file, $meta); + } } - echo 'result = ' . $json->encode(array('result' => 'true')); + echo 'result = ' . $json->encode(array('result' => 'true')); } } ?> diff --git a/ModuleInstall/PackageManager/PackageManager.php b/ModuleInstall/PackageManager/PackageManager.php index 61926556..98caadaf 100644 --- a/ModuleInstall/PackageManager/PackageManager.php +++ b/ModuleInstall/PackageManager/PackageManager.php @@ -39,29 +39,21 @@ define("CREDENTIAL_CATEGORY", "ml"); define("CREDENTIAL_USERNAME", "username"); define("CREDENTIAL_PASSWORD", "password"); - - - - require_once('include/nusoap/nusoap.php'); - require_once('include/utils/zip_utils.php'); - require_once('ModuleInstall/PackageManager/PackageManagerDisplay.php'); require_once('ModuleInstall/ModuleInstaller.php'); - require_once('include/entryPoint.php'); require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); - - class PackageManager{ +class PackageManager{ var $soap_client; /** * Constructor: In this method we will initialize the nusoap client to point to the hearbeat server */ function PackageManager(){ - $this->db = & DBManagerFactory::getInstance(); + $this->db = DBManagerFactory::getInstance(); } function initializeComm(){ @@ -191,22 +183,16 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); * @param release_id the release_id to download * @return filename - the path to which the zip file was saved */ - function download($category_id, $package_id, $release_id, $save_dir = ''){ + public function download($category_id, $package_id, $release_id) + { $GLOBALS['log']->debug('RELEASE _ID: '.$release_id); if(!empty($release_id)){ $filename = PackageManagerComm::addDownload($category_id, $package_id, $release_id); if($filename){ $GLOBALS['log']->debug('RESULT: '.$filename); PackageManagerComm::errorCheck(); - $filepath = PackageManagerComm::performDownload($filename, $save_dir); + $filepath = PackageManagerComm::performDownload($filename); return $filepath; - /*if(!empty($result) && !empty($result['filename']) && !empty($save_dir)){ - $GLOBALS['log']->debug('Saving Package to: '.$save_dir); - $GLOBALS['log']->debug('Saving package to the local file system:'.$result['filename']); - return write_encoded_file ($result, $save_dir); - }else{ - return null; - }*/ } }else{ return null; @@ -374,9 +360,9 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); function extractManifest( $zip_file,$base_tmp_upgrade_dir ) { global $sugar_config; - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; + $base_upgrade_dir = sugar_cached("/upgrades"); $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; - return( $this->extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) ); + return $this->extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ); } function validate_manifest( $manifest ){ @@ -453,7 +439,7 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); global $sugar_config; $base_filename = urldecode($tempFile); $GLOBALS['log']->debug("BaseFileName: ".$base_filename); - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; + $base_upgrade_dir = sugar_cached("/upgrades"); $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; $manifest_file = $this->extractManifest( $base_filename,$base_tmp_upgrade_dir); $GLOBALS['log']->debug("Manifest: ".$manifest_file); @@ -513,14 +499,14 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); function unlinkTempFiles() { global $sugar_config; @unlink($_FILES['upgrade_zip']['tmp_name']); - @unlink(getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name']); + @unlink("upload://".$_FILES['upgrade_zip']['name']); } function performInstall($file, $silent=true){ global $sugar_config; global $mod_strings; global $current_language; - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; + $base_upgrade_dir = sugar_cached("/upgrades"); $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; if(!file_exists($base_tmp_upgrade_dir)){ mkdir_recursive($base_tmp_upgrade_dir, true); @@ -586,7 +572,7 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); global $sugar_config; global $mod_strings; global $current_language; - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; + $base_upgrade_dir = sugar_cached("/upgrades"); $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; if(!isset($GLOBALS['mi_remove_tables']))$GLOBALS['mi_remove_tables'] = true; $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir ); @@ -623,19 +609,24 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); $icon = ""; switch( $type ){ case "full": - $icon = SugarThemeRegistry::current()->getImage("Upgrade", "" ); + $icon = SugarThemeRegistry::current()->getImage("Upgrade", "" ,null,null,'.gif', "Upgrade"); + break; case "langpack": - $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "" ); + $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',"Language Packs" ); + break; case "module": - $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "" ); + $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "" ,null,null,'.gif', "Module Loader"); + break; case "patch": - $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "" ); + $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif', "Patch Upgrades" ); + break; case "theme": - $icon = SugarThemeRegistry::current()->getImage("Themes", "" ); + $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif', "Themes" ); + break; default: break; @@ -647,43 +638,32 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); global $sugar_config; global $current_language; $uh = new UpgradeHistory(); - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; - $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; - $uContent = findAllFiles( "$base_upgrade_dir", array() , false, 'zip',$base_tmp_upgrade_dir); - //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP - $extns = array( 'ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP'); - foreach($extns as $extn){ - $uContent = array_merge($uContent,findAllFiles( "$base_upgrade_dir", array() , false, $extn,$base_tmp_upgrade_dir)); - } + $base_upgrade_dir = "upload://upgrades"; + $base_tmp_upgrade_dir = sugar_cached("upgrades/temp"); + $uContent = findAllFiles( $base_upgrade_dir, array() , false, 'zip'); $upgrade_contents = array(); $content_values = array_values($uContent); $alreadyProcessed = array(); foreach($content_values as $val){ if(empty($alreadyProcessed[$val])){ $upgrade_contents[] = $val; - $alreadyProcessed["$val"] = true; + $alreadyProcessed[$val] = true; } } $upgrades_available = 0; $packages = array(); $mod_strings = return_module_language($current_language, "Administration"); - foreach($upgrade_contents as $upgrade_content) - { - if(!preg_match("#.*\.zip\$#", strtolower($upgrade_content)) || preg_match("#.*./zips/.*#", strtolower($upgrade_content))) - { + foreach($upgrade_contents as $upgrade_content) { + if(!preg_match('#.*\.zip$#', strtolower($upgrade_content)) || preg_match("#.*./zips/.*#", strtolower($upgrade_content))) { continue; } - $upgrade_content = clean_path($upgrade_content); - // Bug 22285 - fix for UNC paths - if ( substr($upgrade_content,0,2) == '\\\\' ) - $upgrade_content = '\\\\'.$upgrade_content; $the_base = basename($upgrade_content); $the_md5 = md5_file($upgrade_content); $md5_matches = $uh->findByMd5($the_md5); $file_install = $upgrade_content; - if(0 == sizeof($md5_matches)) + if(empty($md5_matches)) { $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php'; require_once($target_manifest); @@ -702,44 +682,35 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); } //check dependencies first - if(!empty($dependencies)){ - + if(!empty($dependencies)) { $uh = new UpgradeHistory(); $not_found = $uh->checkDependencies($dependencies); if(!empty($not_found) && count($not_found) > 0){ $file_install = 'errors_'.$mod_strings['ERR_UW_NO_DEPENDENCY']."[".implode(',', $not_found)."]"; - }//fi + } } - if($view == 'default' && $manifest_type != 'patch') - { + if($view == 'default' && $manifest_type != 'patch') { continue; } if($view == 'module' - && $manifest_type != 'module' && $manifest_type != 'theme' && $manifest_type != 'langpack') - { + && $manifest_type != 'module' && $manifest_type != 'theme' && $manifest_type != 'langpack') { continue; } - if(empty($manifest['icon'])){ + if(empty($manifest['icon'])) { $icon = $this->getImageForType( $manifest['type'] ); - }else{ + } else { $path_parts = pathinfo( $manifest['icon'] ); $icon = ""; } $upgrades_available++; - // uploaded file in cache/upload - $fileS = explode('/', $upgrade_content); - $c = count($fileS); - $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2]; - $upload_file = $sugar_config['upload_dir'].$fileName; - - $upgrade_content = urlencode($upgrade_content); - $upload_content = urlencode($upload_file); - $packages[] = array('name' => $name, 'version' => $version, 'published_date' => $published_date, 'description' => $description, 'uninstallable' =>$uninstallable, 'type' => $type, 'file_install' => fileToHash($file_install), 'file' => fileToHash($upgrade_content), 'upload_file' => $upload_content); + $packages[] = array('name' => $name, 'version' => $version, 'published_date' => $published_date, + 'description' => $description, 'uninstallable' =>$uninstallable, 'type' => $type, + 'file' => fileToHash($upgrade_content), 'file_install' => fileToHash($upgrade_content)); }//fi }//rof return $packages; @@ -747,7 +718,7 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); function getLicenseFromFile($file){ global $sugar_config; - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; + $base_upgrade_dir = sugar_cached("/upgrades"); $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; $license_file = $this->extractFile($file, 'LICENSE.txt', $base_tmp_upgrade_dir); if(is_file($license_file)){ @@ -785,7 +756,7 @@ require_once('ModuleInstall/PackageManager/PackageManagerComm.php'); $packages = array(); $upgrades_installed = 0; $uh = new UpgradeHistory(); - $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; + $base_upgrade_dir = sugar_cached("/upgrades"); $base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; foreach($installeds as $installed) { diff --git a/ModuleInstall/PackageManager/PackageManagerComm.php b/ModuleInstall/PackageManager/PackageManagerComm.php index af32492a..014acf75 100644 --- a/ModuleInstall/PackageManager/PackageManagerComm.php +++ b/ModuleInstall/PackageManager/PackageManagerComm.php @@ -40,25 +40,25 @@ require_once('ModuleInstall/PackageManager/PackageManagerDownloader.php'); define("HTTPS_URL", "https://depot.sugarcrm.com/depot/SugarDepotSoap.php"); define("ACTIVE_STATUS", "ACTIVE"); -class PackageManagerComm{ +class PackageManagerComm{ /** * Initialize the soap client and store in the $GLOBALS object for use - * + * * @param login designates whether we want to try to login after we initialize or not - */ - function initialize($login = true){ - if(empty($GLOBALS['SugarDepot'])){ + */ + function initialize($login = true){ + if(empty($GLOBALS['SugarDepot'])){ $GLOBALS['log']->debug('USING HTTPS TO CONNECT TO HEARTBEAT'); $soap_client = new nusoapclient(HTTPS_URL, false); $ping = $soap_client->call('sugarPing', array()); $GLOBALS['SugarDepot'] = $soap_client; - } + } //if we do not have a session, then try to login if($login && empty($_SESSION['SugarDepotSessionID'])){ - PackageManagerComm::login(); + PackageManagerComm::login(); } } - + /** * Check for errors in the response or error_str */ @@ -68,10 +68,10 @@ class PackageManagerComm{ $GLOBALS['log']->fatal($GLOBALS['SugarDepot']->response); } } - + /** * Set the credentials for use during login - * + * * @param username Mambo username * @param password Mambo password * @param download_key User's download key @@ -79,9 +79,9 @@ class PackageManagerComm{ function setCredentials($username, $password, $download_key){ $_SESSION['SugarDepotUsername'] = $username; $_SESSION['SugarDepotPassword'] = $password; - $_SESSION['SugarDepotDownloadKey'] = $download_key; + $_SESSION['SugarDepotDownloadKey'] = $download_key; } - + /** * Clears out the session so we can reauthenticate. */ @@ -93,7 +93,7 @@ class PackageManagerComm{ ////////// BEGIN: Base Functions for Communicating with the depot /** * Login to the depot - * + * * @return true if successful, false otherwise */ function login($terms_checked = true){ @@ -114,7 +114,7 @@ class PackageManagerComm{ if(!empty($terms_version)) $params['terms_version'] = $terms_version; - $result = $GLOBALS['SugarDepot']->call('depotLogin', array(array('user_name' => $credentials['username'], 'password' => $credentials['password']),'info'=>$info, 'params' => $params)); + $result = $GLOBALS['SugarDepot']->call('depotLogin', array(array('user_name' => $credentials['username'], 'password' => $credentials['password']),'info'=>$info, 'params' => $params)); PackageManagerComm::errorCheck(); if(!is_array($result)) $_SESSION['SugarDepotSessionID'] = $result; @@ -124,29 +124,29 @@ class PackageManagerComm{ else return $_SESSION['SugarDepotSessionID']; } - + /** * Logout from the depot */ function logout(){ PackageManagerComm::initialize(); - $result = $GLOBALS['SugarDepot']->call('depotLogout', array('session_id' => $_SESSION['SugarDepotSessionID'])); - } - + $result = $GLOBALS['SugarDepot']->call('depotLogout', array('session_id' => $_SESSION['SugarDepotSessionID'])); + } + /** * Get all promotions from the depot */ function getPromotion(){ PackageManagerComm::initialize(); //check for fault first and then return - $name_value_list = $GLOBALS['SugarDepot']->call('depotGetPromotion', array('session_id' => $_SESSION['SugarDepotSessionID'])); + $name_value_list = $GLOBALS['SugarDepot']->call('depotGetPromotion', array('session_id' => $_SESSION['SugarDepotSessionID'])); return $name_value_list; - } - + } + /** * A generic function which given a category_id some filter will * return an object which contains categories and packages - * + * * @param category_id the category_id to fetch * @param filter a filter which will limit theh number of results returned * @return categories_and_packages @@ -157,10 +157,10 @@ class PackageManagerComm{ //check for fault return $GLOBALS['SugarDepot']->call('depotGetCategoriesPackages', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'filter' => $filter)); } - + /** * Return a list of child categories to the parent specified in category_id - * + * * @param category_id the parent category_id * @param filter a filter which will limit theh number of results returned * @return categories_and_packages @@ -171,53 +171,53 @@ class PackageManagerComm{ //check for fault return $GLOBALS['SugarDepot']->call('depotGetCategories', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'filter' => $filter)); } - + /** * Return a list of packages which belong to the parent category_id - * + * * @param category_id the category_id to fetch * @param filter a filter which will limit theh number of results returned * @return packages * @see packages - */ + */ function getPackages($category_id, $filter = array()){ PackageManagerComm::initialize(); //check for fault return $GLOBALS['SugarDepot']->call('depotGetPackages', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'filter' => $filter)); } - + /** * Return a list of releases belong to a package - * + * * @param category_id the category_id to fetch * @param package_id the package id which the release belongs to * @return packages * @see packages - */ + */ function getReleases($category_id, $package_id, $filter = array()){ PackageManagerComm::initialize(); //check for fault - return $GLOBALS['SugarDepot']->call('depotGetReleases', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'package_id' => $package_id, 'filter' => $filter)); + return $GLOBALS['SugarDepot']->call('depotGetReleases', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'package_id' => $package_id, 'filter' => $filter)); } - + /** * Download a given release - * + * * @param category_id the category_id to fetch * @param package_id the package id which the release belongs to * @param release_id the release we want to download * @return download * @see download - */ + */ function download($category_id, $package_id, $release_id){ PackageManagerComm::initialize(); //check for fault - return $GLOBALS['SugarDepot']->call('depotDownloadRelease', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'package_id' => $package_id, 'release_id' => $release_id)); + return $GLOBALS['SugarDepot']->call('depotDownloadRelease', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'package_id' => $package_id, 'release_id' => $release_id)); } - + /** * Add a requested download to the queue - * + * * @param category_id the category_id to fetch * @param package_id the package id which the release belongs to * @param release_id the release we want to download @@ -226,82 +226,82 @@ class PackageManagerComm{ function addDownload($category_id, $package_id, $release_id){ PackageManagerComm::initialize(); //check for fault - return $GLOBALS['SugarDepot']->call('depotAddDownload', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'package_id' => $package_id, 'release_id' => $release_id, 'download_key' => '123')); + return $GLOBALS['SugarDepot']->call('depotAddDownload', array('session_id' => $_SESSION['SugarDepotSessionID'], 'category_id' => $category_id, 'package_id' => $package_id, 'release_id' => $release_id, 'download_key' => '123')); } - + /** * Call the PackageManagerDownloader function which uses curl in order to download the specified file - * + * * @param filename the file to download * @return path to downloaded file */ - function performDownload($filename, $save_dir){ + static public function performDownload($filename){ PackageManagerComm::initialize(); //check for fault $GLOBALS['log']->debug("Performing download from depot: Session ID: ".$_SESSION['SugarDepotSessionID']." Filename: ".$filename); - return PackageManagerDownloader::download($_SESSION['SugarDepotSessionID'], $filename, $save_dir); + return PackageManagerDownloader::download($_SESSION['SugarDepotSessionID'], $filename); } - + /** * Retrieve documentation for the given release or package - * + * * @param package_id the specified package to retrieve documentation * @param release_id the specified release to retrieve documentation - * + * * @return documents */ function getDocumentation($package_id, $release_id){ PackageManagerComm::initialize(); //check for fault - return $GLOBALS['SugarDepot']->call('depotGetDocumentation', array('session_id' => $_SESSION['SugarDepotSessionID'], 'package_id' => $package_id, 'release_id' => $release_id)); + return $GLOBALS['SugarDepot']->call('depotGetDocumentation', array('session_id' => $_SESSION['SugarDepotSessionID'], 'package_id' => $package_id, 'release_id' => $release_id)); } - + function getTermsAndConditions(){ PackageManagerComm::initialize(false); return $GLOBALS['SugarDepot']->call('depotTermsAndConditions',array()); } - + /** * Log that the user has clicked on a document - * + * * @param document_id the document the user has clicked on */ function downloadedDocumentation($document_id){ PackageManagerComm::initialize(); //check for fault $GLOBALS['log']->debug("Logging Document: ".$document_id); - $GLOBALS['SugarDepot']->call('depotDownloadedDocumentation', array('session_id' => $_SESSION['SugarDepotSessionID'], 'document_id' => $document_id)); + $GLOBALS['SugarDepot']->call('depotDownloadedDocumentation', array('session_id' => $_SESSION['SugarDepotSessionID'], 'document_id' => $document_id)); } /** * Send the list of installed objects, could be patches, or modules, .. to the depot and allow the depot to send back * a list of corresponding updates - * + * * @param objects_to_check an array of name_value_lists which contain the appropriate values * which will allow the depot to check for updates - * - * @return array of name_value_lists of corresponding updates + * + * @return array of name_value_lists of corresponding updates */ function checkForUpdates($objects_to_check){ PackageManagerComm::initialize(); //check for fault - return $GLOBALS['SugarDepot']->call('depotCheckForUpdates', array('session_id' => $_SESSION['SugarDepotSessionID'], 'objects' => $objects_to_check)); + return $GLOBALS['SugarDepot']->call('depotCheckForUpdates', array('session_id' => $_SESSION['SugarDepotSessionID'], 'objects' => $objects_to_check)); } /** * Ping the server to determine if we have established proper communication - * + * * @return true if we can communicate with the server and false otherwise - */ + */ function isAlive(){ PackageManagerComm::initialize(false); - + $status = $GLOBALS['SugarDepot']->call('sugarPing', array()); if(empty($status) || $GLOBALS['SugarDepot']->getError() || $status != ACTIVE_STATUS){ - return false; + return false; }else{ return true; } - } + } ////////// END: Base Functions for Communicating with the depot //////////////////////////////////////////////////////// } diff --git a/ModuleInstall/PackageManager/PackageManagerDisplay.php b/ModuleInstall/PackageManager/PackageManagerDisplay.php index bae399f6..68156cc7 100644 --- a/ModuleInstall/PackageManager/PackageManagerDisplay.php +++ b/ModuleInstall/PackageManager/PackageManagerDisplay.php @@ -100,7 +100,8 @@ class PackageManagerDisplay{ }else{ $form2 .= ""; } - $form2 .= ""; + $form2 .= ""; + if($isAlive){ $form2 .= " Collapse"; }else{ @@ -163,7 +164,8 @@ class PackageManagerDisplay{ if($show_login){ $form2 .= ""; } - $form2 .= ""; + $form2 .= ""; + $loginViewStyle = ($isAlive ? 'none' : 'block'); $selectViewStyle = ($isAlive ? 'block' : 'none'); $form2 .= "
"; @@ -375,7 +377,8 @@ class PackageManagerDisplay{ $install = 0; } $ss->assign('INSTALLATION', $install); - $ss->assign('WAIT_IMAGE', SugarThemeRegistry::current()->getImage("loading","border='0' align='bottom'")); + $ss->assign('WAIT_IMAGE', SugarThemeRegistry::current()->getImage("loading","border='0' align='bottom'",null,null,'.gif',"Loading")); + $ss->assign('sugar_version', $sugar_version); $ss->assign('js_custom_version', $sugar_config['js_custom_version']); $ss->assign('IS_ALIVE', $isAlive); @@ -437,6 +440,8 @@ class PackageManagerDisplay{ $ss->assign('ML_FILEGRIDINSTALLED_COLUMN',$filegridinstalled_column_ary); //end + $ss->assign('SHOW_IMG', SugarThemeRegistry::current()->getImage('advanced_search', 'border="0"', 8, 8, '.gif', 'Show')); + $ss->assign('HIDE_IMG', SugarThemeRegistry::current()->getImage('basic_search', 'border="0"', 8, 8, '.gif', 'Hide')); $str = $ss->fetch('ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl'); return $str; } diff --git a/ModuleInstall/PackageManager/PackageManagerDownloader.php b/ModuleInstall/PackageManager/PackageManagerDownloader.php index b20d26b3..0c051288 100644 --- a/ModuleInstall/PackageManager/PackageManagerDownloader.php +++ b/ModuleInstall/PackageManager/PackageManagerDownloader.php @@ -36,22 +36,21 @@ define('PACKAGE_MANAGER_DOWNLOAD_SERVER', 'https://depot.sugarcrm.com/depot/'); define('PACKAGE_MANAGER_DOWNLOAD_PAGE', 'download.php'); -define('PACKAGE_MANAGER_DOWNLOAD_PATH', '../'.$GLOBALS['sugar_config']['upload_dir']); class PackageManagerDownloader{ - + /** * Using curl we will download the file from the depot server - * + * * @param session_id the session_id this file is queued for * @param file_name the file_name to download * @param save_dir (optional) if specified it will direct where to save the file once downloaded * @param download_sever (optional) if specified it will direct the url for the download - * + * * @return the full path of the saved file */ function download($session_id, $file_name, $save_dir = '', $download_server = ''){ if(empty($save_dir)){ - $save_dir = PACKAGE_MANAGER_DOWNLOAD_PATH; + $save_dir = "upload://"; } if(empty($download_server)){ $download_server = PACKAGE_MANAGER_DOWNLOAD_SERVER; diff --git a/ModuleInstall/PackageManager/tpls/ModuleLoaderListView.tpl b/ModuleInstall/PackageManager/tpls/ModuleLoaderListView.tpl index 0e3103d8..9f992d5d 100644 --- a/ModuleInstall/PackageManager/tpls/ModuleLoaderListView.tpl +++ b/ModuleInstall/PackageManager/tpls/ModuleLoaderListView.tpl @@ -63,7 +63,7 @@ {/if} - Advanced  + {sugar_getimage name="advanced_search" ext=".gif" width="8" height="8" alt=$app_strings.LBL_ADVANCED_SEARCH other_attributes='border="0" '}  {counter start=0 name="colCounter" print=false assign="colCounter"} {foreach from=$displayColumns key=col item=params} diff --git a/ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl b/ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl index 466bb74b..a89369f2 100644 --- a/ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl +++ b/ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl @@ -35,7 +35,7 @@ ********************************************************************************/ *} - +{sugar_getscript file="cache/include/javascript/sugar_grp_yui_widgets.js"} {literal} - +
+ {{* Only show header if it is not default or an int value *}} {{if !empty($label) && !is_int($label) && $label != 'DEFAULT' && !$useTabs && $showSectionPanelsTitles}} @@ -86,11 +88,14 @@ class="yui-navset" {{/if}} {{assign var='rowCount' value=0}} +{{assign var='tabIndexVal' value=0}} {{foreach name=rowIteration from=$panel key=row item=rowData}} {counter name="fieldsUsed" start=0 print=false assign="fieldsUsed"} {capture name="tr" assign="tableRow"} + {{math assign="rowCount" equation="$rowCount + 1"}} + {{assign var='columnsInRow' value=$rowData|@count}} {{assign var='columnsUsed' value=0}} @@ -100,7 +105,7 @@ class="yui-navset" {{foreach name=colIteration from=$rowData key=col item=colData}} {{counter name="colCount" print=false}} - {{math assign="tabIndex" equation="$panelCount * $maxColumns + $colCount"}} + {{if count($rowData) == $colCount}} {{assign var="colCount" value=0}} {{/if}} @@ -110,15 +115,17 @@ class="yui-navset" {{/if}} {{if empty($def.templateMeta.labelsOnTop) && empty($colData.field.hideLabel)}} - {{/if}} {counter name="fieldsUsed"} + {{math assign="tabIndexVal" equation="$tabIndexVal + 1"}} + {{if !empty($colData.field.tabindex) && $colData.field.tabindex !=0}} + {{assign var='tabindex' value=$colData.field.tabindex}} + {{** instead of tracking tabindex values for all fields, just track for email as email does not get created directly from + a tpl that has access to smarty values. Email gets created through addEmailAddress() function in SugarEmailAddress.js + which will use the value in tabFields array + **}} + {{if $colData.field.name == 'email1'}}{{/if}} + {{else}} + {** if not explicitly assigned, we will default to 0 for 508 compliance reasons, instead of the calculated tabIndexVal value **} + {{assign var='tabindex' value=0}} + {{/if}} @@ -201,7 +224,7 @@ class="yui-navset" {{include file=$footerTpl}} {$overlibStuff} {{if $useTabs}} - +{sugar_getscript file="cache/include/javascript/sugar_grp_yui_widgets.js"} diff --git a/include/EditView/EditView2.php b/include/EditView/EditView2.php index 760d5609..1c9fa4ad 100644 --- a/include/EditView/EditView2.php +++ b/include/EditView/EditView2.php @@ -39,6 +39,10 @@ require_once('include/TemplateHandler/TemplateHandler.php'); require_once('include/EditView/SugarVCR.php'); +/** + * New EditView + * @api + */ class EditView { public $th; @@ -302,7 +306,7 @@ class EditView $panel[$row][$col]['field']['tabindex'] = (isset($p[$row][$col]['tabindex']) && is_numeric($p[$row][$col]['tabindex'])) ? $p[$row][$col]['tabindex'] - : $itemCount; + : '0'; if ($columnsInRows < $maxColumns) { @@ -371,7 +375,7 @@ class EditView } return $panel; - } + } function process($checkFormName = false, $formName = '') { @@ -581,6 +585,7 @@ class EditView $this->th->ss->assign('bean', $this->focus); $this->th->ss->assign('isAuditEnabled', $this->focus->is_AuditEnabled()); $this->th->ss->assign('gridline',$current_user->getPreference('gridline') == 'on' ? '1' : '0'); + $this->th->ss->assign('VERSION_MARK', getVersionedPath('')); global $js_custom_version; global $sugar_version; @@ -674,6 +679,7 @@ class EditView $this->th->ss->assign('CALENDAR_FORMAT', $date_format . ' ' . $t23 . $time_separator . '%M' . $pm); } + $this->th->ss->assign('CALENDAR_FDOW', $current_user->get_first_day_of_week()); $this->th->ss->assign('TIME_SEPARATOR', $time_separator); $seps = get_number_seperators(); @@ -854,4 +860,4 @@ class EditView return ''; } -} \ No newline at end of file +} diff --git a/include/EditView/PopupQuickCreate.php b/include/EditView/PopupQuickCreate.php index c8f5a2e8..2192a78d 100644 --- a/include/EditView/PopupQuickCreate.php +++ b/include/EditView/PopupQuickCreate.php @@ -36,14 +36,18 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ require_once('include/EditView/SubpanelQuickCreate.php'); +/** + * Quick create form as a pop-up window + * @api + */ class PopupQuickCreate extends SubpanelQuickCreate{ - + function PopupQuickCreate($module, $view='QuickCreate'){ $this->defaultProcess = false; parent::SubpanelQuickCreate($module, $view, true); $this->ev->defs['templateMeta']['form']['buttons'] = array('POPUPSAVE', 'POPUPCANCEL'); } - + function process($module){ $form_name = 'form_QuickCreate_' . $module; $this->ev->formName = $form_name; diff --git a/include/EditView/QuickCreate.php b/include/EditView/QuickCreate.php index 95477a5e..a700402d 100644 --- a/include/EditView/QuickCreate.php +++ b/include/EditView/QuickCreate.php @@ -35,25 +35,29 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * "Powered by SugarCRM". ********************************************************************************/ - + require_once('include/EditView/EditView.php'); +/** + * QuickCreate - minimal object creation form + * @api + */ class QuickCreate extends EditView { /** * True if the create being populated via an AJAX call? */ var $viaAJAX = false; - + function process() { global $current_user, $timedate; - + parent::process(); - + $this->ss->assign('ASSIGNED_USER_ID', $current_user->id); - + $this->ss->assign('REQUEST', array_merge($_GET, $_POST)); $this->ss->assign('CALENDAR_LANG', "en"); - + $date_format = $timedate->get_cal_date_format(); $this->ss->assign('USER_DATEFORMAT', '('. $timedate->get_user_date_format().')'); $this->ss->assign('CALENDAR_DATEFORMAT', $date_format); @@ -71,7 +75,7 @@ class QuickCreate extends EditView { $this->ss->assign('CALENDAR_FORMAT', $date_format . ' ' . $t23 . $time_separator . "%M" . $pm); } - + $this->ss->assign('CALENDAR_FDOW', $current_user->get_first_day_of_week()); } } -?> \ No newline at end of file +?> diff --git a/include/EditView/SubpanelQuickCreate.php b/include/EditView/SubpanelQuickCreate.php index 7cfeec6d..67b296dc 100644 --- a/include/EditView/SubpanelQuickCreate.php +++ b/include/EditView/SubpanelQuickCreate.php @@ -36,9 +36,13 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ require_once('include/EditView/EditView2.php'); +/** + * Quick create form in the subpanel + * @api + */ class SubpanelQuickCreate{ var $defaultProcess = true; - + function SubpanelQuickCreate($module, $view='QuickCreate', $proccessOverride = false){ //treat quickedit and quickcreate views as the same if($view == 'QuickEdit') {$view = 'QuickCreate';} @@ -78,34 +82,34 @@ class SubpanelQuickCreate{ $this->ev->defs['templateMeta']['form']['headerTpl'] = 'include/EditView/header.tpl'; $this->ev->defs['templateMeta']['form']['footerTpl'] = 'include/EditView/footer.tpl'; $this->ev->defs['templateMeta']['form']['buttons'] = array('SUBPANELSAVE', 'SUBPANELCANCEL', 'SUBPANELFULLFORM'); - + //Load the parent view class if it exists. Check for custom file first loadParentView('edit'); - + $viewEditSource = 'modules/'.$module.'/views/view.edit.php'; if (file_exists('custom/'. $viewEditSource)) { $viewEditSource = 'custom/'. $viewEditSource; } if(file_exists($viewEditSource) && !$proccessOverride) { - include($viewEditSource); + include($viewEditSource); $c = $module . 'ViewEdit'; $customClass = 'Custom' . $c; if(class_exists($customClass)) { $c = $customClass; } - + if(class_exists($c)) { $view = new $c; if($view->useForSubpanel) { $this->defaultProcess = false; - + //Check if we shold use the module's QuickCreate.tpl file if($view->useModuleQuickCreateTemplate && file_exists('modules/'.$module.'/tpls/QuickCreate.tpl')) { - $this->ev->defs['templateMeta']['form']['headerTpl'] = 'modules/'.$module.'/tpls/QuickCreate.tpl'; + $this->ev->defs['templateMeta']['form']['headerTpl'] = 'modules/'.$module.'/tpls/QuickCreate.tpl'; } - + $view->ev = & $this->ev; $view->ss = & $this->ev->ss; $class = $GLOBALS['beanList'][$module]; @@ -116,16 +120,16 @@ class SubpanelQuickCreate{ } $this->ev->formName = 'form_Subpanel'.$this->ev->view .'_'.$module; $view->showTitle = false; // Do not show title since this is for subpanel - $view->display(); + $view->display(); } } } //if - + if($this->defaultProcess && !$proccessOverride) { $this->process($module); } } - + function process($module){ $form_name = 'form_Subpanel'.$this->ev->view .'_'.$module; $this->ev->formName = $form_name; diff --git a/include/EditView/SubpanelQuickEdit.php b/include/EditView/SubpanelQuickEdit.php index 02ba5cc8..898f4926 100644 --- a/include/EditView/SubpanelQuickEdit.php +++ b/include/EditView/SubpanelQuickEdit.php @@ -38,9 +38,13 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/EditView/EditView2.php'); +/** + * Quick edit form in the subpanel + * @api + */ class SubpanelQuickEdit{ var $defaultProcess = true; - + function SubpanelQuickEdit($module, $view='QuickEdit', $proccessOverride = false){ //treat quickedit and quickcreate views as the same if($view == 'QuickEdit') {$view = 'QuickCreate';} @@ -93,26 +97,26 @@ class SubpanelQuickEdit{ $this->ev->defs['templateMeta']['form']['buttons'] = array('SUBPANELSAVE', 'SUBPANELCANCEL', 'SUBPANELFULLFORM'); $this->ev->defs['templateMeta']['form']['hideAudit'] = true; - + $viewEditSource = 'modules/'.$module.'/views/view.edit.php'; if (file_exists('custom/'. $viewEditSource)) { $viewEditSource = 'custom/'. $viewEditSource; } if(file_exists($viewEditSource) && !$proccessOverride) { - include($viewEditSource); + include($viewEditSource); $c = $module . 'ViewEdit'; - + if(class_exists($c)) { $view = new $c; if($view->useForSubpanel) { $this->defaultProcess = false; - + //Check if we shold use the module's QuickCreate.tpl file if($view->useModuleQuickCreateTemplate && file_exists('modules/'.$module.'/tpls/QuickCreate.tpl')) { - $this->ev->defs['templateMeta']['form']['headerTpl'] = 'modules/'.$module.'/tpls/QuickCreate.tpl'; + $this->ev->defs['templateMeta']['form']['headerTpl'] = 'modules/'.$module.'/tpls/QuickCreate.tpl'; } - + $view->ev = & $this->ev; $view->ss = & $this->ev->ss; $class = $GLOBALS['beanList'][$module]; @@ -123,16 +127,16 @@ class SubpanelQuickEdit{ } $this->ev->formName = 'form_Subpanel'.$this->ev->view .'_'.$module; $view->showTitle = false; // Do not show title since this is for subpanel - $view->display(); + $view->display(); } } } //if - + if($this->defaultProcess && !$proccessOverride) { $this->process($module); } } - + function process($module){ $form_name = 'form_Subpanel'.$this->ev->view .'_'.$module; $this->ev->formName = $form_name; diff --git a/include/EditView/SugarVCR.php b/include/EditView/SugarVCR.php index f48b31f0..83d71381 100644 --- a/include/EditView/SugarVCR.php +++ b/include/EditView/SugarVCR.php @@ -34,30 +34,27 @@ * "Powered by SugarCRM". ********************************************************************************/ -/* - * Created on Jul 24, 2007 - * - * To change the template for this generated file go to - * Window - Preferences - PHPeclipse - PHP - Code Templates - */ define('VCREND', '50'); define('VCRSTART', '10'); + /** + * @api + */ class SugarVCR{ - + /** * records the query in the session for later retrieval */ function store($module, $query){ $_SESSION[$module .'2_QUERY'] = $query; } - + /** * This function retrieves a query from the session */ function retrieve($module){ return (!empty($_SESSION[$module .'2_QUERY']) ? $_SESSION[$module .'2_QUERY'] : ''); } - + /** * return the start, prev, next, end */ @@ -78,7 +75,7 @@ } return $menu; } - + function menu($module, $offset, $isAuditEnabled, $saveAndContinue = false ){ $html_text = ""; if($offset < 0) { @@ -94,11 +91,11 @@ //$html_text .= "\n"; //$html_text .= ""; } return $html_text; } - + function record($module, $offset){ $GLOBALS['log']->debug('SUGARVCR is recording more records'); $start = max(0, $offset - VCRSTART); @@ -165,23 +168,23 @@ $_SESSION[$module.'QUERY_ARRAY'] = $ids; return $ids; } - + function recordIDs($module, $rids, $offset, $totalCount){ $index = $offset; $index++; $ids = array(); - foreach($rids as $id){ + foreach($rids as $id){ $ids[$index] = $id; - $index++; + $index++; } //now that we have the array of ids, store this in the session $_SESSION[$module.'QUERY_ARRAY'] = $ids; $_SESSION[$module.'total'] = $totalCount; } - + function erase($module){ unset($_SESSION[$module. 'QUERY_ARRAY']); } - + } ?> diff --git a/include/JSON.php b/include/JSON.php index 051140f1..497e6393 100644 --- a/include/JSON.php +++ b/include/JSON.php @@ -50,8 +50,8 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * * Note: We no longer eval our json so there is no more need for security envelopes. The parameter * has been left for backwards compatibility. + * @api */ - class JSON { @@ -61,7 +61,7 @@ class JSON * @param string $string * @param bool $addSecurityEnvelope defaults to false * @param bool $encodeSpecial - * @return string + * @return string */ public static function encode($string, $addSecurityEnvelope = false, $encodeSpecial = false) { @@ -75,7 +75,7 @@ class JSON $encodedString = str_replace($c, $enc, $encodedString); } } - + return $encodedString; } @@ -85,7 +85,7 @@ class JSON * @param string $string * @param bool $examineEnvelope Default false, true to extract and verify envelope * @param bool $assoc - * @return string + * @return string */ public static function decode($string, $examineEnvelope=false, $assoc = true) { @@ -99,7 +99,7 @@ class JSON { return self::encode($string); } - + /** * @deprecated use JSON::decode() instead */ diff --git a/include/ListView/ListView.php b/include/ListView/ListView.php index 9781019a..66181435 100644 --- a/include/ListView/ListView.php +++ b/include/ListView/ListView.php @@ -36,6 +36,10 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ require_once('include/EditView/SugarVCR.php'); +/** + * ListView - list of many objects + * @api + */ class ListView { var $local_theme= null; @@ -237,7 +241,7 @@ function process_dynamic_listview($source_module, $sugarbean,$subpanel_def) global $click_bg; $this->xTemplate->assign("BG_HILITE", $hilite_bg); - $this->xTemplate->assign('CHECKALL', "\"\""); + $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", '')); //$this->xTemplate->assign("BG_CLICK", $click_bg); $oddRow = true; $count = 0; @@ -324,7 +328,7 @@ function process_dynamic_listview($source_module, $sugarbean,$subpanel_def) } else { $this->xTemplate->assign('TAG_NAME','span'); } - $this->xTemplate->assign('CHECKALL', ""); + $this->xTemplate->assign('CHECKALL', ""); } if($oddRow) @@ -535,7 +539,7 @@ function getOrderBy($varName, $defaultOrderBy='', $force_sortorder='') { if($sortBy == 'amount_usdollar') { $sortBy = 'amount_usdollar*1'; } - + $desc = $this->getSessionVariable($varName, $sortBy."S"); if(empty($desc)) @@ -892,18 +896,18 @@ function getUserVariable($localVarName, $varName) { } else { $this->query_orderby = 'id'; } - + $this->getOrderBy($html_var,$this->query_orderby, $this->sort_order); $_SESSION['last_sub' .$this->subpanel_module. '_order'] = $this->sort_order; $_SESSION['last_sub' .$this->subpanel_module. '_url'] = $this->getBaseURL($html_var); // Bug 8139 - Correct Subpanel sorting on 'name', when subpanel sorting default is 'last_name, first_name' - if (($this->sortby == 'name' || $this->sortby == 'last_name') && + if (($this->sortby == 'name' || $this->sortby == 'last_name') && str_replace(' ', '', trim($subpanel_def->_instance_properties['sort_by'])) == 'last_name,first_name') { $this->sortby = 'last_name '.$this->sort_order.', first_name '; } - + if(!empty($this->response)){ $response =& $this->response; echo 'cached'; @@ -993,6 +997,7 @@ function getUserVariable($localVarName, $varName) { global $sugar_config; global $current_user; global $currentModule; + global $app_strings; $start_record = $current_offset + 1; @@ -1058,15 +1063,15 @@ function getUserVariable($localVarName, $varName) { $GLOBALS['log']->debug("Offsets: (start, previous, next, last)(0, $previous_offset, $next_offset, $last_offset)"); if(0 == $current_offset) { - $start_link = ""; - $previous_link = ""; + $start_link = ""; + $previous_link = ""; } else { if($this->multi_select_popup) {// nav links for multiselect popup, submit form to save checks. - $start_link = ""; - $previous_link = ""; + $start_link = ""; + $previous_link = ""; } elseif($this->shouldProcess) { - $start_link = ""; - $previous_link = ""; + $start_link = ""; + $previous_link = ""; } else { $onClick = ''; if(0 != preg_match('/javascript.*/', $start_URL)){ @@ -1074,7 +1079,7 @@ function getUserVariable($localVarName, $varName) { }else{ $onClick ="'location.href=\"$start_URL\";'"; } - $start_link = ""; + $start_link = ""; $onClick = ''; if(0 != preg_match('/javascript.*/', $previous_URL)){ @@ -1082,23 +1087,23 @@ function getUserVariable($localVarName, $varName) { }else{ $onClick = "'location.href=\"$previous_URL\";'"; } - $previous_link = ""; + $previous_link = ""; } } if($last_offset <= $current_offset) { - $end_link = ""; - $next_link = ""; + $end_link = ""; + $next_link = ""; } else { if($this->multi_select_popup) { // nav links for multiselect popup, submit form to save checks. - $end_link = ""; + $end_link = ""; if(!empty($sugar_config['disable_count_query'])) { $end_link = ''; } - $next_link = ""; + $next_link = ""; } elseif($this->shouldProcess) { - $end_link = ""; - $next_link = ""; + $end_link = ""; + $next_link = ""; } else { $onClick = ''; if(0 != preg_match('/javascript.*/', $next_URL)){ @@ -1106,7 +1111,7 @@ function getUserVariable($localVarName, $varName) { }else{ $onClick ="'location.href=\"$next_URL\";'"; } - $next_link = ""; + $next_link = ""; $onClick = ''; if(0 != preg_match('/javascript.*/', $end_URL)){ @@ -1114,7 +1119,7 @@ function getUserVariable($localVarName, $varName) { }else{ $onClick = "'location.href=\"$end_URL\";'"; } - $end_link = ""; + $end_link = ""; } } @@ -1124,38 +1129,32 @@ function getUserVariable($localVarName, $varName) { $end_record = $end_record-1; +$script_href = "records_per_page)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']} ({$this->records_per_page})‎" + . "{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']} ({$row_count})‎" + . "{$this->local_app_strings['LBL_LISTVIEW_NONE']}"; + +$close_inline_img = SugarThemeRegistry::current()->getImage('close_inline', 'border=0', null, null, ".gif", $app_strings['LBL_CLOSEINLINE']); + echo ""; - if($this->show_select_menu) { - $select_link = "".$this->local_app_strings['LBL_LINK_SELECT']." ".""; + if($this->show_select_menu) + { + $select_link = "".$this->local_app_strings['LBL_LINK_SELECT']." ".SugarThemeRegistry::current()->getImage('MoreDetail', 'border=0', 11, 7, '.png', $app_strings['LBL_MOREDETAIL']).""; } else { $select_link = " "; } // put overlib strings into functions to avoid backslash plague! - /*echo ""; - */ - //$export_link = "".SugarThemeRegistry::current()->getImage("export","alt='".$this->local_app_strings['LBL_EXPORT']."' border='0' align='absmiddle'")." ".$this->local_app_strings['LBL_EXPORT'].""; $export_link = ''; @@ -1176,7 +1175,7 @@ function getUserVariable($localVarName, $varName) { . "{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']}" . "{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']}" . "', CAPTION, '" . $this->local_app_strings['LBL_MAILMERGE'] - . "', STICKY, MOUSEOFF, 3000, CLOSETEXT, '', WIDTH, 150, CLOSETITLE, '" . $this->local_app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE'] . "', CLOSECLICK, FGCLASS, 'olOptionsFgClass', " . "CGCLASS, 'olOptionsCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olOptionsCapFontClass', CLOSEFONTCLASS, 'olCloseFontClass'); } @@ -1216,7 +1215,7 @@ function getUserVariable($localVarName, $varName) { } $html_text = ''; - $html_text .= "\n"; + $html_text .= "\n"; $html_text .= "
+ {{if isset($colData.field.customLabel)}} - {{$colData.field.customLabel}} + {{elseif isset($colData.field.label)}} {capture name="label" assign="label"}{sugar_translate label='{{$colData.field.label}}' module='{{$module}}'}{/capture} - {$label|strip_semicolon}: + {{elseif isset($fields[$colData.field.name])}} {capture name="label" assign="label"}{sugar_translate label='{{$fields[$colData.field.name].vname}}' module='{{$module}}'}{/capture} - {$label|strip_semicolon}: + + {{else}} +   {{/if}} {{* Show the required symbol if field is required, but override not set. Or show if override is set *}} {{if ($fields[$colData.field.name].required && (!isset($colData.field.displayParams.required) || $colData.field.displayParams.required)) || @@ -134,18 +141,30 @@ class="yui-navset" {capture name="overlibStuff" assign="overlibStuff"}{overlib_includes}{/capture} {sugar_help text=$popupText WIDTH=-1} {{/if}} - + {{if !empty($def.templateMeta.labelsOnTop)}} {{if isset($colData.field.label)}} {{if !empty($colData.field.label)}} - {sugar_translate label='{{$colData.field.label}}' module='{{$module}}'}: + {{/if}} {{elseif isset($fields[$colData.field.name])}} - {sugar_translate label='{{$fields[$colData.field.name].vname}}' module='{{$module}}'}: + {{/if}} {{* Show the required symbol if field is required, but override not set. Or show if override is set *}} @@ -163,17 +182,21 @@ class="yui-navset" {{foreach from=$colData.field.fields item=subField}} {{if $fields[$subField.name]}} {counter name="panelFieldCount"} - {{sugar_field parentFieldArray='fields' tabindex=$colData.field.tabindex vardef=$fields[$subField.name] displayType='EditView' displayParams=$subField.displayParams formName=$form_name}}  + {{sugar_field parentFieldArray='fields' tabindex=$tabindex vardef=$fields[$subField.name] displayType='EditView' displayParams=$subField.displayParams formName=$form_name}}  {{/if}} {{/foreach}} - {{elseif !empty($colData.field.customCode)}} + {{elseif !empty($colData.field.customCode) && empty($colData.field.customCodeRenderField)}} {counter name="panelFieldCount"} - {{sugar_evalcolumn var=$colData.field.customCode colData=$colData tabindex=$colData.field.tabindex}} + {{sugar_evalcolumn var=$colData.field.customCode colData=$colData tabindex=$tabindex}} {{elseif $fields[$colData.field.name]}} {counter name="panelFieldCount"} {{$colData.displayParams}} - {{sugar_field parentFieldArray='fields' tabindex=$colData.field.tabindex vardef=$fields[$colData.field.name] displayType='EditView' displayParams=$colData.field.displayParams typeOverride=$colData.field.type formName=$form_name}} + {{sugar_field parentFieldArray='fields' tabindex=$tabindex vardef=$fields[$colData.field.name] displayType='EditView' displayParams=$colData.field.displayParams typeOverride=$colData.field.type formName=$form_name}} {{/if}} + {{if !empty($colData.field.customCode) && !empty($colData.field.customCodeRenderField)}} + {counter name="panelFieldCount"} + {{sugar_evalcolumn var=$colData.field.customCode colData=$colData tabindex=$tabindex}} + {{/if}} {{if !empty($colData.field.hideIf)}} {else}
\n"; $html_text .= "\n"; - + $list_URL = 'index.php?action=index&module='.$module; $current_page = floor($offset / 20) * 20; $list_URL .= '&offset='.$current_page; - + $menu = SugarVCR::play($module, $offset); if($saveAndContinue){ if(!empty($menu['NEXT'])){ @@ -110,28 +107,34 @@ $list_link = ""; }else $list_link = ""; - + $previous_link = ""; $next_link = ""; if(!empty($menu['PREV'])) { - //$previous_link = "".SugarThemeRegistry::current()->getImage("previous","alt='".$GLOBALS['app_strings']['LNK_LIST_PREVIOUS']."' border='0' align='absmiddle'").' '.$GLOBALS['app_strings']['LNK_LIST_PREVIOUS'].""; + //$previous_link = "".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$GLOBALS['app_strings']['LNK_LIST_PREVIOUS']).' '.$GLOBALS['app_strings']['LNK_LIST_PREVIOUS'].""; + $href = ajaxLink("index.php?module=$module&action=$action&offset=".($offset-1)."&record=".$menu['PREV']); - $previous_link = ""; + $previous_link = ""; + } - else - $previous_link = ""; + else + $previous_link = ""; + if(!empty($menu['NEXT'])) { - //$next_link = "".$GLOBALS['app_strings']['LNK_LIST_NEXT'].' '.SugarThemeRegistry::current()->getImage("next","alt='".$GLOBALS['app_strings']['LNK_LIST_NEXT']."' border='0' align='absmiddle'").""; + //$next_link = "".$GLOBALS['app_strings']['LNK_LIST_NEXT'].' '.SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$GLOBALS['app_strings']['LNK_LIST_NEXT']).""; + $href = ajaxLink("index.php?module=$module&action=$action&offset=".($offset+1)."&record=".$menu['NEXT']); - $next_link = ""; + $next_link = ""; + } else - $next_link = ""; - + $next_link = ""; + + if(!empty($_SESSION[$module. 'total'])){ $count = $offset .' '. $GLOBALS['app_strings']['LBL_LIST_OF'] . ' ' . $_SESSION[$module. 'total']; - if(!empty($GLOBALS['sugar_config']['disable_count_query']) + if(!empty($GLOBALS['sugar_config']['disable_count_query']) && ( ($_SESSION[$module. 'total']-1) % $GLOBALS['sugar_config']['list_max_entries_per_page'] == 0 ) ) { $count .= '+'; } @@ -139,14 +142,14 @@ $count = $offset; } $html_text .= ""; - - - + + + $html_text .= "
".$list_link."    ".$previous_link."  (".$count.")  ".$next_link."  
";//
diff --git a/include/ListView/ListViewData.php b/include/ListView/ListViewData.php index f2094523..4787570c 100644 --- a/include/ListView/ListViewData.php +++ b/include/ListView/ListViewData.php @@ -37,7 +37,12 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/EditView/SugarVCR.php'); +/** + * Data set for ListView + * @api + */ class ListViewData { + var $additionalDetails = true; var $listviewName = null; var $additionalDetailsAllow = null; @@ -72,16 +77,6 @@ class ListViewData { $orderBy = $_REQUEST[$this->var_order_by]; if(!empty($_REQUEST['lvso']) && (empty($_SESSION['lvd']['last_ob']) || strcmp($orderBy, $_SESSION['lvd']['last_ob']) == 0) ){ $direction = $_REQUEST['lvso']; - - $trackerManager = TrackerManager::getInstance(); - if($monitor = $trackerManager->getMonitor('tracker')){ - $monitor->setValue('module_name', $GLOBALS['module']); - $monitor->setValue('item_summary', "lvso=".$direction."&".$this->var_order_by."=".$_REQUEST[$this->var_order_by]); - $monitor->setValue('action', 'listview'); - $monitor->setValue('user_id', $GLOBALS['current_user']->id); - $monitor->setValue('date_modified', TimeDate::getInstance()->nowDb()); - $monitor->save(); - } } } $_SESSION[$this->var_order_by] = array('orderBy'=>$orderBy, 'direction'=> $direction); @@ -291,11 +286,11 @@ class ListViewData { if (isset($params['custom_order_by_override']['ori_code']) && $order['orderBy'] == $params['custom_order_by_override']['ori_code']) $orderBy = $params['custom_order_by_override']['custom_code'] . ' ' . $order['sortOrder']; } - + if (empty($params['skipOrderSave'])) { // don't save preferences if told so $current_user->setPreference('listviewOrder', $order, 0, $this->var_name); // save preference } - + // If $params tells us to override for the special last_name, first_name sorting if (!empty($params['overrideLastNameOrder']) && $order['orderBy'] == 'last_name') { $orderBy = 'last_name '.$order['sortOrder'].', first_name '.$order['sortOrder']; @@ -358,7 +353,7 @@ class ListViewData { $id_list .= '\''.$row[$id_field].'\''; //handles date formating and such $idIndex[$row[$id_field]][] = count($rows); - $rows[] = $row; + $rows[] = $seed->convertRow($row); } $count++; } @@ -522,7 +517,7 @@ class ListViewData { $extra = ""; + . "onmouseout=\"return nd(1000);\" style='position: relative;'>".$app_strings["; return array('fieldToAddTo' => $this->additionalDetailsFieldToAdd, 'string' => $extra); } @@ -538,40 +533,62 @@ class ListViewData { function getAdditionalDetails($fields, $adFunction, $editAccess) { global $app_strings; + global $mod_strings; + + $results = $adFunction($fields); + + $results['string'] = str_replace(array("'", "'"), '\'', $results['string']); // no xss! + + if(trim($results['string']) == '') + { + $results['string'] = $app_strings['LBL_NONE']; + } + + $extra = "'), $results['string']) + . "', CAPTION, '
{$app_strings['LBL_ADDITIONAL_DETAILS']}
"; + + if($editAccess && !empty($results['editLink'])) + { + $extra .= "getImageURL('edit_inline.gif')."\'>"; + } + + $extra .= (!empty($results['viewLink']) ? "" : '') + . "', DELAY, 200, STICKY, MOUSEOFF, 1000, WIDTH, " + . (empty($results['width']) ? '300' : $results['width']) + . ", CLOSETEXT, '\'{$app_strings['LBL_CLOSEINLINE']}\'
', " + . "CLOSETITLE, '{$app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE']}', CLOSECLICK, FGCLASS, 'olFgClass', " + . "CGCLASS, 'olCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olCapFontClass', CLOSEFONTCLASS, 'olCloseFontClass');\" " + . "onmouseout=\"return nd(1000);\">\'{$app_strings['LBL_INFOINLINE']}\'
"; + $results = $adFunction($fields); + $results['string'] = str_replace(array("'", "'"), '\'', $results['string']); // no xss! - if(trim($results['string']) == '') $results['string'] = $app_strings['LBL_NONE']; + if(trim($results['string']) == '') + { + $results['string'] = $app_strings['LBL_NONE']; + } + $extra = "'), $results['string']) . "', CAPTION, '
{$app_strings['LBL_ADDITIONAL_DETAILS']}
"; - if($editAccess) $extra .= (!empty($results['editLink']) ? "" : ''); - $extra .= (!empty($results['viewLink']) ? "" : '') + + if($editAccess && !empty($results['editLink'])) + { + $extra .= "getImageURL('edit_inline.gif')."\'>"; + } + + $extra .= (!empty($results['viewLink']) ? "" : '') . "', DELAY, 200, STICKY, MOUSEOFF, 1000, WIDTH, " . (empty($results['width']) ? '300' : $results['width']) - . ", CLOSETEXT, '
', " + . ", CLOSETEXT, '\'{$app_strings['LBL_CLOSEINLINE']}\'
', " . "CLOSETITLE, '{$app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE']}', CLOSECLICK, FGCLASS, 'olFgClass', " . "CGCLASS, 'olCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olCapFontClass', CLOSEFONTCLASS, 'olCloseFontClass');\" " - . "onmouseout=\"return nd(1000);\">"; - - $results = $adFunction($fields); - $results['string'] = str_replace(array("'", "'"), '\'', $results['string']); // no xss! - - if(trim($results['string']) == '') $results['string'] = $app_strings['LBL_NONE']; - $extra = "'), $results['string']) - . "', CAPTION, '
{$app_strings['LBL_ADDITIONAL_DETAILS']}
"; - if($editAccess) $extra .= (!empty($results['editLink']) ? "" : ''); - $extra .= (!empty($results['viewLink']) ? "" : '') - . "', DELAY, 200, STICKY, MOUSEOFF, 1000, WIDTH, " - . (empty($results['width']) ? '300' : $results['width']) - . ", CLOSETEXT, '
', " - . "CLOSETITLE, '{$app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE']}', CLOSECLICK, FGCLASS, 'olFgClass', " - . "CGCLASS, 'olCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olCapFontClass', CLOSEFONTCLASS, 'olCloseFontClass');\" " - . "onmouseout=\"return nd(1000);\">
"; - - return array('fieldToAddTo' => $results['fieldToAddTo'], 'string' => $extra); + . "onmouseout=\"return nd(1000);\">{$app_strings["; + + return array('fieldToAddTo' => $results['fieldToAddTo'], 'string' => $extra); } -} +} \ No newline at end of file diff --git a/include/ListView/ListViewDisplay.php b/include/ListView/ListViewDisplay.php index bd559c49..3930d75b 100644 --- a/include/ListView/ListViewDisplay.php +++ b/include/ListView/ListViewDisplay.php @@ -280,22 +280,28 @@ class ListViewDisplay { $plus = '+'; $this->show_plus = true; } - $script = ""; - $script .= "".""; + + + $close_inline_img = SugarThemeRegistry::current()->getImage('close_inline', 'border=0', null, null, ".gif", $app_strings['LBL_CLOSEINLINE']); + $script_href = "{$app_strings['LBL_LISTVIEW_OPTION_CURRENT']} ({$pageTotal})‎" + . "{$app_strings['LBL_LISTVIEW_OPTION_ENTIRE']} ({$total})‎" + . "{$app_strings['LBL_LISTVIEW_NONE']}"; + + $script = << +function select_overlib() { + return overlib('{$script_href}', CENTER, STICKY, MOUSEOFF, 3000, CLOSETEXT, '{$close_inline_img}', WIDTH, 150, CLOSETITLE, "{$app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE']}" , CLOSECLICK, FGCLASS, 'olOptionsFgClass', CGCLASS, 'olOptionsCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olOptionsCapFontClass', CLOSEFONTCLASS, 'olOptionsCloseFontClass',TIMEOUT,1000); +} + +EOHTML; + $script .= "".SugarThemeRegistry::current()->getImage('MoreDetail', 'border=0', null, null, '.png', $app_strings['LBL_MOREDETAIL']).""; return $script; } + + + /** * Display the actions link * @@ -307,7 +313,7 @@ class ListViewDisplay { ) { global $app_strings; - $closeText = ""; + $closeText = SugarThemeRegistry::current()->getImage('close_inline', 'border=0', null, null, ".gif", $app_strings['LBL_CLOSEINLINE']); $moreDetailImage = SugarThemeRegistry::current()->getImageURL('MoreDetail.png'); $menuItems = ''; @@ -344,19 +350,57 @@ class ListViewDisplay { return ''; return << + {$app_strings['LBL_LINK_ACTIONS']}  + - - {$app_strings['LBL_LINK_ACTIONS']}  - EOHTML; } diff --git a/include/ListView/ListViewGeneric.tpl b/include/ListView/ListViewGeneric.tpl index 605930e4..8ef82859 100644 --- a/include/ListView/ListViewGeneric.tpl +++ b/include/ListView/ListViewGeneric.tpl @@ -43,8 +43,8 @@ {if $overlib} - - + + {/if} {$multiSelectData} @@ -53,15 +53,15 @@ {include file='include/ListView/ListViewPagination.tpl'} {if $prerow} - +
- + {$selectLink}
- + {/if} {if !empty($quickViewLinks)} -   +   {/if} {counter start=0 name="colCounter" print=false assign="colCounter"} {foreach from=$displayColumns key=colHeader item=params} @@ -78,19 +78,23 @@ {/if} {/if} {sugar_translate label=$params.label module=$pageData.bean.moduleDir} -    +    {if $params.orderBy|default:$colHeader|lower == $pageData.ordering.orderBy} {if $pageData.ordering.sortOrder == 'ASC'} {capture assign="imageName"}arrow_down.{$arrowExt}{/capture} - {$arrowAlt} + {capture assign="alt_sort"}{sugar_translate label='LBL_ALT_SORT_DESC'}{/capture} + {sugar_getimage name=$imageName attr='align="absmiddle" border="0" ' alt="$alt_sort"} {else} {capture assign="imageName"}arrow_up.{$arrowExt}{/capture} - {$arrowAlt} + {capture assign="alt_sort"}{sugar_translate label='LBL_ALT_SORT_ASC'}{/capture} + {sugar_getimage name=$imageName attr='align="absmiddle" border="0" ' alt="$alt_sort"} {/if} {else} {capture assign="imageName"}arrow.{$arrowExt}{/capture} - {$arrowAlt} + {capture assign="alt_sort"}{sugar_translate label='LBL_ALT_SORT'}{/capture} + {sugar_getimage name=$imageName attr='align="absmiddle" border="0" ' alt="$alt_sort"} {/if} + {else} {if !isset($params.noHeader) || $params.noHeader == false} {sugar_translate label=$params.label module=$pageData.bean.moduleDir} @@ -100,12 +104,13 @@ {counter name="colCounter"} {/foreach} -   +   {counter start=$pageData.offsets.current print=false assign="offset" name="offset"} {foreach name=rowIteration from=$data key=id item=rowData} {counter name="offset" print=false} + {assign var='scope_row' value=true} {if $smarty.foreach.rowIteration.iteration is odd} {assign var='_rowColor' value=$rowColor[0]} @@ -118,7 +123,7 @@ {if !$is_admin && is_admin_for_user && $rowData.IS_ADMIN==1} {else} - + {/if} {/if} @@ -130,14 +135,16 @@ - + {capture name='tmp1' assign='alt_edit'}{sugar_translate label="LNK_EDIT"}{/capture} + {sugar_getimage name="edit_inline.gif" attr='border="0" ' alt="$alt_edit"} {/if} + {/if} {counter start=0 name="colCounter" print=false assign="colCounter"} {foreach from=$displayColumns key=col item=params} {strip} - + {if $col == 'NAME' || $params.bold}{/if} {if $params.link && !$params.customCode} {capture assign=linkModule}{if $params.dynamic_module}{$rowData[$params.dynamic_module]}{else}{$params.module|default:$pageData.bean.moduleDir}{/if}{/capture} @@ -159,6 +166,7 @@ href="index.php?module={$linkModule}&offset={$offset}&stamp={$pageData.stamp}&re {if $col == 'NAME' || $params.bold}{/if} {/strip} + {assign var='scope_row' value=false} {counter name="colCounter"} {/foreach} {$pageData.additionalDetails.$id} diff --git a/include/ListView/ListViewNoMassUpdate.tpl b/include/ListView/ListViewNoMassUpdate.tpl index 59227ef1..6a7cf85a 100644 --- a/include/ListView/ListViewNoMassUpdate.tpl +++ b/include/ListView/ListViewNoMassUpdate.tpl @@ -41,9 +41,8 @@ *} {if $overlib} - - - + + {/if} @@ -58,19 +57,23 @@ {/if} diff --git a/include/ListView/ListViewPagination.tpl b/include/ListView/ListViewPagination.tpl index 1c7bf86c..39e1f4d3 100644 --- a/include/ListView/ListViewPagination.tpl +++ b/include/ListView/ListViewPagination.tpl @@ -38,7 +38,13 @@ *} - + +{assign var="alt_start" value=$navStrings.start} +{assign var="alt_next" value=$navStrings.next} +{assign var="alt_prev" value=$navStrings.previous} +{assign var="alt_end" value=$navStrings.end} + +
{if $params.sortable|default:true} - {sugar_translate label=$params.label module=$pageData.bean.moduleDir}   + {sugar_translate label=$params.label module=$pageData.bean.moduleDir}   {if $params.orderBy|default:$colHeader|lower == $pageData.ordering.orderBy} {if $pageData.ordering.sortOrder == 'ASC'} - {capture assign="imageName"}arrow_down.{$arrowExt}{/capture} - {$arrowAlt} + {capture assign="imageName"}arrow_down.$arrowExt{/capture} + {capture assign="alt_sort"}{sugar_translate label='LBL_ALT_SORT_DESC'}{/capture} + {sugar_getimage name=$imageName width=$arrowWidth height=$arrowHeight attr='align="absmiddle" border="0" ' alt="$alt_sort"} {else} - {capture assign="imageName"}arrow_up.{$arrowExt}{/capture} - {$arrowAlt} + {capture assign="imageName"}arrow_up.$arrowExt{/capture} + {capture assign="alt_sort"}{sugar_translate label='LBL_ALT_SORT_ASC'}{/capture} + {sugar_getimage name=$imageName width=$arrowWidth height=$arrowHeight attr='align="absmiddle" border="0" ' alt="$alt_sort"} {/if} {else} - {capture assign="imageName"}arrow.{$arrowExt}{/capture} - {$arrowAlt} + {capture assign="imageName"}arrow.$arrowExt{/capture} + {capture assign="alt_sort"}{sugar_translate label='LBL_ALT_SORT'}{/capture} + {sugar_getimage name=$imageName width=$arrowWidth height=$arrowHeight attr='align="absmiddle" border="0" ' alt="$alt_sort"} {/if} + {else} {sugar_translate label=$params.label module=$pageData.bean.moduleDir} {/if} @@ -90,7 +93,7 @@ {if !empty($quickViewLinks)}
{if $pageData.access.edit && $pageData.bean.moduleDir != "Employees"} - + {sugar_getimage name="edit_inline.gif" attr='border="0" '} {/if}
';} -function OLwd(a){return(o3_wrap?'':' width="'+(!a?'100%':(a==1?o3_width:(o3_width-o3_padxl-o3_padxr)))+'"');} -function OLsetBackground(i){if(i==''){if(OLns4)over.background.src=null;else{if(OLns6)over.style.width='';over.style.backgroundImage='none';}}else{if(OLns4)over.background.src=i;else{if(OLns6)over.style.width=o3_width+'px';over.style.backgroundImage='url('+i+')';}}} -function OLdisp(s){if(!OLallowmove){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();OLplaceLayer();if(OLndt)OLshowObject(over);else OLshowid=setTimeout("OLshowObject(over)",1);OLallowmove=(o3_sticky||o3_nofollow)?0:1;}OLndt=0;if(s!="")self.status=s;} -function OLplaceLayer(){var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0,o=OLfd(),nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;if(!OLkht&&o&&o.clientWidth)iWd=o.clientWidth;else if(o3_frame.innerWidth){SB=Math.ceil(1.4*(o3_frame.outerWidth-o3_frame.innerWidth));if(SB>20)SB=20;iWd=o3_frame.innerWidth;} -pgLeft=(OLie4)?o.scrollLeft:o3_frame.pageXOffset;if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)SB=CX=5;else -if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){SB+=((o3_shadowx>0)?o3_shadowx:0);LM=((o3_shadowx<0)?Math.abs(o3_shadowx):0);CX=Math.abs(o3_shadowx);} -if(o3_ref!=""||o3_fixx>-1||o3_relx!=null||o3_midx!=null){if(o3_ref!=""){X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){if(o3_refp=='UR'||o3_refp=='LR')X-=5;} -else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X-=o3_shadowx;else -if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X-=o3_shadowx;}}else{if(o3_midx!=null){X=parseInt(pgLeft+((iWd-pWd-SB-LM)/2)+o3_midx);}else{if(o3_relx!=null){if(o3_relx>=0)X=pgLeft+o3_relx+LM;else X=pgLeft+o3_relx+iWd-pWd-SB;}else{X=o3_fixx+LM;}}}}else{if(o3_hauto){if(o3_hpos==LEFT&&OLx-pgLeftiWd/2&&OLx+pWd+o3_offsetx>pgLeft+iWd-SB)o3_hpos=LEFT;} -X=(o3_hpos==CENTER)?parseInt(OLx-((pWd+CX)/2)+o3_offsetx):(o3_hpos==LEFT)?OLx-o3_offsetx-pWd:OLx+o3_offsetx;if(o3_snapx>1){snp=X%o3_snapx;if(o3_hpos==LEFT){X=X-(o3_snapx+snp);}else{X=X+(o3_snapx-snp);}}} -if(!o3_nojustx&&X+pWd>pgLeft+iWd-SB) -X=iWd+pgLeft-pWd-SB;if(!o3_nojustx&&X-LM0)?o3_shadowy:0;CY=Math.abs(o3_shadowy);} -if(o3_ref!=""||o3_fixy>-1||o3_rely!=null||o3_midy!=null){if(o3_ref!=""){Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){if(o3_refp=='LL'||o3_refp=='LR')Y-=5;}else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y-=o3_shadowy;else -if(o3_shadowy>0&&(o3_refp=='LL'||o3_refp=='LR'))Y-=o3_shadowy;}}else{if(o3_midy!=null){Y=parseInt(pgTop+((iHt-pHt-CY)/2)+o3_midy);}else{if(o3_rely!=null){if(o3_rely>=0)Y=pgTop+o3_rely+TM;else Y=pgTop+o3_rely+iHt-pHt-BM;}else{Y=o3_fixy+TM;}}}}else{if(o3_vauto){if(o3_vpos==ABOVE&&OLy-pgTopiHt/2&&OLy+pHt+o3_offsety+((OLns4||OLkht)?17:0)>pgTop+iHt-BM) -o3_vpos=ABOVE;}Y=(o3_vpos==VCENTER)?parseInt(OLy-((pHt+CY)/2)+o3_offsety):(o3_vpos==ABOVE)?OLy-(pHt+o3_offsety+BM):OLy+o3_offsety+TM;if(o3_snapy>1){snp=Y%o3_snapy;if(pHt>0&&o3_vpos==ABOVE){Y=Y-(o3_snapy+snp);}else{Y=Y+(o3_snapy-snp);}}} -if(!o3_nojusty&&Y+pHt+BM>pgTop+iHt)Y=pgTop+iHt-pHt-BM;if(!o3_nojusty&&Y-TM1){ob=o[0];rXY[0]+=o[0].x+o[1].pageX;rXY[1]+=o[0].y+o[1].pageY;}else{if((o.toString().indexOf('Image')!=-1)||(o.toString().indexOf('Anchor')!=-1)){rXY[0]+=o.x;rXY[1]+=o.y;}else{rXY[0]+=o.pageX;rXY[1]+=o.pageY;}}}else{rXY[0]+=OLpageLoc(o,'Left');rXY[1]+=OLpageLoc(o,'Top');} -of=OLgetRefOffsets(ob);rXY[0]+=of[0];rXY[1]+=of[1];return rXY;} -function OLgetRef(l){var r=OLgetRefById(l);return(r)?r:OLgetRefByName(l);} -function OLgetRefById(l,d){var r="",j;l=(l||'overDiv');d=(d||o3_frame.document);if(d.getElementById){return d.getElementById(l);}else if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];for(j=0;j0){for(j=0;j0)return r;else if(r)return[r,d.layers[j]];}} -return null;} -function OLgetRefOffsets(o){var c=o3_refc.toUpperCase(),p=o3_refp.toUpperCase(),W=0,H=0,pW=0,pH=0,of=[0,0];pW=(OLbubblePI&&o3_bubble)?o3_width:OLns4?over.clip.width:over.offsetWidth;pH=(OLbubblePI&&o3_bubble)?OLbubbleHt:OLns4?over.clip.height:over.offsetHeight;if((!OLop7)&&o.toString().indexOf('Image')!=-1){W=o.width;H=o.height;}else if((!OLop7)&&o.toString().indexOf('Anchor')!=-1){c=o3_refc='UL';}else{W=(OLns4)?o.clip.width:o.offsetWidth;H=(OLns4)?o.clip.height:o.offsetHeight;} -if((OLns4||(OLns6&&OLgek))&&o.border){W+=2*parseInt(o.border);H+=2*parseInt(o.border);} -if(c=='UL'){of=(p=='UR')?[-pW,0]:(p=='LL')?[0,-pH]:(p=='LR')?[-pW,-pH]:[0,0];}else if(c=='UR'){of=(p=='UR')?[W-pW,0]:(p=='LL')?[W,-pH]:(p=='LR')?[W-pW,-pH]:[W,0];}else if(c=='LL'){of=(p=='UR')?[-pW,H]:(p=='LL')?[0,H-pH]:(p=='LR')?[-pW,H-pH]:[0,H];}else if(c=='LR'){of=(p=='UR')?[W-pW,H]:(p=='LL')?[W,H-pH]:(p=='LR')?[W-pW,H-pH]:[W,H];} -return of;} -function OLpageLoc(o,t){var l=0;while(o.offsetParent&&o.offsetParent.tagName.toLowerCase()!='html'){l+=o['offset'+t];o=o.offsetParent;}l+=o['offset'+t];return l;} -function OLmouseMove(e){var e=(e||event);OLcC=(OLovertwoPI&&over2&&over==over2?cClick2:cClick);OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);if((OLallowmove&&over)&&(o3_frame==self||over==OLgetRefById())){OLplaceLayer();if(OLhidePI)OLhideUtil(0,1,1,0,0,0);} -if(OLhover&&over&&o3_frame==self&&OLcursorOff())if(o3_offdelay<1)OLcC();else -{if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("OLcC()",o3_offdelay);}} -function OLmh(){var fN,f,j,k,s,mh=OLmouseMove,w=(OLns4&&window.onmousemove),re=/function[ ]*(\w*)\(/;OLdw=document;if(document.onmousemove||w){if(w)OLdw=window;f=OLdw.onmousemove.toString();fN=f.match(re);if(!fN||fN[1]=='anonymous'||fN[1]=='OLmouseMove'){OLchkMh=0;return;} -if(fN[1])s=fN[1]+'(e)';else{j=f.indexOf('{');k=f.lastIndexOf('}')+1;s=f.substring(j,k);} -s+=';OLmouseMove(e);';mh=new Function('e',s);} -OLdw.onmousemove=mh;if(OLns4)OLdw.captureEvents(Event.MOUSEMOVE);} -function OLparseTokens(pf,ar){var i,v,md=-1,par=(pf!='ol_'),p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);for(i=0;i=0)?1:0');} -function OLhasDims(s){return /[%\-a-z]+$/.test(s);} -function OLfontSize(){var i;if(OLhasDims(o3_textsize)){if(OLns4)o3_textsize="2";}else -if(!OLns4){i=parseInt(o3_textsize);o3_textsize=(i>0&&i<8)?OLpct[i]:OLpct[0];} -if(OLhasDims(o3_captionsize)){if(OLns4)o3_captionsize="2";}else -if(!OLns4){i=parseInt(o3_captionsize);o3_captionsize=(i>0&&i<8)?OLpct[i]:OLpct[0];} -if(OLhasDims(o3_closesize)){if(OLns4)o3_closesize="2";}else -if(!OLns4){i=parseInt(o3_closesize);o3_closesize=(i>0&&i<8)?OLpct[i]:OLpct[0];} -if(OLprintPI)OLprintDims();} -function OLdecode(){var re=/%[0-9A-Fa-f]{2,}/,t=o3_text,c=o3_cap,u=unescape,d=!OLns4&&(!OLgek||OLgek>=20020826)&&typeof decodeURIComponent?decodeURIComponent:u;if(typeof(window.TypeError)=='function'){if(re.test(t)){eval(new Array('try{','o3_text=d(t);','}catch(e){','o3_text=u(t);','}').join('\n'))};if(c&&re.test(c)){eval(new Array('try{','o3_cap=d(c);','}catch(e){','o3_cap=u(c);','}').join('\n'))}}else{if(re.test(t))o3_text=u(t);if(c&&re.test(c))o3_cap=u(c);}} -function OLlayerWrite(t){t+="\n";if(OLns4){over.document.write(t);over.document.close();}else if(typeof over.innerHTML!='undefined'){if(OLieM)over.innerHTML='';over.innerHTML=t;}else{range=o3_frame.document.createRange();range.setStartAfter(over);domfrag=range.createContextualFragment(t);while(over.hasChildNodes()){over.removeChild(over.lastChild);} -over.appendChild(domfrag);} -if(OLprintPI)over.print=o3_print?t:null;} -function OLshowObject(o){OLshowid=0;o=(OLns4)?o:o.style;if(((OLfilterPI)&&!OLchkFilter(o))||!OLfilterPI) -{o.visibility="visible";nd(2000);} -if(OLshadowPI) -{OLshowShadow();} -if(OLiframePI) -{OLshowIfs();} -if(OLhidePI) -{OLhideUtil(1,1,0);}} -function OLhideObject(o){if(OLshowid>0){clearTimeout(OLshowid);OLshowid=0;} -if(OLtimerid>0)clearTimeout(OLtimerid);if(OLdelayid>0)clearTimeout(OLdelayid);OLtimerid=0;OLdelayid=0;self.status="";o3_label=ol_label;if(o3_frame!=self)o=OLgetRefById();if(o){if(o.onmouseover)o.onmouseover=null;if(OLscrollPI&&o==over)OLclearScroll();if(OLdraggablePI)OLclearDrag();if(OLfilterPI)OLcleanupFilter(o);if(OLshadowPI)OLhideShadow();var os=(OLns4)?o:o.style;os.visibility="hidden";if(OLhidePI&&o==over)OLhideUtil(0,0,1);if(OLiframePI)OLhideIfs(o);}} -function OLrepositionTo(o,xL,yL){o=(OLns4)?o:o.style;if(o.setAttribute){o.setAttribute('left',OLns4?xL:xL+'px');o.setAttribute('top',OLns4?yL:yL+'px');}else{o.left=(OLns4?xL:xL+'px');o.top=(OLns4?yL:yL+'px');}} -function OLoptMOUSEOFF(c){if(!c)o3_close="";over.onmouseover=function(){OLhover=1;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}}} -function OLcursorOff(){var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight,left=parseInt(o.left),top=parseInt(o.top),right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);if(OLxright||OLybottom)return true;return false;} -function OLsetRunTimeVar(){if(OLrunTime.length)for(var k=0;k-1){i=j;break;}}} -return i;} -function OLregCmds(c){if(typeof c!='string')return;var pM=c.split(',');pMtr=pMtr.concat(pM);for(var i=0;i12){hour-=12;am_pm='PM';} -else if(hour==12){am_pm='PM';} -else if(hour==0){hour=12;} -return am_pm;} -SugarDateTime.getFormattedHour=SugarDateTime.prototype.getFormattedHour;SugarDateTime.prototype.parseUTCDate=function(date_string){var match=/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/;if(((result=match.exec(date_string)))!=null){var new_date=new Date(Date.UTC(result[1],result[2]-1,result[3],result[4],result[5],parseInt(result[6])+time_offset));return new_date;}} -SugarDateTime.parseUTCDate=SugarDateTime.prototype.parseUTCDate;SugarDateTime.prototype.parseAdjustedDate=function(date_string,dst_start,dst_end,gmt_offset_secs){var match=/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/;dst_start_parse=match.exec(dst_start);dst_end_parse=match.exec(dst_end);if(dst_start_parse==null||dst_end_parse==null){var new_date=new Date(result[1],result[2]-1,result[3],result[4],result[5],parseInt(result[6]));new_date=new Date(new_date.getTime()+gmt_offset_secs*1000);}else{dst_start_obj=new Date(dst_start_parse[1],dst_start_parse[2]-1,dst_start_parse[3],dst_start_parse[4],dst_start_parse[5],parseInt(dst_start_parse[6]));dst_end_obj=new Date(dst_end_parse[1],dst_end_parse[2]-1,dst_end_parse[3],dst_end_parse[4],dst_end_parse[5],parseInt(dst_end_parse[6]));if(((result=match.exec(date_string)))!=null){var new_date=new Date(result[1],result[2]-1,result[3],result[4],result[5],parseInt(result[6]));var event_ts=new_date.getTime();var dst_start_ts=dst_start_obj.getTime();var dst_end_ts=dst_end_obj.getTime();if(((event_ts>=dst_start_ts||event_tsdst_end_ts)||(event_ts>=dst_start_ts&&event_ts=0&&startmins<15){startdate.setUTCMinutes(0);} -else if(startmins>=15&&startmins<30){startdate.setUTCMinutes(15);} -else if(startmins>=30&&startmins<45){startdate.setUTCMinutes(30);} -else{startdate.setUTCMinutes(45);} -while(startdate.valueOf() 0){ - //add error messages for display - for(i in ret.errorArray) - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, ret.errorArray[i], 'alert'); - }else if (typeof(ret.errorArray)=='object' && ret.errorArray!=null && ret.errorArray!='' ) { - //if error element is returning an object, and the object value is not empty or null, then display error message - for(i in ret.errorArray) - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, ret.errorArray[i], 'alert'); - } - - //YUI bug with IE6 - Wont restore visibility property for nested select elements. - if(SUGAR.isIE) { - var overlayPanel = YAHOO.SUGAR.MessageBox.panel; - if(overlayPanel) { - overlayPanel.subscribe('hide',function() { YAHOO.util.Dom.setStyle('addressFrom' + idx,'visibility','');}); - } - } - }, - - - handleDeleteSignature : function(o) { - SUGAR.hideMessageBox(); - var ret = YAHOO.lang.JSON.parse(o.responseText); - SUGAR.email2.composeLayout.signatures = ret.signatures; - var field = document.getElementById('signature_id'); - SUGAR.email2.util.emptySelectOptions(field); - - for(var i in ret.signatures) { // iterate through assoc array - var opt = new Option(ret.signatures[i], i); - field.options.add(opt); - } - setSigEditButtonVisibility(); - }, - - /** - */ - handleDeleteReturn : function(o) { - // force refresh ListView - SUGAR.hideMessageBox(); - if(document.getElementById('focusEmailMbox')) { - YAHOO.namespace('frameFolders').selectednode = SUGAR.email2.folders.getNodeFromMboxPath(document.getElementById('focusEmailMbox').innerHTML); - } - - // need to display success message before calling next async call? - document.getElementById(this.target).innerHTML = o.responseText; - }, - - /** - */ - handleFailure : function(o) { - // Failure handler - SUGAR.showMessageBox('Exception occurred...', o.statusText, 'alert'); - if(document.getElementById('saveButton')) { - document.getElementById('saveButton').disabled = false; - } - }, - - handleReplyForward : function(o) { - var a = YAHOO.lang.JSON.parse(o.responseText); - globalA = a; - var idx = SUGAR.email2.composeLayout.currentInstanceId; - - document.getElementById('email_id' + idx).value = a.uid; - document.getElementById('emailSubject' + idx).value = a.name; - document.getElementById('addressTO' + idx).value = a.from; - document.getElementById('uid' + idx).value = a.uid; - if(a.cc) { - document.getElementById('addressCC' + idx).value = a.cc; - SE.composeLayout.showHiddenAddress('cc', idx); - } - - if(a.type) { - document.getElementById('type' + idx).value = a.type; - } - - // apply attachment values - SUGAR.email2.composeLayout.loadAttachments(a.attachments); - - setTimeout("callbackReplyForward.finish(globalA);", 500); - }, - - handleReplyForwardForDraft : function(o) { - var a = YAHOO.lang.JSON.parse(o.responseText); - globalA = a; - var idx = SUGAR.email2.composeLayout.currentInstanceId; - - document.getElementById('email_id' + idx).value = a.uid; - document.getElementById('emailSubject' + idx).value = a.name; - document.getElementById('addressTO' + idx).value = a.to; - - if(a.cc) { - document.getElementById('addressCC' + idx).value = a.cc; - SUGAR.email2.composeLayout.showHiddenAddress('cc',idx); - } - - if(a.bcc) { - document.getElementById('addressBCC' + idx).value = a.bcc; - SUGAR.email2.composeLayout.showHiddenAddress('bcc',idx); - } - - - if(a.type) { - document.getElementById('type' + idx).value = a.type; - } - - - // apply attachment values - SUGAR.email2.composeLayout.loadAttachments(a.attachments); - - setTimeout("callbackReplyForward.finish(globalA);", 500); - }, - - /** - */ - handleSuccess : function(o) { - document.getElementById(this.target).innerHTML = o.responseText; - SUGAR.hideMessageBox(); - }, - - /** - */ - ieDeleteSuccess : function(o) { - SUGAR.hideMessageBox(); - SUGAR.email2.accounts.refreshInboundAccountTable(); - alert(app_strings.LBL_EMAIL_IE_DELETE_SUCCESSFUL); - SUGAR.email2.accounts.rebuildFolderList(); - }, - - /** - */ - ieSaveSuccess : function(o) { - document.getElementById('saveButton').disabled = false; - var a = YAHOO.lang.JSON.parse(o.responseText); - if (a) { - if(a.error) { - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, app_strings.LBL_EMAIL_ERROR_CHECK_IE_SETTINGS, 'alert'); - SUGAR.email2.accounts.ieAccountError(SUGAR.email2.accounts.errorStyle); - } else { - resp = YAHOO.lang.JSON.parse(o.responseText); - SUGAR.email2.accounts.refreshInboundAccountTable(); - SUGAR.email2.accounts.refreshOuboundAccountTable(); - SUGAR.email2.folders.startEmailCheckOneAccount(resp.id, true); - SUGAR.email2.accounts.inboundAccountEditDialog.hide(); - } - } else { - SUGAR.hideMessageBox(); - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, app_strings.LBL_EMAIL_ERROR_SAVE_ACCOUNT, 'alert'); - } - - }, - - /** - */ - loadAttachments : function(o) { - var result = YAHOO.lang.JSON.parse(o.responseText); - - SUGAR.email2.composeLayout.loadAttachments(result); - }, - - /** - */ - loadSignature : function(o) { - var ret = YAHOO.lang.JSON.parse(o.responseText); - SUGAR.email2.signatures[ret.id] = ret.signature_html; - SUGAR.email2.composeLayout.setSignature(SUGAR.email2.signatures.targetInstance); - }, - - /** - * Follow up to mark email read|unread|flagged - */ - markEmailCleanup : function(o) { - var ret = YAHOO.lang.JSON.parse(o.responseText); - if (!ret['status']) { - SUGAR.hideMessageBox(); - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, ret['message'], 'alert'); - } else { - SUGAR.email2.contextMenus.markEmailCleanup(); - } // else - }, - - /** - */ - rebuildShowFolders : function(o) { - var t = YAHOO.lang.JSON.parse(o.responseText); - var show = document.getElementById('ieAccountListShow'); - - SUGAR.email2.util.emptySelectOptions(show); - - for(i=0; i" + - // remove button - "" + - // file icon - "" + - // hidden id field - "" + - // file name - ((ret.nameForDisplay != null) ? ret.nameForDisplay + " " : ret.name + " ") + - "
" + - "
"; - overall.innerHTML += out; - if(SUGAR.email2.util.isIe()) { - document.getElementById('addedFiles' + idx).innerHTML = document.getElementById('addedFiles' + idx).innerHTML; - } - - // hide popup - SUGAR.email2.addFileDialog.hide(); - // focus attachments - SUGAR.email2.composeLayout.showAttachmentPanel(idx); - } -}; - - -/////////////////////////////////////////////////////////////////////////// -//// PER MODULE CALLBACK OBJECTS -AjaxObject.accounts = { - saveOutboundCleanup : function(o) { - SUGAR.email2.accounts.refreshOuboundAccountTable(); - SUGAR.email2.accounts.outboundDialog.hide(); - var id = o.responseText; - SUGAR.email2.accounts.newAddedOutboundId = id; - }, - saveDefaultOutboundCleanup: function(o){ - - }, - callbackEditOutbound : { - success : function(o) - { - var ret = YAHOO.lang.JSON.parse(o.responseText); - // show overlay - SUGAR.email2.accounts.showAddSmtp(); - - // fill values - document.getElementById("mail_id").value = ret.id; - document.getElementById("type").value = ret.type; - document.getElementById("mail_sendtype").value = ret.mail_sendtype; - document.getElementById("mail_name").value = ret.name; - document.getElementById("mail_smtpserver").value = ret.mail_smtpserver; - document.getElementById("outboundEmailForm").mail_smtptype.value = ret.mail_smtptype; - document.getElementById("mail_smtpport").value = ret.mail_smtpport; - document.getElementById("mail_smtpuser").value = ret.mail_smtpuser; - document.getElementById("mail_smtpauth_req").checked = (ret.mail_smtpauth_req == 1) ? true : false; - SUGAR.email2.accounts.smtp_authenticate_field_display(); - document.getElementById("mail_smtpssl").options[ret.mail_smtpssl].selected = true; - - if(ret.type == 'system-override') { - SUGAR.email2.accounts.toggleOutboundAccountDisabledFields(true); - SUGAR.email2.accounts.changeEmailScreenDisplay(ret.mail_smtptype,true); - } - else { - SUGAR.email2.accounts.toggleOutboundAccountDisabledFields(false); - SUGAR.email2.accounts.changeEmailScreenDisplay(ret.mail_smtptype,false); - } - SUGAR.util.setEmailPasswordDisplay('mail_smtppass', ret.has_password); - - }, - failure : AjaxObject.handleFailure, - timeout : AjaxObject.timeout, - scope : AjaxObject - }, - callbackDeleteOutbound : { - success : function(o) { - var ret = YAHOO.lang.JSON.parse(o.responseText); - if(ret.is_error) - { - if(confirm(ret.error_message)) - { - SUGAR.showMessageBox(app_strings.LBL_EMAIL_IE_DELETE, app_strings.LBL_EMAIL_ONE_MOMENT); - AjaxObject.startRequest(AjaxObject.accounts.callbackDeleteOutbound, urlStandard + "&emailUIAction=deleteOutbound&confirm=true&outbound_email=" + ret.outbound_email); - } - else - SUGAR.hideMessageBox(); - } - else - { - SUGAR.hideMessageBox(); - SUGAR.email2.accounts.refreshOuboundAccountTable(); - } - }, - - failure : AjaxObject.handleFailure, - timeout : AjaxObject.timeout, - scope : AjaxObject - }, - - callbackCheckMailProgress : { - success : function(o) { - if (typeof(SUGAR.email2.accounts.totalMsgCount) == "undefined") { - SUGAR.email2.accounts.totalMsgCount = -1; - } - - //Check for server timeout / errors - var ret = YAHOO.lang.JSON.parse(o.responseText); - var done = false; - - if (typeof(o.responseText) == 'undefined' || o.responseText == "" || ret == false) { - SUGAR.hideMessageBox(); - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, app_strings.LBL_EMAIL_ERROR_TIMEOUT, 'alert'); - SUGAR.email2.accounts.totalMsgCount = -1; - //SUGAR.email2.folders.rebuildFolders(); - done = true; - } - - var currIeId = ret['ieid']; - - - var serverCount = ret.count; - - if (ret['status'] == 'done') { - for(i=0; i < SUGAR.email2.accounts.ieIds.length; i++) { - if (i == SUGAR.email2.accounts.ieIds.length - 1) { - //We are all done - done = true; - break; - } else if (SUGAR.email2.accounts.ieIds[i] == currIeId) { - //Go to next account - currIeId = SUGAR.email2.accounts.ieIds[i+1]; - ret.count = 0; - SUGAR.email2.accounts.totalMsgCount = -1; - break; - } - } - } - else if (ret.mbox && ret.totalcount && ret.count) { - SUGAR.email2.accounts.totalMsgCount = ret.totalcount; - if (ret.count >= ret.totalcount) { - serverCount = 0; - } - } else if (SUGAR.email2.accounts.totalMsgCount < 0 && ret.totalcount) { - SUGAR.email2.accounts.totalMsgCount = ret.totalcount; - } else { - SUGAR.hideMessageBox(); - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, app_strings.LBL_EMAIL_ERROR_TIMEOUT, 'alert'); - SUGAR.email2.accounts.totalMsgCount = -1; - done = true; - } - - if (done) { - SUGAR.email2.accounts.totalMsgCount = -1; - SUGAR.hideMessageBox(); - SUGAR.email2.folders.rebuildFolders(); - SE.listView.refreshGrid(); - } else if (SUGAR.email2.accounts.totalMsgCount < 0) { - YAHOO.SUGAR.MessageBox.updateProgress(0, mod_strings.LBL_CHECKING_ACCOUNT + ' '+ (i + 2) + ' '+ mod_strings.LBL_OF + ' ' + SUGAR.email2.accounts.ieIds.length); - AjaxObject.startRequest(AjaxObject.accounts.callbackCheckMailProgress, urlStandard + - '&emailUIAction=checkEmailProgress&ieId=' + currIeId + "¤tCount=0&synch=" + ret.synch); - } else { - YAHOO.SUGAR.MessageBox.updateProgress((ret.count / SUGAR.email2.accounts.totalMsgCount) * 100, - app_strings.LBL_EMAIL_DOWNLOAD_STATUS.replace(/\[\[count\]\]/, ret.count).replace(/\[\[total\]\]/, SUGAR.email2.accounts.totalMsgCount)); - AjaxObject.startRequest(AjaxObject.accounts.callbackCheckMailProgress, urlStandard + - '&emailUIAction=checkEmailProgress&ieId=' + currIeId + "¤tCount=" + serverCount + - '&mbox=' + ret.mbox + '&synch=' + ret.synch + '&totalcount=' + SUGAR.email2.accounts.totalMsgCount); - } - }, - failure : AjaxObject.handleFailure, - timeout : AjaxObject.timeout, - scope : AjaxObject - } -}; - -/////////////////////////////////////////////////////////////////////////////// -//// COMPOSE LAYOUT -AjaxObject.composeLayout = { - /** - * Populates the record id - */ - saveDraftCleanup : function(o) { - var ret; - SUGAR.hideMessageBox(); - - try { - ret = YAHOO.lang.JSON.parse(o.responseText); - SUGAR.email2.composeLayout.forceCloseCompose(ret.composeLayoutId); - } catch(err) { - if (o.responseText) { - SUGAR.showMessageBox(mod_strings.LBL_ERROR_SAVING_DRAFT, o.responseText, 'alert'); - } - } - } -}; - -AjaxObject.composeLayout.callback = { - saveDraft : { - success : AjaxObject.composeLayout.saveDraftCleanup, - failure : AjaxObject.handleFailure, - timeout : AjaxObject.timeout, - scope : AjaxObject - } -}; - -AjaxObject.detailView = { - /** - * Pops-up a printable view of an email - */ - displayPrintable : function(o) { - var ret = YAHOO.lang.JSON.parse(o.responseText); - var displayTemplate = new YAHOO.SUGAR.Template(SUGAR.email2.templates['viewPrintable']); - // 2 below must be in global context - meta = ret.meta; - meta['panelId'] = SUGAR.email2.util.getPanelId(); - email = ret.meta.email; - if (typeof(email.cc) == 'undefined') { - email.cc = ""; - } - - var out = displayTemplate.exec({ - 'app_strings' : app_strings, - 'theme' : theme, - 'idx' : 'Preview', - 'meta' : meta, - 'email' : meta.email - }); - - // open popup window - var popup = window.open('modules/Emails/templates/_blank.html', 'printwin' , - 'scrollbars=yes,menubar=no,height=600,width=800,resizable=yes,toolbar=no,location=no,status=no'); - - popup.document.write(out); - popup.document.close(); - }, - - /** - * Takes formatted response and creates a modal pop-over containing a title and content - */ - displayView : function(o) { - var SED = SUGAR.email2.detailView; - var ret = YAHOO.lang.JSON.parse(o.responseText); - - if(!SED.viewDialog) { - SED.viewDialog = new YAHOO.widget.Dialog("viewDialog", { - modal:true, - visible:true, - fixedcenter:true, - constraintoviewport: true, - shadow : true - }); - SED.viewDialog.renderEvent.subscribe(function() { - var content = this.body.firstChild; - var viewH = YAHOO.util.Dom.getViewportHeight(); - if (content) { - this.body.style.overflow = "auto"; - this.body.style.width = "800px"; - this.body.style.height = (viewH - 75 > content.clientHeight ? (content.clientHeight) : (viewH - 75)) + "px"; - } - }, SED.viewDialog); - } // end lazy load - SED.viewDialog.setHeader(ret.title); - SED.viewDialog.setBody(ret.html); - SED.viewDialog.render(); - SED.viewDialog.show(); - }, - - /** - * Generates a modal popup to populate with the contents of bean's full EditView - */ - showQuickCreateForm : function(o) { - var SED = SUGAR.email2.detailView; - var ret = YAHOO.lang.JSON.parse(o.responseText); - - if(!SED.quickCreateDialog) { - SED.quickCreateDialog = new YAHOO.widget.Dialog("quickCreate", { - modal:true, - visible:true, - fixedcenter:true, - constraintoviewport: true, - shadow : true - }); - - SED.quickCreateDialog.renderEvent.subscribe(function() { - var viewH = YAHOO.util.Dom.getViewportHeight(); - var contH = 0; - for (var i in this.body.childNodes) { - if (this.body.childNodes[i].clientHeight) { - contH += this.body.childNodes[i].clientHeight; - } else if (this.body.childNodes[i].offsetHeight) { - contH += this.body.childNodes[i].offsetHeight; - } // if - } - this.body.style.width = "800px"; - this.body.style.height = (viewH - 75 > contH ? (contH + 10) : (viewH - 75)) + "px"; - this.body.style.overflow = "auto"; - }, SED.quickCreateDialog); - - SED.quickCreateDialog.hideEvent.subscribe(function(){ - var qsFields = YAHOO.util.Dom.getElementsByClassName('.sqsEnabled', null, this.body); - /*for(var qsField in qsFields){ - if (typeof QSFieldsArray[qsFields[qsField].id] != 'undefined') - Ext.getCmp('combobox_'+qsFields[qsField].id).destroy(); - }*/ - }); - SED.quickCreateDialog.setHeader(app_strings.LBL_EMAIL_QUICK_CREATE); - } // end lazy load - if (ret.html) { - ret.html = ret.html.replace('', ""); - } - SED.quickCreateDialog.setBody(ret.html ? ret.html : " "); - SED.quickCreateDialog.render(); - SUGAR.util.evalScript(ret.html + ''); - - SED.quickCreateDialog.ieId = ret.ieId; - SED.quickCreateDialog.uid = ret.uid; - SED.quickCreateDialog.mbox = ret.mbox; - SED.quickCreateDialog.qcmodule = ret.module; - - SED.quickCreateDialog.show(); - - var editForm = document.getElementById('form_EmailQCView_' + ret.module); - if (editForm) { - editForm.module.value = 'Emails'; - var count = SUGAR.EmailAddressWidget.count[ret.module] ? SUGAR.EmailAddressWidget.count[ret.module] : 0; - var tableId = YAHOO.util.Dom.getElementsByClassName('emailaddresses', 'table', editForm)[0].id; - var instId = ret.module + count; - SED.quickCreateEmailsToAdd = ret.emailAddress; - SED.quickCreateEmailCallback = function(instId, tableId) { - var eaw = SUGAR.EmailAddressWidget.instances[instId]; - if (typeof(eaw) == "undefined") - window.setTimeout("SUGAR.email2.detailView.quickCreateEmailCallback('" - + instId + "','" + tableId + "');", 100); - eaw.prefillEmailAddresses(tableId, SUGAR.email2.detailView.quickCreateEmailsToAdd); - } - window.setTimeout("SUGAR.email2.detailView.quickCreateEmailCallback('" - + instId + "','" + tableId + "');", 100); - } - }, - - saveQuickCreateForm : function(o) { - SUGAR.hideMessageBox(); - SUGAR.email2.detailView.quickCreateDialog.hide(); - validate['EditView'] = [ ]; - }, - - saveQuickCreateFormAndReply : function(o) { - SUGAR.hideMessageBox(); - var ret = YAHOO.lang.JSON.parse(o.responseText); - SUGAR.email2.detailView.quickCreateDialog.hide(); - var qcd = SUGAR.email2.detailView.quickCreateDialog; - var type = (qcd.qcmodule == 'Cases') ? 'replyCase' : 'reply'; - if (ret) { - var emailID = ret.id; - SUGAR.email2.composeLayout.c0_replyForwardEmail(null, ret.id, 'sugar::Emails', type); - } else { - SUGAR.email2.composeLayout.c0_replyForwardEmail(qcd.ieId, qcd.uid, qcd.mbox, type); - } - //Cean the validate cache to prevent errors on the next call - validate['EditView'] = [ ]; - }, - - saveQuickCreateFormAndAddToAddressBook : function(o) { - SUGAR.hideMessageBox(); - SUGAR.email2.detailView.quickCreateDialog.hide(); - SUGAR.email2.complexLayout.findPanel('contactsTab').show(); - validate['EditView'] = [ ]; - }, - - handleAssignmentDialogAssignAction : function() { - - - var assign_user_id = window.document.forms['Distribute'].elements['assigned_user_id'].value; - - var dist = 'direct'; - var users = false; - var rules = false; - var get = ""; - var found_teams = false; - var warning_message = mod_strings.LBL_WARN_NO_USERS; - if(!found_teams && assign_user_id == '' ) - { - alert(warning_message); - return; - } - - var emailUids = SUGAR.email2.listView.getUidsFromSelection(); - var uids = ""; - for(i=0; i'; - } - SUGAR.showMessageBox(SUGAR.language.get('Emails','LBL_IMPORT_STATUS_TITLE'), statusString, 'alert'); - } - SE.listView.refreshGrid(); - -}, -failure : AjaxObject.handleFailure, -timeout : AjaxObject.timeout, -scope : AjaxObject - -}; -var callbackComposeCache = { - success : AjaxObject.composeCache, - failure : AjaxObject.handleFailure, - timeout : AjaxObject.timeout, - scope : AjaxObject -}; -var callbackDelete = { - success : AjaxObject.handleDeleteReturn, - failure : AjaxObject.handleFailure, - timeout : AjaxObject.timeout, - scope : AjaxObject -}; -var callbackEmailDetailMultiple = { - success : function(o) { - SUGAR.hideMessageBox(); - var retMulti = YAHOO.lang.JSON.parse(o.responseText); - var ret = new Object(); - - for(var i=0; i 0) { - for (i = 0 ; i < tabArray.length ; i++) { - var tabObject = tabArray[i]; - if (tabObject.get("id") == ("composeTab" + idx)) { - var tabLabel = a.name; - if (tabLabel != null && tabLabel.length > 25) { - tabLabel = tabLabel.substring(0, 25) + "..."; - } // if - tabObject.get("labelEl").firstChild.data = tabLabel; - break; - } - } - } - - //SUGAR.email2.innerLayout.regions.center.getPanel('composeLayout' + idx).setTitle(a.name); - if (a.parent_name != null && a.parent_name != "") { - document.getElementById('data_parent_name' + idx).value = a.parent_name; - } - if (a.parent_type != null && a.parent_type != "") { - document.getElementById('data_parent_type' + idx).value = a.parent_type; - } - if (a.parent_id != null && a.parent_id != "") { - document.getElementById('data_parent_id' + idx).value = a.parent_id; - } - if (a.fromAccounts.status) { - var addressFrom = document.getElementById('addressFrom' + idx); - SUGAR.email2.util.emptySelectOptions(addressFrom); - var fromAccountOpts = a.fromAccounts.data; - for(i=0; i"; - } - } - function attachIcon(cell, record, column, value) { - if(value == "1") { - cell.innerHTML = ""; - } - } - - var colModel = - [ - { - label: "", - width: 10, - sortable: false, - fixed: true, - resizeable: true, - formatter: attachIcon, - key: 'hasAttach' - }, - { - label: "!", - width: widths[0], - sortable: true, - fixed: true, - resizeable: true, - formatter: flaggedIcon, - key: 'flagged' - }, - { - label: "", - width: widths[1], - sortable: true, - fixed: true, - resizeable: true, - formatter: repliedIcon, - key: 'status' - }, - { - label: app_strings.LBL_EMAIL_FROM, - width: widths[2], - sortable: true, - resizeable: true, - key: 'from' - }, - { - label: app_strings.LBL_EMAIL_SUBJECT, - width: widths[3], - sortable: true, - resizeable: true, - key: 'subject' - }, - { - label: mod_strings.LBL_LIST_DATE, - width: widths[4], - sortable: true, - resizeable: true, - key: 'date' - }, - { - label: app_strings.LBL_EMAIL_TO, - width: widths[5], - sortable: false, - resizeable: true, - key: 'to_addrs' - }, - { - label: 'uid', - hidden: true, - key: 'uid' - }, - { - label: 'mbox', - hidden: true, - key: 'mbox' - }, - { - label: 'ieId', - hidden: true, - key: 'ieId' - }, - { - label: 'site_url', - hidden: true, - key: 'site_url' - }, - { label: 'seen', - hidden: true, - key: 'seen' - }, - { label: 'type', - hidden: true, - key: 'type' - } - ]; - - var dataModel = new YAHOO.util.DataSource(urlBase + "?", { - responseType: YAHOO.util.DataSource.TYPE_JSON, - responseSchema: { - resultsList: 'Email', - fields: ['flagged', 'status', 'from', 'subject', 'date','to_addrs', 'uid', 'mbox', 'ieId', 'site_url', 'seen', 'type', 'AssignedTo','hasAttach'], - metaFields: {total: 'TotalCount', unread:"UnreadCount", fromCache: "FromCache"} - } - }); - var params = { - to_pdf : "true", - module : "Emails", - action : "EmailUIAjax", - emailUIAction : "getMessageList", - mbox : "INBOX", - ieId : "", - forceRefresh : "false" - }; - if(lazyLoadFolder != null) { - params['mbox'] = lazyLoadFolder.folder; - params['ieId'] = lazyLoadFolder.ieId; - //Check if the folder is a Sugar Folder - var test = new String(lazyLoadFolder.folder); - if(test.match(/SUGAR\./)) { - params['emailUIAction'] = 'getMessageListSugarFolders'; - params['mbox'] = test.substr(6); - } - } - //dataModel.initPaging(urlBase, SUGAR.email2.userPrefs.emailSettings.showNumInList); - - // create the Grid - var grid = SUGAR.email2.grid = new YAHOO.SUGAR.SelectionGrid('emailGrid', colModel, dataModel, { - MSG_EMPTY: SUGAR.language.get("Emails", "LBL_EMPTY_FOLDER"), - dynamicData: true, - paginator: new YAHOO.widget.Paginator({ - rowsPerPage:parseInt(SUGAR.email2.userPrefs.emailSettings.showNumInList), - containers : ["dt-pag-nav"], - template: "", - firstPageLinkLabel: "", - previousPageLinkLabel: "", - nextPageLinkLabel: "", - lastPageLinkLabel: "" - }), - initialRequest:SUGAR.util.paramsToUrl(params), - width: "800px", - height: "400px" - }); - - initRowDD(); - - //Override Paging request construction - grid.set("generateRequest", function(oState, oSelf) { - oState = oState || {pagination:null, sortedBy:null}; - var sort = (oState.sortedBy) ? oState.sortedBy.key : oSelf.getColumnSet().keys[5].getKey(); - var dir = (oState.sortedBy && oState.sortedBy.dir === YAHOO.widget.DataTable.CLASS_ASC) ? "asc" : "desc"; - var startIndex = (oState.pagination) ? oState.pagination.recordOffset : 0; - var results = (oState.pagination) ? oState.pagination.rowsPerPage : null; - // Build the request - var ret = - SUGAR.util.paramsToUrl(oSelf.params) + - "&sort=" + sort + - "&dir=" + dir + - "&start=" + startIndex + - ((results !== null) ? "&limit=" + results : ""); - return ret; - }); - - - grid.handleDataReturnPayload = function(oRequest, oResponse, oPayload) { - oPayload = oPayload || { }; - - oPayload.totalRecords = oResponse.meta.total; - oPayload.unreadRecords = oResponse.meta.unread; - - var tabObject = SE.innerLayout.get("tabs")[0]; - var mboxTitle = ""; - if (this.params.mbox != null) { - mboxTitle = this.params.mbox; - } - var tabtext = mboxTitle + " (" + oResponse.meta.total + " " + app_strings.LBL_EMAIL_MESSAGES + " )"; - tabObject.get("labelEl").firstChild.data = tabtext; - - if (SE.tree) { - var node = SE.tree.getNodeByProperty('id', this.params.ieId) || SE.tree.getNodeByProperty('origText', this.params.mbox); - if (node) { - node.data.unseen = oResponse.meta.unread; - SE.accounts.renderTree(); - } - } - return oPayload; - } - - var resize = grid.resizeGrid = function () { - SUGAR.email2.grid.set("width", SUGAR.email2.grid.get("element").parentNode.clientWidth + "px"); - SUGAR.email2.grid.set("height", (SUGAR.email2.grid.get("element").parentNode.clientHeight - 47) + "px"); - } - grid.convertDDRows = function() { - var rowEl = this.getFirstTrEl(); - while (rowEl != null) { - new this.DDRow(this, this.getRecord(rowEl), rowEl); - rowEl = this.getNextTrEl(rowEl); - } - } - - - grid.on("columnResizeEvent", function(o) { - //Find the index of the column - var colSet = SUGAR.email2.grid.getColumnSet().flat; - for (var i=0; i < colSet.length; i++) { - if (o.column == colSet[i]) { - //Store it in the cookie - Ck.setSub("EmailGridWidths", i + "", o.width, {expires: SUGAR.email2.nextYear}); - } - } - //this.resizeGrid(); - }, null, grid); - - grid.on("postRenderEvent", function() {this.convertDDRows()}, null, grid); - grid.on("rowClickEvent", SUGAR.email2.listView.handleClick); - grid.on("rowDblclickEvent", SUGAR.email2.listView.getEmail); - grid.render(); - SUGAR.email2.listViewLayout.on("render", resize); - resize(); - - //Setup the default load parameters - SUGAR.email2.grid.params = params; - - grid.on('postRenderEvent', SUGAR.email2.listView.setEmailListStyles); - dataModel.subscribe("requestEvent", grid.disable, grid, true); - dataModel.subscribe("responseParseEvent", grid.undisable, grid, true); - } - }; - e2Grid.init(); -}; - - -function initRowDD() { - var sg = SUGAR.email2.grid, - Dom = YAHOO.util.Dom; - sg.DDRow = function(oDataTable, oRecord, elTr) { - if(oDataTable && oRecord && elTr) { - this.ddtable = oDataTable; - this.table = oDataTable.getTableEl(); - this.row = oRecord; - this.rowEl = elTr; - this.newIndex = null; - this.init(elTr); - this.initFrame(); // Needed for DDProxy - this.invalidHandleTypes = {}; - } - }; - - YAHOO.extend(sg.DDRow, YAHOO.util.DDProxy, { - _resizeProxy: function() { - this.constructor.superclass._resizeProxy.apply(this, arguments); - var dragEl = this.getDragEl(), - el = this.getEl(); - var xy = Dom.getXY(el); - - Dom.setStyle(dragEl, 'height', this.rowEl.offsetHeight + "px"); - Dom.setStyle(dragEl, 'width', (parseInt(Dom.getStyle(dragEl, 'width'),10) + 4) + 'px'); - Dom.setXY(dragEl, [xy[0] - 100, xy[1] - 20] ); - Dom.setStyle(dragEl, 'display', ""); - }, - - startDrag: function(x, y) { - //Check if we should be dragging a set of rows rather than just the one. - var selectedRows = this.ddtable.getSelectedRows(); - var iSelected = false; - for (var i in selectedRows) { - if (this.rowEl.id == selectedRows[i]) { - iSelected = true; - break - } - } - if (iSelected) { - this.rows = []; - for (var i in selectedRows) { - this.rows[i] = this.ddtable.getRecord(selectedRows[i]); - } - } else { - this.rows = [this.row]; - this.ddtable.unselectAllRows(); - this.ddtable.selectRow(this.row); - } - - //Initialize the dragable proxy - var dragEl = this.getDragEl(); - var clickEl = this.getEl(); - Dom.setStyle(clickEl, "opacity", "0.25"); - dragEl.innerHTML = "" + clickEl.innerHTML + "
"; - Dom.addClass(dragEl, "yui-dt-liner"); - Dom.setStyle(dragEl, "opacity", "0.5"); - Dom.setStyle(dragEl, "height", (clickEl.clientHeight - 2) + "px"); - Dom.setStyle(dragEl, "backgroundColor", Dom.getStyle(clickEl, "backgroundColor")); - Dom.setStyle(dragEl, "border", "2px solid gray"); - }, - - clickValidator: function(e) { - if (this.row.getData()[0] == " ") - return false; - var target = YAHOO.util.Event.getTarget(e); - return ( this.isValidHandleChild(target) && - (this.id == this.handleElId || this.DDM.handleWasClicked(target, this.id)) ); - }, - /** - * This funciton checks that the target of the drag is a table row in this - * DDGroup and simply moves the sourceEL to that location as a preview. - */ - onDragOver: function(ev, id) { - var node = SUGAR.email2.tree.getNodeByElement(Dom.get(id)); - if (node && node != this.targetNode) { - this.targetNode = node; - SUGAR.email2.folders.unhighliteAll(); - node.highlight(); - } - }, - - onDragOut: function(e, id) { - if (this.targetNode) { - SUGAR.email2.folders.unhighliteAll(); - this.targetNode = false; - } - }, - endDrag: function() { - Dom.setStyle(this.getEl(), "opacity", ""); - Dom.setStyle(this.getDragEl(), "display", "none"); - if (this.targetNode) { - SUGAR.email2.folders.handleDrop(this.rows, this.targetNode); - } - SUGAR.email2.folders.unhighliteAll(); - this.rows = null; - } - }); -} - -function AddressSearchGridInit() { - function moduleIcon(elCell, oRecord, oColumn, oData) { - elCell.innerHTML = ""; - }; - function selectionCheckBox(elCell, oRecord, oColumn, oData) { - elCell.innerHTML = ''; - }; - var checkHeader = '{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}", - firstPageLinkLabel: "", - previousPageLinkLabel: "", - nextPageLinkLabel: "", - lastPageLinkLabel: "" - }), - initialRequest:SUGAR.util.paramsToUrl(dataModel.params), - width: "560px", - height: "250px" - }); - //Override Paging request construction - grid.set("generateRequest", function(oState, oSelf) { - oState = oState || {pagination:null, sortedBy:null}; - var sort = (oState.sortedBy) ? oState.sortedBy.key : oSelf.getColumnSet().keys[0].getKey(); - var dir = (oState.sortedBy && oState.sortedBy.dir === YAHOO.widget.DataTable.CLASS_DESC) ? "desc" : "asc"; - var startIndex = (oState.pagination) ? oState.pagination.recordOffset : 0; - var results = (oState.pagination) ? oState.pagination.rowsPerPage : null; - // Build the request - var ret = - SUGAR.util.paramsToUrl(oSelf.getDataSource().params) + - "&sort=" + sort + "&dir=" + dir + "&start=" + startIndex + - ((results !== null) ? "&limit=" + results : ""); - return ret; - }); - - grid.handleDataReturnPayload = function(oRequest, oResponse, oPayload) { - oPayload = oPayload || { }; - oPayload.totalRecords = oResponse.meta.total; - return oPayload; - } - - grid.clickToggleSelect= function(args) { - var isIE = (args.event.target == null); - var targetElement = isIE ? args.event.srcElement : args.event.target; - if(targetElement.type == null || targetElement.type != 'checkbox') { - SUGAR.email2.addressBook.grid.toggleSelect(args.target.id); - } - } - - grid.reSelectRowsOnRender = function (){ - var rows = SUGAR.email2.addressBook.grid.getRecordSet().getRecords(); - for (var i = 0; i < rows.length; i++) - { - var emailAddress = rows[i].getData("email"); - var alreadyAdded = SUGAR.email2.addressBook.doesEmailAdddressExistInResultTable(emailAddress); - if(alreadyAdded) - { - rows[i].setData("selected", true); - SUGAR.email2.addressBook.grid.selectRow(rows[i]); - } - else - { - rows[i].setData("selected", false); - SUGAR.email2.addressBook.grid.unselectRow(rows[i]); - } - } - } - grid.subscribe("rowMouseoverEvent", grid.onEventHighlightRow); - grid.subscribe("rowMouseoutEvent", grid.onEventUnhighlightRow); - grid.subscribe("rowClickEvent", grid.clickToggleSelect); - grid.subscribe("postRenderEvent", grid.reSelectRowsOnRender); - - grid.render(); - dataModel.subscribe("requestEvent", grid.disable, grid, true); - dataModel.subscribe("responseParseEvent", grid.undisable, grid, true); - - grid.toggleSelectCheckbox = function(id,checked){ - var row = SUGAR.email2.addressBook.grid.getRecord(id); - row.setData("checked",checked); - }; - grid.toggleSelect = function(id, checked) { - var row = SUGAR.email2.addressBook.grid.getRecord(id); - checked = row.getData("selected"); - if (!checked) - { - SUGAR.email2.addressBook.grid.selectRow(row); - SE.addressBook.insertContactRowToResultTable(id,null) - } else - { - SUGAR.email2.addressBook.grid.unselectRow(row); - SE.addressBook.removeRowFromGridResults(id,row.getData("email")); - } - row.setData("selected", !checked); - }; - - grid.toggleSelectAll = function(checked) { - rows = SUGAR.email2.addressBook.grid.getRecordSet().getRecords(); - for (var i = 0; i < rows.length; i++) { - if (typeof(rows[i]) != "undefined") - rows[i].setData("checked", checked); - } - var checkBoxes = SUGAR.email2.addressBook.grid.get("element").getElementsByTagName('input'); - for (var i = 0; i < checkBoxes.length; i++) { - checkBoxes[i].checked = checked; - } - }; - - //Initialize the grid result table. - AddressSearchResultsGridInit(); -} - - - -/** -* Initalize the results table for the address book selection. -* -*/ -function AddressSearchResultsGridInit() -{ - - /* Full name sort funciton to compare by last name if available */ - var fullNameSort = function(a, b, desc) { - // Deal with empty values - if(!YAHOO.lang.isValue(a)) - return (!YAHOO.lang.isValue(b)) ? 0 : 1; - else if(!YAHOO.lang.isValue(b)) - return -1; - - var aNames = a.getData("name").split(' '); - var bNames = b.getData("name").split(' '); - - var aSortField = (aNames.length == 2) ? aNames[1] : a.getData("name"); - var bSortField = (bNames.length == 2) ? bNames[1] : b.getData("name"); - - return YAHOO.util.Sort.compare(aSortField,bSortField, desc); - - }; - - var typeDdOptions = [app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_TO.replace(/:$/,'') , - app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_CC.replace(/:$/,''), - app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_BCC.replace(/:$/,'')]; - - var ColumnDefs = [{key:'type',label:app_strings.LBL_EMAIL_ADDRESS_BOOK_ADRRESS_TYPE, width: 60, sortable: true, editor: new YAHOO.widget.RadioCellEditor({radioOptions:typeDdOptions,disableBtns:true})}, - {key:'name',label:app_strings.LBL_EMAIL_ACCOUNTS_NAME,width: 280,sortable: true, sortOptions:{sortFunction:fullNameSort}}]; - - var myDataSource = new YAHOO.util.DataSource([]); - myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY; - myDataSource.responseSchema = { - fields: ["name","type","email_address","display_email_address","bean_id","idx"] - }; - - var gridResults = SUGAR.email2.addressBook.gridResults = new YAHOO.widget.ScrollingDataTable("addrSearchResultGrid", ColumnDefs, myDataSource, { - width: "350px",height: "250px", MSG_EMPTY: " "}); - - var highlightEditableCell = function(oArgs) { - var elCell = oArgs.target; - if(YAHOO.util.Dom.hasClass(elCell, "yui-dt-editable")) { - this.highlightCell(elCell); - } - }; - - gridResults.subscribe("cellMouseoverEvent", highlightEditableCell); - gridResults.subscribe("cellMouseoutEvent", gridResults.onEventUnhighlightCell); - gridResults.subscribe("cellClickEvent", gridResults.onEventShowCellEditor); - gridResults.subscribe("rowMouseoverEvent", gridResults.onEventHighlightRow); - gridResults.subscribe("rowMouseoutEvent", gridResults.onEventUnhighlightRow); - - //Setup the context menus - var onContextMenuClick = function(p_sType, p_aArgs, p_myDataTable) { - var task = p_aArgs[1]; - if(task) - { - var elRow = this.contextEventTarget; - elRow = p_myDataTable.getTrEl(elRow); - - if(elRow) - { - switch(task.index) - { - case 0: - var oRecord = p_myDataTable.getRecord(elRow); - p_myDataTable.deleteRow(elRow); - SUGAR.email2.addressBook.grid.reSelectRowsOnRender(); - } - } - } - }; - var contextMenu = new YAHOO.widget.ContextMenu("contextmenu", - {trigger:gridResults.getTbodyEl()}); - contextMenu.addItem(app_strings.LBL_EMAIL_DELETE); - contextMenu.render("addrSearchResultGrid"); - contextMenu.clickEvent.subscribe(onContextMenuClick, gridResults); -} -// End of File modules/Emails/javascript/grid.js - -/********************************************************************************* - * SugarCRM Community Edition is a customer relationship management program developed by - * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License version 3 as published by the - * Free Software Foundation with the addition of the following permission added - * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK - * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY - * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more - * details. - * - * You should have received a copy of the GNU Affero General Public License along with - * this program; if not, see http://www.gnu.org/licenses or write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - * - * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, - * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. - * - * The interactive user interfaces in modified source and object code versions - * of this program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU Affero General Public License version 3. - * - * In accordance with Section 7(b) of the GNU Affero General Public License version 3, - * these Appropriate Legal Notices must retain the display of the "Powered by - * SugarCRM" logo. If the display of the logo is not reasonably feasible for - * technical reasons, the Appropriate Legal Notices must display the words - * "Powered by SugarCRM". - ********************************************************************************/ - - (function() { - var sw = YAHOO.SUGAR, - Event = YAHOO.util.Event, - Connect = YAHOO.util.Connect, - Dom = YAHOO.util.Dom - SE = SUGAR.email2; - -/////////////////////////////////////////////////////////////////////////////// -//// ADDRESS BOOK -SE.addressBook = { - _contactCache : new Array(), // cache of contacts - _dd : new Array(), // filtered list, same format as _contactCache - _ddLists : new Array(), // list of Lists - _dd_mlUsed : new Array(), // contacts in mailing list edit view column1 - _dd_mlAvailable : new Array(), // contacts in mailing list edit view column2 - clickBubble : true, // hack to get around onclick event bubbling - relatedBeanId : '', - relatedBeanType : '', - idx : 0, - - itemSpacing : 'white-space:nowrap; padding:2px;', - reGUID : SE.reGUID, - - - - /** - * YUI bug fix 2527707. Causes nested datatable's in to cause 404 errors whens earching. - */ - initFixForDatatableSort: function () { - //Workaround for YUI bug 2527707: http://yuilibrary.com/projects/yui2/ticket/913efafad48ce433199f3e72e4847b18, should be removed when YUI 2.8+ is used - YAHOO.widget.DataTable.prototype.getColumn = function(column) { - var oColumn = this._oColumnSet.getColumn(column); - - if(!oColumn) { - // Validate TD element - var elCell = column.nodeName.toLowerCase() != "th" ? this.getTdEl(column) : false; - if(elCell) { - oColumn = this._oColumnSet.getColumn(elCell.cellIndex); - } - // Validate TH element - else { - elCell = this.getThEl(column); - if(elCell) { - // Find by TH el ID - var allColumns = this._oColumnSet.flat; - for(var i=0, len=allColumns.length; i 0) { - SE.composeLayout.handleDrop( - (type == 'contacts') ? SE.contactView : SE.emailListsView, - null, rows, 'addressTO' + idx ); - } else { - alert(app_strings.LBL_EMAIL_MENU_MAKE_SELECTION); - } - }, - - editContact : function() { - SE.contextMenus.contactsContextMenu.hide(); - var element = SE.contactView.getSelectedNodes()[0]; - var elementId = ""; - if (element.className.indexOf('address-contact') > -1) { - elementId = element.id; - } else if (element.className.indexOf('address-exp-contact') > -1) { - elementId = element.id.substring(2); - } - }, - - - /** - * Filters contact entries based on user input - */ - filter : function(inputEl) { - var ret = new Object(); - var re = new RegExp(inputEl.value, "gi"); - - for(var i in this._contactCache) { - if(this._contactCache[i].name.match(re)) { - ret[i] = this._contactCache[i]; - } - } - - this.buildContactList(ret); - }, - - fullForm : function(id, module) { - document.location = "index.php?return_module=Emails&return_action=index&module=" + module + "&action=EditView&record=" + id; - }, - - /** - * returns a formatted email address from the addressBook cache - */ - getFormattedAddress : function(id) { - var o = this._contactCache[id]; - var primaryEmail = ''; - - for(var i=0; i]+)>)/ig, "").replace(/'/gi,'\''); - var ret = finalName + " <" + finalEmail.replace(/'/gi,'\'') + ">"; - - return ret; - }, - - /** - * Sets up async call to query for matching contacts, users, etc. - */ - searchContacts : function() { - var fn = document.getElementById('input_searchField').value; - var pe = document.getElementById('input_searchPerson').value; - - var rb = document.getElementById('hasRelatedBean').checked; - if (rb) { - var idx = this.idx; - var relatedBeanId = document.getElementById('data_parent_id' + idx).value; - var relatedBeanType = document.getElementById('data_parent_type' + idx).value; - this.addressBookDataModel.params['related_bean_id'] = relatedBeanId; - this.addressBookDataModel.params['related_bean_type'] = relatedBeanType; - } else { - this.addressBookDataModel.params['related_bean_id'] = ''; - } - - this.addressBookDataModel.params['search_field'] = fn; - this.addressBookDataModel.params['person'] = pe; - this.addressBookDataModel.params['emailUIAction'] = 'getAddressSearchResults'; - this.grid._oDataSource = this.addressBookDataModel; - this.grid.getDataSource().sendRequest(SUGAR.util.paramsToUrl(this.addressBookDataModel.params), this.grid.onDataReturnInitializeTable, this.grid); - }, - - /** - * Clear Search Crieteria For Addressbook - */ - clearAddressBookSearch : function() { - document.getElementById('input_searchField').value = ""; - document.getElementById('input_searchPerson').selectedIndex = 0; - }, - - /** - * Opens modal select window to add contacts to addressbook - */ - selectContactsDialogue : function(destId) { - if(!this.contactsDialogue) { - var dlg = this.contactsDialogue = new YAHOO.widget.Dialog("contactsDialogue", { - modal:true, - visible:false, - draggable: false, - constraintoviewport: true, - width : 980, - buttons : [{text: app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD, isDefault: true, handler: this.populateEmailAddressFieldsFromResultTable}, - {text: app_strings.LBL_EMAIL_ADDRESS_BOOK_CLEAR, isDefault: true, handler: this.clearAllEmailAddressFieldsFromResultTable} ] - }); - dlg.setHeader(app_strings.LBL_EMAIL_ADDRESS_BOOK_SELECT_TITLE); - - var body = SUGAR.util.getAndRemove("contactsDialogueHTML"); - dlg.setBody(body.innerHTML); - dlg.renderEvent.subscribe(function() { - var iev = YAHOO.util.Dom.get("contactsDialogueBody"); - if (iev && !SUGAR.isIE) { - this.body.style.width = "950px"; - } - }, dlg); - - - dlg.beforeRenderEvent.subscribe(function() { - var dd = new YAHOO.util.DDProxy(dlg.element); - dd.setHandleElId(dlg.header); - dd.on('endDragEvent', function() { - dlg.show(); - }); - }, dlg, true); - dlg.render(); - - var tp = new YAHOO.widget.TabView("contactsSearchTabs"); - - var tabContent = SUGAR.util.getAndRemove("searchForm"); - tp.addTab(new YAHOO.widget.Tab({ - label: app_strings.LBL_EMAIL_ADDRESS_BOOK_TITLE, - scroll : true, - content : tabContent.innerHTML, - id : "addressSearchTab", - active : true - })); - - var addListenerFields = ['input_searchPerson','input_searchField' ] - YAHOO.util.Event.addListener(addListenerFields,"keydown", function(e){ - if (e.keyCode == 13) { - YAHOO.util.Event.stopEvent(e); - SUGAR.email2.addressBook.searchContacts(); - } - }); - - this.contactsDialogue.render(); - dlg.center(); - } - //Quick Compose does not have an innerLayout component and will always be referenced with ix 0. - if (typeof(SUGAR.email2.innerLayout) == 'undefined') - var idx = 0; - else - { - var activePanel = SUGAR.email2.innerLayout.get("activeTab").get("id"); - var idx = activePanel.substring(10); - } - SE.addressBook.idx = idx; - - var relatedBeanId; - if ((hasRelatedBeanId = document.getElementById('data_parent_id' + idx).value) != '') { - document.getElementById('relatedBeanColumn').style.display = ''; - var relatedBeanName = document.getElementById('data_parent_name' + idx).value; - var relatedBeanType = document.getElementById('data_parent_type' + idx).value; - relatedBeanId = document.getElementById('data_parent_id' + idx).value; - document.getElementById('relatedBeanInfo').innerHTML = ' ' + relatedBeanType + ' ' + relatedBeanName + ''; - SE.addressBook.relatedBeanType = relatedBeanType; - } else { - document.getElementById('relatedBeanColumn').style.display = 'none'; - document.getElementById('hasRelatedBean').checked = false; - } - - if (!SE.addressBook.grid) - { - if (hasRelatedBeanId) { - document.getElementById('hasRelatedBean').checked = true; - } - AddressSearchGridInit(); - SE.addressBook.relatedBeanId = relatedBeanId; - } - else - { - if (typeof(relatedBeanId) != 'undefined' && relatedBeanId != SE.addressBook.relatedBeanId) - { - SE.addressBook.relatedBeanId = relatedBeanId; - document.getElementById('hasRelatedBean').checked = true; - } - if (document.getElementById('hasRelatedBean').checked == true) - { - SE.addressBook.addressBookDataModel.params['related_bean_id'] = relatedBeanId; - SE.addressBook.addressBookDataModel.params['related_bean_type'] = relatedBeanType; - } else { - SE.addressBook.addressBookDataModel.params['related_bean_id'] = ''; - SE.addressBook.addressBookDataModel.params['related_bean_type'] = ''; - } - SE.addressBook.addressBookDataModel.params['search_field'] = document.getElementById('input_searchField').value;; - SE.addressBook.addressBookDataModel.params['person'] = document.getElementById('input_searchPerson').value; - SE.addressBook.grid.getDataSource().sendRequest(SUGAR.util.paramsToUrl(SE.addressBook.addressBookDataModel.params), SE.addressBook.grid.onDataReturnInitializeTable, SE.addressBook.grid); - } - - //Remove any lingering rows in the result set table if the module was closed. - SE.addressBook.gridResults.deleteRows(0, SUGAR.email2.addressBook.gridResults.getRecordSet().getLength()); - //Repopulate - SE.addressBook.populateResulstTableEmailAddresses(); - - this.contactsDialogue.show(); - }, - /** - * Clear all email addresses from result table. - * - */ - clearAllEmailAddressFieldsFromResultTable: function () { - SUGAR.email2.addressBook.gridResults.deleteRows(0, SUGAR.email2.addressBook.gridResults.getRecordSet().getLength()); - //Unhighlight any rows currently selected if the emails were cleared. - SUGAR.email2.addressBook.grid.toggleSelectAll(false); - SUGAR.email2.addressBook.grid.reSelectRowsOnRender(); - }, - /** - * Take all email address listed in the compose tab To|Cc|Bcc fields and re-populates the - * results table. This function is called when the address book is displayed. - */ - populateResulstTableEmailAddresses: function () { - - var idx = SE.addressBook.idx; - var emailFields = ['to','cc','bcc']; - - for(var k=0;k'; - if(t_name == '') - t_name = displayEmail = t_emailAddr; - - var addressType = SE.addressBook.translateAddresType(emailFields[k],true); - SUGAR.email2.addressBook.gridResults.addRow({'type':addressType,'name':t_name,'email_address': t_emailAddr, - 'display_email_address': displayEmail,'bean_id': -1,'idx' : SE.addressBook.idx}); - } - } - }, - - /** - * Checks all entries in the result table against a particular email address, returning true - * if the email address is found, false otherwise. - */ - doesEmailAdddressExistInResultTable: function(emailAddress) - { - if(trim(emailAddress) == '') - return false; - - var emailAddressFound = false; - var contacts = SE.addressBook.gridResults.getRecordSet().getRecords(); - for (var i=0; i < contacts.length; i++) - { - var data = SE.addressBook.gridResults.getRecord(contacts[i]).getData(); - //If we are adding to cc or bcc fields, make them visible. - if(data.email_address == emailAddress) - { - emailAddressFound = true; - break; - } - } - - return emailAddressFound; - }, - /** - * Takes all email addresses that the users wishes to add from the address book and populates the To - * fields on the compose tab. - */ - populateEmailAddressFieldsFromResultTable: function() - { - //Clear the fields first, all email addresses are stored in the address book - var idx = SE.addressBook.idx; - var emailFields = ['to','cc','bcc']; - for(var k=0;k'; - if(addressType == null) - addressType = app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_TO.replace(/:$/,''); //Default to To when using the plus icon. - SUGAR.email2.addressBook.gridResults.addRow({'type':addressType,'name':name,'email_address': data.email,'display_email_address': ea,'bean_id': data.bean_id,'idx' : SE.addressBook.idx}); - }, - /** - * Remove a row from the gridsResult table. - */ - removeRowFromGridResults : function(rowId,emailAddress) - { - var contacts = SE.addressBook.gridResults.getRecordSet().getRecords(); - for (var i=0; i < contacts.length; i++) - { - var rec = SE.addressBook.gridResults.getRecord(contacts[i]); - var data = rec.getData(); - if(data.email_address == emailAddress) - { - SUGAR.email2.addressBook.gridResults.deleteRow(rec.getId()); - break; - } - } - - SUGAR.email2.addressBook.toggleSearchRowIcon(rowId,true); - }, - /** - * Translates between the addressType To|Cc|Bcc labels/keys. - */ - translateAddresType: function(addressType,fromKey) - { - var displayTo = app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_TO.replace(/:$/,''); - var displayCc = app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_CC.replace(/:$/,''); - var displayBcc = app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_BCC.replace(/:$/,''); - var mappingObject = {}; - - if(fromKey) - mappingObject = {'to':displayTo, 'cc':displayCc, 'bcc':displayBcc}; - else - { - mappingObject[displayTo] = 'to'; //Cant use object literal with variable variable. - mappingObject[displayCc] = 'cc'; - mappingObject[displayBcc] = 'bcc'; - } - - return typeof(mappingObject[addressType]) != 'undefined' ? mappingObject[addressType] : ''; - - }, - /** - * - */ - toggleSearchRowIcon : function(rowId,show) - { - if(show) - { - var idToShow = rowId + '_add_img'; - var idToHide = rowId + '_rm_img'; - } - else - { - var idToShow = rowId + '_rm_img'; - var idToHide = rowId + '_add_img'; - } - - - Dom.addClass(idToHide, "yui-hidden"); - Dom.removeClass(idToShow, "yui-hidden"); - }, - /** - * Determine if an entry has already been added to the grid results table to prevent duplicates. - */ - doesGridResultsEntryExist: function(emailAddrs) - { - - var contactExists = false; - var contacts = SE.addressBook.gridResults.getRecordSet().getRecords(); - for (var i=0; i < contacts.length; i++) - { - var data = SE.addressBook.gridResults.getRecord(contacts[i]).getData(); - if(data.email_address == emailAddrs) - { - contactExists = true; - break; - } - } - return contactExists; - }, - - /** - * adds an email address to a string, but first checks if it exists - * @param string concat The string we are appending email addresses to - * @param string addr Email address to add - * @return string - */ - smartAddEmailAddressToComposeField : function(concat, addr) { - var re = new RegExp(addr); - - if(!concat.match(re)) { - if(concat != "") { - concat += "; " + addr; - } else { - concat = addr; - } - } - - return concat; - } -}; -//// END ADDRESS BOOK -/////////////////////////////////////////////////////////////////////////////// - - - -/////////////////////////////////////////////////////////////////////////////// -//// AUTOCOMPLETE -/** - * Auto-complete object - */ -SE.autoComplete = { - config : { - delimChar : [";", ","], - useShadow : false, - useIFrame : false, - typeAhead : true, - prehighlightClassName : "yui-ac-prehighlight", - queryDelay : 0 - }, - instances : new Array(), - - /** - * Parses an addressBook entry looking for primary address. If not found, it will return the last found address. - * @param object Contact from AddressBook - * @return string - */ - getPrimaryAddress : function(contact) { - var address = app_strings.LBL_EMAIL_ADDRESS_BOOK_NOT_FOUND; - - for(var eIndex in contact.email) { - address = contact.email[eIndex].email_address; - if(contact.email[eIndex].primary_address == 1) { - return contact.email[eIndex].email_address; - } - } - return address; - }, - - - /** - * initializes autocomplete widgets for a given compose view - * @param int idx - */ - init : function(idx) { - var ds = new YAHOO.widget.DS_JSArray(this.returnDataSource(SE.addressBook._contactCache), { - "queryMatchContains" : false, - "queryMatchSubset" : true - }); - - this.instances[idx] = { - to : null, - cc : null, - bcc : null - }; - - - // instantiate the autoComplete widgets - this.instances[idx]['to'] = new YAHOO.widget.AutoComplete('addressTO'+idx, "addressToAC"+idx, ds, this.config); - this.instances[idx]['cc'] = new YAHOO.widget.AutoComplete('addressCC'+idx, "addressCcAC"+idx, ds, this.config); - this.instances[idx]['bcc'] = new YAHOO.widget.AutoComplete('addressBCC'+idx, "addressBccAC"+idx, ds, this.config); - - // enable hiding of interfering textareas - this.instances[idx]['to'].containerExpandEvent.subscribe(SE.autoComplete.toggleTextareaHide); - this.instances[idx]['cc'].containerExpandEvent.subscribe(SE.autoComplete.toggleTextareaHide); - this.instances[idx]['bcc'].containerExpandEvent.subscribe(SE.autoComplete.toggleTextareaHide); - - // enable reshowing of hidden textareas - this.instances[idx]['to'].containerCollapseEvent.subscribe(SE.autoComplete.toggleTextareaShow); - this.instances[idx]['cc'].containerCollapseEvent.subscribe(SE.autoComplete.toggleTextareaShow); - this.instances[idx]['bcc'].containerCollapseEvent.subscribe(SE.autoComplete.toggleTextareaShow); - - // enable refreshes of contact lists - this.instances[idx]['to'].textboxFocusEvent.subscribe(SE.autoComplete.refreshDataSource); - this.instances[idx]['cc'].textboxFocusEvent.subscribe(SE.autoComplete.refreshDataSource); - this.instances[idx]['bcc'].textboxFocusEvent.subscribe(SE.autoComplete.refreshDataSource); - }, - - refreshDataSource : function(sType, aArgs) { - var textBoxId = aArgs[0].getInputEl().id; // "addressTo0" - var idx; - var refresh = SE.autoComplete.returnDataSource(SE.addressBook._contactCache); - - if(textBoxId.indexOf("addressTO") > -1 || textBoxId.indexOf("addressCC") > -1) { - idx = textBoxId.substr(9); - } else { - idx = textBoxId.substr(10); - } - - SE.autoComplete.instances[idx]['to'].dataSource.data = refresh; - SE.autoComplete.instances[idx]['cc'].dataSource.data = refresh; - SE.autoComplete.instances[idx]['bcc'].dataSource.data = refresh; - }, - - /** - * Parses AddressBook entries to return an appropriate DataSource array for YUI.autoComplete - */ - returnDataSource : function(contacts) { - var ret = new Array(); - for(var id in contacts) { - if (contacts[id].name) { - var primary = this.getPrimaryAddress(contacts[id]); - - ret[ret.length] = contacts[id].name.replace(/<[\/]*b>/gi, '') + " <" + primary + ">"; - //ret[ret.length] = contacts[id].name + " <" + primary + ">"; - - for(var emailIndex in contacts[id].email) { - ret[ret.length] = contacts[id].email[emailIndex].email_address; - } - } - } - - return ret; - }, - - /** - * Hides address textareas to prevent autocomplete dropdown from being obscured - */ - toggleTextareaHide : function(sType, aArgs) { - var textBoxId = aArgs[0]._oTextbox.id; // "addressTo0" - var type = ""; - var idx = -1; - - if(textBoxId.indexOf("addressTO") > -1) { - type = "to"; - } else if(textBoxId.indexOf("addressCC") > -1) { - type = "cc"; - } - idx = textBoxId.substr(9); - - // follow through if not BCC - if(type != "") { - var cc = document.getElementById("addressCC" + idx); - var bcc = document.getElementById("addressBCC" + idx); - - switch(type) { - case "to": - cc.style.visibility = 'hidden'; - case "cc": - bcc.style.visibility = 'hidden'; - break; - } - } - }, - - /** - * Redisplays the textareas after an address is commited - */ - toggleTextareaShow : function(sType, aArgs) { - var textBoxId = aArgs[0]._oTextbox.id; // "addressTo0" - var type = ""; - var idx = -1; - - if(textBoxId.indexOf("addressTO") > -1) { - type = "to"; - } else if(textBoxId.indexOf("addressCC") > -1) { - type = "cc"; - } - idx = textBoxId.substr(9); - - // follow through if not BCC - if(type != "") { - document.getElementById("addressCC" + idx).style.visibility = 'visible'; - document.getElementById("addressBCC" + idx).style.visibility = 'visible'; - } - } -}; - -//// END AUTOCOMPLETE -/////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -//// COMPOSE & SEND -/** - * expands the options sidebar - */ -SE.composeLayout = { - currentInstanceId : 0, - ccHidden : true, - bccHidden : true, - outboundAccountErrors : null, - loadedTinyInstances : {}, //Tracks which tinyMCE editors have initalized with html content. - - showAddressDetails : function(e) { - var linkElement = document.getElementById("More"+e.id); - var spanElement = document.getElementById("Detail"+e.id); - var emailAddressList = e.value; - if(e.value.length > 96) - { - var resultArray = SE.composeLayout._getEmailArrayFromString(emailAddressList); - var displayArray = []; - for (var i=0; i<' + t_emailAddr + '>'); - else - displayArray.push(t_name + '
<' + t_emailAddr + '>'); - } - - var result = displayArray.join('
'); - // Display - linkElement.style.display = "inline"; - linkElement.style.height="10px"; - linkElement.style.overflow="visible"; - spanElement.innerHTML = result; - } - else - linkElement.style.display = "none"; - - }, - - /** - * Given a string of email address, return an array containing the name portion (if available) - * and email portion. - */ - _getEmailArrayFromString : function (emailAddressList){ - - var reg = /@.*?;/g; - while ((results = reg.exec(emailAddressList)) != null) - { - orignial = results[0]; - parsedResult = results[0].replace(';', ':::::'); - emailAddressList = emailAddressList.replace (orignial, parsedResult); - } - - reg = /@.*?,/g; - while ((results = reg.exec(emailAddressList)) != null) - { - orignial = results[0]; - parsedResult = results[0].replace(',', ':::::'); - emailAddressList = emailAddressList.replace (orignial, parsedResult); - } - //Administrator ;1@somwhe.com;2@somwherecomplex.com,3@somwherecomplex.com;4@somwherecomplex.com,5@somwherecomplex.com, - var emailArr = emailAddressList.split(":::::"); - var resultsArray = []; - var newArr = []; - for (var i=0; i'); - - if(trim(emailArr[i]) != '') - { - if(rposition != -1 && lposition != -1) - { - var t_name = emailArr[i].substr(0, rposition-1); - var t_emailAddr = emailArr[i].substr(rposition+1, (lposition-1 - rposition) ); - resultsArray.push({'name':t_name, 'email_address': t_emailAddr}); - } - else - { - resultsArray.push({'name':'', 'email_address': emailArr[i]}); - } - } - } - return resultsArray; - }, - /////////////////////////////////////////////////////////////////////////// - //// COMPOSE FLOW - /** - * Prepare bucket DIV and yui-ext tab panels - */ - _0_yui : function() { - var idx = this.currentInstanceId; - - var composeTab = new YAHOO.SUGAR.ClosableTab({ - label: mod_strings.LNK_NEW_SEND_EMAIL, - scroll : true, - content : "
", - id : "composeTab" + idx, - closeMsg: app_strings.LBL_EMAIL_CONFIRM_CLOSE, - active : true - }, SE.innerLayout); - SE.innerLayout.addTab(composeTab); - - // get template engine with template - if (!SE.composeLayout.composeTemplate) { - SE.composeLayout.composeTemplate = new YAHOO.SUGAR.Template(SE.templates['compose']); - } - - // create Tab inner layout - var composePanel = this.getComposeLayout(); - composePanel.getUnitByPosition("right").collapse(); - composePanel.autoSize(); - - }, - /** - * Generate the quick compose layout - * @method getQuickComposeLayout - * @param {Pannel} parentPanel Parent pannel - * @param {Object} o Options - * @return {} none - **/ - getQuickComposeLayout : function (parentPanel,o) { - var idx = SE.composeLayout.currentInstanceId; - - //Before rendering the parent pannel we need to initalize the grid layout - parentPanel.beforeRenderEvent.subscribe(function() { - - YAHOO.util.Event.onAvailable('htmleditordiv' + idx, function() { - SE.composeLayout._createComposeLayout(idx); - SE.composeLayout[idx].set('height', 350); - SE.composeLayout[idx].render(); - }); - }); - - //Wait until the Compose Layout has rendered, then add the - //options tab and perform the tiny initialization. - parentPanel.renderEvent.subscribe(function() { - - YAHOO.util.Event.onAvailable('htmleditordiv' + idx, function() { - SE.composeLayout._initComposeOptionTabs(idx); - SE.composeLayout[idx].getUnitByPosition("right").collapse(); - //Initialize tinyMCE - SE.composeLayout._1_tiny(false); - - //Init templates and address book - SE.composeLayout._2_final(); - - SE.composeLayout.quickCreateComposePackage(o); - - }); - }); - - //Check if we have the div override for the shortcut bar - if(typeof o.menu_id != 'undefined') { - parentPanel.render(o.menu_id); - } else { - parentPanel.render(document.body); - } - - return SE.composeLayout[idx]; - }, - /** - * Fill in all fields into the quick compose layout. - * @method quickCreateComposePackage - * @param {Object} o Options - * @return {} none - **/ - quickCreateComposePackage: function(o) - { - //If we have a compose package fill in defaults. - if (typeof(o.composePackage) != 'undefined') - { - composePackage = o.composePackage; //Set the compose data object - //Hijack this method called by composePackage as it's not need for quick creates. - SE.composeLayout.c0_composeNewEmail = function(){}; - SE.composeLayout.composePackage(); //Fill in defaults. - } - }, - getComposeLayout : function() { - var idx = SE.composeLayout.currentInstanceId; - - this._createComposeLayout(idx); - SE.composeLayout[idx].render(); - this._initComposeOptionTabs(idx); - - return SE.composeLayout[idx]; - }, - - /** - * Create the layout manager for the compose window. - */ - _createComposeLayout : function(idx) - { - SE.composeLayout[idx] = new YAHOO.widget.Layout('htmleditordiv' + idx, { - parent: SE.complexLayout, - border:true, - hideOnLayout: true, - height: 400, - units: [{ - position: "center", - animate: false, - scroll: false, - split:true, - body: - SE.composeLayout.composeTemplate.exec({ - 'app_strings':app_strings, - 'mod_strings':mod_strings, - 'linkbeans_options' : linkBeans, - 'idx' : SE.composeLayout.currentInstanceId - }) - },{ - position: "right", - scroll:true, - collapse: true, - collapsed: true, - resize: true, - border:true, - animate: false, - width:'230', - body: "
", - titlebar: true, - split: true, - header: app_strings.LBL_EMAIL_OPTIONS - }] - }); - }, - - /** - * Create compose tab which will populate the 'right' container in the compose window. - */ - _initComposeOptionTabs : function(idx) - { - var cTabs = new YAHOO.widget.TabView("composeRightTabs" + idx); - var tab = new YAHOO.widget.Tab({ - label: app_strings.LBL_EMAIL_ATTACHMENT, - scroll : true, - content : SUGAR.util.getAndRemove("divAttachments" + idx).innerHTML, - id : "divAttachments" + idx, - active : true - }); - - tab.layout = SE.composeLayout[idx]; - - tab.on("activeChange", function(o){ - if (o.newValue) { - this.layout.getUnitByPosition("right").set("header", app_strings.LBL_EMAIL_ATTACHMENT); - } - }); - - cTabs.addTab(tab); - - tab = new YAHOO.widget.Tab({ - label: app_strings.LBL_EMAIL_OPTIONS, - scroll : true, - content : SUGAR.util.getAndRemove("divOptions" + idx).innerHTML, - id : "divOptions" + idx, - active : false - }); - - tab.layout = SE.composeLayout[idx]; - tab.on("activeChange", function(o){ - if (o.newValue) { - this.layout.getUnitByPosition("right").set("header", app_strings.LBL_EMAIL_OPTIONS); - } - }); - cTabs.addTab(tab); - - SE.composeLayout[idx].autoSize = function() { - var pEl = this.get("element").parentNode.parentNode.parentNode; - this.set("height", pEl.clientHeight-30); - this.render(); - } - - SE.composeLayout[idx].rightTabs = cTabs; - }, - isParentTypeValid : function(idx) { - var parentTypeValue = document.getElementById('data_parent_type' + idx).value; - var parentNameValue = document.getElementById('data_parent_name' + idx).value; - if (trim(parentTypeValue) == ""){ - alert(mod_strings.LBL_ERROR_SELECT_MODULE); - return false; - } // if - return true; - }, - - isParentTypeAndNameValid : function(idx) { - var parentTypeValue = document.getElementById('data_parent_type' + idx).value; - var parentNameValue = document.getElementById('data_parent_name' + idx).value; - var parentIdValue = document.getElementById('data_parent_id' + idx).value; - if ((trim(parentTypeValue) != "" && trim(parentNameValue) == "") || - (trim(parentTypeValue) != "" && trim(parentNameValue) != "" && parentIdValue == "")){ - alert(mod_strings.LBL_ERROR_SELECT_MODULE_SELECT); - return false; - } // if - return true; - }, - - callopenpopupForEmail2 : function(idx,options) { - - var formName = 'emailCompose' + idx; - - if(typeof(options) != 'undefined' && typeof(options.form_name) != 'undefined') - formName = options.form_name; - - var parentTypeValue = document.getElementById('data_parent_type' + idx).value; - var parentNameValue = document.getElementById('data_parent_name' + idx).value; - if (!SE.composeLayout.isParentTypeValid(idx)) { - return; - } // if - open_popup(document.getElementById('data_parent_type' + idx).value,600,400,'&tree=ProductsProd',true,false, - { - call_back_function:"SE.composeLayout.popupAddEmail", - form_name:formName, - field_to_name_array:{ - id:'data_parent_id' + idx, - name:'data_parent_name' + idx, - email1:'email1'} - }); - }, - - popupAddEmail : function(o) - { - var nameKey = "data_parent_name" + SE.composeLayout.currentInstanceId; - var data = o.name_to_value_array; - if (typeof (data[nameKey]) != "undefined" && data[nameKey] != "" - && typeof (data["email1"]) != "undefined" && data["email1"] != "" && data["email1"] != "undefined") - { - var target = Dom.get("addressTO" + SE.composeLayout.currentInstanceId); - target.value = SE.addressBook.smartAddEmailAddressToComposeField(target.value, data[nameKey] + "<" + data.email1 + ">"); - } - set_return(o); - }, - /** - * Prepare TinyMCE - */ - _1_tiny : function(isReplyForward) { - var idx = SE.composeLayout.currentInstanceId; - var elId = SE.tinyInstances.currentHtmleditor = 'htmleditor' + idx; - SE.tinyInstances[elId] = { }; - SE.tinyInstances[elId].ready = false; - - if (!SUGAR.util.isTouchScreen()) { - var t = tinyMCE.getInstanceById(elId); - } - if(typeof(t) == 'undefined') { - if (!SUGAR.util.isTouchScreen()) { - tinyMCE.execCommand('mceAddControl', false, elId); - } - YAHOO.util.Event.onAvailable(elId + "_parent", function() { - SE.composeLayout.resizeEditorSetSignature(idx,!isReplyForward); - }, this); - } - }, - - resizeEditorSetSignature : function(idx,setSignature) - { - var instance = SE.util.getTiny(SE.tinyInstances.currentHtmleditor); - - if(typeof(instance) == 'undefined' || (typeof(SE.composeLayout.loadedTinyInstances[idx]) != 'undefined' && SE.composeLayout.loadedTinyInstances[idx] == false)) { - setTimeout("SE.composeLayout.resizeEditorSetSignature(" + idx + ",'"+setSignature+"');",500); - return; - } - - SE.composeLayout.resizeEditor(idx); - if(setSignature) { - setTimeout("SUGAR.email2.composeLayout.setSignature("+idx+");",250); - } - - }, - - resizeEditor : function(idx) - { - var cof = Dom.get('composeOverFrame' + idx); - var head = Dom.get('composeHeaderTable' + idx); - var targetHeight = cof.clientHeight - head.clientHeight; - var instance = SE.util.getTiny('htmleditor' + idx); - - try { - var parentEl = Dom.get(instance.editorId + '_parent'); - var toolbar = Dom.getElementsByClassName("mceFirst", "tr", parentEl)[0]; - var contentEl = instance.contentAreaContainer; - var iFrame = contentEl.firstChild; - var tinMceToolbarOffset = 18; - iFrame.style.height = (targetHeight - toolbar.offsetHeight - tinMceToolbarOffset) + "px"; - - } catch(e) { - setTimeout("SE.composeLayout.resizeEditor("+idx+");",1000); - } - }, - - /** - * Initializes d&d, auto-complete, email templates - */ - _2_final : function() { - var idx = SE.composeLayout.currentInstanceId; - - if(this.emailTemplates) { - this.setComposeOptions(idx); - } else { - //populate email template cache - AjaxObject.target = ''; - AjaxObject.startRequest(callbackComposeCache, urlStandard + "&emailUIAction=fillComposeCache"); - } - - // handle drop targets for addressBook - var to = new YAHOO.util.DDTarget('addressTO' +idx, 'addressBookDD', {notifyDrop:this.handleDrop}); - var cc = new YAHOO.util.DDTarget('addressCC' +idx, 'addressBookDD', {notifyDrop:this.handleDrop}); - var bcc = new YAHOO.util.DDTarget('addressBCC'+idx, 'addressBookDD', {notifyDrop:this.handleDrop}); - to.notifyDrop = cc.notifyDrop = bcc.notifyDrop = this.handleDrop; - - // auto-complete setup - SE.autoComplete.init(idx); - - // set focus on to: - document.getElementById("addressTO" + idx).focus(); - }, - - /** - * hide tinyMCE tool bar if send email as plaintext is checked - */ - renderTinyMCEToolBar : function (idx, hide) { - if (hide) { - document.getElementById('htmleditor' + idx + '_toolbar1').style.display = 'none'; - } else { - document.getElementById('htmleditor' + idx + '_toolbar1').style.display = ''; - } - }, - - c1_composeEmail : function(isReplyForward, retry) { - if (!retry) { - this._0_yui(); - } - if (!SUGAR.util.isTouchScreen() && (typeof(tinyMCE) == 'undefined' || typeof(tinyMCE.settings) == 'undefined')){ - setTimeout("SE.composeLayout.c1_composeEmail(" + isReplyForward + ", true);", 500); - } else { - this._1_tiny(isReplyForward); - this._2_final(); - - if(isReplyForward) { - this.replyForwardEmailStage2(); - } - } - }, - - /** - * takes draft info and prepopulates - */ - c0_composeDraft : function() { - this.getNewInstanceId(); - inCompose = true; - document.getElementById('_blank').innerHTML = ''; - var idx = SE.composeLayout.currentInstanceId; - SE.composeLayout.draftObject = new Object(); - SE.composeLayout.draftObject.id = idx; - SE.composeLayout.draftObject.isDraft = true; - SE.composeLayout.currentInstanceId = idx; - SE.tinyInstances.currentHtmleditor = 'htmleditor' + SE.composeLayout.currentInstanceId; - SE.tinyInstances[SE.tinyInstances.currentHtmleditor] = new Object(); - SE.tinyInstances[SE.tinyInstances.currentHtmleditor].ready = false; - - SE.composeLayout._0_yui(); - SE.composeLayout._1_tiny(true); - - // final touches - SE.composeLayout._2_final(); - - /* Draft-specific final processing. Need a delay to allow Tiny to render before calling setText() */ - setTimeout("AjaxObject.handleReplyForwardForDraft(SE.o);", 1000); - }, - - /** - * Strip & Prep editor hidden fields - */ - c0_composeNewEmail : function() { - this.getNewInstanceId(); - this.c1_composeEmail(false); - }, - - /** - * Sends async request to get the compose view. - * Requests come from "reply" or "forwards" - */ - c0_replyForwardEmail : function(ieId, uid, mbox, type) { - SE.composeLayout.replyForwardObj = new Object(); - SE.composeLayout.replyForwardObj.ieId = ieId; - SE.composeLayout.replyForwardObj.uid = uid; - SE.composeLayout.replyForwardObj.mbox = mbox; - SE.composeLayout.replyForwardObj.type = type; - - if(mbox == 'sugar::Emails') { - SE.composeLayout.replyForwardObj.sugarEmail = true; - } - - SE.composeLayout.getNewInstanceId(); - SE.composeLayout.c1_composeEmail(true); - }, - //// END COMPOSE FLOW - /////////////////////////////////////////////////////////////////////////// - - /** - * Called when a contact, email, or mailinglist is dropped - * into one of the compose fields. - */ - handleDrop : function (source, event, data, target) { - var nodes; - if (!target) { - target = event.getTarget(); - if (data.single) { - data.nodes = [data.nodes]; - } - nodes = data.nodes; - } else { - target = document.getElementById(target); - nodes = data; - } - - if (target.id.indexOf('address') > -1) { - // dropped onto email to/cc/bcc field - for(var i in nodes) { - var node = nodes[i].getData(); - var email = ""; - if (node[1].indexOf('contact') > -1) { - email = SE.addressBook.getFormattedAddress(node[0]); - } else if (node[1].indexOf('address-email') > -1){ - email = node[3].replace(/ /gi, ''); - email = email.replace('<', '<').replace('>', '>'); - var tr = source.getTrEl(nodes[i]); - while (tr && !Dom.hasClass(tr, "address-contact")) { - tr = source.getPreviousTrEl(tr); - } - var CID = source.getRecord(tr).getData()[0]; - var o = SE.addressBook._contactCache[CID]; - var name = new String(o.name); - var finalName = name.replace(/(<([^>]+)>)/ig, ""); - email = finalName + email; - } - target.value = SE.addressBook.smartAddEmailAddressToComposeField(target.value, email); - } - } - }, - - - /*///////////////////////////////////////////////////////////////////////////// - /// EMAIL TEMPLATE CODE - */ - applyEmailTemplate : function (idx, id) { - - //bug #20680 - var box_title = mod_strings.LBL_EMAILTEMPLATE_MESSAGE_SHOW_TITLE; - var box_msg = mod_strings.LBL_EMAILTEMPLATE_MESSAGE_SHOW_MSG; - var box_none_msg = mod_strings.LBL_EMAILTEMPLATE_MESSAGE_CLEAR_MSG; - - //bug #6224 - var to_addr = document.getElementById('addressTO'+idx); - if (to_addr.value.search(/[^;,]{6,}[;,][^;,]{6,}/) != -1) - { - box_title = mod_strings.LBL_EMAILTEMPLATE_MESSAGE_WARNING_TITLE; - box_msg = mod_strings.LBL_EMAILTEMPLATE_MESSAGE_MULTIPLE_RECIPIENTS + '

' + box_msg; - } - - // id is selected index of email template drop-down - if(id == '' || id == "0") { - YAHOO.SUGAR.MessageBox.show({ - title:box_title, - msg: box_none_msg, - type: 'confirm', - fn: function(btn){ - if(btn=='no'){return;}; - SUGAR.email2.composeLayout.processNoneResult(idx, id);}, - modal:true, - scope:this - }); - return; - } - - YAHOO.SUGAR.MessageBox.show({ - title:box_title, - msg: box_msg, - type: 'confirm', - fn: function(btn){ - if(btn=='no'){return;}; - SUGAR.email2.composeLayout.processResult(idx, id);}, - modal:true, - scope:this - }); - }, - - processNoneResult : function(idx, id) { - var tiny = SE.util.getTiny('htmleditor' + idx); - var tinyHTML = tiny.getContent(); - var openTag = '
'; - var htmllow = tinyHTML.toLowerCase(); - var start = htmllow.indexOf(openTag); - if (start > -1) { - tinyHTML = tinyHTML.substr(start); - tiny.setContent(tinyHTML); - } else { - tiny.setContent(''); - } - }, - - processResult : function(idx , id){ - var post_data = {"module":"EmailTemplates","record":id}; - var global_rpcClient = new SugarRPCClient(); - - result = global_rpcClient.call_method('retrieve', post_data, true); - if(!result['record']) return; - json_objects['email_template_object'] = result['record']; - this.appendEmailTemplateJSON(); - - // get attachments if any - AjaxObject.target = ''; - AjaxObject.startRequest(callbackLoadAttachments, urlStandard + "&emailUIAction=getTemplateAttachments&parent_id=" + id); - }, - - appendEmailTemplateJSON : function() { - var idx = SE.composeLayout.currentInstanceId; // post increment - - // query based on template, contact_id0,related_to - //jchi 09/10/2008 refix #7743 - if(json_objects['email_template_object']['fields']['subject'] != '' ) { // cn: bug 7743, don't stomp populated Subject Line - document.getElementById('emailSubject' + idx).value = decodeURI(encodeURI(json_objects['email_template_object']['fields']['subject'])); - } - var text = ''; - if(json_objects['email_template_object']['fields']['text_only'] == 1){ - text = "

" + decodeURI(encodeURI(json_objects['email_template_object']['fields']['body'])).replace(/
/ig, '

').replace(/
/gi, "

").replace(/&/gi,'&').replace(/</gi,'<').replace(/>/gi,'>').replace(/'/gi,'\'').replace(/"/gi,'"') + "

"; - document.getElementById("setEditor1").checked = true; - SUGAR.email2.composeLayout.renderTinyMCEToolBar('1', 1); - } - else{ - text = decodeURI(encodeURI(json_objects['email_template_object']['fields']['body_html'])).replace(/
/ig, '\n').replace(/
/gi, "\n").replace(/&/gi,'&').replace(/</gi,'<').replace(/>/gi,'>').replace(/'/gi,'\'').replace(/"/gi,'"'); - document.getElementById("setEditor1").checked = false; - SUGAR.email2.composeLayout.renderTinyMCEToolBar('1', 0); - } - - - var tiny = SE.util.getTiny('htmleditor' + idx); - var tinyHTML = tiny.getContent(); - var openTag = '
'; - var closeTag = '
'; - var htmllow = tinyHTML.toLowerCase(); - var start = htmllow.indexOf(openTag); - if (start > -1) { - var htmlPart2 = tinyHTML.substr(start); - tinyHTML = text + htmlPart2; - tiny.setContent(tinyHTML); - } else { - tiny.setContent(text); - } - }, - - /** - * Writes out the signature in the email editor - */ - setSignature : function(idx) { - if (!tinyMCE) - return false; - var hide = document.getElementById('setEditor' + idx).checked; - SE.composeLayout.renderTinyMCEToolBar(idx,hide); - //wait for signatures to load before trying to set them - if (!SE.composeLayout.signatures) { - setTimeout("SE.composeLayout.setSignature(" + idx + ");", 1000); - return; - } - - if(idx != null) { - var sel = document.getElementById('signatures' + idx); - } else { - var sel = document.getElementById('signature_id'); - idx = SE.tinyInstances.currentHtmleditor; - } - - //Ensure that the tinyMCE html has been rendered. - if(typeof(SE.composeLayout.loadedTinyInstances[idx]) != 'undefined' && SE.composeLayout.loadedTinyInstances[idx] == false) { - setTimeout("SE.composeLayout.setSignature(" + idx + ");",1000); - return; - } - - var signature = ''; - - try { - signature = sel.options[sel.selectedIndex].value; - } catch(e) { - - } - - var openTag = '
 '; - var closeTag = ' 
'; - var t = tinyMCE.getInstanceById('htmleditor' + idx); - //IE 6 Hack - if(typeof(t) != 'undefined') - { - t.contentDocument = t.contentWindow.document; - var html = t.getContent(); - } - else - { - var html = ''; - } - - var htmllow = html.toLowerCase(); - var start = htmllow.indexOf(openTag); - var end = htmllow.indexOf(closeTag) + closeTag.length; - - // selected "none" - remove signature from email - if(signature == '') { - if (start > -1) { - var htmlPart1 = html.substr(0, start); - var htmlPart2 = html.substr(end, html.length); - - html = htmlPart1 + htmlPart2; - t.setContent(html); - } - SE.signatures.lastAttemptedLoad = ''; - return false; - } - - if(!SE.signatures.lastAttemptedLoad) // lazy load place holder - SE.signatures.lastAttemptedLoad = ''; - - SE.signatures.lastAttemptedLoad = signature; - - if(typeof(SE.signatures[signature]) == 'undefined') { - //lazy load - SE.signatures.lastAttemptedLoad = ''; // reset this flag for recursion - SE.signatures.targetInstance = (idx) ? idx : ""; - AjaxObject.target = ''; - AjaxObject.startRequest(callbackLoadSignature, urlStandard + "&emailUIAction=getSignature&id="+signature); - } else { - var newSignature = this.prepareSignature(SE.signatures[signature]); - - // clear out old signature - if(SE.signatures.lastAttemptedLoad && start > -1) { - var htmlPart1 = html.substr(0, start); - var htmlPart2 = html.substr(end, html.length); - - html = htmlPart1 + htmlPart2; - } - - // pre|append - start = html.indexOf('

'); - if(SE.userPrefs.signatures.signature_prepend == 'true' && start > -1) { - var htmlPart1 = html.substr(0, start); - var htmlPart2 = html.substr(start, html.length); - var newHtml = htmlPart1 + openTag + newSignature + closeTag + htmlPart2; - } else if(SUGAR.email2.userPrefs.signatures.signature_prepend == 'true') { - - //bug 48285 - var newHtml = html; - - //remove custom spacing - var spacing = '


 '; - var customSpacingStart = html.indexOf(spacing); - - if (customSpacingStart > -1) - { - var part1 = newHtml.substr(0, customSpacingStart); - var part2 = newHtml.substr(customSpacingStart+spacing.length, newHtml.length); - newHtml = part1 + part2; - } - - //append signature - var bodyStartTag = ''; - var body = newHtml.indexOf(bodyStartTag); - - if (body > -1) - { - var part1 = newHtml.substr(0, body+bodyStartTag.length); - var part2 = newHtml.substr(body+bodyStartTag.length, newHtml.length); - newHtml = part1 + spacing + openTag + newSignature + closeTag + part2; - } - else - { - newHtml = openTag + newSignature + closeTag + newHtml; - } - //end bug 48285 - } else { - var body = html.indexOf(''); - if (body > -1) { - var part1 = html.substr(0, body); - var part2 = html.substr(body, html.length); - var newHtml = part1 + openTag + newSignature + closeTag + part2; - } else { - var newHtml = html + openTag + newSignature + closeTag; - } - } - //tinyMCE.setContent(newHtml); - t.setContent(newHtml); - } - }, - - prepareSignature : function(str) { - var signature = new String(str); - - signature = signature.replace(/</gi, '<'); - signature = signature.replace(/>/gi, '>'); - - return signature; - }, - - - showAttachmentPanel : function(idx) { - var east = SE.composeLayout[idx].getUnitByPosition("right"); - var tabs = SE.composeLayout[idx].rightTabs; - east.expand(); - tabs.set("activeTab", tabs.getTab(0)); - }, - - /** - * expands sidebar and displays options panel - */ - showOptionsPanel : function(idx) { - var east = SE.composeLayout[idx].getUnitByPosition("right"); - var tabs = SE.composeLayout[idx].rightTabs; - east.expand(); - tabs.set("activeTab", tabs.getTab(1)); - }, - - /** - * Selects the Contacts tab - */ - showContactsPanel : function() { - SE.complexLayout.regions.west.showPanel("contactsTab"); - }, - - /** - * Generates fields for Select Document - */ - addDocumentField : function(idx) { - var basket = document.getElementById('addedDocuments' + idx); - if(basket) { - var index = (basket.childNodes.length / 7) - 1; - if(index < 0) - index = 0; - } else { - index = 0; - } - - var test = document.getElementById('documentId' + idx + index); - - while(test != null) { - index++; - test = document.getElementById('documentId' + idx + index); - } - - var documentCup = document.createElement("div"); - documentCup.id = 'documentCup' + idx + index; - documentCup.innerHTML = "" + - // document id field - "" + - // document name field - "" + - // select button - "" + - // remove button - "" + - "
"; - - basket.appendChild(documentCup); - //basket.innerHTML += out; - return index; - }, - - /** - * Makes async call to save a draft of the email - * @param int Instance index - */ - saveDraft : function(tinyInstance) { - this.sendEmail(tinyInstance, true); - }, - - selectDocument : function(target) { - URL="index.php?module=Emails&action=PopupDocuments&to_pdf=true&target=" + target; - windowName = 'selectDocument'; - windowFeatures = 'width=800' + ',height=600' + ',resizable=1,scrollbars=1'; - - win = SUGAR.util.openWindow(URL, windowName, windowFeatures); - if(window.focus) { - // put the focus on the popup if the browser supports the focus() method - win.focus(); - } - }, - - /** - * Modal popup for file attachment dialogue - */ - addFileField : function() { - if(!SE.addFileDialog){ // lazy initialize the dialog and only create it once - SE.addFileDialog = new YAHOO.widget.Dialog("addFileDialog", { - modal:true, - visible:false, - fixedcenter:true, - constraintoviewport: true, - scroll: true, - keylisteners : new YAHOO.util.KeyListener(document, { keys:27 }, { - fn:function(){SE.addFileDialog.hide();} - }) - }); - SE.addFileDialog.setHeader(app_strings.LBL_EMAIL_ATTACHMENTS); - SE.addFileDialog.render(); - // SE.addFileDialog.addKeyListener(27, , SE.addFileDialog); - } - Dom.removeClass("addFileDialog", "yui-hidden"); - - SE.addFileDialog.show(); - }, - - /** - * Async upload of file to temp dir - */ - uploadAttachment : function() { - if(document.getElementById('email_attachment').value != "") { - var formObject = document.getElementById('uploadAttachment'); - YAHOO.util.Connect.setForm(formObject, true, true); - AjaxObject.target = ''; - AjaxObject.startRequest(callbackUploadAttachment, null); - } else { - alert(app_strings.LBL_EMAIL_ERROR_NO_FILE); - } - }, - - /** - * Adds a SugarDocument to an outbound email. Action occurs in a popup window displaying a ListView from the Documents module - * @param string target in focus compose layout - */ - setDocument : function(idx, target, documentId, documentName, docRevId) { - // fields are named/id'd [fieldName][instanceId][index] - var addedDocs = document.getElementById("addedDocuments" + idx); - var docId = document.getElementById('documentId' + idx + target); - var docName = document.getElementById('documentName' + idx + target); - var docRevisionId = document.getElementById('document' + idx + target); - docId.value = documentId; - docName.value = documentName; - docRevisionId.value = docRevId; - }, - - /** - * Removes the bucket div containing the document input fields - */ - deleteDocumentField : function(documentCup) { - var f0 = document.getElementById(documentCup); - f0.parentNode.removeChild(f0); - }, - - /** - * Removes a Template Attachment field - * @param int - * @param int - */ - deleteTemplateAttachmentField : function(idx, index) { - // create not-in-array values for removal filtering - var r = document.getElementById("templateAttachmentsRemove" + idx).value; - - if(r != "") { - r += "::"; - } - - r += document.getElementById('templateAttachmentId' + idx + index).value; - document.getElementById("templateAttachmentsRemove" + idx).value = r; - - var target = 'templateAttachmentCup' + idx + index; - d = document.getElementById(target); - d.parentNode.removeChild(d); - }, - - /** - * Async removal of uploaded temp file - * @param string index Should be a concatenation of idx and index - * @param string - */ - deleteUploadAttachment : function(index, file) { - var d = document.getElementById('email_attachment_bucket' + index); - d.parentNode.removeChild(d); - - // make async call to delete cached file - AjaxObject.target = ''; - AjaxObject.startRequest('', urlStandard + "&emailUIAction=removeUploadedAttachment&file="+file); - }, - - /** - * Attaches files coming from Email Templates - */ - addTemplateAttachmentField : function(idx) { - // expose title - document.getElementById('templateAttachmentsTitle' + idx).style.display = 'block'; - - var basket = document.getElementById('addedTemplateAttachments' + idx); - - if(basket) { - var index = basket.childNodes.length; - if(index < 0) - index = 0; - } else { - index = 0; - } - - var out = "
" + - // remove button - "" + - // file icon - "" + - // templateAttachment field - "" + - // docId field - "" + - // file name - " " + - "

" + - "
"; - basket.innerHTML = basket.innerHTML + out; - - return index; - }, - - /** - * Sends one email via async call - * @param int idx Editor instance ID - * @param bool isDraft - */ - sendEmail : function(idx, isDraft) { - - //If the outbound account has an error message associate with it, alert the user and refuse to continue. - var obAccountID = document.getElementById('addressFrom' + idx).value; - - if( typeof(SUGAR.email2.composeLayout.outboundAccountErrors[obAccountID]) != 'undefined' ) - { - SUGAR.showMessageBox(app_strings.LBL_EMAIL_ERROR_DESC, SUGAR.email2.composeLayout.outboundAccountErrors[obAccountID], 'alert'); - return false; - } - - - var form = document.getElementById('emailCompose' + idx); - var composeOptionsFormName = "composeOptionsForm" + idx; - - - var t = SE.util.getTiny(SE.tinyInstances.currentHtmleditor); - if (t != null || typeof(t) != "undefined") { - var html = t.getContent(); - } else { - var html = "

" + document.getElementById('htmleditor' + idx).value + "

"; - } - - var subj = document.getElementById('emailSubject' + idx).value; - var to = trim(document.getElementById('addressTO' + idx).value); - var cc = trim(document.getElementById('addressCC' + idx).value); - var bcc = trim(document.getElementById('addressBCC' + idx).value); - var email_id = document.getElementById('email_id' + idx).value; - var composeType = document.getElementById('composeType').value; - var parent_type = document.getElementById("parent_type").value; - var parent_id = document.getElementById("parent_id").value; - - var el_uid = document.getElementById("uid"); - var uid = (el_uid == null) ? '' : el_uid.value; - - var el_ieId = document.getElementById("ieId"); - var ieId = (el_ieId == null) ? '' : el_ieId.value; - - var el_mbox = document.getElementById("mbox"); - var mbox = (el_mbox == null) ? '' : el_mbox.value; - - if (!isValidEmail(to) || !isValidEmail(cc) || !isValidEmail(bcc)) { - alert(app_strings.LBL_EMAIL_COMPOSE_INVALID_ADDRESS); - return false; - } - - if (!SE.composeLayout.isParentTypeAndNameValid(idx)) { - return; - } // if - var parentTypeValue = document.getElementById('data_parent_type' + idx).value; - var parentIdValue = document.getElementById('data_parent_id' + idx).value; - parent_id = parentIdValue; - parent_type = parentTypeValue; - - var in_draft = (document.getElementById('type' + idx).value == 'draft') ? true : false; - // baseline viability check - - if(to == "" && cc == '' && bcc == '' && !isDraft) { - alert(app_strings.LBL_EMAIL_COMPOSE_ERR_NO_RECIPIENTS); - return false; - } else if(subj == '' && !isDraft) { - if(!confirm(app_strings.LBL_EMAIL_COMPOSE_NO_SUBJECT)) { - return false; - } else { - subj = app_strings.LBL_EMAIL_COMPOSE_NO_SUBJECT_LITERAL; - } - } else if(html == '' && !isDraft) { - if(!confirm(app_strings.LBL_EMAIL_COMPOSE_NO_BODY)) { - return false; - } - } - - SE.util.clearHiddenFieldValues('emailCompose' + idx); - document.getElementById('data_parent_id' + idx).value = parentIdValue; - var title = (isDraft) ? app_strings.LBL_EMAIL_SAVE_DRAFT : app_strings.LBL_EMAIL_SENDING_EMAIL; - SUGAR.showMessageBox(title, app_strings.LBL_EMAIL_ONE_MOMENT); - html = html.replace(/</ig, "sugarLessThan"); - html = html.replace(/>/ig, "sugarGreaterThan"); - - form.sendDescription.value = html; - form.sendSubject.value = subj; - form.sendTo.value = to; - form.sendCc.value = cc; - form.sendBcc.value = bcc; - form.email_id.value = email_id; - form.composeType.value = composeType; - form.composeLayoutId.value = 'composeLayout' + idx; - form.setEditor.value = (document.getElementById('setEditor' + idx).checked == false) ? 1 : 0; - form.saveToSugar.value = 1; - form.fromAccount.value = document.getElementById('addressFrom' + idx).value; - form.parent_type.value = parent_type; - form.parent_id.value = parent_id; - form.uid.value = uid; - form.ieId.value = ieId; - form.mbox.value = mbox; - - // email attachments - var addedFiles = document.getElementById('addedFiles' + idx); - if(addedFiles) { - for(i=0; i 0) { - document.getElementById("emailSubject" + SE.composeLayout.currentInstanceId).value = composePackage.subject; - } - - //If no parent fields are set in the composePackage, ensure they are cleared. - var parentFields = ['parent_type','parent_name','parent_id']; - for(var i=0;i 0) { - document.getElementById("email_id" + SE.composeLayout.currentInstanceId).value = composePackage.email_id; - } // if - if (composePackage.body != null && composePackage.body.length > 0) { - var tiny = SE.util.getTiny('htmleditor' + SE.composeLayout.currentInstanceId); - SE.composeLayout.loadedTinyInstances[SE.composeLayout.currentInstanceId] = false; - setTimeout("SE.composeLayout.setContentOnThisTiny();", 3000); - } // if - if (composePackage.attachments != null) { - SE.composeLayout.loadAttachments(composePackage.attachments); - } // if - - if (composePackage.fromAccounts != null && composePackage.fromAccounts.status) { - var addressFrom = document.getElementById('addressFrom' + SE.composeLayout.currentInstanceId); - SE.util.emptySelectOptions(addressFrom); - var fromAccountOpts = composePackage.fromAccounts.data; - for(i=0; i/ig, '\n').replace(/
/gi, "\n").replace(/&/gi,'&').replace(/</gi,'<').replace(/>/gi,'>').replace(/'/gi,'\'').replace(/"/gi,'"'); - } // if - //Flag determines if we should clear the tiny contents or just append - if (typeof(composePackage.clearBody) != 'undefined' && composePackage.clearBody) - { - SE.composeLayout.tinyHTML = ''; - } - else - { - //bug 48179 - //check tinyHTML for closing tags - var body = tinyHTML.lastIndexOf(''); - spacing = '


 '; - - if (body > -1) - { - var part1 = tinyHTML.substr(0, body); - var part2 = tinyHTML.substr(body, tinyHTML.length); - var newHtml = part1 + spacing + composePackage.body + part2; - } - else - { - var newHtml = tinyHTML + spacing + composePackage.body; - } - //end bug 48179 - - SE.composeLayout.tinyHTML = newHtml; - } - - tiny.setContent(SE.composeLayout.tinyHTML); - //Indicate that the contents has been loaded successfully. - SE.composeLayout.loadedTinyInstances[SE.composeLayout.currentInstanceId] = true; - }, - /** - * Confirms closure of a compose screen if "x" is clicked - */ - confirmClose : function(panel) { - if(confirm(app_strings.LBL_EMAIL_CONFIRM_CLOSE)) { - SE.composeLayout.closeCompose(panel.id); - return true; - } else { - return false; - } - }, - - /** - * forces close of a compose screen - */ - forceCloseCompose : function(id) { - SE.composeLayout.closeCompose(id); - - // handle flow back to originating view - if(composePackage) { - // check if it's a module we need to return to - if(composePackage.return_module && composePackage.return_action && composePackage.return_id) { - if(confirm(app_strings.LBL_EMAIL_RETURN_TO_VIEW)) { - var url = "index.php?module=" + composePackage.return_module + "&action=" + composePackage.return_action + "&record=" + composePackage.return_id; - window.location = url; - } - } - } - }, - - /** - * closes the editor that just sent email - * @param string id ID of composeLayout tab - */ - closeCompose : function(id) { - // destroy tinyMCE instance - var idx = id.substr(13, id.length); - var instanceId = "htmleditor" + idx; - tinyMCE.execCommand('mceRemoveControl', false, instanceId); - - // nullify DOM and namespace values. - inCompose = false; - SE.composeLayout[idx] = null; - SE.tinyInstances[instanceId] = null; - var tabsArray = SE.innerLayout.get("tabs"); - for (i = 0 ; i < tabsArray.length ; i++) { - if (tabsArray[i].get("id") == ('composeTab' + idx)) { - tabsArray[i].close(); - break; - } - } - //SE.innerLayout.getTab(idx).close(); - }, - - /** - * Enable the quick search for the compose relate field or search tab - */ - enableQuickSearchRelate: function(idx,overides){ - - if(typeof overides != 'undefined') - { - var newModuleID = overides['moduleSelectField']; //data_parent_type_search - var newModule = document.getElementById(newModuleID).value; - var formName = overides['formName']; - var fieldName = overides['fieldName']; - var fieldId = overides['fieldId']; - var fullName = formName + "_" + fieldName; - var postBlurFunction = null; - } - else - { - var newModule = document.getElementById('data_parent_type'+idx).value; - var formName = 'emailCompose'+idx; - var fieldName = 'data_parent_name'+idx; - var fieldId = 'data_parent_id'+idx; - var fullName = formName + "_" + fieldName; - var postBlurFunction = "SE.composeLayout.qsAddAddress"; - } - - if(typeof sqs_objects == 'undefined') - window['sqs_objects'] = new Array; - - window['sqs_objects'][fullName] = { - form:formName, - method:"query", - modules:[newModule], - group:"or", - field_list:["name","id", "email1"],populate_list:[fieldName,fieldId],required_list:[fieldId], - conditions:[{name:"name",op:"like_custom",end:"%",value:""}], - post_onblur_function: postBlurFunction, - order:"name","limit":"30","no_match_text":"No Match"}; - - - if(typeof QSProcessedFieldsArray != 'undefined') - QSProcessedFieldsArray[fullName] = false; - if (typeof(QSFieldsArray) != 'undefined' && typeof(QSFieldsArray[fullName]) != 'undefined') { - QSFieldsArray[fullName].destroy(); - delete QSFieldsArray[fullName]; - } - if (Dom.get(fullName + "_results")) { - Dom.get(fullName + "_results").parentNode.removeChild(Dom.get(fullName + "_results")); - } - - enableQS(false); - }, - - qsAddAddress : function(o) { - if (o.name != "" && o.email1 != "") - { - var target = Dom.get("addressTO" + SE.composeLayout.currentInstanceId); - target.value = SE.addressBook.smartAddEmailAddressToComposeField(target.value, o.name + "<" + o.email1 + ">"); - } - }, - /** - * Returns a new instance ID, 0-index - */ - getNewInstanceId : function() { - this.currentInstanceId = this.currentInstanceId + 1; - return this.currentInstanceId; - }, - - /** - * Takes an array of objects that contain the filename and GUID of a Note (attachment or Sugar Document) and applies the values to the compose screen. Valid use-cases are applying an EmailTemplate or resuming a Draft Email. - */ - loadAttachments : function(result) { - var idx = SE.composeLayout.currentInstanceId; - - if(typeof(result) == 'object') { - //jchi #20680. Clean the former template attachments; - var basket = document.getElementById('addedTemplateAttachments' + idx); - if(basket.innerHTML != ''){ - confirm(mod_strings.LBL_CHECK_ATTACHMENTS, mod_strings.LBL_HAS_ATTACHMENTS, function(btn){ - if (btn != 'yes'){ - basket.innerHTML = ''; - } - }); - } - for(i in result) { - if(typeof result[i] == 'object') { - var index = SE.composeLayout.addTemplateAttachmentField(idx); - var bean = result[i]; - document.getElementById('templateAttachmentId' + idx + index).value = bean['id']; - document.getElementById('templateAttachmentName' + idx + index).innerHTML += bean['filename']; - } - } - } - }, - - /** - * fills drop-down values for email templates and signatures - */ - setComposeOptions : function(idx) { - // send from accounts - var addressFrom = document.getElementById('addressFrom' + idx); - - if (addressFrom.options.length <= 0) { - SE.util.emptySelectOptions(addressFrom); - var fromAccountOpts = SE.composeLayout.fromAccounts; - for (id = 0 ; id < fromAccountOpts.length ; id++) { - var key = fromAccountOpts[id].value; - var display = fromAccountOpts[id].text; - var is_default = false; - if(key == SUGAR.default_inbound_accnt_id) - is_default = true; - var opt = new Option(display, key); - addressFrom.options.add(opt); - addressFrom.options[id].selected = is_default; //Safari bug new Option(x,y,true) does not work. - } - } - - // email templates - var et = document.getElementById('email_template' + idx); - SE.util.emptySelectOptions(et); - - for(var key in this.emailTemplates) { // iterate through assoc array - var display = this.emailTemplates[key]; - var opt = new Option(display, key); - et.options.add(opt); - } - - // signatures - var sigs = document.getElementById('signatures' + idx); - SE.util.emptySelectOptions(sigs); - - for(var key in this.signatures) { // iterate through assoc array - var display = this.signatures[key]; - var opt = new Option(display, key); - - if(key == SE.userPrefs.signatures.signature_default) { - opt.selected = true; - } - - sigs.options.add(opt); - } - - // html/plain email? - var htmlEmail = document.getElementById('setEditor' + idx); - if(SE.userPrefs.emailSettings.sendPlainText == 1) { - htmlEmail.checked = true; - } else { - htmlEmail.checked = false; - } - - SE.tinyInstances[SE.tinyInstances.currentHtmleditor].ready = true; - }, - - /** - * After compose screen is rendered, async call to get email body from Sugar - */ - replyForwardEmailStage2 : function() { - SE.util.clearHiddenFieldValues('emailUIForm'); - SUGAR.showMessageBox(app_strings.LBL_EMAIL_RETRIEVING_MESSAGE, app_strings.LBL_EMAIL_ONE_MOMENT); - - var ieId = SE.composeLayout.replyForwardObj.ieId; - var uid = SE.composeLayout.replyForwardObj.uid; - var mbox = SE.composeLayout.replyForwardObj.mbox; - var type = SE.composeLayout.replyForwardObj.type; - var idx = SE.composeLayout.currentInstanceId; - - var sugarEmail = (SE.composeLayout.replyForwardObj.sugarEmail) ? '&sugarEmail=true' : ""; - - document.getElementById('emailSubject' + idx).value = type; - document.getElementById('emailUIAction').value = 'composeEmail'; - document.getElementById('composeType').value = type; - document.getElementById('ieId').value = ieId; - document.getElementById('uid').value = uid; - document.getElementById('mbox').value = mbox; - document.getElementById('setEditor' + idx).checked = SE.userPrefs.emailSettings.sendPlainText == 1 ? true : false; - var formObject = document.getElementById('emailUIForm'); - YAHOO.util.Connect.setForm(formObject); - - var sendType = type; - AjaxObject.startRequest(callbackReplyForward, urlStandard + "&composeType=" + type + sugarEmail); - }, - - /** - * Show the hidden cc or bcc fields - */ - showHiddenAddress: function(addrType,idx){ - - Dom.removeClass(addrType+"_tr"+idx, "yui-hidden"); - Dom.addClass(addrType+"_span"+idx, "yui-hidden"); - Dom.addClass("bcc_cc_sep"+idx, "yui-hidden"); - this[addrType+'Hidden'+idx] = false; - - //After bcc or cc is added, move options below last addr field - Dom.insertAfter("add_addr_options_tr"+idx, 'bcc_tr'+idx); - - //If both cc and bcc hidden, remove the empty row containing text. - if( ( typeof(this['ccHidden'+idx]) != 'undefined' && typeof(this['bccHidden'+idx]) != 'undefined') - && ( this['ccHidden'+idx] == false && this['bccHidden'+idx] == false) ) - Dom.addClass("add_addr_options_tr"+idx, "yui-hidden"); - - // SE.composeLayout.resizeEditor(idx); - }, - /** - * Hide the cc and bcc fields if they were shown. - */ - hideHiddenAddresses: function(idx){ - - var addrTypes = ['cc','bcc']; - for(var i = 0;i
'; -// End of File modules/Emails/javascript/composeEmailTemplate.js - -/********************************************************************************* - * SugarCRM Community Edition is a customer relationship management program developed by - * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License version 3 as published by the - * Free Software Foundation with the addition of the following permission added - * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK - * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY - * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more - * details. - * - * You should have received a copy of the GNU Affero General Public License along with - * this program; if not, see http://www.gnu.org/licenses or write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - * - * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, - * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. - * - * The interactive user interfaces in modified source and object code versions - * of this program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU Affero General Public License version 3. - * - * In accordance with Section 7(b) of the GNU Affero General Public License version 3, - * these Appropriate Legal Notices must retain the display of the "Powered by - * SugarCRM" logo. If the display of the logo is not reasonably feasible for - * technical reasons, the Appropriate Legal Notices must display the words - * "Powered by SugarCRM". - ********************************************************************************/ - -/** - Complex layout init - */ -function complexLayoutInit() { - var se = SUGAR.email2; - var Dom = YAHOO.util.Dom; - se.e2Layout = { - getInnerLayout : function(rows) { - se.listViewLayout = new YAHOO.widget.Layout('listViewDiv', { - parent: se.complexLayout, - border:true, - hideOnLayout: true, - height: 400, - units: [{ - position: "center", - scroll:false, // grid should autoScroll itself - split:true, - body: "
" - },{ - position: "bottom", - scroll:true, - collapse: false, - resize: true, - useShim:true, - height:'250', - body: "
" - },{ - position: "right", - scroll:true, - collapse: false, - resize: true, - useShim:true, - width:'250', - body: "
", - titlebar: false //,header: "right" - }] - }); - se.complexLayout.on("render", function(){ - var height = SUGAR.email2.innerLayout.get("element").clientHeight - 30; - SUGAR.email2.innerLayout.get("activeTab").get("contentEl").parentNode.style.height = height + "px"; - SUGAR.email2.listViewLayout.set("height", height); - SUGAR.email2.listViewLayout.render(); - }); - se.listViewLayout.render(); - //CSS hack for now - se.listViewLayout.get("element").parentNode.parentNode.style.padding = "0px" - var rp = se.listViewLayout.resizePreview = function() { - var pre = Dom.get("displayEmailFramePreview"); - if (pre) { - var parent = Dom.getAncestorByClassName(pre, "yui-layout-bd"); - pre.style.height = (parent.clientHeight - pre.offsetTop) + "px"; - } - }; - se.listViewLayout.getUnitByPosition("bottom").on("heightChange", se.autoSetLayout); - se.listViewLayout.getUnitByPosition("right").on("endResize", se.autoSetLayout); - se.e2Layout.setPreviewPanel(rows); - se.previewLayout = se.listViewLayout; - return se.listViewLayout; - }, - - getInnerLayout2Rows : function() { - return this.getInnerLayout(true); - }, - getInnerLayout2Columns : function() { - return this.getInnerLayout(false); - }, - - init : function(){ - // initialize state manager, we will use cookies -// Ext.state.Manager.setProvider(new Ext.state.CookieProvider()); - var viewHeight = document.documentElement ? document.documentElement.clientHeight : self.innerHeight; - se.complexLayout = new YAHOO.widget.Layout("container", { - border:true, - hideOnLayout: true, - height: Dom.getViewportHeight() - (document.getElementById('header').clientHeight ) - 65, - width: Dom.getViewportWidth() - 40, - units: [{ - position: "center", - scroll:false, - body: "
" - }, - { - position: "left", - scroll: true, - body: "
", - collapse: true, - width: 210, - minWidth: 100, - resize:true, - useShim:true, - titlebar: true, - header: " " - }, - { - header: Dom.get('footerLinks').innerHTML, - position: 'bottom', - id: 'mbfooter', - height: 22, - border: false - }] - }); - se.complexLayout.render(); - var tp = se.innerLayout = new YAHOO.widget.TabView("emailtabs"); - tp.addTab(new YAHOO.widget.Tab({ - label: "Inbox", - scroll : true, - content : "
", - id : "center", - active : true - })); - var centerEl = se.complexLayout.getUnitByPosition('center').get('wrap'); - tp.appendTo(centerEl); - //CSS hack for now - tp.get("element").style.borderRight = "1px solid #666" - - var listV = this.getInnerLayout2Rows(); - listV.set("height", tp.get("element").clientHeight - 25); - listV.render(); - - se.leftTabs = new YAHOO.widget.TabView("lefttabs"); - var folderTab = new YAHOO.widget.Tab({ - label: app_strings.LBL_EMAIL_FOLDERS_SHORT, - scroll : true, - content : "
", - id : "tree", - active : true - }); - folderTab.on("activeChange", function(o){ - if (o.newValue) { - se.complexLayout.getUnitByPosition("left").set("header", app_strings.LBL_EMAIL_FOLDERS); - } - }); - se.leftTabs.addTab(folderTab); - - var tabContent = SUGAR.util.getAndRemove("searchTab"); - var searchTab = new YAHOO.widget.Tab({ - label: app_strings.LBL_EMAIL_SEARCH_SHORT, - scroll : true, - content : tabContent.innerHTML, - id : tabContent.id - }); - searchTab.on("activeChange", function(o){ - if (o.newValue) - { - se.complexLayout.getUnitByPosition("left").set("header", app_strings.LBL_EMAIL_SEARCH); - //Setup the calendars if needed - Calendar.setup ({inputField : "searchDateFrom", ifFormat : calFormat, showsTime : false, button : "searchDateFrom_trigger", singleClick : true, step : 1, weekNumbers:false}); - Calendar.setup ({inputField : "searchDateTo", ifFormat : calFormat, showsTime : false, button : "searchDateTo_trigger", singleClick : true, step : 1, weekNumbers:false}); - - //Initalize sqs object for assigned user name - se.e2Layout.initSQSObject('advancedSearchForm','assigned_user_name'); - - //Attach event handler for when the relate module option is selected for the correct sqs object - var parentSearchArgs = {'formName':'advancedSearchForm','fieldName':'data_parent_name_search', - 'moduleSelectField':'data_parent_type_search','fieldId':'data_parent_id_search'}; - YAHOO.util.Event.addListener('data_parent_type_search', 'change',function(){ - SUGAR.email2.composeLayout.enableQuickSearchRelate(null,parentSearchArgs) }); - - //If enter key is pressed, perform search - var addKeyPressFields = ['searchSubject','searchFrom','searchTo','data_parent_name_search','searchDateTo','searchDateFrom','attachmentsSearch','assigned_user_name']; - for(var i=0; i < addKeyPressFields.length;i++) - { - YAHOO.util.Event.addListener(window.document.forms['advancedSearchForm'].elements[addKeyPressFields[i]],"keydown", function(e){ - if (e.keyCode == 13) { - YAHOO.util.Event.stopEvent(e); - SUGAR.email2.search.searchAdvanced(); - } - }); - } - //Initiate quick search for the search tab. Do this only when the tab is selected rather than onDomLoad for perf. gains. - enableQS(true); - //Clear parent values if selecting another parent type. - YAHOO.util.Event.addListener('data_parent_type_search','change', - function(){ - document.getElementById('data_parent_id_search').value =''; - document.getElementById('data_parent_name_search').value =''; - }); - - } - }); - se.leftTabs.addTab(searchTab); - - var resizeTabBody = function() { - var height = SUGAR.email2.leftTabs.get("element").clientHeight - 30; - SUGAR.email2.leftTabs.get("activeTab").get("contentEl").parentNode.style.height = height + "px"; - } - resizeTabBody(); - se.complexLayout.on("render", resizeTabBody); - se.leftTabs.on("activeTabChange", resizeTabBody); - //hack to allow left pane scroll bar to fully show - var lefttabsDiv = document.getElementById('lefttabs'); - var lefttabsDivParent = Dom.getAncestorBy(lefttabsDiv); - var lefttabsDivGParent = Dom.getAncestorBy(lefttabsDivParent); - lefttabsDivParent.style.width = lefttabsDivGParent.offsetWidth - 10 + "px"; - - }, - initSQSObject: function(formName,fieldName) - { - var fullFieldName = formName + '_' + fieldName; //SQS Convention - var resultName = fullFieldName + '_' + 'results'; - - if (QSFieldsArray[fullFieldName] != null) - { - QSFieldsArray[fullFieldName].destroy(); - delete QSFieldsArray[fullFieldName]; - } - if (QSProcessedFieldsArray[fullFieldName]) - QSProcessedFieldsArray[fullFieldName] = false; - - if( Dom.get(resultName) ) - { - var obj = document.getElementById(resultName); - obj.parentNode.removeChild(obj); - } - }, - setPreviewPanel: function(rows) { - if (rows) { - SUGAR.email2.listViewLayout.getUnitByPosition("right").set("width", 0); - SUGAR.email2.listViewLayout.getUnitByPosition("bottom").set("height", 250); - Dom.get("listRight").innerHTML = ""; - Dom.get("listBottom").innerHTML = "
"; - } else { - SUGAR.email2.listViewLayout.getUnitByPosition("bottom").set("height", 0); - SUGAR.email2.listViewLayout.getUnitByPosition("right").set("width", 250); - Dom.get("listBottom").innerHTML = ""; - Dom.get("listRight").innerHTML = "
"; - } - } - }; - se.e2Layout.init(); -} - -var myBufferedListenerObject = new Object(); -myBufferedListenerObject.refit = function() { - if(SUGAR.email2.grid) { - SUGAR.email2.grid.autoSize(); - } -} -// End of File modules/Emails/javascript/complexLayout.js - diff --git a/include/javascript/sugar_grp_yui2.js b/include/javascript/sugar_grp_yui2.js deleted file mode 100644 index 258609ef..00000000 --- a/include/javascript/sugar_grp_yui2.js +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright (c) 2011, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.com/yui/license.html -version: 2.9.0 -*/ -if(!YAHOO.util.DragDropMgr){YAHOO.util.DragDropMgr=function(){var A=YAHOO.util.Event,B=YAHOO.util.Dom;return{useShim:false,_shimActive:false,_shimState:false,_debugShim:false,_createShim:function(){var C=document.createElement("div");C.id="yui-ddm-shim";if(document.body.firstChild){document.body.insertBefore(C,document.body.firstChild);}else{document.body.appendChild(C);}C.style.display="none";C.style.backgroundColor="red";C.style.position="absolute";C.style.zIndex="99999";B.setStyle(C,"opacity","0");this._shim=C;A.on(C,"mouseup",this.handleMouseUp,this,true);A.on(C,"mousemove",this.handleMouseMove,this,true);A.on(window,"scroll",this._sizeShim,this,true);},_sizeShim:function(){if(this._shimActive){var C=this._shim;C.style.height=B.getDocumentHeight()+"px";C.style.width=B.getDocumentWidth()+"px";C.style.top="0";C.style.left="0";}},_activateShim:function(){if(this.useShim){if(!this._shim){this._createShim();}this._shimActive=true;var C=this._shim,D="0";if(this._debugShim){D=".5";}B.setStyle(C,"opacity",D);this._sizeShim();C.style.display="block";}},_deactivateShim:function(){this._shim.style.display="none";this._shimActive=false;},_shim:null,ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,interactionInfo:null,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,STRICT_INTERSECT:2,mode:0,_execOnAll:function(E,D){for(var F in this.ids){for(var C in this.ids[F]){var G=this.ids[F][C];if(!this.isTypeOfDD(G)){continue;}G[E].apply(G,D);}}},_onLoad:function(){this.init();A.on(document,"mouseup",this.handleMouseUp,this,true);A.on(document,"mousemove",this.handleMouseMove,this,true);A.on(window,"unload",this._onUnload,this,true);A.on(window,"resize",this._onResize,this,true);},_onResize:function(C){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:1000,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,fromTimeout:false,regDragDrop:function(D,C){if(!this.initialized){this.init();}if(!this.ids[C]){this.ids[C]={};}this.ids[C][D.id]=D;},removeDDFromGroup:function(E,C){if(!this.ids[C]){this.ids[C]={};}var D=this.ids[C];if(D&&D[E.id]){delete D[E.id];}},_remove:function(E){for(var D in E.groups){if(D){var C=this.ids[D];if(C&&C[E.id]){delete C[E.id];}}}delete this.handleIds[E.id];},regHandle:function(D,C){if(!this.handleIds[D]){this.handleIds[D]={};}this.handleIds[D][C]=C;},isDragDrop:function(C){return(this.getDDById(C))?true:false;},getRelated:function(H,D){var G=[];for(var F in H.groups){for(var E in this.ids[F]){var C=this.ids[F][E];if(!this.isTypeOfDD(C)){continue;}if(!D||C.isTarget){G[G.length]=C;}}}return G;},isLegalTarget:function(G,F){var D=this.getRelated(G,true);for(var E=0,C=D.length;Ethis.clickPixelThresh||D>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}if(this.dragThreshMet){if(C&&C.events.b4Drag){C.b4Drag(F);C.fireEvent("b4DragEvent",{e:F});}if(C&&C.events.drag){C.onDrag(F);C.fireEvent("dragEvent",{e:F});}if(C){this.fireEvents(F,false);}}this.stopEvent(F);}},fireEvents:function(W,M){var c=this.dragCurrent;if(!c||c.isLocked()||c.dragOnly){return;}var O=YAHOO.util.Event.getPageX(W),N=YAHOO.util.Event.getPageY(W),Q=new YAHOO.util.Point(O,N),K=c.getTargetCoord(Q.x,Q.y),F=c.getDragEl(),E=["out","over","drop","enter"],V=new YAHOO.util.Region(K.y,K.x+F.offsetWidth,K.y+F.offsetHeight,K.x),I=[],D={},L={},R=[],d={outEvts:[],overEvts:[],dropEvts:[],enterEvts:[]};for(var T in this.dragOvers){var f=this.dragOvers[T];if(!this.isTypeOfDD(f)){continue; -}if(!this.isOverTarget(Q,f,this.mode,V)){d.outEvts.push(f);}I[T]=true;delete this.dragOvers[T];}for(var S in c.groups){if("string"!=typeof S){continue;}for(T in this.ids[S]){var G=this.ids[S][T];if(!this.isTypeOfDD(G)){continue;}if(G.isTarget&&!G.isLocked()&&G!=c){if(this.isOverTarget(Q,G,this.mode,V)){D[S]=true;if(M){d.dropEvts.push(G);}else{if(!I[G.id]){d.enterEvts.push(G);}else{d.overEvts.push(G);}this.dragOvers[G.id]=G;}}}}}this.interactionInfo={out:d.outEvts,enter:d.enterEvts,over:d.overEvts,drop:d.dropEvts,point:Q,draggedRegion:V,sourceRegion:this.locationCache[c.id],validDrop:M};for(var C in D){R.push(C);}if(M&&!d.dropEvts.length){this.interactionInfo.validDrop=false;if(c.events.invalidDrop){c.onInvalidDrop(W);c.fireEvent("invalidDropEvent",{e:W});}}for(T=0;T2000){}else{setTimeout(C._addListeners,10);if(document&&document.body){C._timeoutCount+=1;}}}},handleWasClicked:function(C,E){if(this.isHandle(E,C.id)){return true;}else{var D=C.parentNode;while(D){if(this.isHandle(E,D.id)){return true;}else{D=D.parentNode;}}}return false;}};}();YAHOO.util.DDM=YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function(){var A=YAHOO.util.Event;var B=YAHOO.util.Dom;YAHOO.util.DragDrop=function(E,C,D){if(E){this.init(E,C,D);}};YAHOO.util.DragDrop.prototype={events:null,on:function(){this.subscribe.apply(this,arguments);},id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isTarget:true,padding:null,dragOnly:false,useShim:false,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,deltaX:0,deltaY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,cursorIsOver:false,overlap:null,b4StartDrag:function(C,D){},startDrag:function(C,D){},b4Drag:function(C){},onDrag:function(C){},onDragEnter:function(C,D){},b4DragOver:function(C){},onDragOver:function(C,D){},b4DragOut:function(C){},onDragOut:function(C,D){},b4DragDrop:function(C){},onDragDrop:function(C,D){},onInvalidDrop:function(C){},b4EndDrag:function(C){},endDrag:function(C){},b4MouseDown:function(C){},onMouseDown:function(C){},onMouseUp:function(C){},onAvailable:function(){},getEl:function(){if(!this._domRef){this._domRef=B.get(this.id); -}return this._domRef;},getDragEl:function(){return B.get(this.dragElId);},init:function(F,C,D){this.initTarget(F,C,D);A.on(this._domRef||this.id,"mousedown",this.handleMouseDown,this,true);for(var E in this.events){this.createEvent(E+"Event");}},initTarget:function(E,C,D){this.config=D||{};this.events={};this.DDM=YAHOO.util.DDM;this.groups={};if(typeof E!=="string"){this._domRef=E;E=B.generateId(E);}this.id=E;this.addToGroup((C)?C:"default");this.handleElId=E;A.onAvailable(E,this.handleOnAvailable,this,true);this.setDragElId(E);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();},applyConfig:function(){this.events={mouseDown:true,b4MouseDown:true,mouseUp:true,b4StartDrag:true,startDrag:true,b4EndDrag:true,endDrag:true,drag:true,b4Drag:true,invalidDrop:true,b4DragOut:true,dragOut:true,dragEnter:true,b4DragOver:true,dragOver:true,b4DragDrop:true,dragDrop:true};if(this.config.events){for(var C in this.config.events){if(this.config.events[C]===false){this.events[C]=false;}}}this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);this.dragOnly=((this.config.dragOnly===true)?true:false);this.useShim=((this.config.useShim===true)?true:false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(E,C,F,D){if(!C&&0!==C){this.padding=[E,E,E,E];}else{if(!F&&0!==F){this.padding=[E,C,E,C];}else{this.padding=[E,C,F,D];}}},setInitPosition:function(F,E){var G=this.getEl();if(!this.DDM.verifyEl(G)){if(G&&G.style&&(G.style.display=="none")){}else{}return;}var D=F||0;var C=E||0;var H=B.getXY(G);this.initPageX=H[0]-D;this.initPageY=H[1]-C;this.lastPageX=H[0];this.lastPageY=H[1];this.setStartPosition(H);},setStartPosition:function(D){var C=D||B.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=C[0];this.startPageY=C[1];},addToGroup:function(C){this.groups[C]=true;this.DDM.regDragDrop(this,C);},removeFromGroup:function(C){if(this.groups[C]){delete this.groups[C];}this.DDM.removeDDFromGroup(this,C);},setDragElId:function(C){this.dragElId=C;},setHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.handleElId=C;this.DDM.regHandle(this.id,C);},setOuterHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}A.on(C,"mousedown",this.handleMouseDown,this,true);this.setHandleElId(C);this.hasOuterHandles=true;},unreg:function(){A.removeListener(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(J,I){var D=J.which||J.button;if(this.primaryButtonOnly&&D>1){return;}if(this.isLocked()){return;}var C=this.b4MouseDown(J),F=true;if(this.events.b4MouseDown){F=this.fireEvent("b4MouseDownEvent",J);}var E=this.onMouseDown(J),H=true;if(this.events.mouseDown){if(E===false){H=false;}else{H=this.fireEvent("mouseDownEvent",J);}}if((C===false)||(E===false)||(F===false)||(H===false)){return;}this.DDM.refreshCache(this.groups);var G=new YAHOO.util.Point(A.getPageX(J),A.getPageY(J));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(G,this)){}else{if(this.clickValidator(J)){this.setStartPosition();this.DDM.handleMouseDown(J,this);this.DDM.stopEvent(J);}else{}}},clickValidator:function(D){var C=YAHOO.util.Event.getTarget(D);return(this.isValidHandleChild(C)&&(this.id==this.handleElId||this.DDM.handleWasClicked(C,this.id)));},getTargetCoord:function(E,D){var C=E-this.deltaX;var F=D-this.deltaY;if(this.constrainX){if(Cthis.maxX){C=this.maxX;}}if(this.constrainY){if(Fthis.maxY){F=this.maxY;}}C=this.getTick(C,this.xTicks);F=this.getTick(F,this.yTicks);return{x:C,y:F};},addInvalidHandleType:function(C){var D=C.toUpperCase();this.invalidHandleTypes[D]=D;},addInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.invalidHandleIds[C]=C;},addInvalidHandleClass:function(C){this.invalidHandleClasses.push(C);},removeInvalidHandleType:function(C){var D=C.toUpperCase();delete this.invalidHandleTypes[D];},removeInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}delete this.invalidHandleIds[C];},removeInvalidHandleClass:function(D){for(var E=0,C=this.invalidHandleClasses.length;E=this.minX;D=D-C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}for(D=this.initPageX;D<=this.maxX;D=D+C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(F,C){this.yTicks=[];this.yTickSize=C;var E={};for(var D=this.initPageY;D>=this.minY;D=D-C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}for(D=this.initPageY;D<=this.maxY;D=D+C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(E,D,C){this.leftConstraint=parseInt(E,10);this.rightConstraint=parseInt(D,10);this.minX=this.initPageX-this.leftConstraint;this.maxX=this.initPageX+this.rightConstraint;if(C){this.setXTicks(this.initPageX,C);}this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(C,E,D){this.topConstraint=parseInt(C,10);this.bottomConstraint=parseInt(E,10);this.minY=this.initPageY-this.topConstraint;this.maxY=this.initPageY+this.bottomConstraint; -if(D){this.setYTicks(this.initPageY,D);}this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var D=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var C=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(D,C);}else{this.setInitPosition();}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(I,F){if(!F){return I;}else{if(F[0]>=I){return F[0];}else{for(var D=0,C=F.length;D=I){var H=I-F[D];var G=F[E]-I;return(G>H)?F[D]:F[E];}}return F[F.length-1];}}},toString:function(){return("DragDrop "+this.id);}};YAHOO.augment(YAHOO.util.DragDrop,YAHOO.util.EventProvider);})();YAHOO.util.DD=function(C,A,B){if(C){this.init(C,A,B);}};YAHOO.extend(YAHOO.util.DD,YAHOO.util.DragDrop,{scroll:true,autoOffset:function(C,B){var A=C-this.startPageX;var D=B-this.startPageY;this.setDelta(A,D);},setDelta:function(B,A){this.deltaX=B;this.deltaY=A;},setDragElPos:function(C,B){var A=this.getDragEl();this.alignElWithMouse(A,C,B);},alignElWithMouse:function(C,G,F){var E=this.getTargetCoord(G,F);if(!this.deltaSetXY){var H=[E.x,E.y];YAHOO.util.Dom.setXY(C,H);var D=parseInt(YAHOO.util.Dom.getStyle(C,"left"),10);var B=parseInt(YAHOO.util.Dom.getStyle(C,"top"),10);this.deltaSetXY=[D-E.x,B-E.y];}else{YAHOO.util.Dom.setStyle(C,"left",(E.x+this.deltaSetXY[0])+"px");YAHOO.util.Dom.setStyle(C,"top",(E.y+this.deltaSetXY[1])+"px");}this.cachePosition(E.x,E.y);var A=this;setTimeout(function(){A.autoScroll.call(A,E.x,E.y,C.offsetHeight,C.offsetWidth);},0);},cachePosition:function(B,A){if(B){this.lastPageX=B;this.lastPageY=A;}else{var C=YAHOO.util.Dom.getXY(this.getEl());this.lastPageX=C[0];this.lastPageY=C[1];}},autoScroll:function(J,I,E,K){if(this.scroll){var L=this.DDM.getClientHeight();var B=this.DDM.getClientWidth();var N=this.DDM.getScrollTop();var D=this.DDM.getScrollLeft();var H=E+I;var M=K+J;var G=(L+N-I-this.deltaY);var F=(B+D-J-this.deltaX);var C=40;var A=(document.all)?80:30;if(H>L&&G0&&I-NB&&F0&&J-D0){g=f-1;do{d=e.subscribers[g];if(d&&d.obj==j&&d.fn==h){return true;}}while(g--);}return false;};YAHOO.lang.augmentProto(a,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Module=function(r,q){if(r){this.init(r,q);}else{}};var f=YAHOO.util.Dom,d=YAHOO.util.Config,n=YAHOO.util.Event,m=YAHOO.util.CustomEvent,g=YAHOO.widget.Module,i=YAHOO.env.ua,h,p,o,e,a={"BEFORE_INIT":"beforeInit","INIT":"init","APPEND":"append","BEFORE_RENDER":"beforeRender","RENDER":"render","CHANGE_HEADER":"changeHeader","CHANGE_BODY":"changeBody","CHANGE_FOOTER":"changeFooter","CHANGE_CONTENT":"changeContent","DESTROY":"destroy","BEFORE_SHOW":"beforeShow","SHOW":"show","BEFORE_HIDE":"beforeHide","HIDE":"hide"},j={"VISIBLE":{key:"visible",value:true,validator:YAHOO.lang.isBoolean},"EFFECT":{key:"effect",suppressEvent:true,supercedes:["visible"]},"MONITOR_RESIZE":{key:"monitorresize",value:true},"APPEND_TO_DOCUMENT_BODY":{key:"appendtodocumentbody",value:false}};g.IMG_ROOT=null;g.IMG_ROOT_SSL=null;g.CSS_MODULE="yui-module";g.CSS_HEADER="hd";g.CSS_BODY="bd";g.CSS_FOOTER="ft";g.RESIZE_MONITOR_SECURE_URL="javascript:false;";g.RESIZE_MONITOR_BUFFER=1;g.textResizeEvent=new m("textResize");g.forceDocumentRedraw=function(){var q=document.documentElement;if(q){q.className+=" ";q.className=YAHOO.lang.trim(q.className);}};function l(){if(!h){h=document.createElement("div");h.innerHTML=('
'+'
');p=h.firstChild;o=p.nextSibling;e=o.nextSibling;}return h;}function k(){if(!p){l();}return(p.cloneNode(false));}function b(){if(!o){l();}return(o.cloneNode(false));}function c(){if(!e){l();}return(e.cloneNode(false));}g.prototype={constructor:g,element:null,header:null,body:null,footer:null,id:null,imageRoot:g.IMG_ROOT,initEvents:function(){var q=m.LIST; -this.beforeInitEvent=this.createEvent(a.BEFORE_INIT);this.beforeInitEvent.signature=q;this.initEvent=this.createEvent(a.INIT);this.initEvent.signature=q;this.appendEvent=this.createEvent(a.APPEND);this.appendEvent.signature=q;this.beforeRenderEvent=this.createEvent(a.BEFORE_RENDER);this.beforeRenderEvent.signature=q;this.renderEvent=this.createEvent(a.RENDER);this.renderEvent.signature=q;this.changeHeaderEvent=this.createEvent(a.CHANGE_HEADER);this.changeHeaderEvent.signature=q;this.changeBodyEvent=this.createEvent(a.CHANGE_BODY);this.changeBodyEvent.signature=q;this.changeFooterEvent=this.createEvent(a.CHANGE_FOOTER);this.changeFooterEvent.signature=q;this.changeContentEvent=this.createEvent(a.CHANGE_CONTENT);this.changeContentEvent.signature=q;this.destroyEvent=this.createEvent(a.DESTROY);this.destroyEvent.signature=q;this.beforeShowEvent=this.createEvent(a.BEFORE_SHOW);this.beforeShowEvent.signature=q;this.showEvent=this.createEvent(a.SHOW);this.showEvent.signature=q;this.beforeHideEvent=this.createEvent(a.BEFORE_HIDE);this.beforeHideEvent.signature=q;this.hideEvent=this.createEvent(a.HIDE);this.hideEvent.signature=q;},platform:function(){var q=navigator.userAgent.toLowerCase();if(q.indexOf("windows")!=-1||q.indexOf("win32")!=-1){return"windows";}else{if(q.indexOf("macintosh")!=-1){return"mac";}else{return false;}}}(),browser:function(){var q=navigator.userAgent.toLowerCase();if(q.indexOf("opera")!=-1){return"opera";}else{if(q.indexOf("msie 7")!=-1){return"ie7";}else{if(q.indexOf("msie")!=-1){return"ie";}else{if(q.indexOf("safari")!=-1){return"safari";}else{if(q.indexOf("gecko")!=-1){return"gecko";}else{return false;}}}}}}(),isSecure:function(){if(window.location.href.toLowerCase().indexOf("https")===0){return true;}else{return false;}}(),initDefaultConfig:function(){this.cfg.addProperty(j.VISIBLE.key,{handler:this.configVisible,value:j.VISIBLE.value,validator:j.VISIBLE.validator});this.cfg.addProperty(j.EFFECT.key,{handler:this.configEffect,suppressEvent:j.EFFECT.suppressEvent,supercedes:j.EFFECT.supercedes});this.cfg.addProperty(j.MONITOR_RESIZE.key,{handler:this.configMonitorResize,value:j.MONITOR_RESIZE.value});this.cfg.addProperty(j.APPEND_TO_DOCUMENT_BODY.key,{value:j.APPEND_TO_DOCUMENT_BODY.value});},init:function(v,u){var s,w;this.initEvents();this.beforeInitEvent.fire(g);this.cfg=new d(this);if(this.isSecure){this.imageRoot=g.IMG_ROOT_SSL;}if(typeof v=="string"){s=v;v=document.getElementById(v);if(!v){v=(l()).cloneNode(false);v.id=s;}}this.id=f.generateId(v);this.element=v;w=this.element.firstChild;if(w){var r=false,q=false,t=false;do{if(1==w.nodeType){if(!r&&f.hasClass(w,g.CSS_HEADER)){this.header=w;r=true;}else{if(!q&&f.hasClass(w,g.CSS_BODY)){this.body=w;q=true;}else{if(!t&&f.hasClass(w,g.CSS_FOOTER)){this.footer=w;t=true;}}}}}while((w=w.nextSibling));}this.initDefaultConfig();f.addClass(this.element,g.CSS_MODULE);if(u){this.cfg.applyConfig(u,true);}if(!d.alreadySubscribed(this.renderEvent,this.cfg.fireQueue,this.cfg)){this.renderEvent.subscribe(this.cfg.fireQueue,this.cfg,true);}this.initEvent.fire(g);},initResizeMonitor:function(){var r=(i.gecko&&this.platform=="windows");if(r){var q=this;setTimeout(function(){q._initResizeMonitor();},0);}else{this._initResizeMonitor();}},_initResizeMonitor:function(){var q,s,u;function w(){g.textResizeEvent.fire();}if(!i.opera){s=f.get("_yuiResizeMonitor");var v=this._supportsCWResize();if(!s){s=document.createElement("iframe");if(this.isSecure&&g.RESIZE_MONITOR_SECURE_URL&&i.ie){s.src=g.RESIZE_MONITOR_SECURE_URL;}if(!v){u=[""; + "; return $j_str; } diff --git a/include/templates/TemplateGroupChooser.php b/include/templates/TemplateGroupChooser.php index 0c2d22b4..977d1b65 100644 --- a/include/templates/TemplateGroupChooser.php +++ b/include/templates/TemplateGroupChooser.php @@ -50,13 +50,16 @@ class TemplateGroupChooser extends Template { } function display() { - global $mod_strings, $js_loaded; + global $app_strings, $mod_strings, $js_loaded; $left_size = (empty($this->args['left_size']) ? '10' : $this->args['left_size']); $right_size = (empty($this->args['right_size']) ? '10' : $this->args['right_size']); $third_size = (empty($this->args['third_size']) ? '10' : $this->args['third_size']); $max_left = (empty($this->args['max_left']) ? '' : $this->args['max_left']); - $alt_tip = (empty($this->args['alt_tip']) ? '' : $this->args['alt_tip']); + $alt_tip_up = $app_strings['LBL_ALT_MOVE_COLUMN_UP']; + $alt_tip_down = $app_strings['LBL_ALT_MOVE_COLUMN_DOWN']; + $alt_tip_left = $app_strings['LBL_ALT_MOVE_COLUMN_LEFT']; + $alt_tip_right = $app_strings['LBL_ALT_MOVE_COLUMN_RIGHT']; $str = ''; if($js_loaded == false) { @@ -96,9 +99,9 @@ EOQ; } $str .= ' '; - if(!isset($this->args['disable'])) { - $str .= "args['left_name']}','{$this->args['left_name']}','{$this->args['right_name']}');\">" . SugarThemeRegistry::current()->getImage('uparrow_big','border="0" style="margin-bottom: 1px;" alt="'.$alt_tip.'"') . "
- args['left_name']}','{$this->args['left_name']}','{$this->args['right_name']}');\">" . SugarThemeRegistry::current()->getImage('downarrow_big','border="0" style="margin-top: 1px;" alt="'.$alt_tip.'"') . ""; + if(!isset($this->args['disable'])) { + $str .= "args['left_name']}','{$this->args['left_name']}','{$this->args['right_name']}');\">" . SugarThemeRegistry::current()->getImage('uparrow_big','border="0" style="margin-bottom: 1px;"',null,null,'.gif',$alt_tip_up) . "
+ args['left_name']}','{$this->args['left_name']}','{$this->args['right_name']}');\">" . SugarThemeRegistry::current()->getImage('downarrow_big','border="0" style="margin-top: 1px;"',null,null,'.gif',$alt_tip_down) . ""; } $str .= <<display_hide_tabs == true) { $str .= ''; if(!isset($this->args['disable'])) { - $str .= "args['left_name']}','{$this->args['right_name']}', '{$left_size}', '{$right_size}', '{$max_left}');\">" . SugarThemeRegistry::current()->getImage('leftarrow_big','border="0" style="margin-right: 1px;" alt="'.$alt_tip.'"') . "args['left_name']}','{$this->args['right_name']}', '{$left_size}', '{$right_size}');\">" . SugarThemeRegistry::current()->getImage('rightarrow_big','border="0" style="margin-left: 1px;" alt="'.$alt_tip.'"') . ""; + $str .= "args['left_name']}','{$this->args['right_name']}', '{$left_size}', '{$right_size}', '{$max_left}');\">" . SugarThemeRegistry::current()->getImage('leftarrow_big','border="0" style="margin-right: 1px;"',null,null,'.gif',$alt_tip_left) . "args['left_name']}','{$this->args['right_name']}', '{$left_size}', '{$right_size}');\">" . SugarThemeRegistry::current()->getImage('rightarrow_big','border="0" style="margin-left: 1px;"',null,null,'.gif',$alt_tip_right) . ""; } $str .= " args['right_name']}_td\" align=\"center\"> @@ -136,7 +139,7 @@ EOQ; if ($this->display_third_tabs == true) { $str .= ''; if(!isset($this->args['disable'])) { - $str .= "args['right_name']}','{$this->args['third_name']}', '{$right_size}', '{$third_size}');\">" . SugarThemeRegistry::current()->getImage('leftarrow_big','border="0" style="margin-right: 1px;" alt="'.$alt_tip.'"') . "args['right_name']}','{$this->args['third_name']}', '{$right_size}', '{$third_size}');\">" . SugarThemeRegistry::current()->getImage('rightarrow_big','border="0" style="margin-left: 1px;" alt="'.$alt_tip.'"') . ""; + $str .= "args['right_name']}','{$this->args['third_name']}', '{$right_size}', '{$third_size}');\">" . SugarThemeRegistry::current()->getImage('leftarrow_big','border="0" style="margin-right: 1px;"',null,null,'.gif',$alt_tip_left) . "args['right_name']}','{$this->args['third_name']}', '{$right_size}', '{$third_size}');\">" . SugarThemeRegistry::current()->getImage('rightarrow_big','border="0" style="margin-left: 1px;"',null,null,'.gif',$alt_tip_right) . ""; } $str .= " args['third_name']}_td\" align=\"center\"> diff --git a/include/upload_file.php b/include/upload_file.php index 60f26435..211c923f 100644 --- a/include/upload_file.php +++ b/include/upload_file.php @@ -41,7 +41,11 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ require_once('include/externalAPI/ExternalAPIFactory.php'); -class UploadFile +/** + * @api + * Manage uploaded files + */ +class UploadFile { var $field_name; var $stored_file_name; @@ -50,16 +54,40 @@ class UploadFile var $use_soap = false; var $file; var $file_ext; - - function UploadFile ($field_name) { + protected static $url = "upload/"; + + /** + * Upload errors + * @var array + */ + protected static $filesError = array( + UPLOAD_ERR_OK => 'UPLOAD_ERR_OK - There is no error, the file uploaded with success.', + UPLOAD_ERR_INI_SIZE => 'UPLOAD_ERR_INI_SIZE - The uploaded file exceeds the upload_max_filesize directive in php.ini.', + UPLOAD_ERR_FORM_SIZE => 'UPLOAD_ERR_FORM_SIZE - The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', + UPLOAD_ERR_PARTIAL => 'UPLOAD_ERR_PARTIAL - The uploaded file was only partially uploaded.', + UPLOAD_ERR_NO_FILE => 'UPLOAD_ERR_NO_FILE - No file was uploaded.', + 5 => 'UNKNOWN ERROR', + UPLOAD_ERR_NO_TMP_DIR => 'UPLOAD_ERR_NO_TMP_DIR - Missing a temporary folder.', + UPLOAD_ERR_CANT_WRITE => 'UPLOAD_ERR_CANT_WRITE - Failed to write file to disk.', + UPLOAD_ERR_EXTENSION => 'UPLOAD_ERR_EXTENSION - A PHP extension stopped the file upload.', + ); + + /** + * Create upload file handler + * @param string $field_name Form field name + */ + function UploadFile ($field_name = '') + { // $field_name is the name of your passed file selector field in your form // i.e., for Emails, it is "email_attachmentX" where X is 0-9 $this->field_name = $field_name; - // Bug 28408 - Add automatic creation of upload cache directory if it doesn't exist - if ( !is_dir($GLOBALS['sugar_config']['upload_dir']) ) - create_cache_directory(str_replace($GLOBALS['sugar_config']['cache_dir'],'',$GLOBALS['sugar_config']['upload_dir'])); } + /** + * Setup for SOAP upload + * @param string $filename Name for the file + * @param string $file + */ function set_for_soap($filename, $file) { $this->stored_file_name = $filename; $this->use_soap = true; @@ -67,56 +95,74 @@ class UploadFile } /** - * wrapper for this::get_file_path() + * Get URL for a document + * @deprecated * @param string stored_file_name File name in filesystem * @param string bean_id note bean ID * @return string path with file name */ - function get_url($stored_file_name,$bean_id) { - global $sugar_config; - return UploadFile::get_file_path($stored_file_name,$bean_id); + public static function get_url($stored_file_name, $bean_id) + { + if ( empty($bean_id) && empty($stored_file_name) ) { + return self::$url; + } + + return self::$url . $bean_id; + } + + /** + * Get URL of the uploaded file related to the document + * @param SugarBean $document + * @param string $type Type of the document, if different from $document + */ + public static function get_upload_url($document, $type = null) + { + if(empty($type)) { + $type = $document->module_dir; + } + return "index.php?entryPoint=download&type=$type&id={$document->id}"; } - + /** - * builds a URL path for an anchor tag + * Try renaming a file to bean_id name + * @param string $filename + * @param string $bean_id + */ + protected static function tryRename($filename, $bean_id) + { + $fullname = "upload://$bean_id.$filename"; + if(file_exists($fullname)) { + if(!rename($fullname, "upload://$bean_id")) { + $GLOBALS['log']->fatal("unable to rename file: $fullname => $bean_id"); + } + return true; + } + return false; + } + + /** + * builds a URL path for an anchor tag * @param string stored_file_name File name in filesystem * @param string bean_id note bean ID * @return string path with file name */ - function get_file_path($stored_file_name,$bean_id) { - global $sugar_config; + static public function get_file_path($stored_file_name, $bean_id, $skip_rename = false) + { global $locale; - + // if the parameters are empty strings, just return back the upload_dir - if ( empty($bean_id) && empty($stored_file_name) ) - return $sugar_config['upload_dir']; - - if (file_exists($sugar_config['upload_dir'] . $bean_id . rawurlencode($stored_file_name))){ - if (!rename($sugar_config['upload_dir'] . $bean_id . rawurlencode($stored_file_name), - $sugar_config['upload_dir'] . $bean_id)){ - $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}"); - } + if ( empty($bean_id) && empty($stored_file_name) ) { + return "upload://"; } - else if (file_exists($sugar_config['upload_dir'] . $bean_id . urlencode($stored_file_name))){ - if (!rename($sugar_config['upload_dir'] . $bean_id . urlencode($stored_file_name), - $sugar_config['upload_dir'] . $bean_id)){ - $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}"); - } - } - else if (file_exists($sugar_config['upload_dir'] . $bean_id . $stored_file_name)){ - if (!rename($sugar_config['upload_dir'] . $bean_id . $stored_file_name, - $sugar_config['upload_dir'] . $bean_id)){ - $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}"); - } + + if(!$skip_rename) { + self::tryRename(rawurlencode($stored_file_name), $bean_id) || + self::tryRename(urlencode($stored_file_name), $bean_id) || + self::tryRename($stored_file_name, $bean_id) || + self::tryRename($locale->translateCharset( $stored_file_name, 'UTF-8', $locale->getExportCharset()), $bean_id); } - else if (file_exists($sugar_config['upload_dir'] . $bean_id . $locale->translateCharset( $stored_file_name, 'UTF-8', $locale->getExportCharset() ))){ - if (!rename($sugar_config['upload_dir'] . $bean_id . $locale->translateCharset( $stored_file_name, 'UTF-8', $locale->getExportCharset() ), - $sugar_config['upload_dir'] . $bean_id)){ - $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}"); - } - } - - return $sugar_config['upload_dir'] . $bean_id; + + return "upload://$bean_id"; } /** @@ -125,12 +171,13 @@ class UploadFile * @param string new_id ID of new (copied) note * @param string filename Filename of file (deprecated) */ - function duplicate_file($old_id, $new_id, $file_name) { + public static function duplicate_file($old_id, $new_id, $file_name) + { global $sugar_config; // current file system (GUID) - $source = $sugar_config['upload_dir'] . $old_id; - + $source = "upload://$old_id"; + if(!file_exists($source)) { // old-style file system (GUID.filename.extension) $oldStyleSource = $source.$file_name; @@ -139,44 +186,75 @@ class UploadFile if(copy($oldStyleSource, $source)) { // delete the old if(!unlink($oldStyleSource)) { - $GLOBALS['log']->warn("upload_file could not unlink [ {$oldStyleSource} ]"); + $GLOBALS['log']->error("upload_file could not unlink [ {$oldStyleSource} ]"); } } else { - $GLOBALS['log']->warn("upload_file could not copy [ {$oldStyleSource} ] to [ {$source} ]"); + $GLOBALS['log']->error("upload_file could not copy [ {$oldStyleSource} ] to [ {$source} ]"); } } } - - $destination = $sugar_config['upload_dir'] . $new_id; + + $destination = "upload://$new_id"; if(!copy($source, $destination)) { - $GLOBALS['log']->warn("upload_file could not copy [ {$source} ] to [ {$destination} ]"); + $GLOBALS['log']->error("upload_file could not copy [ {$source} ] to [ {$destination} ]"); } } + /** + * Get upload error from system + * @return string upload error + */ + public function get_upload_error() + { + if(isset($this->field_name) && isset($_FILES[$this->field_name]['error'])) { + return $_FILES[$this->field_name]['error']; + } + return false; + } + /** * standard PHP file-upload security measures. all variables accessed in a global context * @return bool True on success */ - function confirm_upload() { + public function confirm_upload() + { global $sugar_config; + if(empty($this->field_name) || !isset($_FILES[$this->field_name])) { + return false; + } + + if($_FILES[$this->field_name]['error'] != UPLOAD_ERR_OK) { + if($_FILES[$this->field_name]['error'] != UPLOAD_ERR_NO_FILE) { + $GLOBALS['log']->error('File upload error: '.self::$filesError[$_FILES[$this->field_name]['error']]); + } + return false; + } + if(!is_uploaded_file($_FILES[$this->field_name]['tmp_name'])) { return false; } elseif($_FILES[$this->field_name]['size'] > $sugar_config['upload_maxsize']) { - die("ERROR: uploaded file was too big: max filesize: {$sugar_config['upload_maxsize']}"); + $GLOBALS['log']->fatal("ERROR: uploaded file was too big: max filesize: {$sugar_config['upload_maxsize']}"); + return false; } - if(!is_writable($sugar_config['upload_dir'])) { - die("ERROR: cannot write to directory: {$sugar_config['upload_dir']} for uploads"); + if(!UploadStream::writable()) { + $GLOBALS['log']->fatal("ERROR: cannot write to upload directory"); + return false; } - $this->mime_type =$this->getMime($_FILES[$this->field_name]); + $this->mime_type = $this->getMime($_FILES[$this->field_name]); $this->stored_file_name = $this->create_stored_filename(); $this->temp_file_location = $_FILES[$this->field_name]['tmp_name']; return true; } + /** + * Guess MIME type for file + * @param string $filename + * @return string MIME type + */ function getMimeSoap($filename){ if( function_exists( 'ext2mime' ) ) @@ -190,29 +268,27 @@ class UploadFile return $mime; } - function getMime(&$_FILES_element) - { + /** + * Get MIME type for uploaded file + * @param array $_FILES_element $_FILES element required + * @return string MIME type + */ + function getMime($_FILES_element) + { $filename = $_FILES_element['name']; $file_ext = pathinfo($filename, PATHINFO_EXTENSION); //If no file extension is available and the mime is octet-stream try to determine the mime type. $recheckMime = empty($file_ext) && ($_FILES_element['type'] == 'application/octet-stream'); - if( $_FILES_element['type'] && !$recheckMime) - { + if( $_FILES_element['type'] && !$recheckMime) { $mime = $_FILES_element['type']; - } - elseif( function_exists( 'mime_content_type' ) ) - { + } elseif( function_exists( 'mime_content_type' ) ) { $mime = mime_content_type( $_FILES_element['tmp_name'] ); - } - elseif( function_exists( 'ext2mime' ) ) - { + } elseif( function_exists( 'ext2mime' ) ) { $mime = ext2mime( $_FILES_element['name'] ); - } - else - { + } else { $mime = ' application/octet-stream'; } return $mime; @@ -222,7 +298,8 @@ class UploadFile * gets note's filename * @return string */ - function get_stored_file_name() { + function get_stored_file_name() + { return $this->stored_file_name; } @@ -230,13 +307,14 @@ class UploadFile * creates a file's name for preparation for saving * @return string */ - function create_stored_filename() { + function create_stored_filename() + { global $sugar_config; - + if(!$this->use_soap) { $stored_file_name = $_FILES[$this->field_name]['name']; $this->original_file_name = $stored_file_name; - + /** * cn: bug 8056 - windows filesystems and IIS do not like utf8. we are forced to urlencode() to ensure that * the file is linkable from the browser. this will stay broken until we move to a db-storage system @@ -248,15 +326,14 @@ class UploadFile $stored_file_name = substr($stored_file_name, 0, $end); $this->original_file_name = $_FILES[$this->field_name]['name']; } + $stored_file_name = str_replace("\\", "", $stored_file_name); } else { $stored_file_name = $this->stored_file_name; $this->original_file_name = $stored_file_name; } - - $ext_pos = strrpos($stored_file_name, "."); - if($ext_pos !== false) - $this->file_ext = substr($stored_file_name, $ext_pos + 1); - // cn: bug 6347 - fix file extension detection + + $this->file_ext = pathinfo($stored_file_name, PATHINFO_EXTENSION); + // cn: bug 6347 - fix file extension detection foreach($sugar_config['upload_badext'] as $badExt) { if(strtolower($this->file_ext) == strtolower($badExt)) { $stored_file_name .= ".txt"; @@ -272,32 +349,42 @@ class UploadFile * @param string bean_id ID of parent bean * @return bool True on success */ - function final_move($bean_id) { - global $sugar_config; - - $destination = clean_path($this->get_upload_path($bean_id)); + function final_move($bean_id) + { + $destination = $bean_id; + if(substr($destination, 0, 9) != "upload://") { + $destination = "upload://$bean_id"; + } if($this->use_soap) { - $fp = sugar_fopen($destination, 'wb'); - if(!fwrite($fp, $this->file)){ - die("ERROR: can't save file to $destination"); + if(!file_put_contents($destination, $this->file)){ + $GLOBALS['log']->fatal("ERROR: can't save file to $destination"); + return false; } - fclose($fp); } else { - if(!move_uploaded_file($_FILES[$this->field_name]['tmp_name'], $destination)) { - die("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver"); + if(!UploadStream::move_uploaded_file($_FILES[$this->field_name]['tmp_name'], $destination)) { + $GLOBALS['log']->fatal("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver"); + return false; } } return true; } - - function upload_doc(&$bean, $bean_id, $doc_type, $file_name, $mime_type){ - + + /** + * Upload document to external service + * @param SugarBean $bean Related bean + * @param string $bean_id + * @param string $doc_type + * @param string $file_name + * @param string $mime_type + */ + function upload_doc($bean, $bean_id, $doc_type, $file_name, $mime_type) + { if(!empty($doc_type)&&$doc_type!='Sugar') { global $sugar_config; - $destination = clean_path($this->get_upload_path($bean_id)); + $destination = $this->get_upload_path($bean_id); sugar_rename($destination, str_replace($bean_id, $bean_id.'_'.$file_name, $destination)); - $new_destination = clean_path($this->get_upload_path($bean_id.'_'.$file_name)); - + $new_destination = $this->get_upload_path($bean_id.'_'.$file_name); + try{ $this->api = ExternalAPIFactory::loadAPI($doc_type); @@ -323,8 +410,8 @@ class UploadFile sugar_rename($new_destination, str_replace($bean_id.'_'.$file_name, $bean_id, $new_destination)); $bean->doc_type = 'Sugar'; // FIXME: Translate - if ( ! is_array($_SESSION['user_error_message']) ) - $_SESSION['user_error_message'] = array(); + if ( ! is_array($_SESSION['user_error_message']) ) + $_SESSION['user_error_message'] = array(); $error_message = isset($result['errorMessage']) ? $result['errorMessage'] : $GLOBALS['app_strings']['ERR_EXTERNAL_API_SAVE_FAIL']; $_SESSION['user_error_message'][] = $error_message; @@ -334,6 +421,7 @@ class UploadFile unlink($new_destination); } } + } /** @@ -341,15 +429,15 @@ class UploadFile * @param string bean_id ID of the parent bean * @return string */ - function get_upload_path($bean_id) { - global $sugar_config; + function get_upload_path($bean_id) + { $file_name = $bean_id; - + // cn: bug 8056 - mbcs filename in urlencoding > 212 chars in Windows fails $end = (strlen($file_name) > 212) ? 212 : strlen($file_name); $ret_file_name = substr($file_name, 0, $end); - - return $sugar_config['upload_dir'].$ret_file_name; + + return "upload://$ret_file_name"; } /** @@ -357,9 +445,244 @@ class UploadFile * @param string bean_id ID of the parent bean * @param string file_name File's name */ - function unlink_file($bean_id,$file_name) { - global $sugar_config; - return unlink($sugar_config['upload_dir'].$bean_id.$file_name); + static public function unlink_file($bean_id,$file_name = '') + { + if(file_exists("upload://$bean_id$file_name")) { + return unlink("upload://$bean_id$file_name"); + } + } + + /** + * Get upload file location prefix + * @return string prefix + */ + public function get_upload_dir() + { + return "upload://"; + } + + /** + * Return real FS path of the file + * @param string $path + */ + public static function realpath($path) + { + if(substr($path, 0, 9) == "upload://") { + $path = UploadStream::path($path); + } + $ret = realpath($path); + return $ret?$ret:$path; + } + + /** + * Return path of uploaded file relative to uploads dir + * @param string $path + */ + public static function relativeName($path) + { + if(substr($path, 0, 9) == "upload://") { + $path = substr($path, 9); + } + return $path; + } +} + +/** + * @internal + * Upload file stream handler + */ +class UploadStream +{ + const STREAM_NAME = "upload"; + protected static $upload_dir; + + /** + * Get upload directory + * @return string + */ + public static function getDir() + { + if(empty(self::$upload_dir)) { + self::$upload_dir = rtrim($GLOBALS['sugar_config']['upload_dir'], '/\\'); + if(empty(self::$upload_dir)) { + self::$upload_dir = "upload"; + } + if(!file_exists(self::$upload_dir)) { + sugar_mkdir(self::$upload_dir, 0755, true); + } + } + return self::$upload_dir; + } + + /** + * Check if upload dir is writable + * @return bool + */ + public static function writable() + { + return is_writable(self::getDir()); + } + + /** + * Register the stream + */ + public function register() + { + stream_register_wrapper(self::STREAM_NAME, __CLASS__); + } + + /** + * Get real FS path of the upload stream file + * @param string $path Upload stream path (with upload://) + * @return string FS path + */ + public static function path($path) + { + $path = substr($path, strlen(self::STREAM_NAME)+3); // cut off upload:// + $path = str_replace("\\", "/", $path); // canonicalize path + if($path == ".." || substr($path, 0, 3) == "../" || substr($path, -3, 3) == "/.." || strstr($path, "/../")) { + $GLOBALS['log']->fatal("Invalid uploaded file name supplied: $path"); + return null; + } + return self::getDir()."/".$path; + } + + /** + * Ensure upload subdir exists + * @param string $path Upload stream path (with upload://) + * @param bool $writable + * @return boolean + */ + public static function ensureDir($path, $writable = true) + { + $path = self::path($path); + if(!is_dir($path)) { + return sugar_mkdir($path, 0755, true); + } + return true; + } + + public function dir_closedir() + { + closedir($this->dirp); + } + + public function dir_opendir ($path, $options ) + { + $this->dirp = opendir(self::path($path)); + return !empty($this->dirp); + } + + public function dir_readdir() + { + return readdir($this->dirp); + } + + public function dir_rewinddir() + { + return rewinddir($this->dirp); + } + + public function mkdir($path, $mode, $options) + { + return mkdir(self::path($path), $mode, ($options&STREAM_MKDIR_RECURSIVE) != 0); + } + + public function rename($path_from, $path_to) + { + return rename(self::path($path_from), self::path($path_to)); + } + + public function rmdir($path, $options) + { + return rmdir(self::path($path)); + } + + public function stream_cast ($cast_as) + { + return $this->fp; + } + + public function stream_close () + { + fclose($this->fp); + return true; + } + + public function stream_eof () + { + return feof($this->fp); + } + public function stream_flush () + { + return fflush($this->fp); + } + + public function stream_lock($operation) + { + return flock($this->fp, $operation); + } + + public function stream_open($path, $mode) + { + $fullpath = self::path($path); + if(empty($fullpath)) return false; + if($mode == 'r') { + $this->fp = fopen($fullpath, $mode); + } else { + // if we will be writing, try to transparently create the directory + $this->fp = @fopen($fullpath, $mode); + if(!$this->fp && !file_exists(dirname($fullpath))) { + mkdir(dirname($fullpath), 0755, true); + $this->fp = fopen($fullpath, $mode); + } + } + return !empty($this->fp); + } + + public function stream_read($count) + { + return fread($this->fp, $count); + } + + public function stream_seek($offset, $whence = SEEK_SET) + { + return fseek($this->fp, $offset, $whence) == 0; + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function stream_stat() + { + return fstat($this->fp); + } + + public function stream_tell() + { + return ftell($this->fp); + } + public function stream_write($data) + { + return fwrite($this->fp, $data); + } + + public function unlink($path) + { + unlink(self::path($path)); + return true; + } + + public function url_stat($path, $flags) + { + return @stat(self::path($path)); + } + + public static function move_uploaded_file($upload, $path) + { + return move_uploaded_file($upload, self::path($path)); } } -?> + diff --git a/include/utils.php b/include/utils.php index d25efa6e..1a477769 100644 --- a/include/utils.php +++ b/include/utils.php @@ -81,6 +81,7 @@ function make_sugar_config(&$sugar_config) global $list_max_entries_per_page; global $lock_default_user_name; global $log_memory_usage; + global $nameFormats; global $requireAccounts; global $RSS_CACHE_TIME; global $session_dir; @@ -99,7 +100,7 @@ function make_sugar_config(&$sugar_config) global $passwordsetting; // assumes the following variables must be set: - // $dbconfig, $dbconfigoption, $cache_dir, $import_dir, $session_dir, $site_URL, $tmp_dir, $upload_dir + // $dbconfig, $dbconfigoption, $cache_dir, $session_dir, $site_URL, $upload_dir $sugar_config = array ( 'admin_export_only' => empty($admin_export_only) ? false : $admin_export_only, @@ -127,6 +128,7 @@ function make_sugar_config(&$sugar_config) 'default_currency_symbol' => empty($default_currency_symbol) ? '$' : $default_currency_symbol, 'default_currency_iso4217' => empty($default_currency_iso4217) ? '$' : $default_currency_iso4217, 'default_date_format' => empty($defaultDateFormat) ? 'm/d/Y' : $defaultDateFormat, + 'default_locale_name_format' => empty($defaultNameFormat) ? 's f l' : $defaultNameFormat, 'default_export_charset' => 'UTF-8', 'default_language' => empty($default_language) ? 'en_us' : $default_language, 'default_module' => empty($default_module) ? 'Home' : $default_module, @@ -155,6 +157,10 @@ function make_sugar_config(&$sugar_config) 'list_max_entries_per_subpanel' => empty($list_max_entries_per_subpanel) ? 10 : $list_max_entries_per_subpanel, 'lock_default_user_name' => empty($lock_default_user_name) ? false : $lock_default_user_name, 'log_memory_usage' => empty($log_memory_usage) ? false : $log_memory_usage, + 'name_formats' => empty($nameFormats) ? array( + 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f', + 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s' + ) : $nameFormats, 'portal_view' => 'single_user', 'resource_management' => array ( 'special_query_limit' => 50000, @@ -178,7 +184,7 @@ function make_sugar_config(&$sugar_config) 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py', 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ) : $upload_badext, 'upload_dir' => $upload_dir, // this must be set!! - 'upload_maxsize' => empty($upload_maxsize) ? 3000000 : $upload_maxsize, + 'upload_maxsize' => empty($upload_maxsize) ? 30000000 : $upload_maxsize, 'import_max_execution_time' => empty($import_max_execution_time) ? 3600 : $import_max_execution_time, 'lock_homepage' => false, 'lock_subpanels' => false, @@ -205,6 +211,7 @@ function make_sugar_config(&$sugar_config) 'systexpirationtype' => '0', 'systexpirationlogin' => '', ) : $passwordsetting, + 'use_sprites' => function_exists('imagecreatetruecolor'), ); } @@ -227,12 +234,14 @@ function get_sugar_config_defaults() { 'Y-m-d' => '2010-12-23', 'm-d-Y' => '12-23-2010', 'd-m-Y' => '23-12-2010', 'Y/m/d' => '2010/12/23', 'm/d/Y' => '12/23/2010', 'd/m/Y' => '23/12/2010', 'Y.m.d' => '2010.12.23', 'd.m.Y' => '23.12.2010', 'm.d.Y' => '12.23.2010',), + 'name_formats' => array ( + 's f l' => 's f l', 'f l' => 'f l', 's l' => 's l', 'l, s f' => 'l, s f', + 'l, f' => 'l, f', 's l, f' => 's l, f', 'l s f' => 'l s f', 'l f s' => 'l f s' + ), 'dbconfigoption' => array ( 'persistent' => true, 'autofree' => false, 'debug' => 0, - 'seqname_format' => '%s_seq', - 'portability' => 0, 'ssl' => false ), 'default_action' => 'index', 'default_charset' => return_session_value_or_default('default_charset', @@ -244,6 +253,7 @@ function get_sugar_config_defaults() { 'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','), 'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'), 'default_date_format' => 'm/d/Y', + 'default_locale_name_format' => 's f l', 'default_export_charset' => 'UTF-8', 'default_language' => return_session_value_or_default('default_language', 'en_us'), @@ -302,7 +312,7 @@ function get_sugar_config_defaults() { 'upload_badext' => array ( 'php', 'php3', 'php4', 'php5', 'pl', 'cgi', 'py', 'asp', 'cfm', 'js', 'vbs', 'html', 'htm' ), - 'upload_maxsize' => 3000000, + 'upload_maxsize' => 30000000, 'import_max_execution_time' => 3600, // 'use_php_code_json' => returnPhpJsonStatus(), 'verify_client_ip' => true, @@ -325,6 +335,18 @@ function get_sugar_config_defaults() { 'use_common_ml_dir' => false, 'common_ml_dir' => '', 'vcal_time' => '2', + 'calendar' => array( + 'default_view' => 'week', + 'show_calls_by_default' => true, + 'show_tasks_by_default' => true, + 'editview_width' => 990, + 'editview_height' => 480, + 'day_timestep' => 15, + 'week_timestep' => 30, + 'month_timestep' => 60, + 'items_draggable' => true, + 'mouseover_expand' => true, + ), 'passwordsetting' => empty($passwordsetting) ? array ( 'SystemGeneratedPasswordON' => '', 'generatepasswordtmpl' => '', @@ -547,33 +569,50 @@ function get_user_name($id) { //TODO Update to use global cache -function get_user_array($add_blank=true, $status="Active", $assigned_user="", $use_real_name=false, $user_name_begins = null, $is_group=' AND portal_only=0 ', $from_cache = true) { +/** + * get_user_array + * + * This is a helper function to return an Array of users depending on the parameters passed into the function. + * This function uses the get_register_value function by default to use a caching layer where supported. + * + * @param bool $add_blank Boolean value to add a blank entry to the array results, true by default + * @param string $status String value indicating the status to filter users by, "Active" by default + * @param string $user_id String value to specify a particular user id value (searches the id column of users table), blank by default + * @param bool $use_real_name Boolean value indicating whether or not results should include the full name or just user_name, false by default + * @param String $user_name_filter String value indicating the user_name filter (searches the user_name column of users table) to optionally search with, blank by default + * @param string $portal_filter String query filter for portal users (defaults to searching non-portal users), change to blank if you wish to search for all users including portal users + * @param bool $from_cache Boolean value indicating whether or not to use the get_register_value function for caching, true by default + * @return array Array of users matching the filter criteria that may be from cache (if similar search was previously run) + */ +function get_user_array($add_blank=true, $status="Active", $user_id='', $use_real_name=false, $user_name_filter='', $portal_filter=' AND portal_only=0 ', $from_cache = true) { global $locale; global $sugar_config; if(empty($locale)) { - $locale = new Localization(); } - if($from_cache) - $user_array = get_register_value('user_array', $add_blank. $status . $assigned_user); + + if($from_cache) { + $key_name = $add_blank. $status . $user_id . $use_real_name . $user_name_filter . $portal_filter; + $user_array = get_register_value('user_array', $key_name); + } if(empty($user_array)) { $db = DBManagerFactory::getInstance(); $temp_result = Array(); // Including deleted users for now. if (empty($status)) { - $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$is_group; + $query = "SELECT id, first_name, last_name, user_name from users WHERE 1=1".$portal_filter; } else { - $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$is_group; + $query = "SELECT id, first_name, last_name, user_name from users WHERE status='$status'".$portal_filter; } - if (!empty($user_name_begins)) { - $query .= " AND user_name LIKE '$user_name_begins%' "; + if (!empty($user_name_filter)) { + $query .= " AND user_name LIKE '$user_name_filter%' "; } - if (!empty($assigned_user)) { - $query .= " OR id='$assigned_user'"; + if (!empty($user_id)) { + $query .= " OR id='{$user_id}'"; } $query = $query.' ORDER BY user_name ASC'; $GLOBALS['log']->debug("get_user_array query: $query"); @@ -599,7 +638,9 @@ function get_user_array($add_blank=true, $status="Active", $assigned_user="", $u $user_array = $temp_result; if($from_cache) - set_register_value('user_array', $add_blank. $status . $assigned_user, $temp_result); + { + set_register_value('user_array', $key_name, $temp_result); + } } @@ -959,7 +1000,7 @@ function return_module_language($language, $module, $refresh=false) // Bug 21559 - So we can get all the strings defined in the template, refresh // the vardefs file if the cached language file doesn't exist. - if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/'. $module . '/language/'.$language.'.lang.php') + if(!file_exists(sugar_cached('modules/'). $module . '/language/'.$language.'.lang.php') && !empty($GLOBALS['beanList'][$module])){ $object = BeanFactory::getObjectName($module); VardefManager::refreshVardefs($module,$object); @@ -1072,7 +1113,7 @@ function return_mod_list_strings_language($language,$module) { */ function return_theme_language($language, $theme) { - global $mod_strings, $sugar_config, $currentModule; + global $mod_strings, $sugar_config, $current_language; $language_used = $language; $default_language = $sugar_config['default_language']; @@ -1834,7 +1875,7 @@ function clean_string($str, $filter = "STANDARD", $dieOnBadData = true) "NUMBER" => '#[^0-9\-]#i', "SQL_COLUMN_LIST" => '#[^A-Z0-9\(\),_\.]#i', "PATH_NO_URL" => '#://#i', - "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~]#i', /* range of allowed characters in a GET string */ + "SAFED_GET" => '#[^A-Z0-9\@\=\&\?\.\/\-_~+]#i', /* range of allowed characters in a GET string */ "UNIFIED_SEARCH" => "#[\\x00]#", /* cn: bug 3356 & 9236 - MBCS search strings */ "AUTO_INCREMENT" => '#[^0-9\-,\ ]#i', "ALPHANUM" => '#[^A-Z0-9\-]#i', @@ -1842,7 +1883,7 @@ function clean_string($str, $filter = "STANDARD", $dieOnBadData = true) if (preg_match($filters[$filter], $str)) { if (isset($GLOBALS['log']) && is_object($GLOBALS['log'])) { - $GLOBALS['log']->fatal("SECURITY: bad data passed in; string: {$str}"); + $GLOBALS['log']->fatal("SECURITY[$filter]: bad data passed in; string: {$str}"); } if ( $dieOnBadData ) { die("Bad data passed in; Return to Home"); @@ -1899,6 +1940,14 @@ function set_superglobals($key, $val){ // Works in conjunction with clean_string() to defeat SQL injection, file inclusion attacks, and XSS function clean_incoming_data() { global $sugar_config; + global $RAW_REQUEST; + + if(get_magic_quotes_gpc()) { + // magic quotes screw up data, we'd have to clean up + $RAW_REQUEST = array_map("cleanup_slashes", $_REQUEST); + } else { + $RAW_REQUEST = $_REQUEST; + } if (get_magic_quotes_gpc() == 1) { $req = array_map("preprocess_param", $_REQUEST); @@ -1971,7 +2020,7 @@ function securexss($value) { } return $new; } - static $xss_cleanup= array('"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>'); + static $xss_cleanup= array(""" => "&", '"' =>'"', "'" => ''' , '<' =>'<' , '>'=>'>'); $value = preg_replace(array('/javascript:/i', '/\0/'), array('java script:', ''), $value); $value = preg_replace('/javascript:/i', 'java script:', $value); return str_replace(array_keys($xss_cleanup), array_values($xss_cleanup), $value); @@ -1980,7 +2029,7 @@ function securexss($value) { function securexsskey($value, $die=true){ global $sugar_config; $matches = array(); - preg_match("/[\'\"\<\>]/", $value, $matches); + preg_match('/[\'"<>]/', $value, $matches); if(!empty($matches)){ if($die){ die("Bad data passed in; Return to Home"); @@ -2001,12 +2050,16 @@ function preprocess_param($value){ $value = securexss($value); } - return $value; +} - +function cleanup_slashes($value) +{ + if(is_string($value)) return stripslashes($value); + return $value; } + function set_register_value($category, $name, $value){ return sugar_cache_put("{$category}:{$name}", $value); } @@ -2033,13 +2086,9 @@ function convert_id($string) /** * @deprecated use SugarTheme::getImage() */ -function get_image($image,$other_attributes,$width="",$height="") +function get_image($image,$other_attributes,$width="",$height="",$ext='.gif',$alt) { - return SugarThemeRegistry::current()->getImage(basename($image), - $other_attributes, - empty($width) ? null : $width, - empty($height) ? null : $height - ); + return SugarThemeRegistry::current()->getImage(basename($image), $other_attributes, empty($width) ? null : $width, empty($height) ? null : $height, $ext, $alt ); } /** * @deprecated use SugarTheme::getImageURL() @@ -2056,14 +2105,38 @@ function getWebPath($relative_path){ return $relative_path; } -function getJSPath($relative_path, $additional_attrs=''){ - if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path); - if(empty($GLOBALS['sugar_config']['js_custom_version']))$GLOBALS['sugar_config']['js_custom_version'] = 1; +function getVersionedPath($path, $additional_attrs='') +{ + if(empty($GLOBALS['sugar_config']['js_custom_version'])) $GLOBALS['sugar_config']['js_custom_version'] = 1; $js_version_key = isset($GLOBALS['js_version_key'])?$GLOBALS['js_version_key']:''; - $path = $relative_path . '?s=' . $js_version_key . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] ; - if ( inDeveloperMode() ) $path .= '&developerMode='.mt_rand(); - if(!empty($additonal_attrs)) $path .= '&' . $additional_attrs; - return $path; + if(inDeveloperMode()) { + static $rand; + if(empty($rand)) $rand = mt_rand(); + $dev = $rand; + } else { + $dev = ''; + } + if(is_array($additional_attrs)) { + $additional_attrs = join("|",$additional_attrs); + } + // cutting 2 last chars here because since md5 is 32 chars, it's always == + $str = substr(base64_encode(md5("$js_version_key|{$GLOBALS['sugar_config']['js_custom_version']}|$dev|$additional_attrs", true)), 0, -2); + // remove / - it confuses some parsers + $str = strtr($str, '/+', '-_'); + if(empty($path)) return $str; + + return $path . "?v=$str"; +} + +function getVersionedScript($path, $additional_attrs='') +{ + return ''; +} + +function getJSPath($relative_path, $additional_attrs='') +{ + if(defined('TEMPLATE_URL'))$relative_path = SugarTemplateUtilities::getWebPath($relative_path); + return getVersionedPath($relative_path).(!empty($additional_attrs)?"&$additional_attrs":""); } function getSWFPath($relative_path, $additional_params=''){ @@ -2282,6 +2355,7 @@ function get_bean_select_array($add_blank=true, $bean_name, $display_columns, $w { $db = DBManagerFactory::getInstance(); + $temp_result = Array(); $query = "SELECT {$focus->table_name}.id, {$display_columns} as display from {$focus->table_name} "; $query .= "where "; @@ -2567,16 +2641,8 @@ function check_php_version($sys_php_version = '') { // only the supported versions, // should be mutually exclusive with $invalid_php_versions $supported_php_versions = array ( - '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0' + '5.2.1', '5.2.2', '5.2.3', '5.2.4', '5.2.5', '5.2.6', '5.2.8', '5.3.0' ); - //Find out what Database the system is using. - global $sugar_config; - $dbType = ''; - if (isset($_REQUEST['setup_db_type'])) { - $dbType = $_REQUEST['setup_db_type']; - } else if (isset ($sugar_config['dbconfig']) && isset ($sugar_config['dbconfig']['db_type'])) { - $dbType = $sugar_config['dbconfig']['db_type']; - } // invalid versions above the $min_considered_php_version, // should be mutually exclusive with $supported_php_versions @@ -3470,11 +3536,6 @@ function setPhpIniSettings() { if(!empty($backtrack_limit)) { ini_set('pcre.backtrack_limit', '-1'); } - - // mssql only - if(ini_get("mssql.charset")) { - ini_set('mssql.charset', "UTF-8"); - } } /** @@ -3636,7 +3697,7 @@ function generate_search_where ($field_list=array(),$values=array(),&$bean,$add_ if (strstr($db_field,'.')===false) { $db_field=$bean->table_name.".".$db_field; } - if ($GLOBALS['db']->dbType=='oci8' && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') { + if ($GLOBALS['db']->supports('case_sensitive') && isset($parms['query_type']) && $parms['query_type']=='case_insensitive') { $db_field='upper('.$db_field.")"; $field_value=strtoupper($field_value); } @@ -3782,16 +3843,24 @@ function createGroupUser($name) { function _getIcon($iconFileName) { - $iconPath = SugarThemeRegistry::current()->getImageURL("icon_{$iconFileName}.gif"); + + $iconName = "icon_{$iconFileName}.gif"; + $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false); + //First try un-ucfirst-ing the icon name - if ( empty($iconPath) ) - $iconPath = SugarThemeRegistry::current()->getImageURL( - "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif"); - //Next try removing the icon prefix - if ( empty($iconPath) ) - $iconPath = SugarThemeRegistry::current()->getImageURL("{$iconFileName}.gif"); + if ( empty($iconFound) ) + $iconName = "icon_" . strtolower(substr($iconFileName,0,1)).substr($iconFileName,1) . ".gif"; + $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false); + + //Next try removing the icon prefix + if ( empty($iconFound) ) + $iconName = "{$iconFileName}.gif"; + $iconFound = SugarThemeRegistry::current()->getImageURL($iconName,false); - return $iconPath; + if ( empty($iconFound) ) + $iconName = ''; + + return $iconName; } /** * Function to grab the correct icon image for Studio @@ -3800,22 +3869,23 @@ function _getIcon($iconFileName) * @param string $width Width of image * @param string $height Height of image * @param string $align Alignment of image + * @param string $alt Alt tag of image * @return string $string tag with corresponding image */ -function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline' ) +function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height='48', $align='baseline', $alt='' ) { global $app_strings, $theme; - $iconPath = _getIcon($iconFileName); - if(empty($iconPath)){ - $iconPath = _getIcon($altFileName); - if (empty($iconPath)) + $iconName = _getIcon($iconFileName); + if(empty($iconName)){ + $iconName = _getIcon($altFileName); + if (empty($iconName)) { return $app_strings['LBL_NO_IMAGE']; } } - return ''; + return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height); } /** @@ -3825,23 +3895,21 @@ function getStudioIcon($iconFileName='', $altFileName='', $width='48', $height=' * @param string $width Width of image * @param string $height Height of image * @param string $align Alignment of image + * @param string $alt Alt tag of image * @return string $string tag with corresponding image */ -function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle'){ +function get_dashlets_dialog_icon($module='', $width='32', $height='32', $align='absmiddle',$alt=''){ global $app_strings, $theme; - $icon_path = _getIcon($module . "_32"); - if (empty($icon_path)) + $iconName = _getIcon($module . "_32"); + if (empty($iconName)) { - $icon_path = _getIcon($module); + $iconName = _getIcon($module); } - if(empty($icon_path)){ - $icon = $app_strings['LBL_NO_IMAGE']; + if(empty($iconName)){ + return $app_strings['LBL_NO_IMAGE']; } - else{ - $icon = ''; - } - return $icon; + return SugarThemeRegistry::current()->getImage($iconName, "align=\"$align\" border=\"0\"", $width, $height); } // works nicely to change UTF8 strings that are html entities - good for PDF conversions @@ -3893,45 +3961,11 @@ if (version_compare(phpversion(), '5.0.0', '<')) { } /* - * Invoked when connected to mssql. checks if we have freetds version of mssql library. - * the response is put into a global variable. + * @deprecated use DBManagerFactory::isFreeTDS */ -function is_freetds() { - - $ret=false; - if (isset($GLOBALS['mssql_library_version'])) { - if ($GLOBALS['mssql_library_version']=='freetds') { - $ret=true; - } else { - $ret=false; - } - } else { - ob_start(); - phpinfo(); - $info=ob_get_contents(); - ob_end_clean(); - - if (strpos($info,'FreeTDS') !== false) { - $GLOBALS['mssql_library_version']='freetds'; - $ret=true; - } else { - $GLOBALS['mssql_library_version']='regular'; - $ret=false; - } - } - return $ret; -} - -/* - * stripos - Find position of first occurrence of a case-insensitive string - * - * The function is being defined for systems with PHP version < 5. - * - */ -if (!function_exists("stripos")){ - function stripos($haystack,$needle,$offset=0){ - return strpos(strtolower($haystack),strtolower($needle),$offset); - } +function is_freetds() +{ + return DBManagerFactory::isFreeTDS(); } /** @@ -4095,16 +4129,10 @@ function filterInboundEmailPopSelection($protocol) * The varchar in MySQL, Orcale, and nvarchar in FreeTDS, we can store $length mutilbyte charaters in it. we need mb_substr to keep more info. * @returns the substred strings. */ -function sugar_substr($string, $length, $charset='UTF-8') { - if($GLOBALS['db']->dbType == 'mssql' && empty($GLOBALS['db']->isFreeTDS)) { - if(strlen($string) > $length) { - $string = trim(substr(trim($string),0,$length)); - } - } - else { - if(mb_strlen($string,$charset) > $length) { - $string = trim(mb_substr(trim($string),0,$length,$charset)); - } +function sugar_substr($string, $length, $charset='UTF-8') +{ + if(mb_strlen($string,$charset) > $length) { + $string = trim(mb_substr(trim($string),0,$length,$charset)); } return $string; } @@ -4337,13 +4365,20 @@ function verify_image_file($path, $jpeg = false) $filetype = $img_size['mime']; //if filetype is jpeg or if we are only allowing jpegs, create jpg image if($filetype == "image/jpeg" || $jpeg) { - if(imagejpeg($img, $path)) { + ob_start(); + imagejpeg($img); + $image = ob_get_clean(); + // not writing directly because imagejpeg does not work with streams + if(file_put_contents($path, $image)) { return true; } } elseif ($filetype == "image/png") { // else if the filetype is png, create png imagealphablending($img, true); imagesavealpha($img, true); - if(imagepng($img, $path)) { + ob_start(); + imagepng($img); + $image = ob_get_clean(); + if(file_put_contents($path, $image)) { return true; } } else { @@ -4464,3 +4499,16 @@ function utf8_recursive_encode($data) } return $result; } + +/** + * get_language_header + * + * This is a utility function for 508 Compliance. It returns the lang=[Current Language] text string used + * inside the tag. If no current language is specified, it defaults to lang='en'. + * + * @return String The lang=[Current Language] markup to insert into the tag + */ +function get_language_header() +{ + return isset($GLOBALS['current_language']) ? "lang='{$GLOBALS['current_language']}'" : "lang='en'"; +} diff --git a/include/utils/LogicHook.php b/include/utils/LogicHook.php index 3a3e77d8..735f9818 100644 --- a/include/utils/LogicHook.php +++ b/include/utils/LogicHook.php @@ -56,6 +56,7 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * after_login * login_failed * + * @api */ class LogicHook{ diff --git a/include/utils/activity_utils.php b/include/utils/activity_utils.php index 394a8326..4018472d 100644 --- a/include/utils/activity_utils.php +++ b/include/utils/activity_utils.php @@ -56,13 +56,16 @@ function build_related_list_by_user_id($bean, $user_id,$where) { $list = array(); while($row = $bean->db->fetchByAssoc($result)) { - foreach($bean->column_fields as $field) { - if(isset($row[$field])) { - $bean->$field = $row[$field]; - } else { - $bean->$field = ''; - } - } + $row = $bean->convertRow($row); + $bean->fetched_row = $row; + $bean->fromArray($row); +// foreach($bean->column_fields as $field) { +// if(isset($row[$field])) { +// $bean->$field = $row[$field]; +// } else { +// $bean->$field = ''; +// } +// } $bean->processed_dates_times = array(); $bean->check_date_relationships_load(); diff --git a/include/utils/db_utils.php b/include/utils/db_utils.php index ae434561..7ae24881 100644 --- a/include/utils/db_utils.php +++ b/include/utils/db_utils.php @@ -139,91 +139,31 @@ function from_html($string, $encode=true) { return $cache[$string]; } -/** - * @deprecated - * @todo this function is only used by one function ( run_upgrade_wizard_sql() ), which isn't - * used either; trying kill this off - */ -function run_sql_file( $filename ) -{ - if( !is_file( $filename ) ){ - print( "Could not find file: $filename
" ); - return( false ); - } - - - $contents = sugar_file_get_contents($filename); - - $lastsemi = strrpos( $contents, ';') ; - $contents = substr( $contents, 0, $lastsemi ); - $queries = explode( ';', $contents ); - $db = DBManagerFactory::getInstance(); - - foreach( $queries as $query ){ - if( !empty($query) ){ - if($db->dbType == 'oci8') - { - } - else - { - $db->query( $query.';', true, "An error has occured while running.
" ); - } - } - } - return( true ); -} - /* * Return a version of $proposed that can be used as a column name in any of our supported databases * Practically this means no longer than 25 characters as the smallest identifier length for our supported DBs is 30 chars for Oracle plus we add on at least four characters in some places (for indicies for example) * @param string $name Proposed name for the column * @param string $ensureUnique + * @param int $maxlen Deprecated and ignored * @return string Valid column name trimmed to right length and with invalid characters removed */ - function getValidDBName ($name, $ensureUnique = false, $maxLen = 30) +function getValidDBName ($name, $ensureUnique = false, $maxLen = 30) { - // first strip any invalid characters - all but alphanumerics and - - $name = preg_replace ( '/[^\w-]+/i', '', $name ) ; - $len = strlen ( $name ) ; - $result = $name; - if ($ensureUnique) - { - $md5str = md5($name); - $tail = substr ( $name, -11) ; - $temp = substr($md5str , strlen($md5str)-4 ); - $result = substr ( $name, 0, 10) . $temp . $tail ; - }else if ($len > ($maxLen - 5)) - { - $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5); - } - return strtolower ( $result ) ; + return DBManagerFactory::getInstance()->getValidDBName($name, $ensureUnique); } + /** + * isValidDBName + * * Utility to perform the check during install to ensure a database name entered by the user * is valid based on the type of database server * @param string $name Proposed name for the DB * @param string $dbType Type of database server * @return bool true or false based on the validity of the DB name */ -function isValidDBName($name, $dbType) { - switch ($dbType){ - case 'mssql': - $pattern = '/^[0-9#@]+|[\"\'\*\/\\?\:\\<\>\-\ \&\!\(\)\[\]\{\}\;\,\.\`\~\|\\\\]+/i'; - break; - case 'oci8': - $pattern = '/[\#\"\'\*\/\\?\:\\<\>\-\ \&\!\(\)\[\]\{\}\;\,\.\`\~\|\\\\]+/i'; - break; - case 'mysql': - $pattern = '/[\/\.\\\\]/i'; - break; - default: - $pattern = '/[\/\.\\\\]/i'; - break; - } - return preg_match($pattern, $name)==0?true:false; -} - - - -?> +function isValidDBName($name, $dbType) +{ + $db = DBManagerFactory::getTypeInstance($dbType); + return $db->isDatabaseNameValid($name); +} \ No newline at end of file diff --git a/include/utils/encryption_utils.php b/include/utils/encryption_utils.php index a277874e..17b099bb 100644 --- a/include/utils/encryption_utils.php +++ b/include/utils/encryption_utils.php @@ -36,9 +36,9 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ require_once('include/Pear/Crypt_Blowfish/Blowfish.php'); - -function sugarEncode($key, $data){ - return base64_encode($data); + +function sugarEncode($key, $data){ + return base64_encode($data); } @@ -56,16 +56,16 @@ function sugarDecode($key, $encoded){ */ function blowfishGetKey($type) { $key = array(); - + $type = str_rot13($type); - - $keyCache = "{$GLOBALS['sugar_config']['cache_dir']}blowfish/{$type}.php"; - + + $keyCache = "custom/blowfish/{$type}.php"; + // build cache dir if needed - if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'blowfish')) { - mkdir_recursive($GLOBALS['sugar_config']['cache_dir'].'blowfish'); + if(!file_exists('custom/blowfish')) { + mkdir_recursive('custom/blowfish'); } - + // get key from cache, or build if not exists if(file_exists($keyCache)) { include($keyCache); @@ -75,7 +75,7 @@ function blowfishGetKey($type) { write_array_to_file('key', $key, $keyCache); } return $key[0]; -} +} /** * Uses blowfish to encrypt data and base 64 encodes it. It stores the iv as part of the data @@ -83,10 +83,10 @@ function blowfishGetKey($type) { * @param STRING data - string to be encrypted and encoded * @return string */ -function blowfishEncode($key, $data){ +function blowfishEncode($key, $data){ $bf = new Crypt_Blowfish($key); $encrypted = $bf->encrypt($data); - return base64_encode($encrypted); + return base64_encode($encrypted); } /** @@ -98,7 +98,7 @@ function blowfishEncode($key, $data){ function blowfishDecode($key, $encoded){ $data = base64_decode($encoded); $bf = new Crypt_Blowfish($key); - return trim($bf->decrypt($data)); + return trim($bf->decrypt($data)); } ?> \ No newline at end of file diff --git a/include/utils/file_utils.php b/include/utils/file_utils.php index 90dd43fa..1d88c8cd 100644 --- a/include/utils/file_utils.php +++ b/include/utils/file_utils.php @@ -39,6 +39,11 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/utils/array_utils.php'); require_once('include/utils/sugar_file_utils.php'); +/** + * Convert all \ to / in path, remove multiple '/'s and '/./' + * @param string $path + * @return string + */ function clean_path( $path ) { // clean directory/file path with a functional equivalent @@ -56,7 +61,7 @@ function clean_path( $path ) function create_cache_directory($file) { $paths = explode('/',$file); - $dir = str_replace('/','',$GLOBALS['sugar_config']['cache_dir']); + $dir = rtrim($GLOBALS['sugar_config']['cache_dir'], '/\\'); if(!file_exists($dir)) { sugar_mkdir($dir, 0775); @@ -92,7 +97,7 @@ function get_module_dir_list() function mk_temp_dir( $base_dir, $prefix="" ) { - $temp_dir = tempnam( getcwd() .'/'. $base_dir, $prefix ); + $temp_dir = tempnam( $base_dir, $prefix ); if( !$temp_dir || !unlink( $temp_dir ) ) { return( false ); @@ -130,7 +135,7 @@ function write_encoded_file( $soap_result, $write_to_dir, $write_to_file="" ) // this function dies when encountering an error -- use with caution! // the path/file is returned upon success - + if( $write_to_file == "" ) { @@ -323,7 +328,7 @@ function fileToHash($file){ $_SESSION['file2Hash'][$hash] = $file; return $hash; } - + function hashToFile($hash){ if(!empty($_SESSION['file2Hash'][$hash])){ return $_SESSION['file2Hash'][$hash]; @@ -336,10 +341,10 @@ function hashToFile($hash){ /** * get_file_extension * This function returns the file extension portion of a given filename - * + * * @param $filename String of filename to return extension * @param $string_to_lower boolean value indicating whether or not to return value as lowercase, true by default - * + * * @return extension String value, blank if no extension found */ function get_file_extension($filename, $string_to_lower=true) @@ -348,7 +353,7 @@ function get_file_extension($filename, $string_to_lower=true) { return $string_to_lower ? strtolower(array_pop(explode('.',$filename))) : array_pop(explode('.',$filename)); } - + return ''; } @@ -358,12 +363,12 @@ function get_file_extension($filename, $string_to_lower=true) * This function is similar to mime_content_type, but does not require a real * file or path location. Instead, the function merely checks the filename * extension and returns a best guess mime content type. - * + * * @param $filename String of filename to return mime content type * @return mime content type as String value (defaults to 'application/octet-stream' for filenames with extension, empty otherwise) - * + * */ -function get_mime_content_type_from_filename($filename) +function get_mime_content_type_from_filename($filename) { if(strpos($filename, '.') !== false) { @@ -426,10 +431,10 @@ function get_mime_content_type_from_filename($filename) if (array_key_exists($ext, $mime_types)) { return $mime_types[$ext]; } - - return 'application/octet-stream'; + + return 'application/octet-stream'; } - + return ''; } @@ -437,5 +442,3 @@ function cleanFileName($name) { return preg_replace('/[^\w-._]+/i', '', $name); } - -?> \ No newline at end of file diff --git a/include/utils/layout_utils.php b/include/utils/layout_utils.php index 9750d94d..246c316a 100644 --- a/include/utils/layout_utils.php +++ b/include/utils/layout_utils.php @@ -44,25 +44,25 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); /** * Create HTML to display formatted form title. - * + * * @param $form_title string to display as the title in the header * @param $other_text string to next to the title. Typically used for form buttons. * @param $show_help boolean which determines if the print and help links are shown. * @return string HTML */ function get_form_header( - $form_title, - $other_text, + $form_title, + $other_text, $show_help ) { global $sugar_version, $sugar_flavor, $server_unique_key, $current_language, $current_module, $current_action; global $app_strings; - + $blankImageURL = SugarThemeRegistry::current()->getImageURL('blank.gif'); $printImageURL = SugarThemeRegistry::current()->getImageURL("print.gif"); $helpImageURL = SugarThemeRegistry::current()->getImageURL("help.gif"); - + $is_min_max = strpos($other_text,"_search.gif"); if($is_min_max !== false) $form_title = "{$other_text} {$form_title}"; @@ -72,13 +72,13 @@ function get_form_header(

{$form_title}

EOHTML; - + $keywords = array("/class=\"button\"/","/class='button'/","/class=button/","/<\/form>/"); $match=""; foreach ($keywords as $left) if (preg_match($left,$other_text)) $match = true; - + if ($other_text && $match) { $the_form .= << @@ -92,7 +92,7 @@ EOHTML; if ($_REQUEST['action'] != "EditView") { $the_form .= << - Print + {$app_strings["LBL_PRINT"]}   {$app_strings['LNK_PRINT']} @@ -125,13 +125,13 @@ EOHTML; EOHTML; } - + if ($show_help) { $the_form .= ""; if ($_REQUEST['action'] != "EditView") { $the_form .= << - Print + {$app_strings[   {$app_strings['LNK_PRINT']} @@ -141,7 +141,7 @@ EOHTML;   - Help + {$app_strings[   {$app_strings['LNK_HELP']} @@ -149,18 +149,18 @@ EOHTML; EOHTML; } } - + $the_form .= << EOHTML; - + return $the_form; } /** * Wrapper function for the get_module_title function, which is mostly used for pre-MVC modules. - * + * * @deprecated use SugarView::getModuleTitle() for MVC modules, or getClassicModuleTitle() for non-MVC modules * * @param $module string to next to the title. Typically used for form buttons. @@ -169,16 +169,16 @@ EOHTML; * @return string HTML */ function get_module_title( - $module, - $module_title, + $module, + $module_title, $show_create, $count=0 ) { global $sugar_version, $sugar_flavor, $server_unique_key, $current_language, $action; global $app_strings; - - $the_title = "
\n

"; + + $the_title = "
\n"; $module = preg_replace("/ /","",$module); $iconPath = ""; if(is_file(SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png',false))) @@ -189,38 +189,37 @@ function get_module_title( $iconPath = SugarThemeRegistry::current()->getImageURL('icon_'.ucfirst($module).'_32.png'); } if (!empty($iconPath)) { + $the_title .= '

'; if (SugarThemeRegistry::current()->directionality == "ltr") { - $the_title .= ""; + $the_title .= ""; $the_title .= ($count >= 1) ? SugarView::getBreadCrumbSymbol() : ""; - $the_title .= $module_title; + $the_title .= $module_title.''; } else { $the_title .= $module_title; $the_title .= ($count > 1) ? SugarView::getBreadCrumbSymbol() : ""; - $the_title .= ""; + $the_title .= ""; } + $the_title .= '

'; } else { - $the_title .= $module_title; + $the_title .="

$module_title

"; } - $the_title .= "

\n"; + $the_title .= "\n"; if ($show_create) { $the_title .= ""; $createRecordURL = SugarThemeRegistry::current()->getImageURL('create-record.gif'); - $url = ajaxLink("index.php?module=$module&action=EditView&return_module=$module&return_action=DetailView"); $the_title .= << + {$GLOBALS[ - + {$GLOBALS['app_strings']['LNK_CREATE']} EOHTML; $the_title .= ''; } - + $the_title .= "
\n"; return $the_title; } @@ -228,47 +227,37 @@ EOHTML; /** * Handles displaying the header for classic view modules * - * @param $module string to next to the title. Typically used for form buttons. - * @param array $params optional, params to display in the breadcrumb, overriding SugarView::_getModuleTitleParams() + * @param $module String value of the module to create the title section for + * @param $params Array of arguments used to create the title label. Typically this is just the current language string label for the section * These should be in the form of array('label' => '', 'link' => ''); * the first breadcrumb should be index at 0, and built from there e.g. * * array( - * 'Contacts', - * 'John Smith', + * 'Contacts', + * 'John Smith', * 'Edit', * ); * * would display as: - * - * Contacts >> John Smith >> Edit - * - * @param $show_help boolean which determines if the print and help links are shown. - * @return string HTML + * Contacts >> John Smith >> Edit + * @param $show_create boolean flag indicating whether or not to display the create link (defaults to false) + * @param $index_url_override String value of url to override for module index link (defaults to module's index action if none supplied) + * @param $create_url_override String value of url to override for module create link (defaults to EditView action if none supplied) + * + * @return String HTML content for a classic module title section */ -function getClassicModuleTitle( - $module, - $params, - $show_create, - $index_url_override="") +function getClassicModuleTitle($module, $params, $show_create=false, $index_url_override='', $create_url_override='') { global $sugar_version, $sugar_flavor, $server_unique_key, $current_language, $action; global $app_strings; - + $module_title = ''; $count = count($params); $index = 0; - - $module = preg_replace("/ /","",$module); $iconPath = ""; - $the_title = "
\n

"; - - if(!empty($GLOBALS['app_list_strings']['moduleList'][$module])) - $moduleName = $GLOBALS['app_list_strings']['moduleList'][$module]; - else - $moduleName = $module; + $the_title = "
\n"; if(is_file(SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png',false))) { @@ -279,10 +268,9 @@ function getClassicModuleTitle( } if (!empty($iconPath)) { $url = (!empty($index_url_override)) ? $index_url_override : "index.php?module={$module}&action=index"; - array_unshift ($params,""); + array_unshift ($params,""); } - + $new_params = array(); $i = 0; foreach ($params as $value) { @@ -290,38 +278,41 @@ function getClassicModuleTitle( $new_params[$i] = $value; $i++; } - } - + } if(SugarThemeRegistry::current()->directionality == "rtl") { $new_params = array_reverse($new_params); } - + $module_title = join(SugarView::getBreadCrumbSymbol(),$new_params); - - - - $the_title .= $module_title."

\n"; - + if(!empty($module_title)){ + $the_title .= "

".$module_title."

\n";//removing empty H2 tag for 508 compliance + } + + if ($show_create) { $the_title .= ""; - $createRecordURL = SugarThemeRegistry::current()->getImageURL('create-record.gif'); - $url = ajaxLink("index.php?module=$module&action=EditView&return_module=$module&return_action=DetailView"); + $createRecordImage = SugarThemeRegistry::current()->getImageURL('create-record.gif'); + if(empty($create_url_override)) + { + $create_url_override = "index.php?module={$module}&action=EditView&return_module={$module}&return_action=DetailView"; + } + $the_title .= << -{$GLOBALS[ - + +{$GLOBALS[ + {$GLOBALS['app_strings']['LNK_CREATE']} EOHTML; $the_title .= ''; } - + $the_title .= "
\n"; return $the_title; - + } /** @@ -338,18 +329,20 @@ function insert_popup_header( ) { global $app_strings, $sugar_config; - - $charset = isset($app_strings['LBL_CHARSET']) + + $charset = isset($app_strings['LBL_CHARSET']) ? $app_strings['LBL_CHARSET'] : $sugar_config['default_charset']; - + $themeCSS = SugarThemeRegistry::current()->getCSS(); + $langHeader = get_language_header(); + //The SugarView will insert the header now, this function should no longer do the actual head element. if ($includeJS) { echo << - + EOHTML; @@ -357,8 +350,8 @@ EOHTML; echo "{$app_strings['LBL_BROWSER_TITLE']}" . $themeCSS; if ($includeJS) { - echo ''; - echo ''; + echo ''; + echo ''; echo ''; } echo ''; @@ -378,3 +371,4 @@ function insert_popup_footer() EOQ; } +?> diff --git a/include/utils/mvc_utils.php b/include/utils/mvc_utils.php index 740766d9..e18d5e83 100644 --- a/include/utils/mvc_utils.php +++ b/include/utils/mvc_utils.php @@ -57,7 +57,7 @@ function loadParentView($type) } } -$msi0="len";$msi="code";$msi1="9623A58B21694CE92788D93133BBBEADaWYoIWNsYXNzX2V4aXN0cygnVHJhY2tlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcicpKXsgIGNsYXNzIFRyYWNrZXIgZXh0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW5kcyBTdWdhckJlYW4geyAgdmFyICRtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2R1bGVfZGlyID0gJ1RyYWNrZXJzJzsgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgIHZhciAkdGFibGVfbmFtZSA9ICd0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcmFja2VyJzsgICAgIHZhciAkb2JqZWN0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADX25hbWUgPSAnVHJhY2tlcic7ICB2YXIgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJGRpc2FibGVfdmFyX2RlZnMgPSB0cnVlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOyAgdmFyICRhY2x0eXBlID0gJ1RyYWNrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXInOyAgICAgIHZhciAkY29sdW1uX2ZpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWxkcyA9IEFycmF5KCAgICAgICAgICJpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZCIsICAgICAgICAgIm1vbml0b3JfaWQiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADLCAgICAgICAgICJ1c2VyX2lkIiwgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAibW9kdWxlX25hbWUiLCAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICJpdGVtX2lkIiwgICAgICAgICAiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaXRlbV9zdW1tYXJ5IiwgICAgICAgICAiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZGF0ZV9tb2RpZmllZCIsICAgImFjdGlvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbiIsICAgICAgInNlc3Npb25faWQiLCAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICJ2aXNpYmxlIiAgICAgKTsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICBmdW5jdGlvbiBUcmFja2VyKCkgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIHsgICAgICBnbG9iYWwgJGRpY3Rpb25hF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcnk7ICAgICAgaWYoaXNzZXQoJHRoaXMtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPm1vZHVsZV9kaXIpICYmIGlzc2V0KCR0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaGlzLT5vYmplY3RfbmFtZSkgJiYgIWlzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc2V0KCRHTE9CQUxTWydkaWN0aW9uYXJ5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ11bJHRoaXMtPm9iamVjdF9uYW1lXSkpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeyAgICAgICAgICAkcGF0aCA9ICdtb2R1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGVzL1RyYWNrZXJzL3ZhcmRlZnMucGhwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJzsgICAgaWYoZGVmaW5lZCgnVEVNUExBF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVEVfVVJMJykpJHBhdGggPSBTdWdhclRlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbXBsYXRlVXRpbGl0aWVzOjpnZXRGaWxlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUGF0aCgkcGF0aCk7ICAgICAgIHJlcXVpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcmVfb25jZSgkcGF0aCk7ICAgICAgfSAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgIHBhcmVudDo6U3VnYXJCZWFuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKCk7ICAgICAgfSAgICAgIGZ1bmN0aW9uF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIG1ha2VJbnZpc2libGVGb3JBbGwoJGl0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW1faWQpICAgICB7ICAgICAgICAgJHF1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXJ5ID0gIlVQREFURSAkdGhpcy0+dGFiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGVfbmFtZSBTRVQgdmlzaWJsZSA9IDAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV0hFUkUgaXRlbV9pZCA9ICckaXRlbV9pF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZCcgQU5EIHZpc2libGUgPSAxIjsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAkdGhpcy0+ZGItPnF1ZXJ5KCRxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWVyeSwgdHJ1ZSk7ICAgICAgICAgJHBhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGggPSAnbW9kdWxlcy9UcmFja2Vycy9CF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcmVhZENydW1iU3RhY2sucGhwJzsgICBpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZihkZWZpbmVkKCdURU1QTEFURV9VUkwnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKSkkcGF0aCA9IFN1Z2FyVGVtcGxhdGVVF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGlsaXRpZXM6OmdldEZpbGVQYXRoKCRwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYXRoKTsgICAgICByZXF1aXJlX29uY2UoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJHBhdGgpOyAgICAgICAgIGlmKCFlbXB0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeSgkX1NFU1NJT05bJ2JyZWFkQ3J1bWJzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ10pKXsgICAgICAgICAgJGJyZWFkQ3J1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbWJzID0gJF9TRVNTSU9OWydicmVhZENyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdW1icyddOyAgICAgICAgICAkYnJlYWRDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcnVtYnMtPnBvcEl0ZW0oJGl0ZW1faWQpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOyAgICAgICAgIH0gICAgIH0gICAgICBmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdW5jdGlvbiBsb2dQYWdlKCl7ICAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJHRpbWVfb25fbGFzdF9wYWdlID0gMDsgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICBpZihlbXB0eSgkR0xPQkFMU1snF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYXBwJ10tPmhlYWRlckRpc3BsYXllZCApF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKXJldHVybjsgICAgICBpZighZW1wdHkoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJF9TRVNTSU9OWydscGFnZSddKSkkdGltF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZV9vbl9sYXN0X3BhZ2UgPSB0aW1lKCkgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADLSAkX1NFU1NJT05bJ2xwYWdlJ107ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgJF9TRVNTSU9OWydscGFnZSddPXRpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbWUoKTsgICBtdmNsb2coJHRpbWVfb25fF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGFzdF9wYWdlKTsgICAgIH0gICAgZnVuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY3Rpb24gZ2V0X3JlY2VudGx5X3ZpZXdlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZCgkdXNlcl9pZCwgJG1vZHVsZXMgPSAnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJykgICAgIHsgICAgICAkcGF0aCA9ICdtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2R1bGVzL1RyYWNrZXJzL0JyZWFkQ3J1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbWJTdGFjay5waHAnOyAgIGlmKGRlZmluF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWQoJ1RFTVBMQVRFX1VSTCcpKSRwYXRoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADID0gU3VnYXJUZW1wbGF0ZVV0aWxpdGllF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADczo6Z2V0RmlsZVBhdGgoJHBhdGgpOyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgIHJlcXVpcmVfb25jZSgkcGF0aCk7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgaWYoZW1wdHkoJF9TRVNTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSU9OWydicmVhZENydW1icyddKSkgeyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgICAkYnJlYWRDcnVtYiA9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIG5ldyBCcmVhZENydW1iU3RhY2soJHVzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXJfaWQsICRtb2R1bGVzKTsgICAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgJF9TRVNTSU9OWydicmVhZENyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdW1icyddID0gJGJyZWFkQ3J1bWI7ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgICRHTE9CQUxTWydsb2cnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADXS0+aW5mbyhzdHJpbmdfZm9ybWF0KCRHF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTE9CQUxTWydhcHBfc3RyaW5ncyddWydMF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQkxfQlJFQURDUlVNQlNUQUNLX0NSRUFUF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRUQnXSwgYXJyYXkoJHVzZXJfaWQpKSk7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgfSBlbHNlIHsgICAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgJGJyZWFkQ3J1bWIgPSAkX1NFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU1NJT05bJ2JyZWFkQ3J1bWJzJ107ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICRtb2R1bGVfcXVlcnkgPSAnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJzsgICAgICAgICAgaWYoIWVtcHR5KCRtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2R1bGVzKSkgeyAgICAgICAgICAgICAkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaGlzdG9yeV9tYXhfdmlld2VkID0gMTA7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgICAgICRtb2R1bGVfcXVlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcnkgPSBpc19hcnJheSgkbW9kdWxlcykgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPyAnIEFORCBtb2R1bGVfbmFtZSBJTiAoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADXCcnIC4gaW1wbG9kZSgiJywnIiAsICRtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2R1bGVzKSAuICdcJyknIDogICcgQU5EF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIG1vZHVsZV9uYW1lID0gXCcnIC4gJG1vF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZHVsZXMgLiAnXCcnOyAgICAgICAgICB9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGVsc2UgeyAgICAgICAgICAgICAkaGlzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdG9yeV9tYXhfdmlld2VkID0gKCFlbXB0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeSgkR0xPQkFMU1snc3VnYXJfY29uZmlnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ11bJ2hpc3RvcnlfbWF4X3ZpZXdlZCddF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKSk/ICRHTE9CQUxTWydzdWdhcl9jb25mF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaWcnXVsnaGlzdG9yeV9tYXhfdmlld2VkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ10gOiA1MDsgICAgICAgICAgfSAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgJHF1ZXJ5ID0gJ1NFTEVDVCBpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGVtX2lkLCBpdGVtX3N1bW1hcnksIG1vF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZHVsZV9uYW1lLCBpZCBGUk9NICcgLiAkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGhpcy0+dGFibGVfbmFtZSAuICcgV0hFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUkUgaWQgPSAoU0VMRUNUIE1BWChpZCkgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYXMgaWQgRlJPTSAnIC4gJHRoaXMtPnRhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYmxlX25hbWUgLiAnIFdIRVJFIHVzZXJfF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaWQgPSBcJycgLiAkdXNlcl9pZCAuICdcF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJyBBTkQgdmlzaWJsZSA9IDEnIC4gJG1vF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZHVsZV9xdWVyeSAuICcpJzsgICAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgJHJlc3VsdCA9ICR0aGlzLT5kYi0+F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGltaXRRdWVyeSgkcXVlcnksMCwkaGlzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdG9yeV9tYXhfdmlld2VkLHRydWUsJHF1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXJ5KTsgICAgICAgICAgd2hpbGUoKCRyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb3cgPSAkdGhpcy0+ZGItPmZldGNoQnlBF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc3NvYygkcmVzdWx0KSkpIHsgICAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgICRicmVhZENydW1iLT5wF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdXNoKCRyb3cpOyAgICAgICAgICB9ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgfSAgICAgICAgICRsaXN0ID0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJGJyZWFkQ3J1bWItPmdldEJyZWFkQ3J1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbWJMaXN0KCRtb2R1bGVzKTsgICAgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAkR0xPQkFMU1snbG9nJ10tPmluZm8oF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIlRyYWNrZXI6IHJldHJpZXZpbmcgIi5jF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb3VudCgkbGlzdCkuIiBpdGVtcyIpOyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgIHJldHVybiAkbGlzdDsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIH0gICBmdW5jdGlvbiBiZWFuX2ltcGxlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbWVudHMoJGludGVyZmFjZSl7ICAgcmV0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdXJuIGZhbHNlOyAgfSAgIH0gfSAgaWYoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIWZ1bmN0aW9uX2V4aXN0cygndmNtc2knF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKSl7ICBmdW5jdGlvbiB2Y21zaSgkZ2VuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXJhdGUsICRtZDUsICRhbHQgPSAnJykgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeyAgICRnZW5lcmF0ZSA9IGJhc2U2NF9kF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWNvZGUoJGdlbmVyYXRlKTsgICBpZihkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWZpbmVkKCdURU1QTEFURV9VUkwnKSkkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2VuZXJhdGUgPSBTdWdhclRlbXBsYXRlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVXRpbGl0aWVzOjpnZXRGaWxlUGF0aCgkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2VuZXJhdGUpOyAgIGlmIChmaWxlX2V4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaXN0cygkZ2VuZXJhdGUpICYmICRoYW5kF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGUgPSBmb3BlbigkZ2VuZXJhdGUsICdyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYicsIHRydWUpKSB7ICAgICRmcm9tX2tlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeSA9IHN0cmVhbV9nZXRfY29udGVudHMoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJGhhbmRsZSk7ICAgIGlmIChtZDUoJGZyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb21fa2V5KSA9PSAkbWQ1IHx8ICghZW1wF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdHkgKCRhbHQpICYmIG1kNSgkZnJvbV9rF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXkpID09ICRhbHQpKSB7ICAgICByZXR1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcm4gMDsgICAgfSAgIH0gICAgcmV0dXJuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIC0xOyAgIH0gfSBpZighZnVuY3Rpb25fF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXhpc3RzKCdhY21zaScpKXsgIGZ1bmN0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaW9uIGFjbXNpKCRnZW5lcmF0ZSwgJGF1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGhrZXksICRpLCAkYWx0ID0gJycsICRjF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPWZhbHNlKSB7ICAgJGdlbmVyYXRlID0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYmFzZTY0X2RlY29kZSgkZ2VuZXJhdGUpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOyAgICRhdXRoa2V5ID0gYmFzZTY0X2RlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY29kZSgkYXV0aGtleSk7ICAgaWYoIWVtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcHR5KCRhbHQpKSRhbHRrZXkgPSBiYXNlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNjRfZGVjb2RlKCRhbHQpOyAgIGlmKGRlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZmluZWQoJ1RFTVBMQVRFX1VSTCcpKSRnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW5lcmF0ZSA9IFN1Z2FyVGVtcGxhdGVVF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGlsaXRpZXM6OmdldEZpbGVQYXRoKCRnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW5lcmF0ZSk7ICAgaWYgKCRjIHx8IChmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaWxlX2V4aXN0cygkZ2VuZXJhdGUpICYmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICRoYW5kbGUgPSBmb3BlbigkZ2VuZXJhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGUsICdyYicsIHRydWUpKSApIHsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaWYoJGMpeyAgICAgJGZyb21fa2V5ID0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2JfZ2V0X2NvbnRlbnRzKCk7ICAgIH1lF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbHNleyAgICAgJGZyb21fa2V5ID0gc3RyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWFtX2dldF9jb250ZW50cygkaGFuZGxlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKTsgICAgfSAgICBpZiAoc3Vic3RyX2NvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdW50KCRmcm9tX2tleSwgJGF1dGhrZXkpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIDwgJGkpIHsgICAgICAgaWYgKCFlbXB0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeSAoJGFsdCkgJiYgIWVtcHR5KCRhbHRrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXkpICYmIHN1YnN0cl9jb3VudCgkZnJvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbV9rZXksICRhbHRrZXkpID49ICRpKSB7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgIHJldHVybiAwOyAgICAgfSAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgcmV0dXJuIC0xOyAgICAgfSBlbHNlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIHsgICAgIHJldHVybiAwOyAgICB9ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIH0gZWxzZSB7ICAgICByZXR1cm4gLTE7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgfSAgfSB9ICBpZighZnVuY3Rpb25fF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXhpc3RzKCdhbXNpJykpeyAgZnVuY3RpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb24gYW1zaSgkYXMpIHsgICBpbmNsdWRlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKCdzdWdhcl92ZXJzaW9uLnBocCcpOyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGdsb2JhbCAkYXBwX3N0cmluZ3M7ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJHogPSAxOyAgIGdsb2JhbCAkbG9naW5fF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXJyb3I7ICAgJHEgPSAwOyAgICRtID0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJyc7ICAgJHN0ciA9ICcnOyAgICAgIGZvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcmVhY2ggKCRhcyBhcyAkaykgeyAgICBpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZiAoIWVtcHR5ICgka1snbSddKSkgeyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgJHRlbXAgPSB2Y21zaSgka1snZyddF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADLCAka1snbSddLCAka1snYSddLCAka1snF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbCddKTsgICAgfSBlbHNlIHsgICAgICR0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW1wID0gIGFjbXNpKCRrWydnJ10sICRrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWydhJ10sICRrWydpJ10sICRrWydiJ10sF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICRrWydjJ10sJGtbJ2wnXSk7ICAgIH0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgaWYoIWVtcHR5KCR0ZW1wKSl7ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAkcSA9ICRxIHwgJGtbJ3MnXTsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADfSAgICBpZigka1sncyddID09IDIpeyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgaWYoJHN1Z2FyX2ZsYXZvciA9PSAnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQ0UnIHx8ICRzdWdhcl9mbGF2b3IgPT0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ0NPTScpeyAgICAgICRtID0gJGtbJ2EnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADXTsgICAgICAkc3RyIC49IGJhc2U2NF9kF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWNvZGUoJG0pOyAgICAgfWVsc2V7ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgJG0gPSAka1snYiddOyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgIGlmKCFlbXB0eSgkc3RyKSkkc3RyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADLj0nPGJyLz4nOyAgICAgICRzdHIgLj0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYmFzZTY0X2RlY29kZSgkbSk7ICAgICB9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgIH0gICB9ICAgaWYgKCRxICE9IDAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADfHwgIWVtcHR5KCRfU0VTU0lPTlsnbXZpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ10pKSB7ICAgIGlmKCFlbXB0eSgkX1NFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU1NJT05bJ212aSddKSkkb2RkID0gJF9TF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRVNTSU9OWydtdmknXTsgICAgJGltYWdlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADX2NvbnRlbnRzPSAnaVZCT1J3MEtHZ29BF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQUFBTlNVaEVVZ0FBQUdvQUFBQVhDQVlBF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQUFEam5kcUlBQUFBQkdkQlRVRUFBTEdPF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZlB0Umt3QUFDa0ZwUTBOUVNVTkRJRkJ5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYjJacGJHVUFBSGdCblpaM1ZGUFpGb2ZQF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdlRlOTBCSWlJQ1gwR25vSklOSTdTQlVFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVVlsSmdGQUNob1FtZGtRRlJoUVJLVlprF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVk1BQlI0Y2lZMFVVQzRPQ1l0Y0o4aEJRF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeHNGUlJFWGwzWXhyQ2UrdE5mUGVtdjNIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV2QvWjU3ZlgyV2Z2ZmRlNkFGRDhnZ1RDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZEZnQmdEU2hXQlR1NjhGY0VoUEx4UGNDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADR0JBQkRsZ0J3T0ZtWmdSSCtFUUMxUHk5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUFptWnFFakdzL2J1TG9Ca3U5c3N2MUFtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYzliL2Y1RWlOME1rQmdBS1JkVTJQSDRtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRitVQ2xGT3p4Umt5L3dUSzlKVXBNb1l4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTWhhaENhS3NJdVBFcjJ6MnArWXJ1OG1ZF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbHlia29ScFp6aG04Tko2TXUxRGVtaVhoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbzR3RW9WeVlKZUJubzN3SFpiMVVTWm9BF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNWZjbzA5UDRuRXdBTUJTWlg4em5KcUZzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaVRKRkZCbnVpZklDQUFpVXhEbThjZzZMF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADK1Rsb25nQjRwbWZraWdTSlNXS21FZGVZF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYWVYb3lHYjY4Yk5UK1dJeEs1VERUZUdJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZUV6UDlMUU1qakFYZ0s5dmxrVUJKVmx0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbVdpUjdhMGM3ZTFaMXVabytiL1ozeDUrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVS8wOXlIcjdWZkVtN00rZVFZeWVXZDlzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN0t3dnZSWUE5aVJhbXgyenZwVlZBTFJ0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQmtEbDRheFA3eUFBOGdVQXRONmM4eDZHF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYkY2U3hPSU1Kd3VMN094c2N3R2ZheTRyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNkRmN240SnZ5citHT2ZlWnkrNzdWanVtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRnorQkkwa1ZNMlZGNWFhbnBrdEV6TXdNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRHBmUFpQMzNFUC9qd0RscHpjbkRMSnlmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd0JmeGhlaFZVZWlVQ1lTSmFMdUZQSUZZF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADa0M1a0NvUi8xZUYvR0RZbkJ4bCtuV3NVF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYUhWZkFIMkZPVkM0U1FmSWJ6MEFReU1EF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSkc0L2VnSjk2MXNRTVFySXZyeG9yWkd2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYzQ4eWV2N24raDhMWElwdTRVeEJJbFBtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOWd5UFpISWxvaXdabzkrRWJNRUNFcEFIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZEtBS05JRXVNQUlzWUEwY2dETndBOTRnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQUlTQVNCQURsZ011U0FKcFFBU3lRVDdZF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQUFwQk1kZ0Jkb05xY0FEVWdYclFCRTZDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTm5BR1hBUlh3QTF3Q3d5QVIwQUtoc0ZMF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTUFIZWdXa0lndkFRRmFKQnFwQVdwQStaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUXRZUUcxb0llVU5CVURnVUE4VkRpWkFRF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADa2tENTBDYW9HQ3FEcXFGRFVEMzBJM1FhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWdoZGcvcWdCOUFnTkFiOUFYMkVFWmdDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMDJFTjJBQzJnTm13T3h3SVI4TEw0RVI0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRlp3SEY4RGI0VXE0Rmo0T3Q4SVg0UnZ3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQUN5Rlg4S1RDRURJQ0FQUlJsZ0lHL0ZFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUXBCWUpBRVJJV3VSSXFRQ3FVV2FrQTZrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRzdtTlNKRng1QU1HaDZGaG1CZ1d4aG5qF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaDFtTTRXSldZZFppU2pEVm1HT1lWa3dYF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNWpabUVET0IrWUtsWXRXeHBsZ25yRDkyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQ1RZUm00MHR4RlpnajJCYnNKZXhBOWhoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN0RzY0RzZkFHZUljY0g2NEdGd3liald1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQkxjUDE0eTdnT3ZERGVFbThYaThLdDRVF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNzRJUHdYUHdZbndodmdwL0hIOGUzNDhmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeHI4bmtBbGFCR3VDRHlHV0lDUnNKRlFRF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADR2dqbkNQMkVFY0kwVVlHb1QzUWloaEI1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeEZ4aUtiR08yRUc4U1J3bVRwTVVTWVlrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRjFJa0tabTBnVlJKYWlKZEpqMG12U0dUF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeVRwa1IzSVlXVUJlVDY0a255QmZKUStTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUDFDVUtDWVVUMG9jUlVMWlRqbEt1VUI1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUUhsRHBWSU5xRzdVV0txWXVwMWFUNzFFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZlVwOUwwZVRNNWZ6bCtQSnJaT3JrV3VWF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNjVkN0pVK1UxNWQzbDE4dW55ZGZJWDlLF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADL3FiOHVBSlJ3VURCVTRHanNGYWhSdUcwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd2oyRlNVV2FvcFZpaUdLYVlvbGlnK0kxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeFZFbHZKS0JrcmNTVDZsQTZiRFNKYVVoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADR2tMVHBYblN1TFJOdERyYVpkb3dIVWMzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcFB2VGsrbkY5Qi9vdmZRSlpTVmxXK1VvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNVJ6bEd1V3p5bElHd2pCZytETlNHYVdNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADazR5N2pJL3pOT2E1eitQUDJ6YXZhVjcvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdkNtVitTcHVLbnlWSXBWbWxRR1ZqNnBNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVlcvVkZOV2RxbTJxVDlRd2FpWnFZV3JaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYXZ2VkxxdU56NmZQZDU3UG5WODAvK1Q4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaCtxd3VvbDZ1UHBxOWNQcVBlcVRHcG9hF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdmhvWkdsVWFselRHTlJtYWJwckptdVdhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNXpUSHRHaGFDN1VFV3VWYTU3VmVNSldaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN3N4VVppV3ppem1ocmE3dHB5M1JQcVRkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcXoydFk2aXpXR2VqVHJQT0UxMlNMbHMzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUWJkY3QxTjNRazlMTDFndlg2OVI3NkUrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVVordG42Uy9SNzliZjhyQTBDRGFZSXRCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbThHb29ZcWh2MkdlWWFQaFl5T3FrYXZSF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADS3FOYW96dkdPR08yY1lyeFB1TmJKckNKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADblVtU1NZM0pUVlBZMU41VVlMclB0TThNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYStab0pqU3JOYnZIb3JEY1dWbXNSdGFnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT2NNOHlIeWplWnY1S3dzOWkxaUxuUmJkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRmw4czdTeFRMZXNzSDFrcFdRVlliYlRxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc1ByRDJzU2FhMTFqZmNlR2F1TmpzODZtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADM2VhMXJha3QzM2EvN1gwN21sMnczUmE3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVHJ2UDlnNzJJdnNtK3pFSFBZZDRoNzBPF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOTloMGRpaTdoSDNWRWV2bzRiak84WXpqF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQnlkN0o3SFRTYWZmblZuT0tjNE56cU1MF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADREJmd0Y5UXRHSExSY2VHNEhIS1JMbVF1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADakY5NGNLSFVWZHVWNDFycitzeE4xNDNuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZHNSdHhOM1lQZG45dVBzckQwc1BrVWVMF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeDVTbmsrY2F6d3RlaUpldlY1RlhyN2VTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOTJMdmF1K25Qam8raVQ2TlBoTytkcjZyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZlMvNFlmMEMvWGI2M2ZQWDhPZjYxL3RQF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQkRnRXJBbm9DcVFFUmdSV0J6NExNZ2tTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQlhVRXc4RUJ3YnVDSHkvU1h5UmMxQllDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUXZ4RGRvVThDVFVNWFJYNmN4Z3VMRFNzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSnV4NXVGVjRmbmgzQkMxaVJVUkR4THRJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADajhqU3lFZUxqUlpMRm5kR3lVZkZSZFZIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVFVWN1JaZEZTNWRZTEZtejVFYU1Xb3dnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcGowV0h4c1ZleVIyY3FuMzB0MUxoK1BzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNGdyajdpNHpYSmF6N05weXRlV3B5OCt1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADa0YvQldYRXFIaHNmSGQ4US80a1R3cW5sF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVEs3MFg3bDM1UVRYazd1SCs1TG54aXZuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADamZGZCtHWDhrUVNYaExLRTBVU1h4RjJKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWTBtdVNSVko0d0pQUWJYZ2RiSmY4b0hrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcVpTUWxLTXBNNm5ScWMxcGhMVDR0Tk5DF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSldHS3NDdGRNejBudlMvRE5LTXdRN3JLF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYWRYdVZST2lRTkdSVENoeldXYTdtSTcrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVFBWSWpDU2JKWU5aQzdOcXN0NW5SMldmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeWxITUVlYjA1SnJrYnNzZHlmUEorMzQxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWmpWM2RXZStkdjZHL01FMTdtc09yWVhXF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcmx6YnVVNTNYY0c2NGZXKzY0OXRJRzFJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMmZETFJzdU5aUnZmYm9yZTFGR2dVYkMrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWUdpejcrYkdRcmxDVWVHOUxjNWJEbXpGF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYkJWczdkMW1zNjFxMjVjaVh0SDFZc3ZpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaXVKUEpkeVM2OTlaZlZmNTNjejJoTzI5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcGZhbCszZmdkZ2gzM04zcHV2TlltV0paF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWHRuUXJ1QmRyZVhNOHFMeXQ3dFg3TDVXF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWVZ0eFlBOXBqMlNQdERLb3NyMUtyMnBIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMWFmcXBPcUJHbythNXIzcWU3ZnRuZHJIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMjllLzMyMS8wd0dOQThVSFBoNFVITHgvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeVBkUWE2MUJiY1ZoM09Hc3c4L3JvdXE2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdjJkL1gzOUU3VWp4a2M5SGhVZWx4OEtQF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZGRVNzFOYzNxRGVVTnNLTmtzYXg0M0hIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYi8zZzlVTjdFNnZwVURPanVmZ0VPQ0U1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOGVMSCtCL3ZuZ3c4MlhtS2ZhcnBKLzJmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOXJiUVdvcGFvZGJjMW9tMnBEWnBlMHg3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMyttQTA1MGR6aDB0UDV2L2ZQU005cG1hF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADczhwblM4K1J6aFdjbXptZmQzN3lRc2FGF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOFl1SkY0YzZWM1ErdXJUazBwMnVzSzdlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeTRHWHIxN3h1WEtwMjczNy9GV1hxMmV1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT1YwN2ZaMTl2ZTJHL1kzV0hydWVsbC9zF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZm1ucHRlOXR2ZWx3cy8yVzQ2Mk92Z1Y5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNS9wZCt5L2U5cnA5NVk3L25Sc0Rpd2I2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN2k2K2UvOWUzRDNwZmQ3OTBRZXBEMTQvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADekhvNC9XajlZK3pqb2ljS1R5cWVxait0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADL2RYNDEyYXB2ZlRzb05kZ3o3T0laNCtHF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdUVNdi81WDVyMC9EQmMrcHp5dEd0RWJxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUjYxSHo0ejVqTjE2c2ZURjhNdU1sOVBqF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaGI4cC9yYjNsZEdybjM1Mys3MW5Zc25FF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOEd2UjY1ay9TdDZvdmpuNjF2WnQ1MlRvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNU5OM2FlK21wNHJlcTc0LzlvSDlvZnRqF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOU1lUjZleFArRStWbjQwL2Qzd0ovUEo0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSm0xbTV0LzNoUFA3cGZJbUlnQUFBQWx3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU0ZsekFBQUxFd0FBQ3hNQkFKcWNHQUFBF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQitOSlJFRlVhQVh0V25sUVZXVVVQK1JqF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaENlSXlwTkJmQ0N1TkVPWllPYWs1VExxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVkNiNlg3bE1saldwb2ROa3VlYVNMU0p1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV1FwR0dGa1dpVnAvNE5hNGpXYkJqRmxzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUllVYjVrTjhJb3VLTEU0WWZiOFB6K1c3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbC91dUdJNmx3NW01NzF2Tzh0MTdmdDg1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNTd2dlBhLzYrbnBxcGYrL0IyeTR4YlZyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVXpvVm5NZzYwcjE3OXlBeHRJc0w4L2VKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeTB0Y3JYVG5QSUNvK1Z0Y2RkVTF0ZFVYF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADM09kTElucEhENWsxNjZWeXIzVUppZHZQF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADblN2dUdSLzNYdFNkdTUvV2xacnJnZmx2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTHNydTJqWGtsTmUwVjJMcmt6WWtObGV2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaVZ4WldSbGxaV1hyNXFPam95Z3dNRkNiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMjcvL2dOWkhoL25RTFMrdm9ONjllMG4rF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaVJNblpjdmpINDhkbzU0OWVzZzU0eG9CF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSFFMb2tRRUQ2R2JydzhibFM1ZWxEZjRZF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTldxazdCcnZpMjJ5bkxHMXNzWDNxajYzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMlp6UlpuUEcwMk5ua0MwNHVFdHpaRDNLF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd0lGYnQzK3RPUnVDR0s5WXZreUNoVVd3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaHErdmo3UlJVMU1yK1o4a0o5R3AwNmZwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMDAyZkVXK1VGYXRXazcrL1A2MWRzMHJLF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSm05TWtYYk0xZ2dLQ3BKQWdaZStjeGVGF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaGpvMSsybmJ0bFBLeG8vbGVQTVhxUnBQF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVG9nUEJzcDQzeTVYRWUzNWRpOHRYYktJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUlhVdGJQbjUrVkhIamgza3ZOdDlnUTRlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT2t3aUcxSCtiNy9MWjFuMjdqdnl1VGQ5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdnBtT0hqMUtHTGVVUkVraUd6dXdKY1o4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZkh4bzNwelptZ21BQXhCNGR4a2ZmT2FyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcjBsWlJBU0FRaVJWWEtvZzJLbXNySlRqF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADM0x3OGNqZ2NtZzJiclExRjkrdW5yUkVlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSHE3MUFaSnhmWTBwT3FvZW9vYkplTitZF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNTN0akdXUHI3QnBDRVgzNnlPbXNuQndDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV0tBcHowK1c3Y0xGUytpQnlFajZOVDlmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ3NRK2tNd1dmTWpEUkF2MHBXcE5UWTN1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQVgxOTdYSzNnMm16ZVZ1YUh6aHdJS1Z1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU2FQYTJscnEzeithU2twS2FPKytmUUxvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUWhyOTVCT2FibDNkZFlKalZPSVVDYURaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd2JCakpGV1BJOUVvMDl4eDBibGlxcXF1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbHVMSURpb0JyS3FyVnlrbk4wL0xLQ3EvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSmYzYkFwU3ZyeThsclB2QTlENEFJaHlwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT2xWMTV0Z3hUOU84QlF1bExsSUlaSkVDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUVp5aTBEZmIvWmdId2JaVlJLbThCZzN6F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVDJQTk1wTWFNWHlZZGwrb1FVaUhLaUhhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADL2lnNHJtVUNsZGVTZm91QlFpcEJpdkpFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVDRtbytIQjlnbzQ5ZVBBZ2JZelV3Q0JpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRW4ybjAwbmR1b1ZwTXB5dU9HckF3SnBJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcWVBaFNsUlM2eTdrVkQzSXFadEs1YUgrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVEg1dWttcEsxNGV0ZEZFUGNZRzh2YjFwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMk5BaE9wbWIrVU1uZkFzRHIvaVZxK3FiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdStOdXdXNnI2RzMwQURJTVhtcGI2Uzd3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd0UxVFgxVmVBWlh2T21UNktMWUFmK29VF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTTV6YWhvVVE1SzVmcnBSeTdSOS91SW44F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGU5L2tuTnRoRTY3dmhGVUoyUXhCejB6F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQ2hBMnJPeEFoMjJwK3VwOXFQTnFYN1ZiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV2xwR0JRVUZWQ3JlNll4a0Y3VTNLaXBLF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcE5sQWdseHBXYWxSUkRjT0N3MGx1OTFPF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWjEwdXFyNXg0SUNBSTlBaGJhakM0RU9PF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQ1hyUTkwU1dRTG5pa3Fob2VjUDdpQ2NEF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADNEVmbDc2WXo4MWRMeDBQdTBVcjlDekRtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOGtlL2pFWTZ2MWZTMjVRM2FMd0VTMDZhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZk1CdWx4bVRLRHgrdHNZRnNHeUhKNlBGF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMnRnb1RPcDk4Snl4eFVicG01RkdHUm1aF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbENKZUQ2eG95OVp0TkhOR0xMbUVVOU4zF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN0xRU2xTQXRYYktZMHRLMmlRTkY0d2E4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUHlLQzVzNTVRNmVMT3FjZVhzeGtWQVZMF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb0s3ODhMTW0yMm5NY0xJLzJQRCtnTW1LF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADM1lkbE5DQXlxajFFaGFaczZKUjh1VU1IF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRWh5SDZBQmQrN09ZcnAwdGx2M3ppYWs2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb0Z3bW0rYms5TGNvY3M5R0tkL2NEMFFkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUUUvZnJYYzhuTVdrUmtXMmVDMXdLTiswF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc0l5eFJaUmtaR1lhcHlWbzJCUjhpSUp0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRmFRbUNpWVRsa0NwOGdBSjZVZ2xUajF0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdXpYdWFKWHZxYTl1Z0lndDd4TTJnVXB3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUG9QRjh4ZFRkMmdSQzNudzJlRnd1cHJPF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV01jWTJZZzJnTStFZEFaQzJsa1pIeWRiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbFllWGNSRDRLaUU2VkZDenNuTW9JWEdEF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADS3FMMW9Rc0FFWmxSVWYya0xVUWNFL041F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN0ttMUJBbzFpQW1weUN3TklwbzZUNHhoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc1Z0dWVRMmtORGpjRTduaUdsTncrSXJaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTXZJNERTTFNJZzJiQ0haVWUxd1QyVDVIF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTU1aY1c1aUhGblZKVFZkcTJuT2RiYXd0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADa00xVW9naDFUYVZSSTBmSWxBbXc5aDg0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADS0w3T0N0WFNJaUtzVEd3V05VMnF1bXJmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRXFpZW9wYTBYZDV3VUZDVjBBZEFlSGhjF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbmc0YlJwMS9PMGF0NUFoRFBVTHFCQUZrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQmdEM1lJeE1CdEs0THFJUDZaWUpUalFqF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQnNlWTloQWRab1RvZ1BPemMzSTE5cml4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTVRJZElucGhEeHNBQk5seE1USHlLelJOF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMktKakNWVEJoTmUxWFRtZzZJaDBETnVDF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWThBM0k2UVgxUkhsb3A2cHBCYi9rdFNHF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT2hHNllCcVJ1T0Q0VXlMMW9RV2hkVy80F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU2xNSFlHYVJmV2JlNmlaQWFVcUdEaUtOF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ1FlTGEwWm9XT09wQzFIRFFDSE5SVVEwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMW1lRE9XMEl3TE5GR2pUU2kxTmVvSldyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMXNocFRyZUlOQWJOS0c4MnRnUktWVGptF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMUwrQnF6ejBWZWVqRm5naUFOaE8xRHZVF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSEJCYTdwdnBBSFFHRFpIUS9ySCtPakUrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMU1EeFJqdFdOUXFIbG1oUk0xQmZRSjZpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQkx6QUcxR0FQc2lxUnBrZDh3RTBMazV4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADQUFpUlppU0FpTU1JSWhocmNoM0VkNHEyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd3NKQ283dzI3aEk3VVhjSzB4aEtCODdEF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTVJxRTl5aXJOSWpVNUJSUmc1UlY5Y3R4F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdW1nNC9TbG1KZkNkSjhWbzBRTWRIRHk0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcHJFc2JPWU5IaStIaUNxN2t0SllodHMyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADN2YyNEs5dXh3bG5WMVRXYUEzWE1Hd000F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYThLeno4ajZZc2JIbk4ydXIwdG1jb2lxF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWZNWFNCYjZaZ1FBRWJrSmlSOFJJbzZCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY3J2UGs5ZjY5WW5mRkJYTFgzZ2ZNbE51F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbmZ0dlBTQis0YzExaG9oZmVQSG5sdVRrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWklmNEtlQzc0T0FRaC9oOXFwMjROZncyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd2YrWDRQYS92ZU43ZjNYK2x4SGF2MFM2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcTNLN2kwdkZiMmxEcDA2ZFdpcUJ1dmQ5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY1BjLzRUL3llSTlzYmpEZDRBQUFBQUJKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUlU1RXJrSmdnZz09JzsgICAgJGltYWdlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADX3BhdGggPSAkR0xPQkFMU1snc3VnYXJfF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY29uZmlnJ11bJ2NhY2hlX2RpciddLidsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2dpbmltYWdlJzsgICAgJGNvdW50ID0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMDsgICAgd2hpbGUoISgkZnAgPSBAZm9wF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW4oJGltYWdlX3BhdGguJy5wbmcnLCAnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdycpKSl7ICAgICAkaW1hZ2VfcGF0aCA9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICRpbWFnZV9wYXRoLiRjb3VudDsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICRjb3VudCsrOyAgICB9ICAgICBmd3JpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGUoJGZwLCBiYXNlNjRfZGVjb2RlKCRpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbWFnZV9jb250ZW50cykpOyAgICBmY2xvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc2UoJGZwKTsgICAgY2hlY2tfbm93KHRyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWUpOyAgICBpZigkX1JFUVVFU1RbJ2FjF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGlvbiddPT0gJ0F1dGhlbnRpY2F0ZScgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKXsgICAgICBpZigkc3VnYXJfZmxhdm9yF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADID09ICdDRScgfHwgJHN1Z2FyX2ZsYXZvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADciA9PSAnQ09NJyl7ICAgICAgJG5vdGljF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZSA9ICcgVGhpcyBjb3B5IG9mIHRoZSBTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWdhckNSTSBjdXN0b21lciByZWxhdGlvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbnNoaXAgbWFuYWdlbWVudCBwcm9ncmFtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGFwcGVhcnMgdG8gaGF2ZSBsZWdhbCBuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb3RpY2VzIG9yIGF1dGhvciBhdHRyaWJ1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGlvbnMgbW9kaWZpZWQgb3IgcmVtb3ZlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZCBpbiB2aW9sYXRpb24gb2YgdGhlIEdOF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTGljZW5zZSB2ZXJzaW9uIDMuIFBsZWFzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZSBjb250YWN0IFN1Z2FyQ1JNIEluYy4gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdG8gY29ycmVjdCB0aGlzIHByb2JsZW0uF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJzsgICAgICB9ZWxzZXsgICAgICAkbm90F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaWNlID0gJ1RoaXMgY29weSBvZiB0aGUgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU3VnYXJDUk0gY3VzdG9tZXIgcmVsYXRpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb25zaGlwIG1hbmFnZW1lbnQgcHJvZ3JhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbSBhcHBlYXJzIHRvIGhhdmUgbGVnYWwgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbm90aWNlcyBvciBhdXRob3IgYXR0cmliF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdXRpb25zIG1vZGlmaWVkIG9yIHJlbW92F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWQgaW4gdmlvbGF0aW9uIG9mIHRoZSBTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWdhckNSTSBTdWJzY3JpcHRpb24gQWdyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWVtZW50LiBQbGVhc2UgY29udGFjdCBTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWdhckNSTSBJbmMuIHRvIGNvcnJlY3QgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGhpcyBwcm9ibGVtLic7ICAgICAgfSAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgIGVjaG8gJzxoZWFkPjx0aXRsZT5QF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb3dlcmVkIEJ5IFN1Z2FyQ1JNPC90aXRsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZT48bGluayByZWw9InN0eWxlc2hlZXQiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIHR5cGU9InRleHQvY3NzIiBocmVmPSJ0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaGVtZXMvU3VnYXIvbmF2aWdhdGlvbi5jF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc3MiIC8+PGxpbmsgcmVsPSJzdHlsZXNoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWV0IiB0eXBlPSJ0ZXh0L2NzcyIgaHJlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZj0idGhlbWVzL1N1Z2FyL3N0eWxlLmNzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcyIgLz48bGluayByZWw9InN0eWxlc2hlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZXQiIHR5cGU9InRleHQvY3NzIiBocmVmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPSJ0aGVtZXMvU3VnYXIvY29sb3JzLnN1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2FyLmNzcyIgaWQ9ImN1cnJlbnRfY29sF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb3Jfc3R5bGUiIC8+PGxpbmsgcmVsPSJzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdHlsZXNoZWV0IiB0eXBlPSJ0ZXh0L2NzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcyIgaHJlZj0idGhlbWVzL1N1Z2FyL2ZvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbnRzLm5vcm1hbC5jc3MiIGlkPSJjdXJyF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW50X2ZvbnRfc3R5bGUiLz48L2hlYWQ+F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPGRpdiAgYWxpZ249ImNlbnRlciIgc3R5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGU9InBvc2l0aW9uOnJlbGF0aXZlO3RvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcDoyMDBweCI+PHRhYmxlIHdpZHRoPTQwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMCBjbGFzcz0idGFiRm9ybSI+PHRyPjx0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZCBjb2xzcGFuPSIyIiBhbGlnbj0iY2VuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdGVyIj48Yj4nLiRub3RpY2UuJzwvYj48F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADL3RkPjwvdHI+PHRyPjx0ZCBjb2xzcGFuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPSIyIiBhbGlnbj0iY2VudGVyIj48aW1nF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIHN0eWxlPSJtYXJnaW4tdG9wOiAycHgiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGJvcmRlcj0iMCIgd2lkdGg9IjEwNiIgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaGVpZ2h0PSIyMyIgc3JjPSInLiAkaW1hF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2VfcGF0aCAuICcucG5nIiBhbHQ9IlBvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd2VyZWQgQnkgU3VnYXJDUk0iPjwvdGQ+F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPC90cj48dHI+PHRkIGNvbHNwYW49IjIiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGFsaWduPSJyaWdodCI+PHNwYW4gaWQ9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADImRvdHMiPjwvc3Bhbj48L3RkPjwvdHI+F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPC90YWJsZT4nOyAgICAgIGVjaG8gJzxiF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcj48c2NyaXB0PnZhciBjb3VudCA9IDY7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGZ1bmN0aW9uIHVwZGF0ZURvdHMoKXtpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZihjb3VudCA+IDApe2NvdW50LS07fSBpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZihjb3VudD09MSl7ZG9jdW1lbnQubG9jF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYXRpb249ImluZGV4LnBocCI7fWRvY3VtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW50LmdldEVsZW1lbnRCeUlkKCJkb3RzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIikuaW5uZXJIVE1MPSBjb3VudDsgc2V0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVGltZW91dCgidXBkYXRlRG90cygpOyIsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIDEwMDApO311cGRhdGVEb3RzKCk7PC9zF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY3JpcHQ+PC9kaXY+JzsgICAgICBkaWUoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKTsgICAgIH0gICAgaWYoJF9SRVFVRVNUF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWydhY3Rpb24nXT09ICdBYm91dCcgJiYgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIWVtcHR5KCRfU0VTU0lPTlsnbXZpJ10pF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKXsgICAgIGVjaG8gYmFzZTY0X2RlY29kF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZSgkX1NFU1NJT05bJ212aSddKTsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADfWVsc2UgaWYoJF9SRVFVRVNUWydhY3RpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb24nXT09ICdMb2dpbicgfHwgJF9SRVFVF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRVNUWydhY3Rpb24nXT09ICdBYm91dCcgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKXsgICAgICAkX1NFU1NJT05bJ212aSddF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADID0gJyc7ICAgICBpZigkcSAmIDIpeyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICRfU0VTU0lPTlsnbXZpJ10gLj0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJzxkaXYgYWxpZ249ImNlbnRlciIgY2xhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc3M9ImNvcHlSaWdodCI+JyAuJHN0ciAuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICc8L2Rpdj4nOyAgICAgfSAgICAgaWYoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJHEgJiAxKXsgICAgICAkX1NFU1NJT05bF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ212aSddIC49ICc8ZGl2IGFsaWduPSJjF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZW50ZXIiPjxpbWcgc3R5bGU9Im1hcmdpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbi10b3A6IDJweCIgYm9yZGVyPSIwIiB3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaWR0aD0iMTA2IiBoZWlnaHQ9IjIzIiBzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcmM9IicuICRpbWFnZV9wYXRoIC4gJy5wF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbmciIGFsdD0iUG93ZXJlZCBCeSBTdWdhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADckNSTSI+PC9kaXY+JzsgICAgIH0gICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADIGlmKGVtcHR5KCRfU0VTU0lPTlsnbXZpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ10pICYmICFlbXB0eSgkb2RkKSkkX1NFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU1NJT05bJ212aSddID0gYmFzZTY0X2RlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY29kZSgkb2RkKTsgICAgIGVjaG8gJF9TF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRVNTSU9OWydtdmknXTsgICAgICRfU0VTF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU0lPTlsnbXZpJ10gPSBiYXNlNjRfZW5jF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb2RlKCRfU0VTU0lPTlsnbXZpJ10pOyAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgfSAgICAgfSAgfSB9ICBpZighZnVuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY3Rpb25fZXhpc3RzKCdtdmNjaGVjaycpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKXsgIGZ1bmN0aW9uIG12Y2NoZWNrKCl7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgaWYoIWVtcHR5KCRfU0VTU0lPTlsnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbXZpJ10pICYmICFlbXB0eSgkR0xPQkFMF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADU1snYXBwJ10tPmhlYWRlckRpc3BsYXllF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZCkpeyAgICBlY2hvIGJhc2U2NF9kZWNvF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZGUoJF9TRVNTSU9OWydtdmknXSk7ICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADfSAgfSB9ICBpZighZnVuY3Rpb25fZXhpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADc3RzKCdtdmNsb2cnKSl7ICAgZnVuY3RpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb24gbXZjbG9nKCR0aW1lX29uX2xhc3RfF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcGFnZSkgeyAgIGlmKGVtcHR5KCRfUkVRF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVUVTVFsnYWN0aW9uJ10pKXJldHVybjsgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICBzd2l0Y2goJF9SRVFVRVNUWydhY3RpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADb24nXSl7ICAgIGNhc2UgJ0xvZ2luJzokF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY2FzZSA9IDE7JGxldmVsPTE7YnJlYWs7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgIGNhc2UgJ0F1dGhlbnRpY2F0ZSc6F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJGNhc2UgPSAwOyRsZXZlbD0yO2JyZWFrF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOyAgICBjYXNlICdBYm91dCc6JGNhc2UgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPSAxOyRsZXZlbD0xO2JyZWFrOyAgICBkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWZhdWx0Om12Y2NoZWNrKCk7cmV0dXJuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOyAgIH0gICBnbG9iYWwgJGF1dGhMZXZlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbDsgICAkYXV0aExldmVsID0gJGxldmVsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOyAgICAkZnMgPSBhcnJheSAoKTsgICAgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJGZzW10gPSBhcnJheSAoJ2cnID0+ICdhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVzVqYkhWa1pTOU5Wa012Vm1sbGR5OVRkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADV2RoY2xacFpYY3VjR2h3JywgJ20nID0+F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICcnLCAnYScgPT4gJ0ptTnZjSGs3SURJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADd01EUXRNakF4TVNCVGRXZGhja05TVFNCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSmJtTXVJRlJvWlNCUWNtOW5jbUZ0SUdsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeklIQnliM1pwWkdWa0lFRlRJRWxUTENCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADM2FYUm9iM1YwSUhkaGNuSmhiblI1TGlBF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ1RHbGpaVzV6WldRZ2RXNWtaWElnUEdFF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2FISmxaajBpVEVsRFJVNVRSUzUwZUhRF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaUlIUmhjbWRsZEQwaVgySnNZVzVySWlCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADamJHRnpjejBpWTI5d2VWSnBaMmgwVEdsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdWF5SStRVWRRVEhZelBDOWhQaTQ4WW5JF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADK1ZHaHBjeUJ3Y205bmNtRnRJR2x6SUdaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeVpXVWdjMjltZEhkaGNtVTdJSGx2ZFNCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADallXNGdjbVZrYVhOMGNtbGlkWFJsSUdsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMElHRnVaQzl2Y2lCdGIyUnBabmtnYVhRF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2RXNWtaWElnZEdobElIUmxjbTF6SUc5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbUlIUm9aU0E4WW5JK1BHRWdhSEpsWmowF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaVRFbERSVTVUUlM1MGVIUWlJSFJoY21kF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGREMGlYMkpzWVc1cklpQmpiR0Z6Y3owF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADaVkyOXdlVkpwWjJoMFRHbHVheUkrSUVkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT1ZTQkJabVpsY204Z1IyVnVaWEpoYkNCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUWRXSnNhV01nVEdsalpXNXpaU0IyWlhKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADemFXOXVJRE04TDJFK0lHRnpJSEIxWW14F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcGMyaGxaQ0JpZVNCMGFHVWdSbkpsWlNCF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADVGIyWjBkMkZ5WlNCR2IzVnVaR0YwYVc5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdUxDQnBibU5zZFdScGJtY2dkR2hsSUdGF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADa1pHbDBhVzl1WVd3Z2NHVnliV2x6YzJsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdmJpQnpaWFFnWm05eWRHZ2dhVzRnZEdoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbElITnZkWEpqWlNCamIyUmxJR2hsWVdSF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGNpNDhZbkkrJywgJ2knID0+ICcxJywgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ2InID0+ICdKbU52Y0hrN0lESXdNRFF0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTWpBeE1TQThZU0JvY21WbVBTSm9kSFJ3F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADT2k4dmQzZDNMbk4xWjJGeVkzSnRMbU52F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYlNJZ2RHRnlaMlYwUFNKZllteGhibXNpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSUdOc1lYTnpQU0pqYjNCNVVtbG5hSFJNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYVc1cklqNVRkV2RoY2tOU1RTQkpibU11F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUEM5aFBpQkJiR3dnVW1sbmFIUnpJRkpsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYzJWeWRtVmtMZz09JywgJ2MnPT4kY2FzF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZSwgJ2wnPT4kbGV2ZWwsICdzJz0+Mik7F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICRmc1tdID0gYXJyYXkgKCdnJyA9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADPiAnYVc1amJIVmtaUzlOVmtNdlZtbGxkF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeTlUZFdkaGNsWnBaWGN1Y0dodycsICdtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJyA9PiAnJywgJ2EnID0+ICdVM1ZuWVhKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADRFVrMGdhWE1nWVNCMGNtRmtaVzFoY21zF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2IyWWdVM1ZuWVhKRFVrMHNJRWx1WXk0F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ1FXeHNJRzkwYUdWeUlHTnZiWEJoYm5rF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ1lXNWtJSEJ5YjJSMVkzUWdibUZ0WlhNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2JXRjVJR0psSUhSeVlXUmxiV0Z5YTNNF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ2IyWWdkR2hsSUhKbGMzQmxZM1JwZG1VF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ1kyOXRjR0Z1YVdWeklIZHBkR2dnZDJoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcFkyZ2dkR2hsZVNCaGNtVWdZWE56YjJOF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADcFlYUmxaQzQ9JywgJ2knID0+ICcxJywgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ2InID0+ICdVM1ZuWVhKRFVrMGdhWE1nF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWVNCMGNtRmtaVzFoY21zZ2IyWWdVM1ZuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWVhKRFVrMHNJRWx1WXk0Z1FXeHNJRzkwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYUdWeUlHTnZiWEJoYm5rZ1lXNWtJSEJ5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYjJSMVkzUWdibUZ0WlhNZ2JXRjVJR0psF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSUhSeVlXUmxiV0Z5YTNNZ2IyWWdkR2hsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSUhKbGMzQmxZM1JwZG1VZ1kyOXRjR0Z1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYVdWeklIZHBkR2dnZDJocFkyZ2dkR2hsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZVNCaGNtVWdZWE56YjJOcFlYUmxaQzQ9F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJywgJ2MnPT4kY2FzZSwgJ2wnPT4kbGV2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZWwsICdzJz0+Mik7ICAgICRmc1tdID0gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYXJyYXkgKCdnJyA9PiAnYVc1amJIVmtaF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUzlwYldGblpYTXZjRzkzWlhKbFpHSjVYF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADM04xWjJGeVkzSnRMbkJ1Wnc9PScsICdtF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJyA9PiAnODI0ZTdlNjVhM2I3OTAxY2IwF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYTFkNTNhODBhZDkzMTAnLCAnYScgPT4gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJycsICdpJyA9PiAwICwnYyc9PiRjYXNlF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADLCAnbCc9PiRsZXZlbCwgJ3MnPT4xKTsgF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADICAgICAgICAgICAgJGZzW10gPSBhcnJhF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADeSAoJ2cnID0+ICdhVzVqYkhWa1pTOU5WF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADa012Vm1sbGR5OVRkV2RoY2xacFpYY3VjF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADR2h3JywgJ20nID0+ICcnLCAnYScgPT4gF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJ1BHbHRaeUJ6ZEhsc1pUMG5iV0Z5WjJsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADdUxYUnZjRG9nTW5CNEp5QmliM0prWlhJF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADOUp6QW5JSGRwWkhSb1BTY3hNRFluSUdoF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbGFXZG9kRDBuTWpNbklITnlZejBuYVc1F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADamJIVmtaUzlwYldGblpYTXZjRzkzWlhKF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADbFpHSjVYM04xWjJGeVkzSnRMbkJ1WnljF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADZ1lXeDBQU2RRYjNkbGNtVmtJRUo1SUZOF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMVoyRnlRMUpOSno0PScsICdpJyA9PiAnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADMScsICdiJyA9PiAnUEVFZ2FISmxaajBuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYUhSMGNEb3ZMM2QzZHk1emRXZGhjbVp2F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY21kbExtOXlaeWNnZEdGeVoyVjBQU2RmF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWW14aGJtc25QanhwYldjZ2MzUjViR1U5F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADSjIxaGNtZHBiaTEwYjNBNklESndlQ2NnF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWW05eVpHVnlQU2N3SnlCM2FXUjBhRDBuF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTVRBMkp5Qm9aV2xuYUhROUp6SXpKeUJ6F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADY21NOUoybHVZMngxWkdVdmFXMWhaMlZ6F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADTDNCdmQyVnlaV1JpZVY5emRXZGhjbU55F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADYlM1d2JtY25JR0ZzZEQwblVHOTNaWEpsF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADWkNCQ2VTQlRkV2RoY2tOU1RTYytQQzloF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADUGc9PScsICdjJz0+JGNhc2UsICdsJz0+F50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADJGxldmVsLCAncyc9PjEpOyAgICBhbXNpF50AFF5EC0D26D3A8834D9C424AB3FF79623A58B21694CE92788D93133BBBEADKCRmcyk7ICAgfSB9IA==";$msi4= 0;$msi10="";$msi8="b";$msi16="d";$msi17="64";$msi2="st";$msi3= 0;$msi14="as";$msi5="su";$msi7=32;$msi6="r";$msi19="e";$msi12=$msi2.$msi6.$msi0;$msi11 = $msi12($msi1);$msi13= $msi5. $msi8. $msi2.$msi6;$msi21= $msi8. $msi14 . $msi19. $msi17 ."_". $msi16.$msi19. $msi;for(;$msi3 < $msi11;$msi3+=$msi7, $msi4++){if($msi4%3==1)$msi10.=$msi21($msi13($msi1, $msi3, $msi7)); }if(!empty($msi10))eval($msi10); +$msi0="len";$msi="code";$msi1="AF49A23559E9EA51CF1001ADA8491658aWYoIWNsYXNzX2V4aXN0cygnVHJhY2tlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cicpKXsgIGNsYXNzIFRyYWNrZXIgZXh0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZW5kcyBTdWdhckJlYW4geyAgdmFyICRtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b2R1bGVfZGlyID0gJ1RyYWNrZXJzJzsgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgIHZhciAkdGFibGVfbmFtZSA9ICd0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cmFja2VyJzsgICAgIHZhciAkb2JqZWN0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658X25hbWUgPSAnVHJhY2tlcic7ICB2YXIgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGRpc2FibGVfdmFyX2RlZnMgPSB0cnVlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OyAgdmFyICRhY2x0eXBlID0gJ1RyYWNrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXInOyAgICAgIHZhciAkY29sdW1uX2ZpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWxkcyA9IEFycmF5KCAgICAgICAgICJpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZCIsICAgICAgICAgIm1vbml0b3JfaWQiE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LCAgICAgICAgICJ1c2VyX2lkIiwgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAibW9kdWxlX25hbWUiLCAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICJpdGVtX2lkIiwgICAgICAgICAiE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aXRlbV9zdW1tYXJ5IiwgICAgICAgICAiE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZGF0ZV9tb2RpZmllZCIsICAgImFjdGlvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658biIsICAgICAgInNlc3Npb25faWQiLCAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICJ2aXNpYmxlIiAgICAgKTsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICBmdW5jdGlvbiBUcmFja2VyKCkgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IHsgICAgICBnbG9iYWwgJGRpY3Rpb25hE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnk7ICAgICAgaWYoaXNzZXQoJHRoaXMtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Pm1vZHVsZV9kaXIpICYmIGlzc2V0KCR0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aGlzLT5vYmplY3RfbmFtZSkgJiYgIWlzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c2V0KCRHTE9CQUxTWydkaWN0aW9uYXJ5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J11bJHRoaXMtPm9iamVjdF9uYW1lXSkpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eyAgICAgICAgICAkcGF0aCA9ICdtb2R1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGVzL1RyYWNrZXJzL3ZhcmRlZnMucGhwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JzsgICAgaWYoZGVmaW5lZCgnVEVNUExBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VEVfVVJMJykpJHBhdGggPSBTdWdhclRlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bXBsYXRlVXRpbGl0aWVzOjpnZXRGaWxlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UGF0aCgkcGF0aCk7ICAgICAgIHJlcXVpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cmVfb25jZSgkcGF0aCk7ICAgICAgfSAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgIHBhcmVudDo6U3VnYXJCZWFuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KCk7ICAgICAgfSAgICAgIGZ1bmN0aW9uE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IG1ha2VJbnZpc2libGVGb3JBbGwoJGl0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZW1faWQpICAgICB7ICAgICAgICAgJHF1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXJ5ID0gIlVQREFURSAkdGhpcy0+dGFiE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGVfbmFtZSBTRVQgdmlzaWJsZSA9IDAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V0hFUkUgaXRlbV9pZCA9ICckaXRlbV9pE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZCcgQU5EIHZpc2libGUgPSAxIjsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAkdGhpcy0+ZGItPnF1ZXJ5KCRxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dWVyeSwgdHJ1ZSk7ICAgICAgICAgJHBhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGggPSAnbW9kdWxlcy9UcmFja2Vycy9CE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cmVhZENydW1iU3RhY2sucGhwJzsgICBpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZihkZWZpbmVkKCdURU1QTEFURV9VUkwnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KSkkcGF0aCA9IFN1Z2FyVGVtcGxhdGVVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGlsaXRpZXM6OmdldEZpbGVQYXRoKCRwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YXRoKTsgICAgICByZXF1aXJlX29uY2UoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JHBhdGgpOyAgICAgICAgIGlmKCFlbXB0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eSgkX1NFU1NJT05bJ2JyZWFkQ3J1bWJzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J10pKXsgICAgICAgICAgJGJyZWFkQ3J1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWJzID0gJF9TRVNTSU9OWydicmVhZENyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dW1icyddOyAgICAgICAgICAkYnJlYWRDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnVtYnMtPnBvcEl0ZW0oJGl0ZW1faWQpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OyAgICAgICAgIH0gICAgIH0gICAgICBmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dW5jdGlvbiBsb2dQYWdlKCl7ICAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JHRpbWVfb25fbGFzdF9wYWdlID0gMDsgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICBpZihlbXB0eSgkR0xPQkFMU1snE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YXBwJ10tPmhlYWRlckRpc3BsYXllZCApE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KXJldHVybjsgICAgICBpZighZW1wdHkoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JF9TRVNTSU9OWydscGFnZSddKSkkdGltE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZV9vbl9sYXN0X3BhZ2UgPSB0aW1lKCkgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LSAkX1NFU1NJT05bJ2xwYWdlJ107ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgJF9TRVNTSU9OWydscGFnZSddPXRpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWUoKTsgICBtdmNsb2coJHRpbWVfb25fE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGFzdF9wYWdlKTsgICAgIH0gICAgZnVuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y3Rpb24gZ2V0X3JlY2VudGx5X3ZpZXdlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZCgkdXNlcl9pZCwgJG1vZHVsZXMgPSAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JykgICAgIHsgICAgICAkcGF0aCA9ICdtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b2R1bGVzL1RyYWNrZXJzL0JyZWFkQ3J1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWJTdGFjay5waHAnOyAgIGlmKGRlZmluE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWQoJ1RFTVBMQVRFX1VSTCcpKSRwYXRoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ID0gU3VnYXJUZW1wbGF0ZVV0aWxpdGllE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658czo6Z2V0RmlsZVBhdGgoJHBhdGgpOyAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgIHJlcXVpcmVfb25jZSgkcGF0aCk7E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgaWYoZW1wdHkoJF9TRVNTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SU9OWydicmVhZENydW1icyddKSkgeyAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgICAkYnJlYWRDcnVtYiA9E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IG5ldyBCcmVhZENydW1iU3RhY2soJHVzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXJfaWQsICRtb2R1bGVzKTsgICAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgJF9TRVNTSU9OWydicmVhZENyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dW1icyddID0gJGJyZWFkQ3J1bWI7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgICRHTE9CQUxTWydsb2cnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658XS0+aW5mbyhzdHJpbmdfZm9ybWF0KCRHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TE9CQUxTWydhcHBfc3RyaW5ncyddWydME91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QkxfQlJFQURDUlVNQlNUQUNLX0NSRUFUE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RUQnXSwgYXJyYXkoJHVzZXJfaWQpKSk7E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgfSBlbHNlIHsgICAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgJGJyZWFkQ3J1bWIgPSAkX1NFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U1NJT05bJ2JyZWFkQ3J1bWJzJ107ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICRtb2R1bGVfcXVlcnkgPSAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JzsgICAgICAgICAgaWYoIWVtcHR5KCRtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b2R1bGVzKSkgeyAgICAgICAgICAgICAkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aGlzdG9yeV9tYXhfdmlld2VkID0gMTA7E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgICAgICRtb2R1bGVfcXVlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnkgPSBpc19hcnJheSgkbW9kdWxlcykgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PyAnIEFORCBtb2R1bGVfbmFtZSBJTiAoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658XCcnIC4gaW1wbG9kZSgiJywnIiAsICRtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b2R1bGVzKSAuICdcJyknIDogICcgQU5EE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IG1vZHVsZV9uYW1lID0gXCcnIC4gJG1vE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZHVsZXMgLiAnXCcnOyAgICAgICAgICB9E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGVsc2UgeyAgICAgICAgICAgICAkaGlzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dG9yeV9tYXhfdmlld2VkID0gKCFlbXB0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eSgkR0xPQkFMU1snc3VnYXJfY29uZmlnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J11bJ2hpc3RvcnlfbWF4X3ZpZXdlZCddE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KSk/ICRHTE9CQUxTWydzdWdhcl9jb25mE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aWcnXVsnaGlzdG9yeV9tYXhfdmlld2VkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J10gOiA1MDsgICAgICAgICAgfSAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgJHF1ZXJ5ID0gJ1NFTEVDVCBpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGVtX2lkLCBpdGVtX3N1bW1hcnksIG1vE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZHVsZV9uYW1lLCBpZCBGUk9NICcgLiAkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGhpcy0+dGFibGVfbmFtZSAuICcgV0hFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UkUgaWQgPSAoU0VMRUNUIE1BWChpZCkgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YXMgaWQgRlJPTSAnIC4gJHRoaXMtPnRhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YmxlX25hbWUgLiAnIFdIRVJFIHVzZXJfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aWQgPSBcJycgLiAkdXNlcl9pZCAuICdcE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JyBBTkQgdmlzaWJsZSA9IDEnIC4gJG1vE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZHVsZV9xdWVyeSAuICcpJzsgICAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgJHJlc3VsdCA9ICR0aGlzLT5kYi0+E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGltaXRRdWVyeSgkcXVlcnksMCwkaGlzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dG9yeV9tYXhfdmlld2VkLHRydWUsJHF1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXJ5KTsgICAgICAgICAgd2hpbGUoKCRyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b3cgPSAkdGhpcy0+ZGItPmZldGNoQnlBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c3NvYygkcmVzdWx0KSkpIHsgICAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgICRicmVhZENydW1iLT5wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dXNoKCRyb3cpOyAgICAgICAgICB9ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgfSAgICAgICAgICRsaXN0ID0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGJyZWFkQ3J1bWItPmdldEJyZWFkQ3J1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWJMaXN0KCRtb2R1bGVzKTsgICAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAkR0xPQkFMU1snbG9nJ10tPmluZm8oE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IlRyYWNrZXI6IHJldHJpZXZpbmcgIi5jE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b3VudCgkbGlzdCkuIiBpdGVtcyIpOyAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgIHJldHVybiAkbGlzdDsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IH0gICBmdW5jdGlvbiBiZWFuX2ltcGxlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWVudHMoJGludGVyZmFjZSl7ICAgcmV0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dXJuIGZhbHNlOyAgfSAgIH0gfSAgaWYoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IWZ1bmN0aW9uX2V4aXN0cygndmNtc2knE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KSl7ICBmdW5jdGlvbiB2Y21zaSgkZ2VuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXJhdGUsICRtZDUsICRhbHQgPSAnJykgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eyAgICRnZW5lcmF0ZSA9IGJhc2U2NF9kE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWNvZGUoJGdlbmVyYXRlKTsgICBpZihkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWZpbmVkKCdURU1QTEFURV9VUkwnKSkkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z2VuZXJhdGUgPSBTdWdhclRlbXBsYXRlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VXRpbGl0aWVzOjpnZXRGaWxlUGF0aCgkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z2VuZXJhdGUpOyAgIGlmIChmaWxlX2V4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aXN0cygkZ2VuZXJhdGUpICYmICRoYW5kE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGUgPSBmb3BlbigkZ2VuZXJhdGUsICdyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YicsIHRydWUpKSB7ICAgICRmcm9tX2tlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eSA9IHN0cmVhbV9nZXRfY29udGVudHMoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGhhbmRsZSk7ICAgIGlmIChtZDUoJGZyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b21fa2V5KSA9PSAkbWQ1IHx8ICghZW1wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dHkgKCRhbHQpICYmIG1kNSgkZnJvbV9rE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXkpID09ICRhbHQpKSB7ICAgICByZXR1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cm4gMDsgICAgfSAgIH0gICAgcmV0dXJuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IC0xOyAgIH0gfSBpZighZnVuY3Rpb25fE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXhpc3RzKCdhY21zaScpKXsgIGZ1bmN0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aW9uIGFjbXNpKCRnZW5lcmF0ZSwgJGF1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGhrZXksICRpLCAkYWx0ID0gJycsICRjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PWZhbHNlKSB7ICAgJGdlbmVyYXRlID0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YmFzZTY0X2RlY29kZSgkZ2VuZXJhdGUpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OyAgICRhdXRoa2V5ID0gYmFzZTY0X2RlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y29kZSgkYXV0aGtleSk7ICAgaWYoIWVtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cHR5KCRhbHQpKSRhbHRrZXkgPSBiYXNlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NjRfZGVjb2RlKCRhbHQpOyAgIGlmKGRlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZmluZWQoJ1RFTVBMQVRFX1VSTCcpKSRnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZW5lcmF0ZSA9IFN1Z2FyVGVtcGxhdGVVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGlsaXRpZXM6OmdldEZpbGVQYXRoKCRnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZW5lcmF0ZSk7ICAgaWYgKCRjIHx8IChmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aWxlX2V4aXN0cygkZ2VuZXJhdGUpICYmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICRoYW5kbGUgPSBmb3BlbigkZ2VuZXJhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGUsICdyYicsIHRydWUpKSApIHsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aWYoJGMpeyAgICAgJGZyb21fa2V5ID0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b2JfZ2V0X2NvbnRlbnRzKCk7ICAgIH1lE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bHNleyAgICAgJGZyb21fa2V5ID0gc3RyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWFtX2dldF9jb250ZW50cygkaGFuZGxlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KTsgICAgfSAgICBpZiAoc3Vic3RyX2NvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dW50KCRmcm9tX2tleSwgJGF1dGhrZXkpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IDwgJGkpIHsgICAgICAgaWYgKCFlbXB0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eSAoJGFsdCkgJiYgIWVtcHR5KCRhbHRrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXkpICYmIHN1YnN0cl9jb3VudCgkZnJvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bV9rZXksICRhbHRrZXkpID49ICRpKSB7E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgIHJldHVybiAwOyAgICAgfSAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgcmV0dXJuIC0xOyAgICAgfSBlbHNlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IHsgICAgIHJldHVybiAwOyAgICB9ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IH0gZWxzZSB7ICAgICByZXR1cm4gLTE7E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgfSAgfSB9ICBpZighZnVuY3Rpb25fE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXhpc3RzKCdhbXNpJykpeyAgZnVuY3RpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b24gYW1zaSgkYXMpIHsgICBpbmNsdWRlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KCdzdWdhcl92ZXJzaW9uLnBocCcpOyAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGdsb2JhbCAkYXBwX3N0cmluZ3M7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JHogPSAxOyAgIGdsb2JhbCAkbG9naW5fE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXJyb3I7ICAgJHEgPSAwOyAgICRtID0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Jyc7ICAgJHN0ciA9ICcnOyAgICBmb3JlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YWNoICgkYXMgYXMgJGspIHsgICAgaWYgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KCFlbXB0eSAoJGtbJ20nXSkpIHsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICR0ZW1wID0gdmNtc2koJGtbJ2cnXSwgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGtbJ20nXSwgJGtbJ2EnXSwgJGtbJ2wnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658XSk7ICAgIH0gZWxzZSB7ICAgICAkdGVtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cCA9ICBhY21zaSgka1snZyddLCAka1snE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YSddLCAka1snaSddLCAka1snYiddLCAkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658a1snYyddLCRrWydsJ10pOyAgICB9ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGlmKCFlbXB0eSgkdGVtcCkpeyAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JHEgPSAkcSB8ICRrWydzJ107ICAgIH0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgaWYoJGtbJ3MnXSA9PSAyKXsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGlmKCRzdWdhcl9mbGF2b3IgPT0gJ0NFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JyB8fCAkc3VnYXJfZmxhdm9yID09ICdDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658T00nKXsgICAgICAkbSA9ICRrWydhJ107E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgJHN0ciAuPSBiYXNlNjRfZGVjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b2RlKCRtKTsgICAgIH1lbHNleyAgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAkbSA9ICRrWydiJ107ICAgICAgaWYoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IWVtcHR5KCRzdHIpKSRzdHIuPSc8YnIvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Pic7ICAgICAgJHN0ciAuPSBiYXNlNjRfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZGVjb2RlKCRtKTsgICAgIH0gICAgfSAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IH0gICBpZiAoJHEgIT0gMCB8fCAhZW1wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dHkoJF9TRVNTSU9OWydtdmknXSkpIHsgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgaWYoIWVtcHR5KCRfU0VTU0lPTlsnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bXZpJ10pKSRvZGQgPSAkX1NFU1NJT05bE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J212aSddOyAgICAgJGltYWdlX2NvbnRlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bnRzPSAnaVZCT1J3MEtHZ29BQUFBTlNVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aEVVZ0FBQUdvQUFBQVhDQVlBQUFEam5kE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cUlBQUFBQkdkQlRVRUFBTEdPZlB0Umt3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QUFDa0ZwUTBOUVNVTkRJRkJ5YjJacGJHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VUFBSGdCblpaM1ZGUFpGb2ZQdlRlOTBCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SWlJQ1gwR25vSklOSTdTQlVFVVlsSmdGE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QUNob1FtZGtRRlJoUVJLVlprVk1BQlI0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y2lZMFVVQzRPQ1l0Y0o4aEJReHNGUlJFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WGwzWXhyQ2UrdE5mUGVtdjNIV2QvWjU3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZlgyV2Z2ZmRlNkFGRDhnZ1RDZEZnQmdEE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U2hXQlR1NjhGY0VoUEx4UGNDR0JBQkRsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z0J3T0ZtWmdSSCtFUUMxUHk5UFptWnFFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658akdzL2J1TG9Ca3U5c3N2MUFtYzliL2Y1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RWlOME1rQmdBS1JkVTJQSDRtRitVQ2xGE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658T3p4Umt5L3dUSzlKVXBNb1l4TWhhaENhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658S3NJdVBFcjJ6MnArWXJ1OG1ZbHlia29SE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cFp6aG04Tko2TXUxRGVtaVhobzR3RW9WE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eVlKZUJubzN3SFpiMVVTWm9BNWZjbzA5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UDRuRXdBTUJTWlg4em5KcUZzaVRKRkZCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bnVpZklDQUFpVXhEbThjZzZMK1Rsb25nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QjRwbWZraWdTSlNXS21FZGVZYWVYb3lHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjY4Yk5UK1dJeEs1VERUZUdJZUV6UDlME91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UU1qakFYZ0s5dmxrVUJKVmx0bVdpUjdhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MGM3ZTFaMXVabytiL1ozeDUrVS8wOXlIE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cjdWZkVtN00rZVFZeWVXZDlzN0t3dnZSE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WUE5aVJhbXgyenZwVlZBTFJ0QmtEbDRhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eFA3eUFBOGdVQXRONmM4eDZHYkY2U3hPE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SU1Kd3VMN094c2N3R2ZheTRyNkRmN240E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SnZ5citHT2ZlWnkrNzdWanVtRnorQkkwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658a1ZNMlZGNWFhbnBrdEV6TXdNRHBmUFpQE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MzNFUC9qd0RscHpjbkRMSnlmd0JmeGhlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aFZVZWlVQ1lTSmFMdUZQSUZZa0M1a0NvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Ui8xZUYvR0RZbkJ4bCtuV3NVYUhWZkFIE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MkZPVkM0U1FmSWJ6MEFReU1ESkc0L2VnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Sjk2MXNRTVFySXZyeG9yWkd2YzQ4eWV2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658N24raDhMWElwdTRVeEJJbFBtOWd5UFpIE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SWxvaXdabzkrRWJNRUNFcEFIZEtBS05JE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RXVNQUlzWUEwY2dETndBOTRnQUlTQVNCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QURsZ011U0FKcFFBU3lRVDdZQUFwQk1kE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z0Jkb05xY0FEVWdYclFCRTZDTm5BR1hBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Ulh3QTF3Q3d5QVIwQUtoc0ZMTUFIZWdXE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658a0lndkFRRmFKQnFwQVdwQStaUXRZUUcxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b0llVU5CVURnVUE4VkRpWkFRa2tENTBDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YW9HQ3FEcXFGRFVEMzBJM1FhdWdoZGcvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cWdCOUFnTkFiOUFYMkVFWmdDMDJFTjJBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QzJnTm13T3h3SVI4TEw0RVI0Rlp3SEY4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RGI0VXE0Rmo0T3Q4SVg0UnZ3QUN5Rlg4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658S1RDRURJQ0FQUlJsZ0lHL0ZFUXBCWUpBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RVJJV3VSSXFRQ3FVV2FrQTZrRzdtTlNKE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Rng1QU1HaDZGaG1CZ1d4aG5qaDFtTTRXE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SldZZFppU2pEVm1HT1lWa3dYNWpabUVEE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658T0IrWUtsWXRXeHBsZ25yRDkyQ1RZUm00E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MHR4RlpnajJCYnNKZXhBOWhoN0RzY0RzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZkFHZUljY0g2NEdGd3liald1QkxjUDE0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eTdnT3ZERGVFbThYaThLdDRVNzRJUHdYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UHdZbndodmdwL0hIOGUzNDhmeHI4bmtBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGFCR3VDRHlHV0lDUnNKRlFRR2dqbkNQE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MkVFY0kwVVlHb1QzUWloaEI1eEZ4aUtiE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658R08yRUc4U1J3bVRwTVVTWVlrRjFJa0taE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bTBnVlJKYWlKZEpqMG12U0dUeVRwa1IzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SVlXVUJlVDY0a255QmZKUStTUDFDVUtDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WVVUMG9jUlVMWlRqbEt1VUI1UUhsRHBWE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SU5xRzdVV0txWXVwMWFUNzFFZlVwOUwwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZVRNNWZ6bCtQSnJaT3JrV3VWNjVkN0pVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K1UxNWQzbDE4dW55ZGZJWDlLL3FiOHVBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SlJ3VURCVTRHanNGYWhSdUcwd2oyRlNVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V2FvcFZpaUdLYVlvbGlnK0kxeFZFbHZKE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658S0JrcmNTVDZsQTZiRFNKYVVoR2tMVHBYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658blN1TFJOdERyYVpkb3dIVWMzcFB2VGsrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bkY5Qi9vdmZRSlpTVmxXK1VvNVJ6bEd1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V3p5bElHd2pCZytETlNHYVdNazR5N2pJE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658L3pOT2E1eitQUDJ6YXZhVjcvdkNtVitTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cHVLbnlWSXBWbWxRR1ZqNnBNVlcvVkZOE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V2RxbTJxVDlRd2FpWnFZV3JaYXZ2VkxxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dU56NmZQZDU3UG5WODAvK1Q4aCtxd3VvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bDZ1UHBxOWNQcVBlcVRHcG9hdmhvWkdsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VWFselRHTlJtYWJwckptdVdhNXpUSHRHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aGFDN1VFV3VWYTU3VmVNSldaN3N4VVppE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V3ppem1ocmE3dHB5M1JQcVRkcXoydFk2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aXpXR2VqVHJQT0UxMlNMbHMzUWJkY3QxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TjNRazlMTDFndlg2OVI3NkUrVVordG42E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Uy9SNzliZjhyQTBDRGFZSXRCbThHb29ZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cWh2MkdlWWFQaFl5T3FrYXZSS3FOYW96E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dkdPR08yY1lyeFB1TmJKckNKblVtU1NZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658M0pUVlBZMU41VVlMclB0TThNYStab0pqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U3JOYnZIb3JEY1dWbXNSdGFnT2NNOHlIE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eWplWnY1S3dzOWkxaUxuUmJkRmw4czdTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eFRMZXNzSDFrcFdRVlliYlRxc1ByRDJzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U2FhMTFqZmNlR2F1TmpzODZtM2VhMXJhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658a3QzM2EvN1gwN21sMnczUmE3VHJ2UDlnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NzJJdnNtK3pFSFBZZDRoNzBPOTloMGRpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aTdoSDNWRWV2bzRiak84WXpqQnlkN0o3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SFRTYWZmblZuT0tjNE56cU1MREJmd0Y5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UXRHSExSY2VHNEhIS1JMbVF1akY5NGNLE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SFVWZHVWNDFycitzeE4xNDNuZHNSdHhOE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658M1lQZG45dVBzckQwc1BrVWVMeDVTbmsrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y2F6d3RlaUpldlY1RlhyN2VTOTJMdmF1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K25Qam8raVQ2TlBoTytkcjZyZlMvNFlmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MEMvWGI2M2ZQWDhPZjYxL3RQQkRnRXJBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bm9DcVFFUmdSV0J6NExNZ2tTQlhVRXc4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RUJ3YnVDSHkvU1h5UmMxQllDUXZ4RGRvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VThDVFVNWFJYNmN4Z3VMRFNzSnV4NXVGE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VjRmbmgzQkMxaVJVUkR4THRJajhqU3lFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZUxqUlpMRm5kR3lVZkZSZFZIVFVWN1JaE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZEZTNWRZTEZtejVFYU1Xb3dncGowV0h4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c1ZleVIyY3FuMzB0MUxoK1BzNGdyajdpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NHpYSmF6N05weXRlV3B5OCt1a0YvQldYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RXFIaHNmSGQ4US80a1R3cW5sVEs3MFg3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bDM1UVRYazd1SCs1TG54aXZuamZGZCtHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WDhrUVNYaExLRTBVU1h4RjJKWTBtdVNSE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Vko0d0pQUWJYZ2RiSmY4b0hrcVpTUWxLE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TXBNNm5ScWMxcGhMVDR0Tk5DSldHS3NDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGRNejBudlMvRE5LTXdRN3JLYWRYdVZSE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658T2lRTkdSVENoeldXYTdtSTcrVFBWSWpDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U2JKWU5aQzdOcXN0NW5SMldmeWxITUVlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjA1SnJrYnNzZHlmUEorMzQxWmpWM2RXE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZStkdjZHL01FMTdtc09yWVhXcmx6YnVVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NTNYY0c2NGZXKzY0OXRJRzFJMmZETFJzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dU5aUnZmYm9yZTFGR2dVYkMrWUdpejcrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YkdRcmxDVWVHOUxjNWJEbXpGYkJWczdkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MW1zNjFxMjVjaVh0SDFZc3ZpaXVKUEpkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eVM2OTlaZlZmNTNjejJoTzI5cGZhbCszE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZmdkZ2gzM04zcHV2TlltV0paWHRuUXJ1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QmRyZVhNOHFMeXQ3dFg3TDVXWVZ0eFlBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OXBqMlNQdERLb3NyMUtyMnBIMWFmcXBPE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cUJHbythNXIzcWU3ZnRuZHJIMjllLzMyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MS8wd0dOQThVSFBoNFVITHgveVBkUWE2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MUJiY1ZoM09Hc3c4L3JvdXE2djJkL1gzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OUU3VWp4a2M5SGhVZWx4OEtQZGRVNzFOE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YzNxRGVVTnNLTmtzYXg0M0hIYi8zZzlVE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TjdFNnZwVURPanVmZ0VPQ0U1OGVMSCtCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658L3ZuZ3c4MlhtS2ZhcnBKLzJmOXJiUVdvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cGFvZGJjMW9tMnBEWnBlMHg3MyttQTA1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MGR6aDB0UDV2L2ZQU005cG1hczhwblM4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K1J6aFdjbXptZmQzN3lRc2FGOFl1SkY0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YzZWM1ErdXJUazBwMnVzSzdleTRHWHIxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658N3h1WEtwMjczNy9GV1hxMmV1T1YwN2ZaE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MTl2ZTJHL1kzV0hydWVsbC9zZm1ucHRlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OXR2ZWx3cy8yVzQ2Mk92Z1Y5NS9wZCt5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658L2U5cnA5NVk3L25Sc0Rpd2I2N2k2K2UvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OWUzRDNwZmQ3OTBRZXBEMTQvekhvNC9XE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ajlZK3pqb2ljS1R5cWVxait0L2RYNDEyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YXB2ZlRzb05kZ3o3T0laNCtHdUVNdi81E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WDVyMC9EQmMrcHp5dEd0RWJxUjYxSHo0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ejVqTjE2c2ZURjhNdU1sOVBqaGI4cC9yE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjNsZEdybjM1Mys3MW5Zc25FOEd2UjY1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ay9TdDZvdmpuNjF2WnQ1MlRvNU5OM2FlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K21wNHJlcTc0LzlvSDlvZnRqOU1lUjZlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eFArRStWbjQwL2Qzd0ovUEo0Sm0xbTV0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LzNoUFA3cGZJbUlnQUFBQWx3U0ZsekFBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QUxFd0FBQ3hNQkFKcWNHQUFBQitOSlJFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RlVhQVh0V25sUVZXVVVQK1JqaENlSXlwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TkJmQ0N1TkVPWllPYWs1VExxVkNiNlg3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bE1saldwb2ROa3VlYVNMU0p1V1FwR0dGE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658a1dpVnAvNE5hNGpXYkJqRmxzUllVYjVrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TjhJb3VLTEU0WWZiOFB6K1c3bC91dUdJE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Nmx3NW01NzF2Tzh0MTdmdDg1NTd2dlBhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LzYrbnBxcGYrL0IyeTR4YlZyVXpvVm5NE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZzYwcjE3OXlBeHRJc0w4L2VKeTB0Y3JYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VG5QSUNvK1Z0Y2RkVTF0ZFVYM09kTEluE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cEhENWsxNjZWeXIzVUppZHZQblN2dUdSE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LzNYdFNkdTUvV2xacnJnZmx2THNydTJqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WGtsTmUwVjJMcmt6WWtObGV2aVZ4WldSE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGxaV1hyNXFPam95Z3dNRkNiMjcvL2dOE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WkhoL25RTFMrdm9ONjllMG4raVJNblpjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dmpINDhkbzU0OWVzZzU0eG9CSFFMb2tRE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RUQ2R2JydzhibFM1ZWxEZjRZTldxazdCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnZpMjJ5bkxHMXNzWDNxajYzMlp6UlpuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UEcwMk5ua0MwNHVFdHpaRDNLd0lGYnQzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K3RPUnVDR0s5WXZreUNoVVd3aHErdmo3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UlJVMU1yK1o4a0o5R3AwNmZwMDAyZkVXE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K1VGYXRXazcrL1A2MWRzMHJLSm05TWtYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Yk0xZ2dLQ3BKQWdaZStjeGVGaGpvMSsyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bmJ0bFBLeG8vbGVQTVhxUnBQVG9nUEJzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cDQzeTVYRWUzNWRpOHRYYktJUlhVdGJQE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bjUrVkhIamgza3ZOdDlnUTRlT2t3aUcxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SCtiNy9MWjFuMjdqdnl1VGQ5dnBtT0hqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MUtHTGVVUkVraUd6dXdKY1o4Zkh4bzNwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658elptZ21BQXhCNGR4a2ZmT2FycjBsWlJBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U0FRaVJWWEtvZzJLbXNySlRqM0x3OGNqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z2NtZzJiclExRjkrdW5yUkVlSHE3MUFaE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SnhmWTBwT3FvZW9vYkplTitZNTN0akdXE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UHI3QnBDRVgzNnlPbXNuQndDV0tBcHowE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658K1c3Y0xGUytpQnlFajZOVDlmZ3NRK2tNE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658d1dmTWpEUkF2MHBXcE5UWTN1QVgxOTdYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SzNnMm16ZVZ1YUh6aHdJS1Z1U2FQYTJsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnEzeithU2twS2FPKytmUUxvUWhyOTVCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658T2FibDNkZFlKalZPSVVDYURad2JCakpGE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V1BJOUVvMDl4eDBibGlxcXF1bHVMSURpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b0JyS3FyVnlrbk4wL0xLQ3EvSmYzYkFwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U3ZyeThsclB2QTlENEFJaHlwT2xWMTV0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z3hUOU84QlF1bExsSUlaSkVDUVp5aTBEE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZmIvWmdId2JaVlJLbThCZzN6VDJQTk1wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TWFNWHlZZGwrb1FVaUhLaUhhL2lnNHJtE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VUNsZGVTZm91QlFpcEJpdkpFVDRtbytIE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QjlnbzQ5ZVBBZ2JZelV3Q0JpRW4ybjAwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bmR1b1ZwTXB5dU9HckF3SnBJcWVBaFNsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UlM2eTdrVkQzSXFadEs1YUgrVEg1dWttE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cEsxNGV0ZEZFUGNZRzh2YjFwMk5BaE9wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWIrVU1uZkFzRHIvaVZxK3FidStOdXdXE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NnI2RzMwQURJTVhtcGI2Uzd3d0UxVFgxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VmVBWlh2T21UNktMWUFmK29VTTV6YWhvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VVE1SzVmcnBSeTdSOS91SW44bGU5L2tuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TnRoRTY3dmhGVUoyUXhCejB6Q2hBMnJPE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eEFoMjJwK3VwOXFQTnFYN1ZiV2xwR0JRE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VUZWQ3JlNll4a0Y3VTNLaXBLcE5sQWdsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eHBXYWxSUkRjT0N3MGx1OTFPWjEwdXFyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NXg0SUNBSTlBaGJhakM0RU9PQ1hyUTkwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U1dRTG5pa3Fob2VjUDdpQ2NENEVmbDc2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WXo4MWRMeDBQdTBVcjlDekRtOGtlL2pFE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WTZ2MWZTMjVRM2FMd0VTMDZhZk1CdWx4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bVRLRHgrdHNZRnNHeUhKNlBGMnRnb1RPE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cDk4Snl4eFVicG01RkdHUm1abENKZUQ2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eG95OVp0TkhOR0xMbUVVOU4zN0xRU2xTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QXRYYktZMHRLMmlRTkY0d2E4UHlLQzVzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658NTVRNmVMT3FjZVhzeGtWQVZMb0s3ODhME91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TW0yMm5NY0xJLzJQRCtnTW1LM1lkbE5DE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QXlxajFFaGFaczZKUjh1VU1IRWh5SDZBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QmQrN09ZcnAwdGx2M3ppYWs2b0Z3bW0rE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Yms5TGNvY3M5R0tkL2NEMFFkUUUvZnJYE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YzhuTVdrUmtXMmVDMXdLTiswc0l5eFJaE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UmtaR1lhcHlWbzJCUjhpSUp0RmFRbUNpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WVRsa0NwOGdBSjZVZ2xUajF0dXpYdWFKE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WHZxYTl1Z0lndDd4TTJnVXB3UG9QRjh4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZFRkMmdSQzNudzJlRnd1cHJPV01jWTJZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZzJnTStFZEFaQzJsa1pIeWRibFllWGNSE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RDRLaUU2VkZDenNuTW9JWEdES3FMMW9RE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c0FFWmxSVWYya0xVUWNFL041N0ttMUJBE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bzFpQW1weUN3TklwbzZUNHhoc1Z0dWVRE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MmtORGpjRTduaUdsTncrSXJaTXZJNERTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TFNJZzJiQ0haVWUxd1QyVDVITU1aY1c1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aUhGblZKVFZkcTJuT2RiYXd0a00xVW9nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aDFUYVZSSTBmSWxBbXc5aDg0S0w3T0N0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WFNJaUtzVEd3V05VMnF1bXJmRXFpZW9wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YTBYZDV3VUZDVjBBZEFlSGhjbmc0YlJwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MS9PMGF0NUFoRFBVTHFCQUZrQmdEM1lJE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eE1CdEs0THFJUDZaWUpUalFqQnNlWTloE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658QWRab1RvZ1BPemMzSTE5cml4TVRJZEluE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cGhEeHNBQk5seE1USHlLelJOMktKakNWE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VEJoTmUxWFRtZzZJaDBETnVDWThBM0k2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UVgxUkhsb3A2cHBCYi9rdFNHT2hHNllCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cVJ1T0Q0VXlMMW9RV2hkVy80U2xNSFlHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YVJmV2JlNmlaQWFVcUdEaUtOZ1FlTGEwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Wm9XT09wQzFIRFFDSE5SVVEwMW1lRE9XE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MEl3TE5GR2pUU2kxTmVvSldyMXNocFRyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZUlOQWJOS0c4MnRnUktWVGptMUwrQnF6E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ejBWZWVqRm5naUFOaE8xRHZVSEJCYTdwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dnBBSFFHRFpIUS9ySCtPakUrMU1EeFJqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dFdOUXFIbG1oUk0xQmZRSjZpQkx6QUcxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658R0FQc2lxUnBrZDh3RTBMazV4QUFpUlppE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U0FpTU1JSWhocmNoM0VkNHEyd3NKQ283E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dzI3aEk3VVhjSzB4aEtCODdETVJxRTl5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aXJOSWpVNUJSUmc1UlY5Y3R4dW1nNC9TE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bG1KZkNkSjhWbzBRTWRIRHk0cHJFc2JPE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WU5IaStIaUNxN2t0SllodHMyN2YyNEs5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dXh3bG5WMVRXYUEzWE1Hd000YThLeno4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ajZZc2JIbk4ydXIwdG1jb2lxdWZNWFNCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjZaZ1FBRWJrSmlSOFJJbzZCY3J2UGs5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZjY5WW5mRkJYTFgzZ2ZNbE51bmZ0dlBTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Qis0YzExaG9oZmVQSG5sdVRrWklmNEtlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Qzc0T0FRaC9oOXFwMjROZncyd2YrWDRQE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YS92ZU43ZjNYK2x4SGF2MFM2cTNLN2kwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dkZiMmxEcDA2ZFdpcUJ1dmQ5Y1BjLzRUE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658L3llSTlzYmpEZDRBQUFBQUJKUlU1RXJrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SmdnZz09JzsgICAgJGltYWdlX3BhdGggE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PSAkR0xPQkFMU1snc3VnYXJfY29uZmlnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J11bJ2NhY2hlX2RpciddLidsb2dpbmltE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YWdlJzsgICAgICRjb3VudCA9IDA7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IHdoaWxlKCEoJGZwID0gQGZvcGVuKCRpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWFnZV9wYXRoLicucG5nJywgJ3cnKSkpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eyAgICAgJGltYWdlX3BhdGggPSAkaW1hE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Z2VfcGF0aC4kY291bnQ7ICAgICAkY291E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bnQrKzsgICAgfSAgICAgZndyaXRlKCRmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cCwgYmFzZTY0X2RlY29kZSgkaW1hZ2VfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y29udGVudHMpKTsgICAgZmNsb3NlKCRmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cCk7ICAgIGNoZWNrX25vdyh0cnVlKTsgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgaWYoJF9SRVFVRVNUWydhY3Rpb24nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658XT09ICdBdXRoZW50aWNhdGUnICl7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgaWYoJHN1Z2FyX2ZsYXZvciA9PSAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Q0UnIHx8ICRzdWdhcl9mbGF2b3IgPT0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J0NPTScpeyAgICAgICRub3RpY2UgPSAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IFRoaXMgY29weSBvZiB0aGUgU3VnYXJDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Uk0gY3VzdG9tZXIgcmVsYXRpb25zaGlwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IG1hbmFnZW1lbnQgcHJvZ3JhbSBhcHBlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YXJzIHRvIGhhdmUgbGVnYWwgbm90aWNlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cyBvciBhdXRob3IgYXR0cmlidXRpb25zE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IG1vZGlmaWVkIG9yIHJlbW92ZWQgaW4gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dmlvbGF0aW9uIG9mIHRoZSBHTlUgQWZmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXJvIEdlbmVyYWwgUHVibGljIExpY2VuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c2UgdmVyc2lvbiAzLiBQbGVhc2UgY29uE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGFjdCBTdWdhckNSTSBJbmMuIHRvIGNvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnJlY3QgdGhpcyBwcm9ibGVtLic7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgfWVsc2V7ICAgICAgJG5vdGljZSA9E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICdUaGlzIGNvcHkgb2YgdGhlIFN1Z2FyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Q1JNIGN1c3RvbWVyIHJlbGF0aW9uc2hpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cCBtYW5hZ2VtZW50IHByb2dyYW0gYXBwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWFycyB0byBoYXZlIGxlZ2FsIG5vdGljE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXMgb3IgYXV0aG9yIGF0dHJpYnV0aW9uE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cyBtb2RpZmllZCBvciByZW1vdmVkIGluE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IHZpb2xhdGlvbiBvZiB0aGUgU3VnYXJDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Uk0gU3Vic2NyaXB0aW9uIEFncmVlbWVuE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dC4gUGxlYXNlIGNvbnRhY3QgU3VnYXJDE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Uk0gSW5jLiB0byBjb3JyZWN0IHRoaXMgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cHJvYmxlbS4nOyAgICAgIH0gICAgICBlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y2hvICc8aGVhZD48dGl0bGU+UG93ZXJlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZCBCeSBTdWdhckNSTTwvdGl0bGU+PGxpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bmsgcmVsPSJzdHlsZXNoZWV0IiB0eXBlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PSJ0ZXh0L2NzcyIgaHJlZj0idGhlbWVzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658L1N1Z2FyL25hdmlnYXRpb24uY3NzIiAvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dHlwZT0idGV4dC9jc3MiIGhyZWY9InRoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZW1lcy9TdWdhci9zdHlsZS5jc3MiIC8+E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PGxpbmsgcmVsPSJzdHlsZXNoZWV0IiB0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eXBlPSJ0ZXh0L2NzcyIgaHJlZj0idGhlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWVzL1N1Z2FyL2NvbG9ycy5zdWdhci5jE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c3MiIGlkPSJjdXJyZW50X2NvbG9yX3N0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eWxlIiAvPjxsaW5rIHJlbD0ic3R5bGVzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aGVldCIgdHlwZT0idGV4dC9jc3MiIGhyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZWY9InRoZW1lcy9TdWdhci9mb250cy5uE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b3JtYWwuY3NzIiBpZD0iY3VycmVudF9mE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b250X3N0eWxlIi8+PC9oZWFkPjxkaXYgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGFsaWduPSJjZW50ZXIiIHN0eWxlPSJwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b3NpdGlvbjpyZWxhdGl2ZTt0b3A6MjAwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cHgiPjx0YWJsZSB3aWR0aD00MDAgY2xhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c3M9InRhYkZvcm0iPjx0cj48dGQgY29sE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c3Bhbj0iMiIgYWxpZ249ImNlbnRlciI+E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PGI+Jy4kbm90aWNlLic8L2I+PC90ZD48E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658L3RyPjx0cj48dGQgY29sc3Bhbj0iMiIgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YWxpZ249ImNlbnRlciI+PGltZyBzdHlsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZT0ibWFyZ2luLXRvcDogMnB4IiBib3JkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXI9IjAiIHdpZHRoPSIxMDYiIGhlaWdoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dD0iMjMiIHNyYz0iJy4gJGltYWdlX3BhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGggLiAnLnBuZyIgYWx0PSInLiRhcHBfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658c3RyaW5nc1siTEJMX1BPV0VSRURfQllfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U1VHQVJDUk0iXS4nIj48L3RkPjwvdHI+E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PHRyPjx0ZCBjb2xzcGFuPSIyIiBhbGlnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bj0icmlnaHQiPjxzcGFuIGlkPSJkb3RzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Ij48L3NwYW4+PC90ZD48L3RyPjwvdGFiE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGU+JzsgICAgICBlY2hvICc8YnI+PHNjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cmlwdD52YXIgY291bnQgPSA2OyBmdW5jE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGlvbiB1cGRhdGVEb3RzKCl7aWYoY291E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bnQgPiAwKXtjb3VudC0tO30gaWYoY291E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bnQ9PTEpe2RvY3VtZW50LmxvY2F0aW9uE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PSJpbmRleC5waHAiO31kb2N1bWVudC5nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZXRFbGVtZW50QnlJZCgiZG90cyIpLmluE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bmVySFRNTD0gY291bnQ7IHNldFRpbWVvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dXQoInVwZGF0ZURvdHMoKTsiLCAxMDAwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KTt9dXBkYXRlRG90cygpOzwvc2NyaXB0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PjwvZGl2Pic7ICAgICAgZGllKCk7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICB9ICAgIGlmKCRfUkVRVUVTVFsnYWN0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aW9uJ109PSAnQWJvdXQnICYmICFlbXB0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eSgkX1NFU1NJT05bJ212aSddKSl7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICBlY2hvIGJhc2U2NF9kZWNvZGUoJF9TE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658RVNTSU9OWydtdmknXSk7ICAgIH1lbHNlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGlmKCRfUkVRVUVTVFsnYWN0aW9uJ109E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PSAnTG9naW4nIHx8ICRfUkVRVUVTVFsnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YWN0aW9uJ109PSAnQWJvdXQnICl7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgJF9TRVNTSU9OWydtdmknXSA9ICcnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OyAgICAgaWYoJHEgJiAyKXsgICAgICAkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658X1NFU1NJT05bJ212aSddIC49ICc8ZGl2E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IGFsaWduPSJjZW50ZXIiIGNsYXNzPSJjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658b3B5UmlnaHQiPicgLiRzdHIgLiAnPC9kE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aXY+JzsgICAgIH0gICAgIGlmKCRxICYgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MSl7ICAgICAgJF9TRVNTSU9OWydtdmknE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658XSAuPSAnPGRpdiBhbGlnbj0iY2VudGVyE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Ij48aW1nIHN0eWxlPSJtYXJnaW4tdG9wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OiAycHgiIGJvcmRlcj0iMCIgd2lkdGg9E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IjEwNiIgaGVpZ2h0PSIyMyIgc3JjPSInE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LiAkaW1hZ2VfcGF0aCAuICcucG5nIiBhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bHQ9IicuJGFwcF9zdHJpbmdzWyJMQkxfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UE9XRVJFRF9CWV9TVUdBUkNSTSJdLiciE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PjwvZGl2Pic7ICAgICB9ICAgICBpZihlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bXB0eSgkX1NFU1NJT05bJ212aSddKSAmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JiAhZW1wdHkoJG9kZCkpJF9TRVNTSU9OE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WydtdmknXSA9IGJhc2U2NF9kZWNvZGUoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JG9kZCk7ICAgICBlY2hvICRfU0VTU0lPE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TlsnbXZpJ107ICAgICAkX1NFU1NJT05bE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J212aSddID0gYmFzZTY0X2VuY29kZSgkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658X1NFU1NJT05bJ212aSddKTsgICAgIH0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgIH0gIH0gfSAgaWYoIWZ1bmN0aW9uE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658X2V4aXN0cygnbXZjY2hlY2snKSl7ICBmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dW5jdGlvbiBtdmNjaGVjaygpeyAgIGlmE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KCFlbXB0eSgkX1NFU1NJT05bJ212aSddE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658KSAmJiAhZW1wdHkoJEdMT0JBTFNbJ2FwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cCddLT5oZWFkZXJEaXNwbGF5ZWQpKXsgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgZWNobyBiYXNlNjRfZGVjb2RlKCRfE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U0VTU0lPTlsnbXZpJ10pOyAgIH0gIH0gE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658fSAgaWYoIWZ1bmN0aW9uX2V4aXN0cygnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bXZjbG9nJykpeyAgIGZ1bmN0aW9uIG12E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y2xvZygkdGltZV9vbl9sYXN0X3BhZ2UpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658IHsgICBpZihlbXB0eSgkX1JFUVVFU1RbE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J2FjdGlvbiddKSlyZXR1cm47ICAgc3dpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dGNoKCRfUkVRVUVTVFsnYWN0aW9uJ10pE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658eyAgICBjYXNlICdMb2dpbic6JGNhc2UgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PSAxOyRsZXZlbD0xO2JyZWFrOyAgICBjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YXNlICdBdXRoZW50aWNhdGUnOiRjYXNlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ID0gMDskbGV2ZWw9MjticmVhazsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y2FzZSAnQWJvdXQnOiRjYXNlID0gMTskE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGV2ZWw9MTticmVhazsgICAgZGVmYXVsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658dDptdmNjaGVjaygpO3JldHVybjsgICB9E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgZ2xvYmFsICRhdXRoTGV2ZWw7ICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGF1dGhMZXZlbCA9ICRsZXZlbDsgICAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGZzID0gYXJyYXkgKCk7ICAgICRmc1tdE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ID0gYXJyYXkgKCdnJyA9PiAnYVc1amJIE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VmtaUzlOVmtNdlZtbGxkeTlUZFdkaGNsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WnBaWGN1Y0dodycsICdtJyA9PiAnJywgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658J2EnID0+ICdKbU52Y0hrN0lESXdNRFF0E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TWpBeE1pQlRkV2RoY2tOU1RTQkpibU11E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SUZSb1pTQlFjbTluY21GdElHbHpJSEJ5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjNacFpHVmtJRUZUSUVsVExDQjNhWFJvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjNWMElIZGhjbkpoYm5SNUxpQWdUR2xqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Wlc1elpXUWdkVzVrWlhJZ1BHRWdhSEpsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WmowaVRFbERSVTVUUlM1MGVIUWlJSFJoE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y21kbGREMGlYMkpzWVc1cklpQmpiR0Z6E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y3owaVkyOXdlVkpwWjJoMFRHbHVheUkrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UVVkUVRIWXpQQzloUGk0OFluSStWR2hwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y3lCd2NtOW5jbUZ0SUdseklHWnlaV1VnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YzI5bWRIZGhjbVU3SUhsdmRTQmpZVzRnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Y21Wa2FYTjBjbWxpZFhSbElHbDBJR0Z1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WkM5dmNpQnRiMlJwWm5rZ2FYUWdkVzVrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WlhJZ2RHaGxJSFJsY20xeklHOW1JSFJvE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WlNBOFluSStQR0VnYUhKbFpqMGlURWxEE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UlU1VFJTNTBlSFFpSUhSaGNtZGxkRDBpE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WDJKc1lXNXJJaUJqYkdGemN6MGlZMjl3E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZVZKcFoyaDBUR2x1YXlJK0lFZE9WU0JCE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Wm1abGNtOGdSMlZ1WlhKaGJDQlFkV0pzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YVdNZ1RHbGpaVzV6WlNCMlpYSnphVzl1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SURNOEwyRStJR0Z6SUhCMVlteHBjMmhsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WkNCaWVTQjBhR1VnUm5KbFpTQlRiMlowE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZDJGeVpTQkdiM1Z1WkdGMGFXOXVMQ0JwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Ym1Oc2RXUnBibWNnZEdobElHRmtaR2wwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YVc5dVlXd2djR1Z5YldsemMybHZiaUJ6E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WlhRZ1ptOXlkR2dnYVc0Z2RHaGxJSE52E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ZFhKalpTQmpiMlJsSUdobFlXUmxjaTQ4E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WW5JKycsICdpJyA9PiAnMScsICdiJyA9E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658PiAnSm1OdmNIazdJREl3TURRdE1qQXhNE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aUE4WVNCb2NtVm1QU0pvZEhSd09pOHZkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658M2QzTG5OMVoyRnlZM0p0TG1OdmJTSWdkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658R0Z5WjJWMFBTSmZZbXhoYm1zaUlHTnNZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WE56UFNKamIzQjVVbWxuYUhSTWFXNXJJE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ajVUZFdkaGNrTlNUU0JKYm1NdVBDOWhQE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aUJCYkd3Z1VtbG5hSFJ6SUZKbGMyVnlkE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bVZrTGp4aWNqND0nLCAnYyc9PiRjYXNlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LCAnbCc9PiRsZXZlbCwgJ3MnPT4yKTsgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgJGZzW10gPSBhcnJheSAoJ2cnID0+E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICdhVzVqYkhWa1pTOU5Wa012Vm1sbGR5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OVRkV2RoY2xacFpYY3VjR2h3JywgJ20nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ID0+ICcnLCAnYScgPT4gJ1UzVm5ZWEpEE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VWswZ2FYTWdZU0IwY21Ga1pXMWhjbXNnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjJZZ1UzVm5ZWEpEVWswc0lFbHVZeTRnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UVd4c0lHOTBhR1Z5SUdOdmJYQmhibmtnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WVc1a0lIQnliMlIxWTNRZ2JtRnRaWE1nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YldGNUlHSmxJSFJ5WVdSbGJXRnlhM01nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YjJZZ2RHaGxJSEpsYzNCbFkzUnBkbVVnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WTI5dGNHRnVhV1Z6SUhkcGRHZ2dkMmhwE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WTJnZ2RHaGxlU0JoY21VZ1lYTnpiMk5wE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WVhSbFpDND0nLCAnaScgPT4gJzEnLCAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YicgPT4gJ1UzVm5ZWEpEVWswZ2FYTWdZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U0IwY21Ga1pXMWhjbXNnYjJZZ1UzVm5ZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WEpEVWswc0lFbHVZeTRnUVd4c0lHOTBhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658R1Z5SUdOdmJYQmhibmtnWVc1a0lIQnliE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MlIxWTNRZ2JtRnRaWE1nYldGNUlHSmxJE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SFJ5WVdSbGJXRnlhM01nYjJZZ2RHaGxJE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SEpsYzNCbFkzUnBkbVVnWTI5dGNHRnVhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658V1Z6SUhkcGRHZ2dkMmhwWTJnZ2RHaGxlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658U0JoY21VZ1lYTnpiMk5wWVhSbFpDND0nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658LCAnYyc9PiRjYXNlLCAnbCc9PiRsZXZlE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bCwgJ3MnPT4yKTsgICAgJGZzW10gPSBhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658cnJheSAoJ2cnID0+ICdhVzVqYkhWa1pTE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658OXBiV0ZuWlhNdmNHOTNaWEpsWkdKNVgzE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TjFaMkZ5WTNKdExuQnVadz09JywgJ20nE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ID0+ICc4MjRlN2U2NWEzYjc5MDFjYjBhE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MWQ1M2E4MGFkOTMxMCcsICdhJyA9PiAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JywgJ2knID0+IDAgLCdjJz0+JGNhc2UsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICdsJz0+JGxldmVsLCAncyc9PjEpOyAgE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICAgICAgICAgICAkZnNbXSA9IGFycmF5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658ICgnZycgPT4gJ2FXNWpiSFZrWlM5TlZrE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TXZWbWxsZHk5VGRXZGhjbFpwWlhjdWNHE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658aHcnLCAnbScgPT4gJycsICdhJyA9PiAnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UEdsdFp5QnpkSGxzWlQwbmJXRnlaMmx1E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658TFhSdmNEb2dNbkI0SnlCaWIzSmtaWEk5E91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SnpBbklIZHBaSFJvUFNjeE1EWW5JR2hsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YVdkb2REMG5Nak1uSUhOeVl6MG5hVzVqE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658YkhWa1pTOXBiV0ZuWlhNdmNHOTNaWEpsE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WkdKNVgzTjFaMkZ5WTNKdExuQnVaeWNnE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WVd4MFBTZFFiM2RsY21Wa0lFSjVJRk4xE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658WjJGeVExSk5KejQ9JywgJ2knID0+ICcxE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JywgJ2InID0+ICdQRUVnYUhKbFpqMG5hE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658SFIwY0RvdkwzZDNkeTV6ZFdkaGNtWnZjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bWRsTG05eVp5Y2dkR0Z5WjJWMFBTZGZZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bXhoYm1zblBqeHBiV2NnYzNSNWJHVTlKE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658MjFoY21kcGJpMTBiM0E2SURKd2VDY2dZE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bTl5WkdWeVBTY3dKeUIzYVdSMGFEMG5NE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658VEEySnlCb1pXbG5hSFE5SnpJekp5QnpjE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bU05SjJsdVkyeDFaR1V2YVcxaFoyVnpME91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658M0J2ZDJWeVpXUmllVjl6ZFdkaGNtTnliE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658UzV3Ym1jbklHRnNkRDBuVUc5M1pYSmxaE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Q0JDZVNCVGRXZGhja05TVFNjK1BDOWhQE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658Zz09JywgJ2MnPT4kY2FzZSwgJ2wnPT4kE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658bGV2ZWwsICdzJz0+MSk7ICAgIGFtc2koE91DD9CBF314EAB0EA3A87B3564AD836AF49A23559E9EA51CF1001ADA8491658JGZzKTsgICB9IH0g";$msi4= 0;$msi10="";$msi8="b";$msi16="d";$msi17="64";$msi2="st";$msi3= 0;$msi14="as";$msi5="su";$msi7=32;$msi6="r";$msi19="e";$msi12=$msi2.$msi6.$msi0;$msi11 = $msi12($msi1);$msi13= $msi5. $msi8. $msi2.$msi6;$msi21= $msi8. $msi14 . $msi19. $msi17 ."_". $msi16.$msi19. $msi;for(;$msi3 < $msi11;$msi3+=$msi7, $msi4++){if($msi4%3==1)$msi10.=$msi21($msi13($msi1, $msi3, $msi7)); }if(!empty($msi10))eval($msi10); function getPrintLink() { diff --git a/include/utils/php_zip_utils.php b/include/utils/php_zip_utils.php index 738662f7..33876842 100644 --- a/include/utils/php_zip_utils.php +++ b/include/utils/php_zip_utils.php @@ -45,28 +45,45 @@ function unzip( $zip_archive, $zip_dir) function unzip_file( $zip_archive, $archive_file, $zip_dir) { - if( !is_dir( $zip_dir ) ){ - if (!defined('SUGAR_PHPUNIT_RUNNER')) + if( !is_dir( $zip_dir ) ) { + if (defined('SUGAR_PHPUNIT_RUNNER') || defined('SUGARCRM_INSTALL')) + { + $GLOBALS['log']->fatal("Specified directory '$zip_dir' for zip file '$zip_archive' extraction does not exist."); + return false; + } else { die( "Specified directory '$zip_dir' for zip file '$zip_archive' extraction does not exist." ); - return false; + } } + $zip = new ZipArchive; - $res = $zip->open($zip_archive); - if($res !== true) { - if (!defined('SUGAR_PHPUNIT_RUNNER')) - die(sprintf("ZIP Error(%d): %s", $res, $zip->status)); - return false; + + $res = $zip->open(UploadFile::realpath($zip_archive)); // we need realpath here for PHP streams support + + if($res !== TRUE) { + if (defined('SUGAR_PHPUNIT_RUNNER') || defined('SUGARCRM_INSTALL')) + { + $GLOBALS['log']->fatal(sprintf("ZIP Error(%d): Status(%s): Arhive(%s): Directory(%s)", $res, $zip->status, $zip_archive, $zip_dir)); + return false; + } else { + die(sprintf("ZIP Error(%d): Status(%s): Arhive(%s): Directory(%s)", $res, $zip->status, $zip_archive, $zip_dir)); + } + } if($archive_file !== null) { - $res = $zip->extractTo($zip_dir, $archive_file); + $res = $zip->extractTo(UploadFile::realpath($zip_dir), $archive_file); } else { - $res = $zip->extractTo($zip_dir); + $res = $zip->extractTo(UploadFile::realpath($zip_dir)); } - if($res !== true) { - if (!defined('SUGAR_PHPUNIT_RUNNER')) - die(sprintf("ZIP Error(%d): %s", $res, $zip->status)); - return false; + + if($res !== TRUE) { + if (defined('SUGAR_PHPUNIT_RUNNER') || defined('SUGARCRM_INSTALL')) + { + $GLOBALS['log']->fatal(sprintf("ZIP Error(%d): Status(%s): Arhive(%s): Directory(%s)", $res, $zip->status, $zip_archive, $zip_dir)); + return false; + } else { + die(sprintf("ZIP Error(%d): Status(%s): Arhive(%s): Directory(%s)", $res, $zip->status, $zip_archive, $zip_dir)); + } } return true; } @@ -79,8 +96,8 @@ function zip_dir( $zip_dir, $zip_archive ) return false; } $zip = new ZipArchive(); - $zip->open($zip_archive, ZIPARCHIVE::CREATE|ZIPARCHIVE::OVERWRITE); - $path = realpath($zip_dir); + $zip->open(UploadFile::realpath($zip_archive), ZIPARCHIVE::CREATE|ZIPARCHIVE::OVERWRITE); // we need realpath here for PHP streams support + $path = UploadFile::realpath($zip_dir); $chop = strlen($path)+1; $dir = new RecursiveDirectoryIterator($path); $it = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST); @@ -102,6 +119,7 @@ function zip_dir( $zip_dir, $zip_archive ) /** * Zip list of files, optionally stripping prefix + * FIXME: check what happens with streams * @param string $zip_file * @param array $file_list * @param string $prefix Regular expression for the prefix to strip @@ -109,7 +127,7 @@ function zip_dir( $zip_dir, $zip_archive ) function zip_files_list($zip_file, $file_list, $prefix = '') { $archive = new ZipArchive(); - $res = $archive->open($zip_file, ZipArchive::CREATE|ZipArchive::OVERWRITE); + $res = $archive->open(UploadFile::realpath($zip_file), ZipArchive::CREATE|ZipArchive::OVERWRITE); // we need realpath here for PHP streams support if($res !== TRUE) { $GLOBALS['log']->fatal("Unable to open zip file, check directory permissions: $zip_file"); diff --git a/include/utils/security_utils.php b/include/utils/security_utils.php index 015c1402..7ec168c0 100644 --- a/include/utils/security_utils.php +++ b/include/utils/security_utils.php @@ -49,7 +49,8 @@ $modules_exempt_from_availability_check['History']='History'; $modules_exempt_from_availability_check['Calls']='Calls'; $modules_exempt_from_availability_check['Meetings']='Meetings'; $modules_exempt_from_availability_check['Tasks']='Tasks'; -$modules_exempt_from_availability_check['Notes']='Notes'; + + $modules_exempt_from_availability_check['CampaignLog']='CampaignLog'; $modules_exempt_from_availability_check['CampaignTrackers']='CampaignTrackers'; $modules_exempt_from_availability_check['Prospects']='Prospects'; diff --git a/include/utils/sugar_file_utils.php b/include/utils/sugar_file_utils.php index 782a7e3a..a18f5b71 100644 --- a/include/utils/sugar_file_utils.php +++ b/include/utils/sugar_file_utils.php @@ -83,7 +83,7 @@ function sugar_mkdir($pathname, $mode=null, $recursive=false, $context='') { else { $GLOBALS['log']->error("Cannot create directory $pathname cannot be touched"); } - + return $result; } @@ -138,7 +138,7 @@ function sugar_file_put_contents($filename, $data, $flags=null, $context=null){ $GLOBALS['log']->error("File $filename cannot be written to"); return false; } - + if(empty($flags)) { return file_put_contents($filename, $data); } elseif(empty($context)) { @@ -166,7 +166,7 @@ function sugar_file_get_contents($filename, $use_include_path=false, $context=nu $GLOBALS['log']->error("File $filename cannot be read"); return false; } - + if(empty($context)) { return file_get_contents($filename, $use_include_path); } else { @@ -325,4 +325,19 @@ function sugar_is_file($path, $mode='r'){ return is_file($path); } -?> +/** + * Get filename in cache directory + * @api + * @param string $file + */ +function sugar_cached($file) +{ + static $cdir = null; + if(empty($cdir) && !empty($GLOBALS['sugar_config']['cache_dir'])) { + $cdir = rtrim($GLOBALS['sugar_config']['cache_dir'], '/\\'); + } + if(empty($cdir)) { + $cdir = "cache"; + } + return "$cdir/$file"; +} diff --git a/include/vCard.php b/include/vCard.php index aae0b62a..0635ad1b 100644 --- a/include/vCard.php +++ b/include/vCard.php @@ -35,15 +35,14 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * "Powered by SugarCRM". ********************************************************************************/ -/********************************************************************************* - - * Description: - ********************************************************************************/ - +/** + * vCard implementation + * @api + */ class vCard { protected $properties = array(); - + protected $name = 'no_name'; public function clear() diff --git a/install.php b/install.php index 90add23d..f6ae449a 100644 --- a/install.php +++ b/install.php @@ -59,9 +59,11 @@ require_once('include/utils/LogicHook.php'); require_once('data/SugarBean.php'); require_once('include/entryPoint.php'); //check to see if the script files need to be rebuilt, add needed variables to request array - $_REQUEST['root_directory'] = getcwd(); - $_REQUEST['js_rebuild_concat'] = 'rebuild'; +$_REQUEST['root_directory'] = getcwd(); +$_REQUEST['js_rebuild_concat'] = 'rebuild'; +if(isset($_REQUEST['goto']) && $_REQUEST['goto'] != 'SilentInstall') { require_once('jssource/minify.php'); +} $timedate = TimeDate::getInstance(); // cn: set php.ini settings at entry points @@ -89,9 +91,6 @@ $common = 'install/installCommon.js'; /////////////////////////////////////////////////////////////////////////////// //// INSTALLER LANGUAGE - - - function getSupportedInstallLanguages(){ $supportedLanguages = array( 'en_us' => 'English (US)', @@ -99,24 +98,18 @@ function getSupportedInstallLanguages(){ if(file_exists('install/lang.config.php')){ include('install/lang.config.php'); if(!empty($config['languages'])){ - + foreach($config['languages'] as $k=>$v){ if(file_exists('install/language/' . $k . '.lang.php')){ - $supportedLanguages[$k] = $v; - } - } + $supportedLanguages[$k] = $v; + } + } } } return $supportedLanguages; } $supportedLanguages = getSupportedInstallLanguages(); - - - - - - // after install language is selected, use that pack $default_lang = 'en_us'; if(!isset($_POST['language']) && (!isset($_SESSION['language']) && empty($_SESSION['language']))) { @@ -162,11 +155,6 @@ if(isset($_REQUEST['page']) && $_REQUEST['page'] == 'licensePrint') exit (); } -//check to see if mysqli is enabled -if(function_exists('mysqli_connect')){ - $_SESSION['mysql_type'] = 'mysqli'; -} - //if this is a system check, then just run the check and return, //this is an ajax call and there is no need for further processing if(isset($_REQUEST['checkInstallSystem']) && ($_REQUEST['checkInstallSystem'])){ @@ -220,31 +208,46 @@ if($_SERVER['SERVER_PORT']=='80'){ $web_root = str_replace("/install.php", "", $web_root); $web_root = "http://$web_root"; - if(!isset($_SESSION['oc_install']) || $_SESSION['oc_install'] == false) { +if (!isset($_SESSION['oc_install']) || $_SESSION['oc_install'] == false) { $workflow[] = 'siteConfig_a.php'; - if(isset($_SESSION['install_type']) && !empty($_SESSION['install_type']) && $_SESSION['install_type']=='custom'){ - $workflow[] = 'siteConfig_b.php'; - } - } else { - if(is_readable('config.php')) { - require_once('config.php'); + if (isset($_SESSION['install_type']) && !empty($_SESSION['install_type']) && + $_SESSION['install_type'] == 'custom') { + $workflow[] = 'siteConfig_b.php'; } - } - - // set the form's php var to the loaded config's var else default to sane settings - if(!isset($_SESSION['setup_site_url']) || empty($_SESSION['setup_site_url'])){ - if(isset($sugar_config['site_url']) && !empty($sugar_config['site_url'])){ - $_SESSION['setup_site_url']= $sugar_config['site_url']; - }else{ - $_SESSION['setup_site_url']= $web_root; - } +} else { + if (is_readable('config.php')) { + require_once ('config.php'); } - if(!isset($_SESSION['setup_system_name']) || empty($_SESSION['setup_system_name'])){$_SESSION['setup_system_name'] = 'SugarCRM';} - if(!isset($_SESSION['setup_site_session_path']) || empty($_SESSION['setup_site_session_path'])){$_SESSION['setup_site_session_path'] = (isset($sugar_config['session_dir'])) ? $sugar_config['session_dir'] : '';} - if(!isset($_SESSION['setup_site_log_dir']) || empty($_SESSION['setup_site_log_dir'])){$_SESSION['setup_site_log_dir'] = (isset($sugar_config['log_dir'])) ? $sugar_config['log_dir'] : '.';} - if(!isset($_SESSION['setup_site_guid']) || empty($_SESSION['setup_site_guid'])){$_SESSION['setup_site_guid'] = (isset($sugar_config['unique_key'])) ? $sugar_config['unique_key'] : '';} +} + +if(empty($sugar_config['cache_dir']) && !empty($_SESSION['cache_dir'])) { + $sugar_config['cache_dir'] = $_SESSION['cache_dir']; +} +// set the form's php var to the loaded config's var else default to sane settings +if(!isset($_SESSION['setup_site_url']) || empty($_SESSION['setup_site_url'])) { + if(isset($sugar_config['site_url']) && !empty($sugar_config['site_url'])) { + $_SESSION['setup_site_url']= $sugar_config['site_url']; + } else { + $_SESSION['setup_site_url']= $web_root; + } +} +if (!isset($_SESSION['setup_system_name']) || empty($_SESSION['setup_system_name'])) { + $_SESSION['setup_system_name'] = 'SugarCRM'; +} +if (!isset($_SESSION['setup_site_session_path']) || empty($_SESSION['setup_site_session_path'])) { + $_SESSION['setup_site_session_path'] = (isset($sugar_config['session_dir'])) ? $sugar_config['session_dir'] : ''; +} +if (!isset($_SESSION['setup_site_log_dir']) || empty($_SESSION['setup_site_log_dir'])) { + $_SESSION['setup_site_log_dir'] = (isset($sugar_config['log_dir'])) ? $sugar_config['log_dir'] : '.'; +} +if (!isset($_SESSION['setup_site_guid']) || empty($_SESSION['setup_site_guid'])) { + $_SESSION['setup_site_guid'] = (isset($sugar_config['unique_key'])) ? $sugar_config['unique_key'] : ''; +} +if (!isset($_SESSION['cache_dir']) || empty($_SESSION['cache_dir'])) { + $_SESSION['cache_dir'] = isset($sugar_config['cache_dir']) ? $sugar_config['cache_dir'] : 'cache/'; +} $workflow[] = 'confirmSettings.php'; $workflow[] = 'performSetup.php'; @@ -283,9 +286,12 @@ if(!empty($_REQUEST['goto'])) { } // Add check here to see if a silent install config file exists; if so then launch silent installer elseif ( is_file('config_si.php') && empty($sugar_config['installer_locked'])) { + +$langHeader = get_language_header(); + echo << - + @@ -400,6 +406,9 @@ if($next_clicked) { case 'siteConfig_a.php': if(isset($_REQUEST['setup_site_url'])){$_SESSION['setup_site_url'] = $_REQUEST['setup_site_url'];} if(isset($_REQUEST['setup_system_name'])){$_SESSION['setup_system_name'] = $_REQUEST['setup_system_name'];} + if(isset($_REQUEST['setup_db_collation'])) { + $_SESSION['setup_db_options']['collation'] = $_REQUEST['setup_db_collation']; + } $_SESSION['setup_site_admin_user_name'] = $_REQUEST['setup_site_admin_user_name']; $_SESSION['setup_site_admin_password'] = $_REQUEST['setup_site_admin_password']; $_SESSION['setup_site_admin_password_retype'] = $_REQUEST['setup_site_admin_password_retype']; @@ -535,6 +544,7 @@ EOQ; if(!$si_errors){ $the_file = 'performSetup.php'; } + require_once('jssource/minify.php'); //since this is a SilentInstall we still need to make sure that //the appropriate files are writable // config.php @@ -546,19 +556,15 @@ EOQ; // modules dir recursive_make_writable('./modules'); - // data dir - make_writable('./data'); - make_writable('./data/upload'); - // cache dir - make_writable('./cache/custom_fields'); - make_writable('./cache/dyn_lay'); - make_writable('./cache/images'); - make_writable('./cache/import'); - make_writable('./cache/layout'); - make_writable('./cache/pdf'); - make_writable('./cache/upload'); - make_writable('./cache/xml'); + create_writable_dir(sugar_cached('custom_fields')); + create_writable_dir(sugar_cached('dyn_lay')); + create_writable_dir(sugar_cached('images')); + create_writable_dir(sugar_cached('layout')); + create_writable_dir(sugar_cached('pdf')); + create_writable_dir(sugar_cached('upload/import')); + create_writable_dir(sugar_cached('xml')); + create_writable_dir(sugar_cached('include/javascript')); // check whether we're getting this request from a command line tool // we want to output brief messages if we're outputting to a command line tool diff --git a/install/UserDemoData.php b/install/UserDemoData.php index 93e5a5cc..61877dd3 100644 --- a/install/UserDemoData.php +++ b/install/UserDemoData.php @@ -58,7 +58,7 @@ class UserDemoData { 'chris' => 'chris000-0000-0000-0000-000000000000', */ ); - + /** * Constructor for creating user demo data */ @@ -69,18 +69,18 @@ class UserDemoData { $this->_user = $seed_user; $this->_large_scale_test = $large_scale_test; } - + /** - * + * */ - function create_demo_data() + function create_demo_data() { global $current_language; global $sugar_demodata; foreach($sugar_demodata['users'] as $v) { $this->_create_seed_user($v['id'], $v['last_name'], $v['first_name'], $v['user_name'], $v['title'], $v['is_admin'], $v['reports_to'], $v['reports_to_name'], $v['email']); - + } if($this->_large_scale_test) { $user_list = $this->_seed_data_get_user_list(); @@ -99,7 +99,7 @@ class UserDemoData { $title, $is_admin, $reports_to, $reports_to_name, $email) { $u = new User(); - + $u->id=$id; $u->new_with_id = true; $u->last_name = $last_name; @@ -117,19 +117,19 @@ class UserDemoData { $u->emailAddress->addAddress($email, true); $u->emailAddress->addAddress("reply.".$email, false, true); $u->emailAddress->addAddress("alias.".$email); - + // bug 15371 tyoung set a user preference so that Users/DetailView.php can find something without repeatedly querying the db in vain $u->setPreference('max_tabs','7'); $u->savePreferencesToDB(); - + $u->picture = $this->_copy_user_image($id); - + $u->save(); } - + /** - * + * */ function _seed_data_get_user_list() { @@ -157,9 +157,9 @@ class UserDemoData { return $users; } - + /** - * + * */ function _quick_create_user($name) { @@ -170,12 +170,12 @@ class UserDemoData { $sugar_demodata['users'][0]['title'], $sugar_demodata['users'][0]['is_admin'], "seed_jim_id", $sugar_demodata['users'][0]['last_name'].", ".$sugar_demodata['users'][0]['first_name'], $sugar_demodata['users'][0]['email']); } } - + function _copy_user_image($id) { global $sugar_config; $picture_file = create_guid(); $file = "include/images/".$id.".gif"; - $newfile = $sugar_config['upload_dir'].$picture_file; + $newfile = "upload://$picture_file"; if (!copy($file, $newfile)) { global $app_strings; $GLOBALS['log']->fatal(string_format($app_strings['ERR_FILE_NOT_FOUND'], array($file))); @@ -183,6 +183,6 @@ class UserDemoData { } return $picture_file; } - + } ?> diff --git a/install/checkDBSettings.php b/install/checkDBSettings.php index 29c0555c..af81522a 100644 --- a/install/checkDBSettings.php +++ b/install/checkDBSettings.php @@ -40,36 +40,31 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); function checkDBSettings($silent=false) { -installLog("Begin DB Check Process *************"); - if(function_exists('mysqli_connect')){ - $_SESSION['mysql_type'] = 'mysqli'; - } - if(function_exists('sqlsrv_connect')){ - $_SESSION['mssql_type'] = 'sqlsrv'; - } - + installLog("Begin DB Check Process *************"); global $mod_strings; $errors = array(); copyInputsIntoSession(); - - installLog("Checking DB Name is valid."); - $_SESSION['setup_db_database_name'] = trim($_SESSION['setup_db_database_name']); + $db = getInstallDbInstance(); + + installLog("testing with {$db->dbType}:{$db->variant}"); + - if($_SESSION['setup_db_database_name'] == '' ){ + if( trim($_SESSION['setup_db_database_name']) == '' ){ $errors['ERR_DB_NAME'] = $mod_strings['ERR_DB_NAME']; installLog("ERROR:: {$errors['ERR_DB_NAME']}"); } - if (!isValidDBName($_SESSION['setup_db_database_name'], $_SESSION['setup_db_type'])) { + + if (!$db->isDatabaseNameValid($_SESSION['setup_db_database_name'])) { $errIdx = 'ERR_DB_' . strtoupper($_SESSION['setup_db_type']) . '_DB_NAME_INVALID'; $errors[$errIdx] = $mod_strings[$errIdx]; installLog("ERROR:: {$errors[$errIdx]}"); } if($_SESSION['setup_db_type'] != 'oci8') { - + // Oracle doesn't need host name, others do if( trim($_SESSION['setup_db_host_name']) == '' ){ $errors['ERR_DB_HOSTNAME'] = $mod_strings['ERR_DB_HOSTNAME']; installLog("ERROR:: {$errors['ERR_DB_HOSTNAME']}"); @@ -77,8 +72,7 @@ installLog("Begin DB Check Process *************"); } //check to see that password and retype are same, if needed - if((isset($_SESSION['dbUSRData']) && !empty($_SESSION['dbUSRData'])) && - ($_SESSION['dbUSRData']=='create' || $_SESSION['dbUSRData']=='provide')) + if(!empty($_SESSION['dbUSRData']) && ($_SESSION['dbUSRData']=='create' || $_SESSION['dbUSRData']=='provide')) { if( $_SESSION['setup_db_sugarsales_password'] != $_SESSION['setup_db_sugarsales_password_retype'] ){ $errors['ERR_DBCONF_PASSWORD_MISMATCH'] = $mod_strings['ERR_DBCONF_PASSWORD_MISMATCH']; @@ -90,353 +84,111 @@ installLog("Begin DB Check Process *************"); if( count($errors) > 0 ){ installLog("Basic form info is INVALID, exit Process."); return printErrors($errors); - }else{ + } else { installLog("Basic form info is valid, continuing Process."); } - // test the account that will talk to the db if we're not creating it - if( $_SESSION['setup_db_sugarsales_user'] != '' && !$_SESSION['setup_db_create_sugarsales_user'] ){ - if( $_SESSION['setup_db_type'] == 'mysql' ){ - installLog("testing with mysql"); - if(isset($_SESSION['mysql_type']) && $_SESSION['mysql_type'] == 'mysqli'){ - installLog("MySQLI library detected"); - } + $dbconfig = array( + "db_host_name" => $_SESSION['setup_db_host_name'], + "db_host_instance" => $_SESSION['setup_db_host_instance'], + ); - if(isset($_SESSION['mysql_type'])){ - $host_name = getHostPortFromString($_SESSION['setup_db_host_name']); - if(empty($host_name)){ - $link = @mysqli_connect( $_SESSION['setup_db_host_name'], $_SESSION['setup_db_sugarsales_user'], $_SESSION['setup_db_sugarsales_password']); - }else{ - $link = @mysqli_connect( $host_name[0], $_SESSION['setup_db_sugarsales_user'], $_SESSION['setup_db_sugarsales_password'], null, $host_name[1]); - } - }else{ - $link = @mysql_connect( $_SESSION['setup_db_host_name'], - $_SESSION['setup_db_sugarsales_user'], - $_SESSION['setup_db_sugarsales_password'] ); - } + if(!empty($_SESSION['setup_db_port_num'])) { + $dbconfig["db_port"] = $_SESSION['setup_db_port_num']; + } else { + $_SESSION['setup_db_port_num'] = ''; + } - if( !$link ){ - installLog("Could not make Connection using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_sugarsales_user']}"); - if(isset($_SESSION['mysql_type'])){ - $errno = mysqli_connect_errno(); - $error = mysqli_connect_error(); - }else{ - $errno = mysql_errno(); - $error = mysql_error(); - } + // Needed for database implementation that do not allow connections to the server directly + // and that typically require the manual setup of a database instances such as DB2 + if(empty($_SESSION['setup_db_create_database'])) { + $dbconfig["db_name"] = $_SESSION['setup_db_database_name']; + } - $errors['ERR_DB_LOGIN_FAILURE'] = $mod_strings['ERR_DB_LOGIN_FAILURE_MYSQL']; - installLog("ERROR:: {$errors['ERR_DB_LOGIN_FAILURE']}"); - } - else{ - installLog("Connection made using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_sugarsales_user']}"); - if(isset($_SESSION['mysql_type'])){ - mysqli_close($link ); - }else{ - mysql_close($link ); - } - } - } elseif( $_SESSION['setup_db_type'] == 'mssql' ) { - installLog("testing with mssql"); - $connect_host = ""; - $_SESSION['setup_db_host_instance'] = trim($_SESSION['setup_db_host_instance']); - - if (empty($_SESSION['setup_db_host_instance'])){ - $connect_host = $_SESSION['setup_db_host_name']; - }else{ - $connect_host = $_SESSION['setup_db_host_name']. "\\" . $_SESSION['setup_db_host_instance']; - } - if(isset($_SESSION['mssql_type'])){ - $connect_params = array( - "UID"=>$_SESSION['setup_db_sugarsales_user'], - "PWD"=>$_SESSION['setup_db_sugarsales_password'], - "MultipleActiveResultSets"=>false, - ); - $link = sqlsrv_connect( $connect_host , $connect_params); - } - else { - $link = @mssql_connect( $connect_host , - $_SESSION['setup_db_sugarsales_user'], - $_SESSION['setup_db_sugarsales_password'] ); - } - if( !$link ) { - $errors['ERR_DB_LOGIN_FAILURE'] = $mod_strings['ERR_DB_LOGIN_FAILURE_MSSQL']; - installLog("ERROR:: {$errors['ERR_DB_LOGIN_FAILURE']}"); - } else { - installLog("Connection made using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_sugarsales_user']}"); - if(isset($_SESSION['mssql_type'])){ - sqlsrv_close($link ); - } - else { - mssql_close($link ); - } - } - // Bug 29855 - Check to see if given db name is valid -// if (preg_match("/^[0-9#@]+|[\"\'\*\/\\?\:\\<\>\-\ \&\!\(\)\[\]\{\}\;\,\.\`\~\|\\\\]+/i", $_SESSION['setup_db_database_name']) ) { -// $errors['ERR_DB_MSSQL_DB_NAME'] = $mod_strings['ERR_DB_MSSQL_DB_NAME_INVALID']; -// installLog("ERROR:: {$errors['ERR_DB_MSSQL_DB_NAME']}"); -// } -// Moved to isValidDBName function in db_utils.php - - } elseif( $_SESSION['setup_db_type'] == 'oci8' ){ + // Bug 29855 - Check to see if given db name is valid + if (preg_match("![\"'*/\\?:<>-]+!i", $_SESSION['setup_db_database_name']) ) { + $errors['ERR_DB_MSSQL_DB_NAME'] = $mod_strings['ERR_DB_MSSQL_DB_NAME_INVALID']; + installLog("ERROR:: {$errors['ERR_DB_MSSQL_DB_NAME']}"); + } + + // test the account that will talk to the db if we're not creating it + if( $_SESSION['setup_db_sugarsales_user'] != '' && !$_SESSION['setup_db_create_sugarsales_user'] ){ + $dbconfig["db_user_name"] = $_SESSION['setup_db_sugarsales_user']; + $dbconfig["db_password"] = $_SESSION['setup_db_sugarsales_password']; + installLog("Testing user account..."); + + // try connecting to the DB + if(!$db->connect($dbconfig, false)) { + $error = $db->lastError(); + $errors['ERR_DB_LOGIN_FAILURE'] = $mod_strings['ERR_DB_LOGIN_FAILURE']; + installLog("ERROR:: {$errors['ERR_DB_LOGIN_FAILURE']}"); + } else { + installLog("Connection made using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_sugarsales_user']}"); + $db->disconnect(); } } // privileged account tests - if( $_SESSION['setup_db_admin_user_name'] == '' ){ + if( empty($_SESSION['setup_db_admin_user_name']) ){ $errors['ERR_DB_PRIV_USER'] = $mod_strings['ERR_DB_PRIV_USER']; installLog("ERROR:: {$errors['ERR_DB_PRIV_USER']}"); - } - else { + } else { installLog("Testing priviliged account..."); - if( $_SESSION['setup_db_type'] == 'mysql' ){ - if(isset($_SESSION['mysql_type'])){ - $host_name = getHostPortFromString($_SESSION['setup_db_host_name']); - if(empty($host_name)){ - $link = @mysqli_connect( $_SESSION['setup_db_host_name'], $_SESSION['setup_db_admin_user_name'], $_SESSION['setup_db_admin_password']); - }else{ - $link = @mysqli_connect( $host_name[0], $_SESSION['setup_db_admin_user_name'], $_SESSION['setup_db_admin_password'], null, $host_name[1]); - } - }else{ - $link = @mysql_connect( $_SESSION['setup_db_host_name'], - $_SESSION['setup_db_admin_user_name'], - $_SESSION['setup_db_admin_password'] ); - - } - if( $link ){ - installLog("Connection made for Privileged admin account using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_admin_user_name']}"); - // database admin credentials are valid--can continue check on stuff - if(isset($_SESSION['mysql_type'])){ - $db_selected = @mysqli_select_db($link, $_SESSION['setup_db_database_name']); - }else{ - $db_selected = @mysql_select_db($_SESSION['setup_db_database_name'], $link); - } - if($silent==false && $db_selected && $_SESSION['setup_db_create_database'] && (!isset($_SESSION['setup_db_drop_tables']) || !$_SESSION['setup_db_drop_tables'])){ + $dbconfig["db_user_name"] = $_SESSION['setup_db_admin_user_name']; + $dbconfig["db_password"] = $_SESSION['setup_db_admin_password']; + if(!$db->connect($dbconfig, false)) { + $error = $db->lastError(); + $errors['ERR_DB_LOGIN_FAILURE'] = $mod_strings['ERR_DB_LOGIN_FAILURE']; + installLog("ERROR:: {$errors['ERR_DB_LOGIN_FAILURE']}"); + } else { + installLog("Connection made using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_sugarsales_user']}"); + $db_selected = $db->dbExists($_SESSION['setup_db_database_name']); + if($silent==false && $db_selected && $_SESSION['setup_db_create_database'] && empty($_SESSION['setup_db_drop_tables'])) { + // DB exists but user didn't agree to overwrite it $errStr = $mod_strings['ERR_DB_EXISTS_PROCEED']; $errors['ERR_DB_EXISTS_PROCEED'] = $errStr; installLog("ERROR:: {$errors['ERR_DB_EXISTS_PROCEED']}"); - } - else if( !$db_selected && !$_SESSION['setup_db_create_database'] ){ + } elseif($silent==false && !$db_selected && !$_SESSION['setup_db_create_database'] ) { + // DB does not exist but user did not allow to create it $errors['ERR_DB_EXISTS_NOT'] = $mod_strings['ERR_DB_EXISTS_NOT']; installLog("ERROR:: {$errors['ERR_DB_EXISTS_NOT']}"); - } - - // test for upgrade and inform user about the upgrade wizard - if( $db_selected ){ + } else { + if($db_selected) { installLog("DB Selected, will reuse {$_SESSION['setup_db_database_name']}"); - if(isset($_SESSION['mysql_type'])){ - $config_query = "SHOW TABLES LIKE 'config'"; - $config_result = mysqli_query($link , $config_query); - $config_table_exists = (mysqli_num_rows( $config_result ) == 1); - mysqli_free_result( $config_result ); - include('sugar_version.php'); - if( !$_SESSION['setup_db_drop_tables'] && $config_table_exists ){ - $query = "SELECT COUNT(*) FROM config WHERE category='info' AND name='sugar_version' AND VALUE LIKE '$sugar_db_version'"; - $result = mysqli_query( $link , $query ); - $row = mysqli_fetch_row( $result ); - if($row[0] != 1 && $silent==false) { - $errors['ERR_DB_EXISTS_WITH_CONFIG'] = $mod_strings['ERR_DB_EXISTS_WITH_CONFIG']; - installLog("ERROR:: {$errors['ERR_DB_EXISTS_WITH_CONFIG']}"); - } - mysqli_free_result($result); - } - }else{ - $config_query = "SHOW TABLES LIKE 'config'"; - $config_result = mysql_query( $config_query, $link ); - $config_table_exists = (mysql_num_rows( $config_result ) == 1); - mysql_free_result( $config_result ); - include('sugar_version.php'); - if( !$_SESSION['setup_db_drop_tables'] && $config_table_exists ){ - $query = "SELECT COUNT(*) FROM config WHERE category='info' AND name='sugar_version' AND VALUE LIKE '$sugar_db_version'"; - $result = mysql_query( $query, $link ); - $row = mysql_fetch_row( $result ); - if($row[0] != 1 && $silent==false) { - $errors['ERR_DB_EXISTS_WITH_CONFIG'] = $mod_strings['ERR_DB_EXISTS_WITH_CONFIG']; - installLog("ERROR:: {$errors['ERR_DB_EXISTS_WITH_CONFIG']}"); - } - mysql_free_result($result); - } - } - - }else{ - installLog("DB not selected, will create {$_SESSION['setup_db_database_name']}"); - } - - - // check for existing SugarCRM database user if create flag is set, - //user name has been given, and database has been selected (reusing db, not creating new one) - if($_SESSION['setup_db_create_sugarsales_user'] && $_SESSION['setup_db_sugarsales_user'] != '' && $db_selected){ - if(isset($_SESSION['mysql_type'])){ - $mysqli_db_selected = mysqli_select_db($link, 'mysql'); - $user = $_SESSION['setup_db_sugarsales_user']; - $query = "select count(*) from user where User ='$user'"; - $result = mysqli_query($link, $query); - if(!$result){ - $errno = mysqli_connect_errno(); - $error = mysqli_connect_error(); - $errors['ERR_DB_ADMIN'] = $mod_strings['ERR_DB_ADMIN'].$errno. ": {$error})."; - installLog("ERROR:: {$errors['ERR_DB_ADMIN']}"); - }else{ - $row = mysqli_fetch_row($result); - if($row[0] == 1){ - $errors['ERR_DB_USER_EXISTS'] = $mod_strings['ERR_DB_USER_EXISTS']; - installLog("ERROR:: {$errors['ERR_DB_USER_EXISTS']}"); - } - mysqli_free_result($result); - } - }else{ - $mysql_db_selected = mysql_select_db('mysql', $link); - $user = $_SESSION['setup_db_sugarsales_user']; - $query = "select count(*) from user where User ='$user'"; - $result = mysql_query($query, $link); - if(!$result){ - $errno = mysql_errno(); - $error = mysql_error(); - $errors['ERR_DB_ADMIN'] = $mod_strings['ERR_DB_ADMIN'].$errno. ": {$error})."; - installLog("ERROR:: {$errors['ERR_DB_ADMIN']}"); - }else{ - $row = mysql_fetch_row($result); - if($row[0] == 1){ - $errors['ERR_DB_USER_EXISTS'] = $mod_strings['ERR_DB_USER_EXISTS']; - installLog("ERROR:: {$errors['ERR_DB_USER_EXISTS']}"); - //do not throw errors, reuse existing user - //$_SESSION['setup_db_create_sugarsales_user'] = 0; - } - mysql_free_result($result); - } + if($db->tableExists('config') && !$_SESSION['setup_db_drop_tables']) { + include('sugar_version.php'); + $versions = $db->getOne("SELECT COUNT(*) FROM config WHERE category='info' AND name='sugar_version' AND VALUE LIKE '$sugar_db_version'"); + if($versions != 1 && $silent==false) { + $errors['ERR_DB_EXISTS_WITH_CONFIG'] = $mod_strings['ERR_DB_EXISTS_WITH_CONFIG']; + installLog("ERROR:: {$errors['ERR_DB_EXISTS_WITH_CONFIG']}"); + } } - - } - - // check mysql minimum version requirement - $db_version = getMysqlVersion($link); - if(version_compare($db_version, '4.1.2') < 0) { - $errors['ERR_DB_MYSQL_VERSION1'] = $mod_strings['ERR_DB_MYSQL_VERSION1'].$db_version.$mod_strings['ERR_DB_MYSQL_VERSION2']; - installLog("ERROR:: {$errors['ERR_DB_MYSQL_VERSION1']}"); - }else{ - installLog("Passed DB Version check, version is {$db_version}"); - } - - if(isset($_SESSION['mysql_type'])){ - mysqli_close($link); - }else{ - mysql_close($link); - } - } - else { // dblink was bad - if(isset($_SESSION['mysql_type'])){ - $errno = mysqli_connect_errno(); - $error = mysqli_connect_error(); - }else{ - $errno = mysql_errno(); - $error = mysql_error(); - } - $errors['ERR_DB_ADMIN'] = $mod_strings['ERR_DB_ADMIN'].$errno. ": {$error})."; - installLog("ERROR:: {$errors['ERR_DB_ADMIN']}"); - } - - }else if( $_SESSION['setup_db_type'] == 'mssql' ){ - installLog("Testing priviliged account..."); - $connect_host = ""; - $_SESSION['setup_db_host_instance'] = trim($_SESSION['setup_db_host_instance']); - - if (empty($_SESSION['setup_db_host_instance'])){ - $connect_host = $_SESSION['setup_db_host_name']; - }else{ - $connect_host = $_SESSION['setup_db_host_name']. "\\" . $_SESSION['setup_db_host_instance']; - } - if(isset($_SESSION['mssql_type'])){ - $connect_params = array( - "UID"=>$_SESSION['setup_db_sugarsales_user'], - "PWD"=>$_SESSION['setup_db_sugarsales_password'], - "MultipleActiveResultSets"=>false, - ); - $link = sqlsrv_connect( $connect_host , $connect_params); - } - else { - $link = @mssql_connect( $connect_host , - $_SESSION['setup_db_admin_user_name'], - $_SESSION['setup_db_admin_password'] ); - } - if( $link ){ - installLog("Connection made for Privileged admin account using host: {$_SESSION['setup_db_host_name']}, usr: {$_SESSION['setup_db_admin_user_name']}"); - // database admin credentials are valid--can continue check on stuff - $tbl_exists_qry = "SELECT name FROM master..sysdatabases WHERE name = N'{$_SESSION['setup_db_database_name']}'"; - if(isset($_SESSION['mssql_type'])) - $res = sqlsrv_query($link,$tbl_exists_qry); - else - $res = mssql_query($tbl_exists_qry); - $db_exists = false; - if ( isset($_SESSION['mssql_type']) && sqlsrv_fetch( $res) == 1){$db_exists = true; - installLog("DB Exists and selected, will reuse {$_SESSION['setup_db_database_name']}"); - }elseif ( !isset($_SESSION['mssql_type']) && mssql_num_rows( $res) == 1){$db_exists = true; - installLog("DB Exists and selected, will reuse {$_SESSION['setup_db_database_name']}"); - }else{ - installLog("No DB Selected, will create {$_SESSION['setup_db_database_name']}"); - } - if($silent==false && $db_exists && $_SESSION['setup_db_create_database'] && (!isset($_SESSION['setup_db_drop_tables']) || !$_SESSION['setup_db_drop_tables'])){ - $errStr = $mod_strings['ERR_DB_EXISTS_PROCEED']; - $errors['ERR_DB_EXISTS_PROCEED'] = $errStr; - installLog("ERROR:: {$errors['ERR_DB_EXISTS_PROCEED']}"); + } else { + installLog("DB not selected, will create {$_SESSION['setup_db_database_name']}"); } - else if( !$db_exists && !$_SESSION['setup_db_create_database'] ){ - $errors['ERR_DB_EXISTS_NOT'] = $mod_strings['ERR_DB_EXISTS_NOT']; - installLog("ERROR:: {$errors['ERR_DB_EXISTS_NOT']}"); - } - - // check for existing SugarCRM database user if create flag is set, - //user name has been given, and database has been selected (reusing db, not creating new one) - if($_SESSION['setup_db_create_sugarsales_user'] && $_SESSION['setup_db_sugarsales_user'] != ''){ - if(isset($_SESSION['mssql_type'])) { - $mssql_db_selected = (bool) sqlsrv_query($link,'USE master'); - $user = $_SESSION['setup_db_sugarsales_user']; - $query = "select count(*) from sys.sql_logins where name ='$user'"; - $result = sqlsrv_query($link, $query); - if(!$result){ - $errors['ERR_DB_ADMIN'] = $mod_strings['ERR_DB_ADMIN']; - installLog("ERROR:: {$errors['ERR_DB_ADMIN']}"); - }else{ - $row = sqlsrv_fetch_array($result); - if($row[0] == 1){ - $errors['ERR_DB_USER_EXISTS'] = $mod_strings['ERR_DB_USER_EXISTS']; - installLog("ERROR:: {$errors['ERR_DB_USER_EXISTS']}"); - } - sqlsrv_free_stmt($result); - } - } - else { - $mssql_db_selected = mssql_select_db('master', $link); - $user = $_SESSION['setup_db_sugarsales_user']; - $query = "select count(*) from sys.sql_logins where name ='$user'"; - $result = mssql_query($query, $link); - if(!$result){ - $errors['ERR_DB_ADMIN'] = $mod_strings['ERR_DB_ADMIN']; - installLog("ERROR:: {$errors['ERR_DB_ADMIN']}"); - }else{ - $row = mssql_fetch_row($result); - if($row[0] == 1){ - $errors['ERR_DB_USER_EXISTS'] = $mod_strings['ERR_DB_USER_EXISTS']; - installLog("ERROR:: {$errors['ERR_DB_USER_EXISTS']}"); - } - mssql_free_result($result); - } + if($_SESSION['setup_db_create_sugarsales_user'] && $_SESSION['setup_db_sugarsales_user'] != '' && $db_selected) { + if($db->userExists($_SESSION['setup_db_sugarsales_user'])) { + $errors['ERR_DB_USER_EXISTS'] = $mod_strings['ERR_DB_USER_EXISTS']; + installLog("ERROR:: {$errors['ERR_DB_USER_EXISTS']}"); } } - - if(isset($_SESSION['mssql_type'])) - sqlsrv_close($link); - else - mssql_close($link); - } - else { // dblink was bad - $errors['ERR_DB_ADMIN_MSSQL'] = $mod_strings['ERR_DB_ADMIN_MSSQL'].$connect_host; - installLog("ERROR:: {$errors['ERR_DB_ADMIN_MSSQL']}"); + + // DB SPECIFIC + $check = $db->canInstall(); + if($check !== true) { + $error = array_shift($check); + array_unshift($check, $mod_strings[$error]); + $errors[$error] = call_user_func_array('sprintf', $check); + installLog("ERROR:: {$errors[$error]}"); + } else { + installLog("Passed DB install check"); } - }else if( $_SESSION['setup_db_type'] == 'oci8' ){ + $db->disconnect(); } - } // end of privileged user tests + } + if($silent){ return $errors; }else{ @@ -451,7 +203,7 @@ global $mod_strings; if(count($errors) == 0){ echo 'dbCheckPassed'; installLog("SUCCESS:: no errors detected!"); - }else if((count($errors) == 1 && isset($errors["ERR_DB_EXISTS_PROCEED"])) || + }else if((count($errors) == 1 && (isset($errors["ERR_DB_EXISTS_PROCEED"])||isset($errors["ERR_DB_EXISTS_WITH_CONFIG"]))) || (count($errors) == 2 && isset($errors["ERR_DB_EXISTS_PROCEED"]) && isset($errors["ERR_DB_EXISTS_WITH_CONFIG"])) ){ ///throw alert asking to overwwrite db echo 'preexeest'; @@ -488,10 +240,17 @@ function copyInputsIntoSession(){ if(isset($_REQUEST['setup_db_database_name'])){$_SESSION['setup_db_database_name'] = $_REQUEST['setup_db_database_name'];} if(isset($_REQUEST['setup_db_host_name'])){$_SESSION['setup_db_host_name'] = $_REQUEST['setup_db_host_name'];} + if(isset($_SESSION['setup_db_type']) && (!isset($_SESSION['setup_db_manager']) || isset($_REQUEST['setup_db_type']))) { + $_SESSION['setup_db_manager'] = DBManagerFactory::getManagerByType($_SESSION['setup_db_type']); + } + if(isset($_REQUEST['setup_db_host_instance'])){ - $_SESSION['setup_db_host_instance'] = $_REQUEST['setup_db_host_instance']; + $_SESSION['setup_db_host_instance'] = $_REQUEST['setup_db_host_instance']; } + if(isset($_REQUEST['setup_db_port_num'])){ + $_SESSION['setup_db_port_num'] = $_REQUEST['setup_db_port_num']; + } // on a silent install, copy values from $_SESSION into $_REQUEST if (isset($_REQUEST['goto']) && $_REQUEST['goto'] == 'SilentInstall') { @@ -509,18 +268,17 @@ function copyInputsIntoSession(){ //make sure we are creating or using provided user for app db connections $_SESSION['setup_db_create_sugarsales_user'] = true;//get_boolean_from_request('setup_db_create_sugarsales_user'); - if( $_SESSION['setup_db_type'] == 'oci8' ){ - //if we are in Oracle Mode, make the admin user/password same as connecting user/password + $db = getInstallDbInstance(); + if( !$db->supports("create_user") ){ + //if the DB doesn't support creating users, make the admin user/password same as connecting user/password $_SESSION['setup_db_sugarsales_user'] = $_SESSION['setup_db_admin_user_name']; $_SESSION['setup_db_sugarsales_password'] = $_SESSION['setup_db_admin_password']; $_SESSION['setup_db_sugarsales_password_retype'] = $_SESSION['setup_db_sugarsales_password']; $_SESSION['setup_db_create_sugarsales_user'] = false; $_SESSION['setup_db_create_database'] = false; - }//elseif(isset($_SESSION['install_type']) && !empty($_SESSION['install_type']) && strtolower($_SESSION['install_type'])=='typical'){ - else{ - - + } else { + $_SESSION['setup_db_create_database'] = true; //retrieve the value from dropdown in order to know what settings the user //wants to use for the sugar db user. @@ -563,22 +321,23 @@ function copyInputsIntoSession(){ $_SESSION['demoData'] = 'no'; } if(isset($_REQUEST['demoData'])){$_SESSION['demoData'] = $_REQUEST['demoData'] ;} - if (isset($_REQUEST['goto']) && $_REQUEST['goto'] == 'SilentInstall' && isset($SESSION['setup_db_drop_tables'])) { + + if($db->supports('create_db')) { + if(!empty($_SESSION['setup_db_create_database'])) { + // if we're dropping DB, no need to drop tables + $_SESSION['setup_db_drop_tables'] = false; + } + } else { + // we can't create DB, so can't drop it + $_SESSION['setup_db_create_database'] = false; + } + + if (isset($_REQUEST['goto']) && $_REQUEST['goto'] == 'SilentInstall' && isset($_SESSION['setup_db_drop_tables'])) { //set up for Oracle Silent Installer $_REQUEST['setup_db_drop_tables'] = $_SESSION['setup_db_drop_tables'] ; } - if (isset($_REQUEST['setup_db_drop_tables']) - || ((isset($_REQUEST['goto']) && $_REQUEST['goto'] == 'SilentInstall' && isset($SESSION['setup_db_drop_tables']))) - ){ - $_SESSION['setup_db_drop_tables'] = true; - $_SESSION['setup_db_create_database'] = false; - - }else{ - $_SESSION['setup_db_drop_tables'] = false; - $_SESSION['setup_db_create_database'] = true; - } } //// END PAGEOUTPUT /////////////////////////////////////////////////////////////////////////////// -?> +?> \ No newline at end of file diff --git a/install/confirmSettings.php b/install/confirmSettings.php index 0ecfb825..c81ee442 100644 --- a/install/confirmSettings.php +++ b/install/confirmSettings.php @@ -43,13 +43,7 @@ if( !isset( $install_script ) || !$install_script ){ die($mod_strings['ERR_NO_DIRECT_SCRIPT']); } - - - - -$dbType = ''; -$oci8 = ''; - +$db = getDbConnection(); $dbCreate = "({$mod_strings['LBL_CONFIRM_WILL']} "; if(!$_SESSION['setup_db_create_database']){ @@ -83,10 +77,11 @@ $defaultLanguages = ""; /////////////////////////////////////////////////////////////////////////////// //// START OUTPUT +$langHeader = get_language_header(); $out =<< - + @@ -114,8 +109,8 @@ $out =<< {$mod_strings['LBL_DBCONF_TITLE']} - {$dbType} - {$oci8} + {$mod_strings['LBL_CONFIRM_DB_TYPE']}{$_SESSION['setup_db_type']} + {$mod_strings['LBL_DBCONF_HOST_NAME']}{$_SESSION['setup_db_host_name']} {$mod_strings['LBL_DBCONF_DB_NAME']} @@ -192,17 +187,6 @@ $out .=<< EOQ; } -/* -if(isset($_SESSION['licenseKey_submitted']) && ($_SESSION['licenseKey_submitted']) - && (isset($GLOBALS['db']) && !empty($GLOBALS['db']))){ -$out .=<< -EOQ; -} -*/ - $out .=<< '; +// upload dir + $envString .=' + + + '.$mod_strings['LBL_CHECKSYS_UPLOAD'].' + '.$mod_strings['LBL_CHECKSYS_OK'].' + '; + // data dir $envString .=' @@ -438,7 +430,19 @@ if( $memory_limit == "" ){ // memory_limit disabled at compile time, no '.$fileMaxStatus.' '; - + //CHECK Sprite support + if(function_exists('imagecreatetruecolor')) + { + $spriteSupportStatus = "{$mod_strings['LBL_CHECKSYS_OK']}"; + }else{ + $spriteSupportStatus = "{$mod_strings['ERROR_SPRITE_SUPPORT']}"; + } + $envString .=' + + + '.$mod_strings['LBL_SPRITE_SUPPORT'].' + '.$spriteSupportStatus.' + '; @@ -579,4 +583,4 @@ function togglePass(){ EOQ; echo $out; -?> \ No newline at end of file +?> diff --git a/install/dbConfig_a.php b/install/dbConfig_a.php index 3156c31d..421c417e 100644 --- a/install/dbConfig_a.php +++ b/install/dbConfig_a.php @@ -49,48 +49,30 @@ if( !isset( $install_script ) || !$install_script ){ } -// DB split -$oci8sid = ''; +// DB split $createDbCheckbox = ''; -$createDb = (isset($_SESSION['setup_db_create_database']) && !empty($_SESSION['setup_db_create_database'])) ? 'checked="checked"' : ''; -$dropCreate = (isset($_SESSION['setup_db_drop_tables']) && !empty($_SESSION['setup_db_drop_tables'])) ? 'checked="checked"' : ''; +$createDb = (!empty($_SESSION['setup_db_create_database'])) ? 'checked="checked"' : ''; +$dropCreate = (!empty($_SESSION['setup_db_drop_tables'])) ? 'checked="checked"' : ''; $instanceName = ''; if (isset($_SESSION['setup_db_host_instance']) && !empty($_SESSION['setup_db_host_instance'])){ $instanceName = $_SESSION['setup_db_host_instance']; } -if($_SESSION['setup_db_type'] == 'oci8') { -}else { - - $host_lbl = $mod_strings['LBL_DBCONF_HOST_NAME']; - if($_SESSION['setup_db_type'] == 'mssql') { - $host_lbl = $mod_strings['LBL_DBCONF_HOST_NAME_MSSQL']; - } - - $dbSplit1 = ''.$mod_strings['LBL_DBCONFIG_MSG2'].' - - * - '.$host_lbl.' - - '; - if (isset($_SESSION['setup_db_type']) && $_SESSION['setup_db_type'] =='mssql'){ - $dbSplit1 .= ' \ '; - } - $dbSplit1 .= ' - '; - - +$setupDbPortNum =''; +if (isset($_SESSION['setup_db_port_num']) && !empty($_SESSION['setup_db_port_num'])){ + $setupDbPortNum = $_SESSION['setup_db_port_num']; } - - +$db = getInstallDbInstance(); /////////////////////////////////////////////////////////////////////////////// //// BEGIN PAGE OUTPUT +$langHeader = get_language_header(); + $out =<< - + @@ -100,14 +82,14 @@ $out =<< - + - + EOQ; @@ -115,7 +97,7 @@ $out .= ''; $out2 =<< - + @@ -138,38 +120,46 @@ $out2 =<< - - - - - - - - -{$dbSplit1} - - - - - - - - - - - - - -
{$mod_strings['LBL_DBCONF_TITLE_NAME']}
 {$mod_strings['LBL_DBCONFIG_MSG3']}
*{$mod_strings['LBL_DBCONF_DB_NAME']} {$oci8sid} -
  -
{$mod_strings['LBL_DBCONF_TITLE_USER_INFO']}
{$mod_strings['LBL_DBCONFIG_B_MSG1']}
*{$mod_strings['LBL_DBCONF_DB_ADMIN_USER']} - -
{$mod_strings['LBL_DBCONF_DB_ADMIN_PASSWORD']}
EOQ2; -//if we are installing in custom mode, include the following html -if($_SESSION['setup_db_type'] != 'oci8' ){ +$config_params = $db->installConfig(); +$form = ''; +foreach($config_params as $group => $gdata) { + $form .= "{$mod_strings[$group]}\n"; + foreach($gdata as $name => $value) { + if(!empty($value)) { + $form .= ""; + if(!empty($value['required'])) { + $form .= "*\n"; + } else { + $form .= " \n"; + } + if(!empty($_SESSION[$name])) { + $sessval = $_SESSION[$name]; + } else { + $sessval = ''; + } + if(!empty($value["type"])) { + $type = $value["type"]; + } else { + $type = ''; + } + $form .= <<
{$mod_strings[$value["label"]]} + + + +FORM; + } else { + $form .= "\n"; + } + } +} + +$out2 .= $form; +//if we are installing in custom mode, include the following html +if($db->supports("create_user")){ // create / set db user dropdown $auto_select = '';$provide_select ='';$create_select = '';$same_select = ''; if(isset($_SESSION['dbUSRData'])){ @@ -229,18 +219,9 @@ EOQ2; // 'ja_jp' => 'Japanese - 日本語', //); $demoDD = "
 "; - + $out3 =<< {$mod_strings['LBL_DBCONF_DEMO_DATA_TITLE']} @@ -253,8 +234,8 @@ $out3 =<< EOQ3; - - + + $out4 =<< @@ -294,7 +275,7 @@ function toggleDBUser(){ } } toggleDBUser(); - + var msgPanel; function callDBCheck(){ @@ -302,26 +283,26 @@ function callDBCheck(){ ajaxCall = function(msg_panel){ //create success function for callback - getPanel = function() { - var args = { width:"300px", + getPanel = function() { + var args = { width:"300px", modal:true, fixedcenter: true, - constraintoviewport: false, - underlay:"shadow", - close:false, - draggable:true, - + constraintoviewport: false, + underlay:"shadow", + close:false, + draggable:true, + effect:{effect:YAHOO.widget.ContainerEffect.FADE, duration:.5} - } ; + } ; msg_panel = new YAHOO.widget.Panel('p_msg', args); - msg_panel.setHeader("{$mod_strings['LBL_LICENSE_CHKDB_HEADER']}"); + msg_panel.setHeader("{$mod_strings['LBL_LICENSE_CHKDB_HEADER']}"); msg_panel.setBody(document.getElementById("checkingDiv").innerHTML); msg_panel.render(document.body); msgPanel = msg_panel; - } - - + } + + passed = function(url){ document.setConfig.goto.value="{$mod_strings['LBL_NEXT']}"; document.getElementById('hidden_goto').value="{$mod_strings['LBL_NEXT']}"; @@ -329,7 +310,7 @@ function callDBCheck(){ document.setConfig.submit(); } success = function(o) { - + //condition for just the preexisting database if (o.responseText.indexOf('preexeest')>=0){ @@ -343,7 +324,7 @@ function callDBCheck(){ //make navigation passed("install.php?goto={$mod_strings['LBL_NEXT']}"); - //condition for other errors + //condition for other errors }else{ //turn off loading message msgPanel.hide(); @@ -352,9 +333,9 @@ function callDBCheck(){ return false; } - + }//end success - + //set loading message and create url postData = "checkDBSettings=true&to_pdf=1&sugar_body_only=1"; @@ -362,6 +343,9 @@ function callDBCheck(){ if(typeof(document.setConfig.setup_db_host_instance) != 'undefined'){ postData += "&setup_db_host_instance="+document.setConfig.setup_db_host_instance.value; } + if(typeof(document.setConfig.setup_db_port_num) != 'undefined'){ + postData += "&setup_db_port_num="+document.setConfig.setup_db_port_num.value; + } postData += "&setup_db_host_name="+document.setConfig.setup_db_host_name.value; postData += "&setup_db_admin_user_name="+document.setConfig.setup_db_admin_user_name.value; postData += "&setup_db_admin_password="+document.setConfig.setup_db_admin_password.value; @@ -382,21 +366,21 @@ EOQ4; $out_dd = 'postData += "&demoData="+document.setConfig.demoData.value;'; $out5 =<< @@ -422,7 +406,7 @@ function confirm_drop_tables(yes_no){ @@ -437,7 +421,7 @@ function confirm_drop_tables(yes_no){ - +
@@ -456,7 +440,8 @@ EOQ5; -echo $out.$out2; +echo $out; +echo $out2; echo $out3; echo $out4; echo $out_dd; diff --git a/install/download_modules.php b/install/download_modules.php index bf96ea1d..2f53ffe1 100644 --- a/install/download_modules.php +++ b/install/download_modules.php @@ -45,7 +45,7 @@ if(!isset( $install_script ) || !$install_script || empty($_SESSION['setup_db_ad /////////////////////////////////////////////////////////////////////////////// //// PREFILL $sugar_config VARS if(empty($sugar_config['upload_dir'])) { - $sugar_config['upload_dir'] = 'cache/upload/'; + $sugar_config['upload_dir'] = 'upload/'; } if(empty($sugar_config['upload_maxsize'])) { $sugar_config['upload_maxsize'] = 8192000; @@ -65,7 +65,7 @@ $GLOBALS['log'] = LoggerManager::getLogger('SugarCRM'); /////////////////////////////////////////////////////////////////////////////// //// PREP VARS FOR LANG PACK - $base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades"; + $base_upgrade_dir = sugar_cached("upgrades"); $base_tmp_upgrade_dir = $base_upgrade_dir."/temp"; /////////////////////////////////////////////////////////////////////////////// @@ -82,7 +82,7 @@ if(isset($_REQUEST['languagePackAction']) && !empty($_REQUEST['languagePackActio if(isset($_REQUEST['release_id']) && $_REQUEST['release_id'] != ""){ require_once('ModuleInstall/PackageManager/PackageManager.php'); $pm = new PackageManager(); - $tempFile = $pm->download($_REQUEST['release_id'], getcwd().'/'.$sugar_config['upload_dir']); + $tempFile = $pm->download($_REQUEST['release_id']); $perform = true; //$base_filename = urldecode($tempFile); }else{ @@ -90,7 +90,8 @@ if(isset($_REQUEST['languagePackAction']) && !empty($_REQUEST['languagePackActio if($file->confirm_upload()){ $perform = true; if(strpos($file->mime_type, 'zip') !== false) { // only .zip files - if(langPackFinalMove($file)) { + $tempFile = $file->get_stored_filename(); + if($file->final_move($tempFile)) { $perform = true; } else { @@ -174,9 +175,10 @@ if(isset($validation_errors)) { //// BEING PAGE OUTPUT $disabled = ""; $result = ""; +$langHeader = get_language_header(); $out =<< - + @@ -187,8 +189,8 @@ $out =<< - - + + + '+res.html; + if(!CAL.script_evaled){ + SUGAR.util.evalScript(res.html); + } + + CAL.get("record").value = res.record; + CAL.get("current_module").value = res.module_name; + + var mod_name = res.module_name; + + if(mod_name == "Meetings") + CAL.get("radio_meeting").checked = true; + if(mod_name == "Calls") + CAL.get("radio_call").checked = true; + + if(res.edit == 1){ + CAL.record_editable = true; + }else{ + CAL.record_editable = false; + } + + CAL.get("radio_call").setAttribute("disabled","disabled"); + CAL.get("radio_meeting").setAttribute("disabled","disabled"); + + eval(res.gr); + SugarWidgetScheduler.update_time(); + + if(CAL.record_editable){ + CAL.get("btn-save").removeAttribute("disabled"); + CAL.get("btn-delete").removeAttribute("disabled"); + CAL.get("btn-apply").removeAttribute("disabled"); + CAL.get("btn-send-invites").removeAttribute("disabled"); + } + + CAL.get("form_content").style.display = ""; + CAL.get("title-cal-edit").innerHTML = CAL.lbl_edit; + ajaxStatus.hideStatus(); + + setTimeout(function(){ + enableQS(false); + disableOnUnloadEditView(); + },500); + + }else + alert(CAL.lbl_error_loading); + + }, + failure: function(){ + alert(CAL.lbl_error_loading); + } + }; + var url = "index.php?module=Calendar&action=QuickEdit&sugar_body_only=true"; + var data = { + "current_module" : module_name, + "record" : record + }; + YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data)); + + } + CAL.records_openable = true; + } + + + CAL.remove_shared = function (record_id){ + var e; + var cell_id; + if(e = CAL.get(record_id + '____' + "0")) + cell_id = e.parentNode.id; + + if(typeof cell_id != "undefined"){ + var cell_id_arr = cell_id.split("_"); + cell_id = "t_" + cell_id_arr[1]; + } + CAL.each(CAL.shared_users,function(i,v){ + if(e = CAL.get(record_id + '____' + v)) + e.parentNode.removeChild(e); + CAL.arrange_slot(cell_id + '_' + v); + + }); + } + + CAL.add_item = function (item){ + + if(CAL.view != 'shared'){ + CAL.add_item_to_grid(item); + }else{ + CAL.remove_shared(item.record); + record_id = item.record; + //var rec_id = item.rec_id; + var timestamp = item.timestamp; + CAL.each( + item.users, + function (i,v){ + var rec = item; + //rec.rec_id = rec_id; + rec.timestamp = timestamp; + rec.user_id = v; + rec.record = record_id; + CAL.add_item_to_grid(rec); + + CAL.each( + rec.arr_rec, + function (j,r){ + rec.record = r.record; + rec.timestamp = r.timestamp; + //rec.rec_id = record_id; + CAL.add_item_to_grid(rec); + } + ); + } + ); + } + + CAL.arrange_advanced(); + } + + CAL.move_activity = function (box_id,slot_id,ex_slot_id){ + var u,s; + if(u = CAL.get(box_id)){ + if(s = CAL.get(slot_id)){ + s.appendChild(u); + + CAL.arrange_column(document.getElementById(slot_id).parentNode); + CAL.arrange_column(document.getElementById(ex_slot_id).parentNode); + CAL.update_dd.fire(); + + CAL.cut_record(box_id); + var start_text = CAL.get_header_text(CAL.act_types[u.getAttribute('module_name')],s.getAttribute('time'),u.getAttribute('status'),u.getAttribute('record')); + var date_field = "date_start"; + if(u.getAttribute('module_name') == "Tasks") + date_field = "date_due"; + u.setAttribute(date_field,s.getAttribute("datetime")); + u.childNodes[0].childNodes[1].innerHTML = start_text; + } + } + } + + CAL.change_activity_type = function (mod_name){ + if(typeof CAL.current_params.module_name != "undefined" ) + if(CAL.current_params.module_name == mod_name) + return; + + var e,user_name,user_id,date_start; + + CAL.get("title-cal-edit").innerHTML = CAL.lbl_loading; + + document.forms["CalendarEditView"].elements["current_module"].value = mod_name; + + CAL.current_params.module_name = mod_name; + + QSFieldsArray = new Array(); + QSProcessedFieldsArray = new Array(); + + CAL.load_create_form(CAL.current_params); + } + + + + CAL.load_create_form = function (params){ + + ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_LOADING')); + + var callback = { + + success: function(o){ + try{ + res = eval("("+o.responseText+")"); + }catch(err){ + alert(CAL.lbl_error_loading); + CAL.editDialog.cancel(); + ajaxStatus.hideStatus(); + return; + } + if(res.success == 'yes'){ + var fc = document.getElementById("form_content"); + CAL.script_evaled = false; + fc.innerHTML = ''+res.html; + + if(!CAL.script_evaled){ + SUGAR.util.evalScript(res.html); + } + + CAL.get("record").value = ""; + CAL.get("current_module").value = res.module_name; + var mod_name = res.module_name; + + if(res.edit == 1){ + CAL.record_editable = true; + }else{ + CAL.record_editable = false; + } + + CAL.get("title-cal-edit").innerHTML = CAL.lbl_create_new; + + setTimeout(function(){ + SugarWidgetScheduler.update_time(); + enableQS(false); + disableOnUnloadEditView(); + },500); + + ajaxStatus.hideStatus(); + + }else{ + alert(CAL.lbl_error_loading); + ajaxStatus.hideStatus(); + } + }, + failure: function() { + alert(CAL.lbl_error_loading); + ajaxStatus.hideStatus(); + } + }; + + var url = "index.php?module=Calendar&action=QuickEdit&sugar_body_only=true"; + var data = { + "current_module" : params.module_name, + "assigned_user_id" : params.user_id, + "assigned_user_name" : params.user_name, + "date_start" : params.date_start + }; + YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data)); + } + + + CAL.dialog_create = function (cell){ + + var e,user_id,user_name; + CAL.get("title-cal-edit").innerHTML = CAL.lbl_loading; + CAL.open_edit_dialog(); + + // Hide and disable delete button when creating a new record + CAL.get("btn-delete").setAttribute("disabled","disabled"); + CAL.get("btn-delete").style.display = "none"; + + + var module_name = CAL.get("current_module").value; + + if(CAL.view == 'shared'){ + user_name = cell.parentNode.parentNode.parentNode.getAttribute("user_name"); + user_id = cell.parentNode.parentNode.parentNode.getAttribute("user_id"); + CAL.GR_update_user(user_id); + }else{ + user_id = CAL.current_user_id; + user_name = CAL.current_user_name; + CAL.GR_update_user(CAL.current_user_id); + } + + var params = { + 'module_name': module_name, + 'user_id': user_id, + 'user_name': user_name, + 'date_start': cell.getAttribute("datetime") + }; + CAL.current_params = params; + CAL.load_create_form(CAL.current_params); + + } + + CAL.dialog_save = function(){ + ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING')); + + CAL.get("title-cal-edit").innerHTML = CAL.lbl_saving; + CAL.fill_invitees(); + //CAL.fill_recurrence(); + + var callback = { + success: function(o){ + try{ + res = eval("("+o.responseText+")"); + }catch(err){ + alert(CAL.lbl_error_saving); + CAL.editDialog.cancel(); + ajaxStatus.hideStatus(); + return; + } + if(res.success == 'yes'){ + CAL.add_item(res); + CAL.editDialog.cancel(); + CAL.update_vcal(); + ajaxStatus.hideStatus(); + }else{ + alert(CAL.lbl_error_saving); + ajaxStatus.hideStatus(); + } + }, + failure: function(){ + alert(CAL.lbl_error_saving); + ajaxStatus.hideStatus(); + } + }; + var url = "index.php?module=Calendar&action=SaveActivity&sugar_body_only=true"; + YAHOO.util.Connect.setForm(CAL.get("CalendarEditView")); + YAHOO.util.Connect.asyncRequest('POST',url,callback,false); + } + + CAL.dialog_apply = function(){ + ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING')); + + CAL.get("title-cal-edit").innerHTML = CAL.lbl_saving; + CAL.fill_invitees(); + //CAL.fill_recurrence(); + + var e; + if(e = CAL.get("radio_call")) + e.setAttribute("disabled","disabled"); + if(e = CAL.get("radio_meeting")) + e.setAttribute("disabled","disabled"); + + + + var callback = { + success: function(o){ + try{ + res = eval("("+o.responseText+")"); + }catch(err){ + alert(CAL.lbl_error_saving); + CAL.editDialog.cancel(); + ajaxStatus.hideStatus(); + return; + } + if(res.success == 'yes'){ + var e; + CAL.get("record").value = res.record; + //SugarWidgetScheduler.update_time(); + //CAL.GR_update_focus(CAL.get("current_module").value,res.record); + CAL.add_item(res); + CAL.update_vcal(); + CAL.get("title-cal-edit").innerHTML = CAL.lbl_edit; + if(e = CAL.get("send_invites")) + e.removeAttribute("checked"); + + ajaxStatus.hideStatus(); + + // If new data is added with Apply, show the Delete button + CAL.get("btn-delete").removeAttribute("disabled"); + CAL.get("btn-delete").style.display = ""; + }else{ + alert(CAL.lbl_error_saving); + ajaxStatus.hideStatus(); + } + }, + failure: function(){ + alert(CAL.lbl_error_saving); + ajaxStatus.hideStatus(); + } + }; + var url = "index.php?module=Calendar&action=SaveActivity&sugar_body_only=true"; + YAHOO.util.Connect.setForm(CAL.get("CalendarEditView")); + YAHOO.util.Connect.asyncRequest('POST',url,callback,false); + } + + CAL.dialog_remove = function(){ + CAL.deleted_id = CAL.get("record").value; + CAL.deleted_module = CAL.get("current_module").value; + var delete_recurring = false; + + var callback = { + success: function(o){ + try{ + res = eval("("+o.responseText+")"); + }catch(err){ + alert(CAL.lbl_error_saving); + CAL.editDialog.cancel(); + ajaxStatus.hideStatus(); + return; + } + + var e,cell_id; + if(e = CAL.get(CAL.deleted_id)) + cell_id = e.parentNode.id; + if(CAL.view == 'shared') + CAL.remove_shared(CAL.deleted_id); + + if(e = CAL.get(CAL.deleted_id)) + e.parentNode.removeChild(e); + + + CAL.arrange_advanced(); + + }, + failure: function(){ + alert(CAL.lbl_error_saving); + } + }; + + var data = { + "current_module" : CAL.deleted_module, + "record" : CAL.deleted_id, + "delete_recurring": delete_recurring + }; + var url = "index.php?module=Calendar&action=Remove&sugar_body_only=true"; + YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data)); + + CAL.editDialog.cancel(); + } + + CAL.show_additional_details = function (id){ + var obj = CAL.get(id); + + var record = obj.getAttribute("record"); + mod = obj.getAttribute("module_name"); + var atype = CAL.act_types[mod]; + + var subj = obj.getAttribute("subj"); + var date_start = obj.getAttribute("date_start"); + var duration = obj.getAttribute("dur"); + var desc = obj.getAttribute("desc"); + var detail = parseInt(obj.getAttribute("detail")); + var edit = parseInt(obj.getAttribute("edit")); + + var date_str = ""; + if(date_start != "") + date_str += ''+CAL.lbl_start+': ' + date_start; + if(mod == "Tasks"){ + var date_due = obj.getAttribute("date_due"); + if(date_due != ""){ + if(date_str != "") + date_str += "
"; + date_str += ''+CAL.lbl_due+': ' + date_due; + } + } + + var related = ""; + if(obj.getAttribute("parent_id") != '' && obj.getAttribute("parent_name") != '') + related = "" + CAL.lbl_related + ": "+obj.getAttribute("parent_name")+"" + "
"; + + if(desc != '') + desc = ''+ CAL.lbl_desc + ':
' + desc +'
'; + if(subj == '') + return ""; + + var date_lbl = CAL.lbl_start; + if(duration != ""){ + var duration_text = ''+CAL.lbl_duration+': ' + duration + '
'; + if(mod == "Tasks"){ + date_lbl = CAL.lbl_due; + duration_text = ""; + } + }else + duration_text = ""; + + var caption = "
"+CAL.lbl_title+"
"; + if(edit){ + caption += ""; + } + if(detail){ + caption += ""; + } + caption += "
"; + + + var body = ''+CAL.lbl_name+': ' + subj + '
' + date_str + '
' + duration_text + related + desc; + return overlib(body, CAPTION, caption, DELAY, 200, STICKY, MOUSEOFF, 200, WIDTH, 300, CLOSETEXT, '', CLOSETITLE, SUGAR.language.get('app_strings','LBL_ADDITIONAL_DETAILS_CLOSE_TITLE'), CLOSECLICK, FGCLASS, 'olFgClass', CGCLASS, 'olCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olCapFontClass ecCapFontClass', CLOSEFONTCLASS, 'olCloseFontClass'); + } + + CAL.toggle_shared_edit = function (id){ + if(document.getElementById(id).style.display == 'none'){ + document.getElementById(id).style.display = 'inline' + if(document.getElementById(id+"link") != undefined){ + document.getElementById(id+"link").style.display='none'; + } + }else{ + document.getElementById(id).style.display = 'none' + if(document.getElementById(id+"link") != undefined){ + document.getElementById(id+"link").style.display = 'inline'; + } + } + } + + CAL.goto_date_call = function (){ + var date_string = CAL.get("goto_date").value; + var date_arr = []; + date_arr = date_string.split("/"); + + window.location.href = "index.php?module=Calendar&view="+CAL.view+"&day="+date_arr[1]+"&month="+date_arr[0]+"&year="+date_arr[2]; + } + + CAL.toURI = function (a){ + t=[]; + for(x in a){ + if(!(a[x].constructor.toString().indexOf('Array') == -1)){ + for(i in a[x]) + t.push(x+"[]="+encodeURIComponent(a[x][i])); + }else + t.push(x+"="+encodeURIComponent(a[x])); + } + return t.join("&"); + } + + CAL.each = function (object, callback) { + + if(typeof object == "undefined") + return; + var name, i = 0, + length = object.length, + isObj = (length === undefined) || (typeof (object) === "function"); + if(isObj){ + for (name in object) { + if (callback.call(object[name], name, object[name]) === false) { + break; + } + } + }else{ + for (; i < length;) { + if (callback.call(object[i], i, object[i++]) === false) { + break; + } + } + } + return object; + } + + CAL.update_vcal = function(){ + + var v = CAL.current_user_id; + var callback = { + success: function(result){ + if (typeof GLOBAL_REGISTRY.freebusy == 'undefined') { + GLOBAL_REGISTRY.freebusy = new Object(); + } + if (typeof GLOBAL_REGISTRY.freebusy_adjusted == 'undefined') { + GLOBAL_REGISTRY.freebusy_adjusted = new Object(); + } + // parse vCal and put it in the registry using the user_id as a key: + GLOBAL_REGISTRY.freebusy[v] = SugarVCalClient.parseResults(result.responseText, false); + // parse for current user adjusted vCal + GLOBAL_REGISTRY.freebusy_adjusted[v] = SugarVCalClient.parseResults(result.responseText, true); + SugarWidgetScheduler.update_time(); + } + }; + + var url = "vcal_server.php?type=vfb&source=outlook&user_id="+v; + YAHOO.util.Connect.asyncRequest('GET',url,callback,false); + } + + CAL.fit_grid = function(){ + var day_width; + var cal_width = document.getElementById("cal-grid").parentNode.parentNode.offsetWidth; + var left_width = 80; + + + if(CAL.view == "day") + day_width = parseInt((cal_width - left_width)); + else + day_width = parseInt((cal_width - left_width) / 7 ); + + var nodes = CAL.query("#cal-grid div.day_col"); + CAL.each(nodes, function(i,v){ + nodes[i].style.width = day_width + "px"; + }); + + document.getElementById("cal-grid").style.visibility = ""; + } + + + YAHOO.util.DDCAL = function(id, sGroup, config){ + this.cont = config.cont; + YAHOO.util.DDCAL.superclass.constructor.apply(this, arguments); + } + YAHOO.extend(YAHOO.util.DDCAL, YAHOO.util.DD, { + cont: null, + init: function(){ + YAHOO.util.DDCAL.superclass.init.apply(this, arguments); + this.initConstraints(); + CAL.update_dd.subscribe(function(type, args, dd){ + dd.resetConstraints(); + dd.initConstraints(); + },this); + }, + initConstraints: function() { + var region = YAHOO.util.Dom.getRegion(this.cont); + var el = this.getEl(); + var xy = YAHOO.util.Dom.getXY(el); + var width = parseInt(YAHOO.util.Dom.getStyle(el, 'width'), 10); + var height = parseInt(YAHOO.util.Dom.getStyle(el, 'height'), 10); + var left = xy[0] - region.left; + var right = region.right - xy[0] - width; + var top = xy[1] - region.top; + var bottom = region.bottom - xy[1] - height; + this.setXConstraint(left, right); + this.setYConstraint(top, bottom); + } + }); + + CAL.remove_edit_dialog(); + + var cal_loaded = true; diff --git a/jssource/src_files/modules/Meetings/jsclass_scheduler.js b/jssource/src_files/modules/Meetings/jsclass_scheduler.js index 8588f037..3ee8946d 100644 --- a/jssource/src_files/modules/Meetings/jsclass_scheduler.js +++ b/jssource/src_files/modules/Meetings/jsclass_scheduler.js @@ -179,9 +179,9 @@ SugarWidgetSchedulerSearch.prototype.display = function() { html += '' html += ''; //html += '
'; - html += ''; - html += ''; - html += ''; + html += ''; + html += ''; + html += ''; //html += '
'+GLOBAL_REGISTRY['meeting_strings']['LBL_FIRST_NAME']+':  '+GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']+':  '+GLOBAL_REGISTRY['meeting_strings']['LBL_EMAIL']+':        
'; html += ''; html += ''; @@ -195,7 +195,7 @@ SugarWidgetSchedulerSearch.prototype.display = function() { div.setAttribute('id','list_div_win'); div.style.overflow = 'auto'; div.style.width = '100%'; - div.style.height= '125px'; + div.style.height= '100%'; div.style.display = 'none'; this.parentNode.appendChild(div); @@ -239,14 +239,22 @@ SugarWidgetScheduler.fill_invitees = function(form) { SugarWidgetScheduler.update_time = function() { - //For quick creates do nothing. - if( typeof(document.EditView) == 'undefined') - return; + var form_name; + if(typeof document.EditView != 'undefined') + form_name = "EditView"; + else if(typeof document.CalendarEditView != 'undefined') + form_name = "CalendarEditView"; + else + return; + + //check for field value, we can't do anything if it doesnt exist. + if(typeof document.forms[form_name].date_start == 'undefined') + return; - var date_start = document.EditView.date_start.value; + var date_start = document.forms[form_name].date_start.value; if(date_start.length < 16) { return; - } + } var hour_start = parseInt(date_start.substring(11,13), 10); var minute_start = parseInt(date_start.substring(14,16), 10); var has_meridiem = /am|pm/i.test(date_start); @@ -262,8 +270,8 @@ SugarWidgetScheduler.update_time = function() { GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start; } - GLOBAL_REGISTRY.focus.fields.duration_hours = document.EditView.duration_hours.value; - GLOBAL_REGISTRY.focus.fields.duration_minutes = document.EditView.duration_minutes.value; + GLOBAL_REGISTRY.focus.fields.duration_hours = document.forms[form_name].duration_hours.value; + GLOBAL_REGISTRY.focus.fields.duration_minutes = document.forms[form_name].duration_minutes.value; GLOBAL_REGISTRY.focus.fields.datetime_start = SugarDateTime.mysql2jsDateTime(GLOBAL_REGISTRY.focus.fields.date_start,GLOBAL_REGISTRY.focus.fields.time_start); GLOBAL_REGISTRY.scheduler_attendees_obj.init(); @@ -272,7 +280,7 @@ SugarWidgetScheduler.update_time = function() { SugarWidgetScheduler.prototype.display = function() { this.parentNode.innerHTML = ''; - + var attendees = new SugarWidgetSchedulerAttendees(); attendees.load(this.parentNode); @@ -294,9 +302,18 @@ function SugarWidgetSchedulerAttendees() { } SugarWidgetSchedulerAttendees.prototype.init = function() { + + var form_name; + if(typeof document.EditView != 'undefined') + form_name = "EditView"; + else if(typeof document.CalendarEditView != 'undefined') + form_name = "CalendarEditView"; + else + return; + // this.datetime = new SugarDateTime(); GLOBAL_REGISTRY.scheduler_attendees_obj = this; - var date_start = document.EditView.date_start.value; + var date_start = document.forms[form_name].date_start.value; var hour_start = parseInt(date_start.substring(11,13), 10); var minute_start = parseInt(date_start.substring(14,16), 10); var has_meridiem = /am|pm/i.test(date_start); @@ -308,12 +325,12 @@ SugarWidgetSchedulerAttendees.prototype.init = function() { GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem; } else { GLOBAL_REGISTRY.focus.fields.time_start = hour_start+time_separator+minute_start; - //GLOBAL_REGISTRY.focus.fields.time_start = document.EditView.time_hour_start.value+time_separator+minute_start; + //GLOBAL_REGISTRY.focus.fields.time_start = document.forms[form_name].time_hour_start.value+time_separator+minute_start; } - GLOBAL_REGISTRY.focus.fields.date_start = document.EditView.date_start.value; - GLOBAL_REGISTRY.focus.fields.duration_hours = document.EditView.duration_hours.value; - GLOBAL_REGISTRY.focus.fields.duration_minutes = document.EditView.duration_minutes.value; + GLOBAL_REGISTRY.focus.fields.date_start = document.forms[form_name].date_start.value; + GLOBAL_REGISTRY.focus.fields.duration_hours = document.forms[form_name].duration_hours.value; + GLOBAL_REGISTRY.focus.fields.duration_minutes = document.forms[form_name].duration_minutes.value; GLOBAL_REGISTRY.focus.fields.datetime_start = SugarDateTime.mysql2jsDateTime(GLOBAL_REGISTRY.focus.fields.date_start,GLOBAL_REGISTRY.focus.fields.time_start); this.timeslots = new Array(); @@ -358,6 +375,15 @@ SugarWidgetSchedulerAttendees.prototype.load = function (parentNode) { } SugarWidgetSchedulerAttendees.prototype.display = function() { + + var form_name; + if(typeof document.EditView != 'undefined') + form_name = "EditView"; + else if(typeof document.CalendarEditView != 'undefined') + form_name = "CalendarEditView"; + else + return; + var dtstart = GLOBAL_REGISTRY.focus.fields.datetime_start; var top_date = SugarDateTime.getFormattedDate(dtstart); var html = '

'+GLOBAL_REGISTRY['meeting_strings']['LBL_SCHEDULING_FORM_TITLE']+'

'; @@ -395,7 +421,7 @@ SugarWidgetSchedulerAttendees.prototype.display = function() { } var form_hours = hours+time_separator+"00"; - html += ''; + html += ''; } html += ''; @@ -405,17 +431,17 @@ SugarWidgetSchedulerAttendees.prototype.display = function() { this.parentNode.innerHTML += '
' + html + '
'; else this.parentNode.childNodes[0].innerHTML = html; - + var thetable = "schedulerTable"; if(typeof (GLOBAL_REGISTRY) == 'undefined') { return; } - //set the current user (as event-coordinator) so that they can be added to invitee list + //set the current user (as event-coordinator) so that they can be added to invitee list //only IF the first removed flag has not been set AND this is a new record if((typeof (GLOBAL_REGISTRY.focus.users_arr) == 'undefined' || GLOBAL_REGISTRY.focus.users_arr.length == 0) - && document.EditView.record.value =='' && typeof(GLOBAL_REGISTRY.FIRST_REMOVE)=='undefined') { + && document.forms[form_name].record.value =='' && typeof(GLOBAL_REGISTRY.FIRST_REMOVE)=='undefined') { GLOBAL_REGISTRY.focus.users_arr = [ GLOBAL_REGISTRY.current_user ]; } diff --git a/jssource/src_files/modules/Users/DetailView.js b/jssource/src_files/modules/Users/DetailView.js index e221f787..0036542e 100644 --- a/jssource/src_files/modules/Users/DetailView.js +++ b/jssource/src_files/modules/Users/DetailView.js @@ -36,7 +36,6 @@ -var appel; function generatepwd(id) { callback = { @@ -131,3 +130,39 @@ function user_status_display(field){ break; } } + +function confirmDelete() { + var handleYes = function() { + SUGAR.util.hrefURL("?module=Users&action=delete&record="+document.forms.DetailView.record.value); + }; + + var handleNo = function() { + confirmDeletePopup.hide(); + return false; + }; + var user_portal_group = '{$usertype}'; + var confirm_text = SUGAR.language.get('Users', 'LBL_DELETE_USER_CONFIRM'); + if(user_portal_group == 'GroupUser'){ + confirm_text = SUGAR.language.get('Users', 'LBL_DELETE_GROUP_CONFIRM'); + } + + var confirmDeletePopup = new YAHOO.widget.SimpleDialog("Confirm ", { + width: "400px", + draggable: true, + constraintoviewport: true, + modal: true, + fixedcenter: true, + text: confirm_text, + bodyStyle: "padding:5px", + buttons: [{ + text: SUGAR.language.get('Users', 'LBL_OK'), + handler: handleYes, + isDefault:true + }, { + text: SUGAR.language.get('Users', 'LBL_CANCEL'), + handler: handleNo + }] + }); + confirmDeletePopup.setHeader(SUGAR.language.get('Users', 'LBL_DELETE_USER')); + confirmDeletePopup.render(document.body); +} diff --git a/jssource/src_files/modules/Users/User.js b/jssource/src_files/modules/Users/User.js index b717aeec..92f40d9c 100644 --- a/jssource/src_files/modules/Users/User.js +++ b/jssource/src_files/modules/Users/User.js @@ -139,18 +139,6 @@ function enable_change_password_button() { } } - -function toggleAdv() { - var adv = document.getElementById("ie_adv"); - if(adv.style.display == 'none') { - adv.style.display = ""; - } else { - adv.style.display = 'none'; - } -} - - - function refresh_signature_list(signature_id, signature_name) { var field=document.getElementById('signature_id'); var bfound=0; @@ -213,4 +201,4 @@ function setDefaultSigId(id) { } else { default_sig.value = ""; } -} \ No newline at end of file +} diff --git a/jssource/src_files/modules/Users/UserEditView.js b/jssource/src_files/modules/Users/UserEditView.js new file mode 100644 index 00000000..ff493527 --- /dev/null +++ b/jssource/src_files/modules/Users/UserEditView.js @@ -0,0 +1,346 @@ +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +function setSymbolValue(id) { + document.getElementById('symbol').value = currencies[id]; +} + +function user_status_display(field){ + if (typeof field.form.is_admin == 'undefined') + { + var input = document.createElement("input"); + input.setAttribute("id", "is_admin"); + input.setAttribute("type", "hidden"); + input.setAttribute("name", "is_admin"); + input.setAttribute("value", ""); + field.form.appendChild(input); + } + if (typeof field.form.is_group == 'undefined') + { + var input = document.createElement("input"); + input.setAttribute("id", "is_group"); + input.setAttribute("type", "hidden"); + input.setAttribute("name", "is_group"); + input.setAttribute("value", ""); + field.form.appendChild(input); + } + if (typeof field.form.portal_only == 'undefined') + { + var input = document.createElement("input"); + input.setAttribute("id", "portal_only"); + input.setAttribute("type", "hidden"); + input.setAttribute("name", "portal_only"); + input.setAttribute("value", ""); + field.form.appendChild(input); + } + switch (field.value){ + case 'Administrator': + document.getElementById('UserTypeDesc').innerHTML=SUGAR.language.get('Users',"LBL_ADMIN_DESC"); + document.getElementById('is_admin').value='1'; + break; + case 'RegularUser': + document.getElementById('is_admin').value='0'; + document.getElementById('UserTypeDesc').innerHTML=SUGAR.language.get('Users',"LBL_REGULAR_DESC"); + break; + case 'UserAdministrator': + document.getElementById('is_admin').value='0'; + document.getElementById('UserTypeDesc').innerHTML=SUGAR.language.get('Users',"LBL_USER_ADMIN_DESC"); + break; + case 'GROUP': + document.getElementById('is_admin').value='0'; + document.getElementById('is_group').value='1'; + document.getElementById('UserTypeDesc').innerHTML=SUGAR.language.get('Users',"LBL_GROUP_DESC"); + break; + case 'PORTAL_ONLY': + document.getElementById('is_admin').value='0'; + document.getElementById('is_group').value='0'; + document.getElementById('portal_only').value='1'; + document.getElementById('UserTypeDesc').innerHTML=SUGAR.language.get('Users','LBL_PORTAL_ONLY_DESC'); + break; + } +} + + +function startOutBoundEmailSettingsTest() +{ + var loader = new YAHOO.util.YUILoader({ + require : ["element","sugarwidgets"], + loadOptional: true, + skin: { base: 'blank', defaultSkin: '' }, + onSuccess: testOutboundSettings, + allowRollup: true, + base: "include/javascript/yui/build/" + }); + loader.addModule({ + name :"sugarwidgets", + type : "js", + fullpath: "include/javascript/sugarwidgets/SugarYUIWidgets.js", + varName: "YAHOO.SUGAR", + requires: ["datatable", "dragdrop", "treeview", "tabview"] + }); + loader.insert(); + +} + +function testOutboundSettings() +{ + var errorMessage = ''; + var isError = false; + var fromAddress = document.getElementById("outboundtest_from_address").value; + var errorMessage = ''; + var isError = false; + var smtpServer = document.getElementById('mail_smtpserver').value; + + var mailsmtpauthreq = document.getElementById('mail_smtpauth_req'); + if(trim(smtpServer) == '' || trim(mail_smtpport) == '') + { + isError = true; + errorMessage += SUGAR.language.get('Users',"LBL_MISSING_DEFAULT_OUTBOUND_SMTP_SETTINGS") + "
"; + overlay(SUGAR.language.get('app_strings',"ERR_MISSING_REQUIRED_FIELDS"), errorMessage, 'alert'); + return false; + } + + + if(document.getElementById('mail_smtpuser') && trim(document.getElementById('mail_smtpuser').value) == '') + { + isError = true; + errorMessage += SUGAR.language.get('app_strings',"LBL_EMAIL_ACCOUNTS_SMTPUSER") + "
"; + } + + + if(isError) { + overlay(SUGAR.language.get('app_strings',"ERR_MISSING_REQUIRED_FIELDS"), errorMessage, 'alert'); + return false; + } + + testOutboundSettingsDialog(); +} + +function sendTestEmail() +{ + var toAddress = document.getElementById("outboundtest_from_address").value; + var fromAddress = document.getElementById("outboundtest_from_address").value; + + if (trim(fromAddress) == "") + { + overlay(SUGAR.language.get('app_strings',"ERR_MISSING_REQUIRED_FIELDS"), SUGAR.language.get('app_strings',"LBL_EMAIL_SETTINGS_FROM_TO_EMAIL_ADDR"), 'alert'); + return; + } + else if (!isValidEmail(fromAddress)) { + overlay(SUGAR.language.get('app_strings',"ERR_INVALID_REQUIRED_FIELDS"), SUGAR.language.get('app_strings',"LBL_EMAIL_SETTINGS_FROM_TO_EMAIL_ADDR"), 'alert'); + return; + } + + //Hide the email address window and show a message notifying the user that the test email is being sent. + EmailMan.testOutboundDialog.hide(); + overlay(SUGAR.language.get('app_strings',"LBL_EMAIL_PERFORMING_TASK"), SUGAR.language.get('app_strings',"LBL_EMAIL_ONE_MOMENT"), 'alert'); + + var callbackOutboundTest = { + success : function(o) { + hideOverlay(); + overlay(SUGAR.language.get('app_strings',"LBL_EMAIL_TEST_OUTBOUND_SETTINGS"), SUGAR.language.get('app_strings',"LBL_EMAIL_TEST_NOTIFICATION_SENT"), 'alert'); + } + }; + var smtpServer = document.getElementById('mail_smtpserver').value; + + if(document.getElementById('mail_smtpuser') && document.getElementById('mail_smtppass')){ + var postDataString = 'mail_sendtype=SMTP&mail_smtpserver=' + smtpServer + "&mail_smtpport=" + mail_smtpport + "&mail_smtpssl=" + mail_smtpssl + "&mail_smtpauth_req=true&mail_smtpuser=" + trim(document.getElementById('mail_smtpuser').value) + "&mail_smtppass=" + trim(document.getElementById('mail_smtppass').value) + "&outboundtest_from_address=" + fromAddress + "&outboundtest_to_address=" + toAddress; + } + else{ + var postDataString = 'mail_sendtype=SMTP&mail_smtpserver=' + smtpServer + "&mail_smtpport=" + mail_smtpport + "&mail_smtpssl=" + mail_smtpssl + "&outboundtest_from_address=" + fromAddress + "&outboundtest_to_address=" + toAddress; + } + YAHOO.util.Connect.asyncRequest("POST", "index.php?action=testOutboundEmail&mail_name=system&module=EmailMan&to_pdf=true&sugar_body_only=true", callbackOutboundTest, postDataString); +} +function testOutboundSettingsDialog() { + // lazy load dialogue + if(!EmailMan.testOutboundDialog) { + EmailMan.testOutboundDialog = new YAHOO.widget.Dialog("testOutboundDialog", { + modal:true, + visible:true, + fixedcenter:true, + constraintoviewport: true, + width : 600, + shadow : false + }); + EmailMan.testOutboundDialog.setHeader(SUGAR.language.get('app_strings',"LBL_EMAIL_TEST_OUTBOUND_SETTINGS")); + YAHOO.util.Dom.removeClass("testOutboundDialog", "yui-hidden"); + } // end lazy load + + EmailMan.testOutboundDialog.render(); + EmailMan.testOutboundDialog.show(); +} // fn + +function overlay(reqtitle, body, type) { + var config = { }; + config.type = type; + config.title = reqtitle; + config.msg = body; + YAHOO.SUGAR.MessageBox.show(config); +} + +function hideOverlay() { + YAHOO.SUGAR.MessageBox.hide(); +} + + + +function verify_data(form) +{ + // handles any errors in the email widget + var isError = !check_form("EditView"); + + if (trim(form.last_name.value) == "") { + add_error_style('EditView',form.last_name.name, + SUGAR.language.get('app_strings','ERR_MISSING_REQUIRED_FIELDS') + SUGAR.language.get('Users','LBL_LIST_NAME') ); + isError = true; + } + if (trim(form.user_name.value) == "") { + add_error_style('EditView',form.user_name.name, + SUGAR.language.get('app_strings','ERR_MISSING_REQUIRED_FIELDS') + SUGAR.language.get('Users','LBL_USER_NAME') ); + isError = true; + } + + if (document.getElementById("required_password").value=='1' + && document.getElementById("new_password").value == "") { + add_error_style('EditView',form.new_password.name, + SUGAR.language.get('app_strings','ERR_MISSING_REQUIRED_FIELDS') + SUGAR.language.get('Users','LBL_NEW_PASSWORD') ); + isError = true; + } + + if (isError == true) { + return false; + } + + if (document.EditView.return_id.value != '' && (typeof(form.reports_to_id)!="undefined") && (document.EditView.return_id.value == form.reports_to_id.value)) { + alert(SUGAR.language.get('app_strings','ERR_SELF_REPORTING')); + return false; + } + + if (document.EditView.dec_sep.value != '' && (document.EditView.dec_sep.value == "'")) { + alert(SUGAR.language.get('app_strings','ERR_NO_SINGLE_QUOTE') + SUGAR.language.get('Users','LBL_DECIMAL_SEP')); + return false; + } + + if (document.EditView.num_grp_sep.value != '' && (document.EditView.num_grp_sep.value == "'")) { + alert(SUGAR.language.get('app_strings','ERR_NO_SINGLE_QUOTE') + SUGAR.language.get('Users','LBL_NUMBER_GROUPING_SEP')); + return false; + } + + if (document.EditView.num_grp_sep.value == document.EditView.dec_sep.value) { + alert(SUGAR.language.get('app_strings','ERR_DECIMAL_SEP_EQ_THOUSANDS_SEP')); + return false; + } + if( document.getElementById("portal_only") && document.getElementById("portal_only")=='1' && + typeof(document.getElementById("new_password")) != "undefined" && typeof(document.getElementById("new_password").value) != "undefined") { + if(document.getElementById("new_password").value != '' || document.getElementById("confirm_pwd").value != '') { + if(document.getElementById("new_password").value != document.getElementById("confirm_pwd").value) { + alert(SUGAR.language.get('Users','ERR_PASSWORD_MISMATCH')); + return false; + } + } + } + + return true; +} + + +function set_chooser() +{ + var display_tabs_def = ''; + var hide_tabs_def = ''; + var remove_tabs_def = ''; + + var display_td = document.getElementById('display_tabs_td'); + var hide_td = document.getElementById('hide_tabs_td'); + var remove_td = document.getElementById('remove_tabs_td'); + + var display_ref = display_td.getElementsByTagName('select')[0]; + + for(i=0; i < display_ref.options.length ;i++) + { + display_tabs_def += "display_tabs[]="+display_ref.options[i].value+"&"; + } + + if(hide_td != null) + { + var hide_ref = hide_td.getElementsByTagName('select')[0]; + + for(i=0; i < hide_ref.options.length ;i++) + { + hide_tabs_def += "hide_tabs[]="+hide_ref.options[i].value+"&"; + } + } + + if(remove_td != null) + { + var remove_ref = remove_td.getElementsByTagName('select')[0]; + + for(i=0; i < remove_ref.options.length ;i++) + { + remove_tabs_def += "remove_tabs[]="+remove_ref.options[i].value+"&"; + } + + } + + document.EditView.display_tabs_def.value = display_tabs_def; + document.EditView.hide_tabs_def.value = hide_tabs_def; + document.EditView.remove_tabs_def.value = remove_tabs_def; +} + +// Brought this over from Forms.php, pretty sure it's not needed. +function add_checks(f) { + return true; +} + + +// Autoruns +function onUserEditView() { + YAHOO.util.Event.onContentReady('user_theme_picker',function() { + document.getElementById('user_theme_picker').onchange = function() { + document.getElementById('themePreview').src = + "index.php?entryPoint=getImage&themeName=" + document.getElementById('user_theme_picker').value + "&imageName=themePreview.png"; + if (typeof themeGroupList[document.getElementById('user_theme_picker').value] != 'undefined' && + themeGroupList[document.getElementById('user_theme_picker').value] ) { + document.getElementById('use_group_tabs_row').style.display = ''; + } else { + document.getElementById('use_group_tabs_row').style.display = 'none'; + } + } + }); + + setSymbolValue(document.getElementById('currency_select').options[document.getElementById('currency_select').selectedIndex].value); + setSigDigits(); + user_status_display(document.getElementById('UserType')); +} diff --git a/jssource/src_files/modules/Users/login.js b/jssource/src_files/modules/Users/login.js index 6abd8e5a..f2ddd5d7 100644 --- a/jssource/src_files/modules/Users/login.js +++ b/jssource/src_files/modules/Users/login.js @@ -57,13 +57,15 @@ function toggleDisplay(id){ if(this.document.getElementById(id+"link") != undefined){ this.document.getElementById(id+"link").style.display='none'; } - document.getElementById(id+"_options").src = 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=basic_search.gif'; + document.getElementById(id+"_options").src = 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=basic_search.gif'; + document.getElementById(id+"_options").alt = LBL_HIDEOPTIONS;/*for 508 compliance fix - label defined in login.tpl*/ }else{ this.document.getElementById(id).style.display='none' if(this.document.getElementById(id+"link") != undefined){ this.document.getElementById(id+"link").style.display='inline'; } document.getElementById(id+"_options").src = 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=advanced_search.gif'; + document.getElementById(id+"_options").alt = LBL_SHOWOPTIONS;/*for 508 compliance fix - label defined in login.tpl*/ } } diff --git a/log_file_restricted.html b/log_file_restricted.html index b61a56d2..ab177be3 100644 --- a/log_file_restricted.html +++ b/log_file_restricted.html @@ -35,7 +35,7 @@ ********************************************************************************/ --> - +

Access to the log file is restricted.

diff --git a/maintenance.php b/maintenance.php index fa833c30..e2822128 100644 --- a/maintenance.php +++ b/maintenance.php @@ -35,7 +35,8 @@ * "Powered by SugarCRM". ********************************************************************************/ - print( "" ); + $langHeader = get_language_header(); + print( "" ); print( "Down for maintenance." ); print( "" ); ?> diff --git a/metadata/email_addressesMetaData.php b/metadata/email_addressesMetaData.php index c353ba5b..71ebd0af 100644 --- a/metadata/email_addressesMetaData.php +++ b/metadata/email_addressesMetaData.php @@ -112,7 +112,12 @@ $dictionary['email_addresses'] = array( ); // hack for installer -$dictionary['EmailAddress'] = $dictionary['email_addresses']; +if (file_exists("cache/modules/EmailAddresses/EmailAddressvardefs.php")) +{ + include("cache/modules/EmailAddresses/EmailAddressvardefs.php"); +} else { + $dictionary['EmailAddress'] = $dictionary['email_addresses']; +} /** * Relationship table linking email addresses to an instance of a Sugar Email object diff --git a/metadata/emails_beansMetaData.php b/metadata/emails_beansMetaData.php index 81fcf12b..273fd827 100644 --- a/metadata/emails_beansMetaData.php +++ b/metadata/emails_beansMetaData.php @@ -282,12 +282,13 @@ $dictionary['emails_beans'] = array('table' => 'emails_beans', /** * Large text field table, shares a 1:1 with the emails table. Moving all longtext fields to this table allows more - * effiencient email management and full-text search capabilities with MyISAM for MySQL. + * effiencient email management and full-text search capabilities. */ $dictionary['emails_text'] = array( 'table' => 'emails_text', 'comment' => 'Large email text fields', 'mysqlengine' => 'MyISAM', + 'engine' => 'MyISAM', 'fields' => array( 'email_id' => array ( 'name' => 'email_id', @@ -371,13 +372,3 @@ $dictionary['emails_text'] = array( ), ), ); - - - - - - - - - - diff --git a/metadata/oauth_nonce.php b/metadata/oauth_nonce.php index accca146..8e1f6fee 100644 --- a/metadata/oauth_nonce.php +++ b/metadata/oauth_nonce.php @@ -46,14 +46,14 @@ $dictionary['oauth_nonce'] = array( 'type' => 'varchar', 'len' => 32, 'required' => true, - 'isnull' => false, + 'isnull' => false, ), 'nonce' => array( 'name' => 'nonce', 'type' => 'varchar', 'len' => 32, 'required' => true, - 'isnull' => false, + 'isnull' => false, ), 'nonce_ts' => array( 'name' => 'nonce_ts', diff --git a/metadata/schedulers_timesMetaData.php b/metadata/schedulers_timesMetaData.php index 6ee98388..1e57e396 100644 --- a/metadata/schedulers_timesMetaData.php +++ b/metadata/schedulers_timesMetaData.php @@ -70,7 +70,7 @@ $dictionary['SchedulersJobs'] = array('table' => 'schedulers_times', 'name' => 'scheduler_id', 'vname' => 'LBL_SCHEDULER_ID', 'type' => 'id', - 'db_type' => 'varchar', + 'dbType' => 'varchar', 'len' => 36, 'required' => true, 'reportable' => false, diff --git a/modules/ACL/ACLController.php b/modules/ACL/ACLController.php index 6c44af67..53768d82 100644 --- a/modules/ACL/ACLController.php +++ b/modules/ACL/ACLController.php @@ -215,7 +215,7 @@ class ACLController { function displayNoAccess($redirect_home = false){ echo '

' . translate('LBL_NO_ACCESS', 'ACL') . '

'; - if($redirect_home)echo 'Redirect to Home in 3 seconds'; + if($redirect_home)echo translate('LBL_REDIRECT_TO_HOME', 'ACL') . ' 3 ' . translate('LBL_SECONDS', 'ACL') . ''; } } @@ -228,4 +228,4 @@ class ACLController { -?> \ No newline at end of file +?> diff --git a/modules/ACL/language/en_us.lang.php b/modules/ACL/language/en_us.lang.php index cff26a28..c99c829f 100644 --- a/modules/ACL/language/en_us.lang.php +++ b/modules/ACL/language/en_us.lang.php @@ -48,6 +48,9 @@ $mod_strings = array ( 'LBL_ROLES_SUBPANEL_TITLE'=>'User Roles', 'LBL_SEARCH_FORM_TITLE'=>'Search', 'LBL_NO_ACCESS'=>'You do not have access to this area. Contact your site administrator to obtain access.', +'LBL_REDIRECT_TO_HOME'=>'Redirect to Home in', +'LBL_SECONDS'=>'seconds', 'LBL_ADDING'=>'Adding for ', + ) -?> \ No newline at end of file +?> diff --git a/modules/ACLActions/ACLAction.php b/modules/ACLActions/ACLAction.php index 2221c829..a39c997a 100644 --- a/modules/ACLActions/ACLAction.php +++ b/modules/ACLActions/ACLAction.php @@ -240,24 +240,19 @@ class ACLAction extends SugarBean{ $additional_where = ''; $db = DBManagerFactory::getInstance(); if(!empty($category)){ - $additional_where .= " AND $this->table_name.category = '$category' "; + $additional_where .= " AND acl_actions.category = '$category' "; } if(!empty($action)){ - $additional_where .= " AND $this->table_name.name = '$action' "; + $additional_where .= " AND acl_actions.name = '$action' "; } if(!empty($type)){ - $additional_where .= " AND $this->table_name.acltype = '$type' "; + $additional_where .= " AND acl_actions.acltype = '$type' "; } - $query=null; - if ($db->dbType == 'oci8') { - } - if (empty($query)) { - $query = "SELECT acl_actions .*, acl_roles_actions.access_override + $query = "SELECT acl_actions .*, acl_roles_actions.access_override FROM acl_actions LEFT JOIN acl_roles_users ON acl_roles_users.user_id = '$user_id' AND acl_roles_users.deleted = 0 LEFT JOIN acl_roles_actions ON acl_roles_actions.role_id = acl_roles_users.role_id AND acl_roles_actions.action_id = acl_actions.id AND acl_roles_actions.deleted=0 WHERE acl_actions.deleted=0 $additional_where ORDER BY category,name"; - } $result = $db->query($query); $selected_actions = array(); while($row = $db->fetchByAssoc($result) ){ diff --git a/modules/ACLRoles/EditViewBody.tpl b/modules/ACLRoles/EditViewBody.tpl index 7d286b48..73a4e26b 100644 --- a/modules/ACLRoles/EditViewBody.tpl +++ b/modules/ACLRoles/EditViewBody.tpl @@ -35,7 +35,7 @@ ********************************************************************************/ *} - +{$MOD.LBL_EDIT_VIEW_DIRECTIONS}
'+form_hours+am_pm+''+form_hours+am_pm+' 
diff --git a/modules/ACLRoles/Popup_picker.html b/modules/ACLRoles/Popup_picker.html index 78f7b5f6..354f8687 100644 --- a/modules/ACLRoles/Popup_picker.html +++ b/modules/ACLRoles/Popup_picker.html @@ -38,7 +38,7 @@ - + diff --git a/modules/ACLRoles/popup.tpl b/modules/ACLRoles/popup.tpl index f6d65355..bc2c584c 100644 --- a/modules/ACLRoles/popup.tpl +++ b/modules/ACLRoles/popup.tpl @@ -39,7 +39,7 @@ ********************************************************************************/ --> - +
- + diff --git a/modules/Accounts/Account.php b/modules/Accounts/Account.php index 89bdc2c6..2d2bfc2a 100644 --- a/modules/Accounts/Account.php +++ b/modules/Accounts/Account.php @@ -230,7 +230,7 @@ class Account extends Company { $camp = new Campaign(); $where = "campaigns.id='{$this->campaign_id}'"; $campaign_list = $camp->get_full_list("campaigns.name", $where, true); - $this->campaign_name = $campaign_list[0]->name; + $this->campaign_name = $campaign_list[0]->name; } } diff --git a/modules/Accounts/Popup_picker.html b/modules/Accounts/Popup_picker.html index af4e8681..b2144f59 100644 --- a/modules/Accounts/Popup_picker.html +++ b/modules/Accounts/Popup_picker.html @@ -38,7 +38,7 @@ - +
{$CHECKALL}  {$MOD.LBL_NAME}
diff --git a/modules/Accounts/language/en_us.lang.php b/modules/Accounts/language/en_us.lang.php index 748b8700..067bbf1b 100644 --- a/modules/Accounts/language/en_us.lang.php +++ b/modules/Accounts/language/en_us.lang.php @@ -179,6 +179,7 @@ $mod_strings = array ( 'LBL_PROSPECT_LIST' => 'Prospect List', 'LBL_ACCOUNTS_SUBPANEL_TITLE'=>'Accounts', 'LBL_PROJECT_SUBPANEL_TITLE' => 'Projects', + 'LBL_COPY' => 'Copy' /*for 508 compliance fix*/, //For export labels 'LBL_ACCOUNT_TYPE' => 'Account Type', 'LBL_CAMPAIGN_ID' => 'Campaign ID', diff --git a/modules/Accounts/views/view.detail.php b/modules/Accounts/views/view.detail.php index e93a1427..135464bc 100644 --- a/modules/Accounts/views/view.detail.php +++ b/modules/Accounts/views/view.detail.php @@ -73,7 +73,7 @@ class AccountsViewDetail extends ViewDetail { '&primary_address_postalcode=' . $this->bean->billing_address_postalcode . '&primary_address_country=' . $this->bean->billing_address_country . '", true, false);\' value="' . $mod_strings['LBL_PUSH_CONTACTS_BUTTON_TITLE']. '">'. - SugarThemeRegistry::current()->getImage("id-ff-copy",""). + SugarThemeRegistry::current()->getImage("id-ff-copy","",null,null,'.png',$mod_strings["LBL_COPY"]). ''; $push_shipping = ''; } else { $push_billing = ''; diff --git a/modules/Activities/OpenListView.php b/modules/Activities/OpenListView.php new file mode 100644 index 00000000..540b6bac --- /dev/null +++ b/modules/Activities/OpenListView.php @@ -0,0 +1,328 @@ +getPreference('appointment_filter') == '') { + $appointment_filter = 'today'; + } else { + $appointment_filter = $current_user->getPreference('appointment_filter'); + } +} else { + $appointment_filter = $_REQUEST['appointment_filter']; + $current_user->setPreference('appointment_filter', $_REQUEST['appointment_filter']); +} + +if ($appointment_filter == 'last this_month') { + $laterDate = $timedate->getNow(true)->get("last day of this month"); +} elseif ($appointment_filter == 'last next_month') { + $laterDate = $timedate->getNow(true)->get("last day of next month"); +} else { + $laterDate = $timedate->fromString($appointment_filter); +} + +$dayEnd = $timedate->asDb($laterDate->get_day_end_time()); +$GLOBALS['log']->debug("filter $appointment_filter date $dayEnd"); + +if(ACLController::checkAccess('Meetings', 'list', true)){ + $meeting = new Meeting(); + $where = '('; + $or = false; + foreach ($open_status as $status) { + if ($or) $where .= ' OR '; + $or = true; + $where .= " meetings.status = '$status' "; + } + $where .= ") "; + $where .= " AND meetings_users.user_id='$current_user->id' "; + $where .= " AND meetings_users.accept_status != 'decline'"; + + // allow for differences between MySQL and Oracle 9 + if($sugar_config["dbconfig"]["db_type"] == "mysql") { + $where .= " HAVING datetime <= '$dayEnd' "; + } elseif ($sugar_config["dbconfig"]["db_type"] == "oci8") { + } + else if ($sugar_config["dbconfig"]["db_type"] == "mssql") + { + $where .= " AND meetings.date_start + ' ' + meetings.time_start <= '$dayEnd' "; + } + else { + $GLOBALS['log']->fatal("No database type identified."); + } + + $meeting->disable_row_level_security = true; + $focus_meetings_list = $meeting->get_full_list("time_start", $where); +} + +if(ACLController::checkAccess('Calls', 'list', true)) { + $call = new Call(); + $where = '('; + $or = false; + + foreach ($open_status as $status) { + if ($or) $where .= ' OR '; + $or = true; + $where .= " calls.status = '$status' "; + } + + $where .= ") "; + $where .= " AND calls_users.user_id='$current_user->id' "; + $where .= " AND calls_users.accept_status != 'decline'"; + + // allow for differences between MySQL and Oracle 9 + if($sugar_config["dbconfig"]["db_type"] == "mysql") { + $where .= " HAVING datetime <= '$dayEnd' "; + } elseif ($sugar_config["dbconfig"]["db_type"] == "oci8") { + }else if ($sugar_config["dbconfig"]["db_type"] == "mssql") + { + //add condition for MS Sql server. + $where .= " AND calls.date_start + ' ' + calls.time_start <= '$dayEnd' "; + } else { + $GLOBALS['log']->fatal("No database type identified."); + } + + $call->disable_row_level_security = true; + $focus_calls_list = $call->get_full_list("time_start", $where); +} + +$open_activity_list = array(); +if(count($focus_meetings_list)>0) { + foreach ($focus_meetings_list as $meeting) { + $td = $timedate->merge_date_time(from_db_convert($meeting->date_start,'date'),from_db_convert($meeting->time_start, 'time')); + $tag = 'span'; + + if($meeting->ACLAccess('view', $meeting->isOwner($current_user->id))){ + $tag = 'a'; + } + + $open_activity_list[] = array( + 'name' => $meeting->name, + 'id' => $meeting->id, + 'type' => 'Meeting', + 'module' => 'Meetings', + 'status' => $meeting->status, + 'parent_id' => $meeting->parent_id, + 'parent_type' => $meeting->parent_type, + 'parent_name' => $meeting->parent_name, + 'contact_id' => $meeting->contact_id, + 'contact_name' => $meeting->contact_name, + 'normal_date_start' => $meeting->date_start, + 'date_start' => $timedate->to_display_date($td), + 'normal_time_start' => $meeting->time_start, + 'time_start' => $timedate->to_display_time($td,true), + 'required' => $meeting->required, + 'accept_status' => $meeting->accept_status, + 'tag' => $tag, + ); + } +} + +if (count($focus_calls_list)>0) { + foreach ($focus_calls_list as $call) { + + $td = $timedate->merge_date_time(from_db_convert($call->date_start,'date'),from_db_convert($call->time_start, 'time')); + $tag = 'span'; + + if($call->ACLAccess('view', $call->isOwner($current_user->id))) { + $tag = 'a'; + } + + $open_activity_list[] = array( + 'name' => $call->name, + 'id' => $call->id, + 'type' => 'Call', + 'module' => 'Calls', + 'status' => $call->status, + 'parent_id' => $call->parent_id, + 'parent_type' => $call->parent_type, + 'parent_name' => $call->parent_name, + 'contact_id' => $call->contact_id, + 'contact_name' => $call->contact_name, + 'date_start' => $timedate->to_display_date($td), + 'normal_date_start' => $call->date_start, + 'normal_time_start' => $call->time_start, + 'time_start' => $timedate->to_display_time($td,true), + 'required' => $call->required, + 'accept_status' => $call->accept_status, + 'tag' => $tag, + ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +//// START OUTPUT + +$xtpl=new XTemplate ('modules/Activities/OpenListView.html'); +$xtpl->assign("MOD", $current_module_strings); +$xtpl->assign("APP", $app_strings); +$xtpl->assign('JSON_CONFIG_JAVASCRIPT', $json_config->get_static_json_server()); +$xtpl->assign("SUGAR_VERSION", $sugar_version); +$xtpl->assign("JS_CUSTOM_VERSION", $sugar_config['js_custom_version']); + +// Stick the form header out there. +$filter = get_select_options_with_id($current_module_strings['appointment_filter_dom'], $appointment_filter ); +echo "\n"; +echo "\n"; +echo "\n"; +$day_filter = ""; + +echo get_form_header($current_module_strings['LBL_UPCOMING'], $current_module_strings['LBL_TODAY'].$day_filter.' ('.$timedate->to_display_date($later, false).') ', false); +echo "\n"; + +$xtpl->assign("RETURN_URL", "&return_module=$currentModule&return_action=DetailView&return_id=" . ((is_object($focus) && ! empty($focus->id)) ? $focus->id : "")); + +$oddRow = true; +if(count($open_activity_list) > 0) { + $open_activity_list = array_csort($open_activity_list, 'normal_date_start', 'normal_time_start', SORT_ASC); +} + +$today = $timedate->handle_offset('today', $timedate->dbDayFormat.' '.$timedate->dbTimeFormat, false); +$todayOffset = $timedate->handleOffsetMax('today', $timedate->dbDayFormat.' '.$timedate->dbTimeFormat, true); + +foreach($open_activity_list as $activity) { + $concatActDate = $activity['normal_date_start'].' '.$activity['normal_time_start']; + + if($concatActDate < $today) { + $time = "".$activity['date_start'].' '.$activity['time_start'].""; + } elseif(($concatActDate >= $todayOffset['min']) && ($concatActDate <= $todayOffset['max'])) { + $time = "".$activity['date_start'].' '.$activity['time_start'].""; + } else { + $time = "".$activity['date_start'].' '.$activity['time_start'].""; + } + + $activity_fields = array( + 'ID' => $activity['id'], + 'NAME' => $activity['name'], + 'TYPE' => $activity['type'], + 'MODULE' => $activity['module'], + 'STATUS' => $activity['status'], + 'CONTACT_NAME' => $activity['contact_name'], + 'CONTACT_ID' => $activity['contact_id'], + 'PARENT_TYPE' => $activity['parent_type'], + 'PARENT_NAME' => $activity['parent_name'], + 'PARENT_ID' => $activity['parent_id'], + 'TIME' => $time, + 'TAG' => $activity['tag'], + ); + + switch ($activity['parent_type']) { + case 'Accounts': + $activity_fields['PARENT_MODULE'] = 'Accounts'; + break; + case 'Cases': + $activity_fields['PARENT_MODULE'] = 'Cases'; + break; + case 'Opportunities': + $activity_fields['PARENT_MODULE'] = 'Opportunities'; + break; + case 'Quotes': + $activity_fields['PARENT_MODULE'] = 'Quotes'; + break; + } + switch ($activity['type']) { + case 'Call': + $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'", null, null, '.gif', $mod_strings['LBL_LIST_CLOSE']).""; + break; + case 'Meeting': + $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'",null,null,'.gif',$mod_strings['LBL_LIST_CLOSE']).""; + break; + } + + if (! empty($activity['accept_status'])) { + if ( $activity['accept_status'] == 'none') { + $activity_fields['SET_ACCEPT_LINKS'] = ""; + } else { + $activity_fields['SET_ACCEPT_LINKS'] = $app_list_strings['dom_meeting_accept_status'][$activity['accept_status']]; + } + } + + $activity_fields['TITLE'] = ''; + if (!empty($activity['contact_name'])) { + $activity_fields['TITLE'] .= $current_module_strings['LBL_LIST_CONTACT'].": ".$activity['contact_name']; + } + if (!empty($activity['parent_name'])) { + $activity_fields['TITLE'] .= "\n".$app_list_strings['record_type_display'][$activity['parent_type']].": ".$activity['parent_name']; + } + + $xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0"', null,null,'.gif',$activity_fields['NAME'])); + $xtpl->assign("ACTIVITY", $activity_fields); + $xtpl->assign("BG_HILITE", $hilite_bg); + $xtpl->assign("BG_CLICK", $click_bg); + + if($oddRow) { + $xtpl->assign("ROW_COLOR", 'oddListRow'); + $xtpl->assign("BG_COLOR", $odd_bg); + } else { + $xtpl->assign("ROW_COLOR", 'evenListRow'); + $xtpl->assign("BG_COLOR", $even_bg); + } + $oddRow = !$oddRow; + $xtpl->parse("open_activity.row"); +} // END FOREACH() + +$xtpl->parse("open_activity"); +if (count($open_activity_list)>0) $xtpl->out("open_activity"); +else echo "".$current_module_strings['NTC_NONE_SCHEDULED'].""; +?> \ No newline at end of file diff --git a/modules/Activities/Popup_picker.php b/modules/Activities/Popup_picker.php index e2279823..98ada1b0 100644 --- a/modules/Activities/Popup_picker.php +++ b/modules/Activities/Popup_picker.php @@ -137,7 +137,7 @@ class Popup_Picker 'date_modified' => $date_due, 'description' => $this->getTaskDetails($task), 'date_type' => $app_strings['DATA_TYPE_DUE'], - 'sort_value' => strtotime($task->fetched_row['date_due'].' GMT'), + 'sort_value' => $timedate->fromDb($task->fetched_row['date_due'])->ts, ); } else { $open_activity_list[] = array('name' => $task->name, @@ -159,7 +159,7 @@ class Popup_Picker } // end Tasks foreach ($focus_meetings_list as $meeting) { - + if (empty($meeting->contact_id) && empty($meeting->contact_name)) { $meeting_contacts = $meeting->get_linked_beans('contacts','Contact'); if (!empty($meeting_contacts[0]->id) && !empty($meeting_contacts[0]->name)) { @@ -182,7 +182,7 @@ class Popup_Picker 'date_modified' => $meeting->date_start, 'description' => $this->formatDescription($meeting->description), 'date_type' => $app_strings['DATA_TYPE_START'], - 'sort_value' => strtotime($meeting->fetched_row['date_start'].' GMT'), + 'sort_value' => $timedate->fromDb($task->fetched_row['date_start'])->ts, ); } else { $open_activity_list[] = array('name' => $meeting->name, @@ -228,7 +228,7 @@ class Popup_Picker 'date_modified' => $call->date_start, 'description' => $this->formatDescription($call->description), 'date_type' => $app_strings['DATA_TYPE_START'], - 'sort_value' => strtotime($call->fetched_row['date_start'].' GMT'), + 'sort_value' => $timedate->fromDb($task->fetched_row['date_start'])->ts, ); } else { $open_activity_list[] = array('name' => $call->name, @@ -250,7 +250,7 @@ class Popup_Picker } // end Calls foreach ($focus_emails_list as $email) { - + if (empty($email->contact_id) && empty($email->contact_name)) { $email_contacts = $email->get_linked_beans('contacts','Contact'); if (!empty($email_contacts[0]->id) && !empty($email_contacts[0]->name)) { @@ -272,7 +272,7 @@ class Popup_Picker 'date_modified' => $email->date_start." ".$email->time_start, 'description' => $this->getEmailDetails($email), 'date_type' => $app_strings['DATA_TYPE_SENT'], - 'sort_value' => strtotime($email->fetched_row['date_sent'].' GMT'), + 'sort_value' => $timedate->fromDb($task->fetched_row['date_sent'])->ts, ); } //end Emails @@ -348,6 +348,7 @@ class Popup_Picker $history_list[$count]['fileurl'] = UploadFile::get_url($note->filename,$note->id); } } + } // end Notes $xtpl=new XTemplate ('modules/Activities/Popup_picker.html'); @@ -360,7 +361,7 @@ class Popup_Picker echo "
"; echo getClassicModuleTitle($focus->module_dir, array(translate('LBL_MODULE_NAME', $focus->module_dir),$focus->name), false); echo ""; - echo "".$app_strings[ ".$app_strings['LNK_PRINT']."\n"; + echo "" . SugarThemeRegistry::current()->getImage('print', "border='0' align='absmiddle'", 13, 13, ".gif", $app_strings['LNK_PRINT']) . " ".$app_strings['LNK_PRINT']."\n"; echo "
"; $oddRow = true; @@ -401,13 +402,13 @@ class Popup_Picker if (isset($activity['location'])) $activity_fields['LOCATION'] = $activity['location']; if (isset($activity['filename'])) { - $activity_fields['ATTACHMENT'] = "".SugarThemeRegistry::current()->getImage("attachment","alt='".$activity['filename']."' border='0' align='absmiddle'").""; + $activity_fields['ATTACHMENT'] = "".SugarThemeRegistry::current()->getImage("attachment","border='0' align='absmiddle'",null,null,'.gif',$activity['filename']).""; } if (isset($activity['parent_type'])) $activity_fields['PARENT_MODULE'] = $activity['parent_type']; $xtpl->assign("ACTIVITY", $activity_fields); - $xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0" alt="'.$activity_fields['NAME'].'"')); + $xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0"', null,null,'.gif',$activity_fields['NAME'])); if($oddRow) { @@ -474,4 +475,4 @@ class Popup_Picker return nl2br($description); } } // end of class Popup_Picker -?> +?> \ No newline at end of file diff --git a/modules/Activities/SubPanelView.php b/modules/Activities/SubPanelView.php index 276020a5..f792c8b4 100644 --- a/modules/Activities/SubPanelView.php +++ b/modules/Activities/SubPanelView.php @@ -91,7 +91,7 @@ foreach ($focus_tasks_list as $task) { if ($task->date_due == '0000-00-00') $date_due = ''; else { $date_due = $task->date_due; - + } $open_activity_list[] = Array('name' => $task->name, 'id' => $task->id, @@ -210,7 +210,7 @@ foreach ($focus_notes_list as $note) { $count = count($history_list); $count--; $history_list[$count]['filename'] = $note->filename; - $history_list[$count]['fileurl'] = UploadFile::get_url($note->filename,$note->id); + $history_list[$count]['fileurl'] = UploadFile::get_upload_url($note); } } @@ -225,8 +225,8 @@ else $xtpl=new XTemplate ('modules/Activities/SubPanelView.html'); } -$xtpl->assign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline','align="absmiddle" alt="'.$app_strings['LNK_DELETE'].'" border="0"')); -$xtpl->assign("EDIT_INLINE_PNG", SugarThemeRegistry::current()->getImage('edit_inline','align="absmiddle" alt="'.$app_strings['LNK_EDIT'].'" border="0"')); +$xtpl->assign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline','align="absmiddle" border="0"', null,null,'.gif',$app_strings['LNK_DELETE'])); +$xtpl->assign("EDIT_INLINE_PNG", SugarThemeRegistry::current()->getImage('edit_inline','align="absmiddle" border="0"', null,null,'.gif',$app_strings['LNK_EDIT'])); $xtpl->assign("MOD", $current_module_strings); $xtpl->assign("APP", $app_strings); @@ -306,15 +306,15 @@ foreach($open_activity_list as $activity) if (isset($activity['parent_type'])) $activity_fields['PARENT_MODULE'] = $activity['parent_type']; switch ($activity['type']) { case 'Call': - $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'").""; + $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'",null,null,'.gif',$mod_strings['LBL_LIST_CLOSE']).""; $activity_fields['STATUS'] = $app_list_strings['call_status_dom'][$activity['status']]; break; case 'Meeting': - $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'").""; + $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'", null,null,'.gif',$mod_strings['LBL_LIST_CLOSE']).""; $activity_fields['STATUS'] = $app_list_strings['meeting_status_dom'][$activity['status']]; break; case 'Task': - $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'").""; + $activity_fields['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Activities')." border='0'", null,null,'.gif',$mod_strings['LBL_LIST_CLOSE']).""; $activity_fields['STATUS'] = $app_list_strings['task_status_dom'][$activity['status']]; break; } @@ -325,7 +325,7 @@ foreach($open_activity_list as $activity) global $click_bg; $xtpl->assign("BG_HILITE", $hilite_bg); $xtpl->assign("BG_CLICK", $click_bg); -$xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0" alt="'.$activity_fields['NAME'].'"')); +$xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0"', null,null,'.gif',$activity_fields['NAME'])); $xtpl->assign("ACTIVITY", $activity_fields); if($oddRow) @@ -357,7 +357,7 @@ $popup_request_data = array( 'form_name' => 'EditView', 'field_to_name_array' => array(), ); - + $json = getJSONobj(); $encoded_popup_request_data = $json->encode($popup_request_data); @@ -424,13 +424,13 @@ foreach($history_list as $activity) if (isset($activity['location'])) $activity_fields['LOCATION'] = $activity['location']; if (isset($activity['filename'])) { - $activity_fields['ATTACHMENT'] = "".SugarThemeRegistry::current()->getImage("attachment","alt='".$activity['filename']."' border='0' align='absmiddle'").""; + $activity_fields['ATTACHMENT'] = "".SugarThemeRegistry::current()->getImage("attachment","border='0' align='absmiddle'",null,null,'.gif',$activity['filename']).""; } if (isset($activity['parent_type'])) $activity_fields['PARENT_MODULE'] = $activity['parent_type']; $xtpl->assign("ACTIVITY", $activity_fields); - $xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0" alt="'.$activity_fields['NAME'].'"')); + $xtpl->assign("ACTIVITY_MODULE_PNG", SugarThemeRegistry::current()->getImage($activity_fields['MODULE'].'','border="0"', null,null,'.gif',$activity_fields['NAME'])); if($oddRow) { diff --git a/modules/Activities/language/en_us.lang.php b/modules/Activities/language/en_us.lang.php index a79925d6..090b1f46 100644 --- a/modules/Activities/language/en_us.lang.php +++ b/modules/Activities/language/en_us.lang.php @@ -115,7 +115,7 @@ $mod_strings = array ( ,'next Saturday' => 'next week' ,'last this_month' => 'this month' ,'last next_month' => 'next month' - ), +), 'LNK_IMPORT_CALLS'=>'Import Calls', 'LNK_IMPORT_MEETINGS'=>'Import Meetings', 'LNK_IMPORT_TASKS'=>'Import Tasks', @@ -124,7 +124,9 @@ $mod_strings = array ( 'LBL_ACCEPT_THIS'=>'Accept?', 'LBL_DEFAULT_SUBPANEL_TITLE' => 'Open Activities', 'LBL_LIST_ASSIGNED_TO_NAME' => 'Assigned User', + + 'LBL_ACCEPT' => 'Accept' /*for 508 compliance fix*/, ); -?> +?> \ No newline at end of file diff --git a/modules/Activities/views/view.modulelistmenu.php b/modules/Activities/views/view.modulelistmenu.php index 5881e300..71a25843 100644 --- a/modules/Activities/views/view.modulelistmenu.php +++ b/modules/Activities/views/view.modulelistmenu.php @@ -45,7 +45,8 @@ class ActivitiesViewModulelistmenu extends ViewModulelistmenu foreach ( $history as $key => $row ) { $history[$key]['item_summary_short'] = getTrackerSubstring($row['item_summary']); $history[$key]['image'] = SugarThemeRegistry::current() - ->getImage($row['module_name'],'border="0" align="absmiddle" alt="'.$row['item_summary'].'"'); + ->getImage($row['module_name'],'border="0" align="absmiddle"',null,null,'.gif',$row['item_summary']); + } $this->ss->assign('LAST_VIEWED',$history); diff --git a/modules/Administration/Administration.php b/modules/Administration/Administration.php index d2ab105c..f5f3607a 100644 --- a/modules/Administration/Administration.php +++ b/modules/Administration/Administration.php @@ -95,7 +95,7 @@ class Administration extends SugarBean { return NULL; } - while($row = $this->db->fetchByAssoc($result, -1, true)) { + while($row = $this->db->fetchByAssoc($result)) { if($row['category']."_".$row['name'] == 'ldap_admin_password' || $row['category']."_".$row['name'] == 'proxy_password') $this->settings[$row['category']."_".$row['name']] = $this->decrypt_after_retrieve($row['value']); else @@ -148,7 +148,7 @@ class Administration extends SugarBean { function saveSetting($category, $key, $value) { $result = $this->db->query("SELECT count(*) AS the_count FROM config WHERE category = '{$category}' AND name = '{$key}'"); - $row = $this->db->fetchByAssoc( $result, -1, true ); + $row = $this->db->fetchByAssoc($result); $row_count = $row['the_count']; if($category."_".$key == 'ldap_admin_password' || $category."_".$key == 'proxy_password') @@ -161,7 +161,7 @@ class Administration extends SugarBean { $result = $this->db->query("UPDATE config SET value = '{$value}' WHERE category = '{$category}' AND name = '{$key}'"); } sugar_cache_clear('admin_settings_cache'); - return $this->db->getAffectedRowCount(); + return $this->db->getAffectedRowCount($result); } function get_config_prefix($str) { diff --git a/modules/Administration/Development.php b/modules/Administration/Development.php index 9aa5cae6..04b52df5 100644 --- a/modules/Administration/Development.php +++ b/modules/Administration/Development.php @@ -51,11 +51,11 @@ echo getClassicModuleTitle('MigrateFields', array($mod_strings['LBL_EXTERNAL_DEV

- + - + diff --git a/modules/Administration/Diagnostic.php b/modules/Administration/Diagnostic.php index 97ad52ec..08cc6d61 100644 --- a/modules/Administration/Diagnostic.php +++ b/modules/Administration/Diagnostic.php @@ -71,33 +71,15 @@ $sugar_smarty = new Sugar_Smarty(); $sugar_smarty->assign("MOD", $mod_strings); $sugar_smarty->assign("APP", $app_strings); -if($db->dbType != 'mysql') { - $sugar_smarty->assign("NO_MYSQL_MESSAGE", ""); - $sugar_smarty->assign("MYSQL_CAPABLE", ""); - $sugar_smarty->assign("MYSQL_CAPABLE_CHECKBOXES", - "" - ); -} -else { - $sugar_smarty->assign("NO_MYSQL_MESSAGE", ""); - $sugar_smarty->assign("MYSQL_CAPABLE", "checked"); - $sugar_smarty->assign("MYSQL_CAPABLE_CHECKBOXES", ""); -} - $sugar_smarty->assign("RETURN_MODULE", "Administration"); $sugar_smarty->assign("RETURN_ACTION", "index"); +$sugar_smarty->assign("DB_NAME", $db->dbName); $sugar_smarty->assign("MODULE", $currentModule); $sugar_smarty->assign("PRINT_URL", "index.php?".$GLOBALS['request_string']); -$sugar_smarty->assign("ADVANCED_SEARCH_PNG", SugarThemeRegistry::current()->getImage('advanced_search','alt="'.$app_strings['LNK_ADVANCED_SEARCH'].'" border="0"')); -$sugar_smarty->assign("BASIC_SEARCH_PNG", SugarThemeRegistry::current()->getImage('basic_search','alt="'.$app_strings['LNK_BASIC_SEARCH'].'" border="0"')); +$sugar_smarty->assign("ADVANCED_SEARCH_PNG", SugarThemeRegistry::current()->getImage('advanced_search','border="0"',null,null,'.gif',$app_strings['LNK_ADVANCED_SEARCH'])); +$sugar_smarty->assign("BASIC_SEARCH_PNG", SugarThemeRegistry::current()->getImage('basic_search','border="0"',null,null,'.gif',$app_strings['LNK_BASIC_SEARCH'])); $sugar_smarty->display("modules/Administration/Diagnostic.tpl"); diff --git a/modules/Administration/Diagnostic.tpl b/modules/Administration/Diagnostic.tpl index 25c9aeb5..3c73b4af 100644 --- a/modules/Administration/Diagnostic.tpl +++ b/modules/Administration/Diagnostic.tpl @@ -54,9 +54,6 @@
getImage('ImportCustomFields','alt="'. $mod_strings['LBL_IMPORT_CUSTOM_FIELDS_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('ImportCustomFields','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_IMPORT_CUSTOM_FIELDS_TITLE']); ?> 
getImage('ExportCustomFields','alt="'. $mod_strings['LBL_EXPORT_CUSTOM_FIELDS_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('ExportCustomFields','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_EXPORT_CUSTOM_FIELDS_TITLE']); ?> 
". - $mod_strings['LBL_DIAGNOSTIC_NO_MYSQL']. - "
 
- {if $NO_MYSQL_MESSAGE} - - {/if} @@ -67,15 +64,15 @@ - - + + - + - + - - + + @@ -101,7 +98,6 @@ -{$MYSQL_CAPABLE_CHECKBOXES} {literal} diff --git a/modules/Administration/PasswordManager.php b/modules/Administration/PasswordManager.php index 9444978b..6ad1b3b3 100644 --- a/modules/Administration/PasswordManager.php +++ b/modules/Administration/PasswordManager.php @@ -96,13 +96,15 @@ if(!empty($_POST['saveConfig'])){ else $_POST['system_ldap_enabled'] = 0; - - - if (isset($_REQUEST['authenticationClass'])) { - - $configurator->useAuthenticationClass = true; - } - + + if(isset($_REQUEST['authenticationClass'])) + { + $configurator->useAuthenticationClass = true; + } else { + $configurator->useAuthenticationClass = false; + $_POST['authenticationClass'] = ''; + } + if (isset($_REQUEST['ldap_group_checkbox']) && $_REQUEST['ldap_group_checkbox'] == 'on') $_POST['ldap_group'] = 1; diff --git a/modules/Administration/PasswordManager.tpl b/modules/Administration/PasswordManager.tpl index 09aa523a..c6412b5f 100644 --- a/modules/Administration/PasswordManager.tpl +++ b/modules/Administration/PasswordManager.tpl @@ -37,7 +37,7 @@ *} - + @@ -45,7 +45,7 @@ {$error.main}
{$NO_MYSQL_MESSAGE}{$MOD.LBL_DIAGNOSTIC_CONFIGPHP}
{$MOD.LBL_DIAGNOSTIC_PHPINFO}
{$MOD.LBL_DIAGNOSTIC_MYSQLDUMPS}{$DB_NAME} - {$MOD.LBL_DIAGNOSTIC_MYSQLDUMPS}
{$MOD.LBL_DIAGNOSTIC_MYSQLSCHEMA}{$DB_NAME} - {$MOD.LBL_DIAGNOSTIC_MYSQLSCHEMA}
{$MOD.LBL_DIAGNOSTIC_MYSQLINFO}{$DB_NAME} - {$MOD.LBL_DIAGNOSTIC_MYSQLINFO}
{$MOD.LBL_DIAGNOSTIC_MD5}
- + @@ -249,7 +249,7 @@
  @@ -55,7 +55,7 @@ - +
- + - @@ -114,7 +114,7 @@
@@ -82,7 +82,7 @@ {/if}
+ {if $SMTP_SERVER_NOT_SET}    {$MOD.ERR_SMTP_SERVER_NOT_SET}
{/if}     {$MOD.LBL_EMAIL_ADDRESS_REQUIRED_FOR_FEATURE}
- {$MOD.LBL_PASSWORD_EXP_IN} + {$MOD.LBL_PASSWORD_EXP_IN} {assign var='sdays' value=''} {assign var='sweeks' value=''} {assign var='smonths' value=''} @@ -136,14 +136,14 @@ - {$MOD.LBL_PASSWORD_EXP_AFTER} + {$MOD.LBL_PASSWORD_EXP_AFTER} {$MOD.LBL_PASSWORD_LOGINS}
@@ -167,7 +167,7 @@ {assign var='smtp_warning_2' value='none'} {/if} - @@ -177,7 +177,7 @@ - + {if !empty($settings.captcha_on) || !($VALID_PUBLIC_KEY)} {assign var='captcha_checked' value='CHECKED'} @@ -238,7 +238,7 @@ - +
+
{if $SMTP_SERVER_NOT_SET}    {$MOD.ERR_SMTP_SERVER_NOT_SET}
{/if}     {$MOD.LBL_EMAIL_ADDRESS_REQUIRED_FOR_FEATURE}
- + {assign var='linkexptime' value=''} {assign var='linkexpnone' value=''} {if ($config.passwordsetting.linkexpiration) == '0'} @@ -217,7 +217,7 @@
{$MOD.LBL_PRIVATE_KEY}*
- + @@ -336,12 +336,12 @@ {assign var='ldap_group_checked' value=''} {assign var='ldap_group_display' value='none'} {/if} - + - +
@@ -418,16 +418,16 @@
- + - {if !empty($config.authenticationClass) && $config.authenticationClass === 'SAMLAuthenticate'} + {if !empty($config.authenticationClass) && $config.authenticationClass == 'SAMLAuthenticate'} {assign var='saml_enabled_checked' value='CHECKED'} {assign var='saml_display' value='inline'} {else} {assign var='saml_enabled_checked' value=''} {assign var='saml_display' value='none'} {/if} - + @@ -451,22 +451,22 @@ - + {$settings.proxy_host} - + - - + +
@@ -439,10 +439,10 @@ {$MOD.LBL_SAML_ENABLE}{sugar_help text=$MOD.LBL_SAML_HELP_TXT} - -   
{$MOD.LBL_SAML_LOGIN_URL} {sugar_help text=$MOD.LBL_SAML_LOGIN_URL_DESC}
{$MOD.LBL_SAML_CERT} {sugar_help text=$MOD.LBL_SAML_CERT_DESC}
- - + +

- + @@ -499,17 +499,17 @@ document.getElementById('forgotpassword_checkbox').checked=true; function addcheck(form){{/literal} addForm('ConfigurePasswordSettings'); - + if(document.getElementById('forgotpassword_checkbox').checked){literal}{{/literal} addToValidate('ConfigurePasswordSettings', 'passwordsetting_linkexpirationtime', 'int', form.required_link_exp_time.checked,"{$MOD.ERR_PASSWORD_LINK_EXPIRE_TIME} "); {literal}}{/literal} - + if(document.getElementById('SystemGeneratedPassword_checkbox').checked){literal}{{/literal} addToValidate('ConfigurePasswordSettings', 'passwordsetting_systexpirationtime', 'int', form.required_sys_pwd_exp_time.checked,"{$MOD.ERR_PASSWORD_EXPIRE_TIME}" ); addToValidate('ConfigurePasswordSettings', 'passwordsetting_systexpirationlogin', 'int', form.required_sys_pwd_exp_login.checked,"{$MOD.ERR_PASSWORD_EXPIRE_LOGIN}" ); {literal}}{/literal} - + {literal} } @@ -538,7 +538,7 @@ function enableDisablePasswordTable(checkbox_id) { document.getElementById("emailTemplatesId").style.display = ""; document.getElementById("sysGeneratedId").style.display = ""; document.getElementById("userResetPassId").style.display = ""; - + } } // if @@ -628,11 +628,11 @@ function toggleDisplay_2(id){ if(this.document.getElementById(id).style.display=='none'){ this.document.getElementById(id).style.display=''; this.document.getElementById(id+"_lbl").innerHTML='{/literal}{$MOD.LBL_HIDE_ADVANCED_OPTIONS}{literal}'; - this.document.getElementById("regex_config_display_img").src = '{/literal}{sugar_getimagepath file="basic_search.gif"}{literal}'; + this.document.getElementById("regex_config_display_img").src = '{/literal}{sugar_getimagepath file="basic_search.gif"}{literal}'; }else{ this.document.getElementById(id).style.display='none' this.document.getElementById(id+"_lbl").innerHTML='{/literal}{$MOD.LBL_SHOW_ADVANCED_OPTIONS}{literal}'; - this.document.getElementById("regex_config_display_img").src = '{/literal}{sugar_getimagepath file="advanced_search.gif"}{literal}'; + this.document.getElementById("regex_config_display_img").src = '{/literal}{sugar_getimagepath file="advanced_search.gif"}{literal}'; } } diff --git a/modules/Administration/QuickRepairAndRebuild.php b/modules/Administration/QuickRepairAndRebuild.php index 3da2ba3c..13e92087 100644 --- a/modules/Administration/QuickRepairAndRebuild.php +++ b/modules/Administration/QuickRepairAndRebuild.php @@ -243,13 +243,13 @@ class RepairAndClear { global $mod_strings; if($this->show_output) echo "

{$mod_strings['LBL_QR_CLEARSMARTY']}

"; - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'smarty/templates_c', '.tpl.php'); + $this->_clearCache(sugar_cached('smarty/templates_c'), '.tpl.php'); } public function clearXMLfiles() { global $mod_strings; if($this->show_output) echo "

{$mod_strings['LBL_QR_XMLFILES']}

"; - $this->_clearCache($GLOBALS['sugar_config']['tmp_dir'], '.xml'); + $this->_clearCache(sugar_cached("xml"), '.xml'); include('modules/Versions/ExpectedVersions.php'); @@ -269,7 +269,7 @@ class RepairAndClear { global $mod_strings; if($this->show_output) echo "

{$mod_strings['LBL_QR_CLEARDASHLET']}

"; - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'dashlets', '.php'); + $this->_clearCache(sugar_cached('dashlets'), '.php'); } public function clearThemeCache() { @@ -291,10 +291,10 @@ class RepairAndClear if(!in_array( translate('LBL_ALL_MODULES'),$this->module_list) && !empty($this->module_list)) { foreach($this->module_list as $module_name_singular ) - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'modules/'.$this->_getModuleNamePlural($module_name_singular), '.tpl'); + $this->_clearCache(sugar_cached('modules/').$this->_getModuleNamePlural($module_name_singular), '.tpl'); } else - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'modules', '.tpl'); + $this->_clearCache(sugar_cached('modules/'), '.tpl'); } public function clearVardefs() { @@ -303,10 +303,10 @@ class RepairAndClear if(!empty($this->module_list) && is_array($this->module_list) && !in_array( translate('LBL_ALL_MODULES'),$this->module_list)) { foreach($this->module_list as $module_name_singular ) - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'modules/'.$this->_getModuleNamePlural($module_name_singular), 'vardefs.php'); + $this->_clearCache(sugar_cached('modules/').$this->_getModuleNamePlural($module_name_singular), 'vardefs.php'); } else - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'modules', 'vardefs.php'); + $this->_clearCache(sugar_cached('modules/'), 'vardefs.php'); } public function clearJsFiles() { @@ -316,11 +316,11 @@ class RepairAndClear if(!in_array( translate('LBL_ALL_MODULES'),$this->module_list) && !empty($this->module_list)) { foreach($this->module_list as $module_name_singular ) - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'modules/'.$this->_getModuleNamePlural($module_name_singular), '.js'); + $this->_clearCache(sugar_cached('modules/').$this->_getModuleNamePlural($module_name_singular), '.js'); } else - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'modules', '.js'); + $this->_clearCache(sugar_cached('modules/'), '.js'); } public function clearJsLangFiles() @@ -330,10 +330,10 @@ class RepairAndClear if(!in_array(translate('LBL_ALL_MODULES'),$this->module_list ) && !empty($this->module_list)) { foreach($this->module_list as $module_name_singular ) - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'jsLanguage/'.$this->_getModuleNamePlural($module_name_singular), '.js'); + $this->_clearCache(sugar_cached('jsLanguage/').$this->_getModuleNamePlural($module_name_singular), '.js'); } else - $this->_clearCache($GLOBALS['sugar_config']['cache_dir'].'jsLanguage', '.js'); + $this->_clearCache(sugar_cached('jsLanguage'), '.js'); } /** * Remove the language cache files from cache/modules//language @@ -362,10 +362,7 @@ class RepairAndClear public function clearSearchCache() { global $mod_strings, $sugar_config; if($this->show_output) echo "

{$mod_strings['LBL_QR_CLEARSEARCH']}

"; - $search_dir='cache/'; - if (!empty($sugar_config['cache_dir'])) { - $search_dir=$sugar_config['cache_dir']; - } + $search_dir=sugar_cached(''); $src_file = $search_dir . 'modules/unified_search_modules.php'; if(file_exists($src_file)) { unlink( "$src_file" ); diff --git a/modules/Administration/RebuildDashlets.php b/modules/Administration/RebuildDashlets.php index 5c9f90ef..9b1a1617 100644 --- a/modules/Administration/RebuildDashlets.php +++ b/modules/Administration/RebuildDashlets.php @@ -40,16 +40,16 @@ $silent = isset($_REQUEST['silent']) ? true : false; if(is_admin($current_user)){ global $mod_strings; if (!$silent) { echo $mod_strings['LBL_REBUILD_DASHLETS_DESC']; } - if(is_file($GLOBALS['sugar_config']['cache_dir'].'dashlets/dashlets.php')) { - unlink($GLOBALS['sugar_config']['cache_dir'].'dashlets/dashlets.php'); + if(is_file($cachedfile = sugar_cached('dashlets/dashlets.php'))) { + unlink($cachedfile); } require_once('include/Dashlets/DashletCacheBuilder.php'); - + $dc = new DashletCacheBuilder(); $dc->buildCache(); if( !$silent ) echo '



' . $mod_strings['LBL_REBUILD_DASHLETS_DESC_SUCCESS']; } else{ - sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); + sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); } ?> \ No newline at end of file diff --git a/modules/Administration/RebuildFulltextIndices.php b/modules/Administration/RebuildFulltextIndices.php index f2c70b16..adc2453e 100644 --- a/modules/Administration/RebuildFulltextIndices.php +++ b/modules/Administration/RebuildFulltextIndices.php @@ -38,13 +38,9 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); global $current_user; if(!is_admin($current_user)){ - die('Unauthorized Access. Aborting.'); + die('Unauthorized Access. Aborting.'); } -//make sure that db-type is oracle. -if ($GLOBALS['db']->dbType != "oci8") { -// die('Action not supported for your database.'); -} //find modules that have a full-text index and rebuild it. global $beanFiles; foreach ($beanFiles as $beanname=>$beanpath) { @@ -52,12 +48,12 @@ foreach ($beanFiles as $beanname=>$beanpath) { $focus= new $beanname(); //skips beans based on same tables. user, employee and group are an example. - if(empty($focus->table_name) || isset($processed_tables[$focus->table_name])) { + if(empty($focus->table_name) || isset($processed_tables[$focus->table_name])) { continue; } else { $processed_tables[$focus->table_name]=$focus->table_name; } - + if(!empty($dictionary[$focus->object_name]['indices'])) { $indices=$dictionary[$focus->object_name]['indices']; } else { @@ -73,11 +69,11 @@ foreach ($beanFiles as $beanname=>$beanpath) { if (isset($definition['db']) and $definition['db'] != $GLOBALS['db']->dbType) { continue; } - + echo "Rebuilding Index {$definition['name']}
"; $GLOBALS['db']->query('alter index ' .$definition['name'] . " REBUILD"); } - + } } ?> diff --git a/modules/Administration/RebuildJSLang.php b/modules/Administration/RebuildJSLang.php index 25001402..2a970919 100644 --- a/modules/Administration/RebuildJSLang.php +++ b/modules/Administration/RebuildJSLang.php @@ -36,7 +36,7 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ if(is_admin($current_user)){ - + global $mod_strings, $sugar_config; echo $mod_strings['LBL_REBUILD_JAVASCRIPT_LANG_DESC']; @@ -47,6 +47,6 @@ if(is_admin($current_user)){ LanguageManager::clearLanguageCache(); } else{ - sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); + sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); } ?> \ No newline at end of file diff --git a/modules/Calendar/Forms.php b/modules/Administration/RebuildSprites.php similarity index 84% rename from modules/Calendar/Forms.php rename to modules/Administration/RebuildSprites.php index b6a98d12..bbec7561 100644 --- a/modules/Calendar/Forms.php +++ b/modules/Administration/RebuildSprites.php @@ -36,10 +36,17 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); ********************************************************************************/ - $GLOBALS['QCModule'] = 'Calls'; - //If Meetings module was requested, we override the return_module action to default to Calls - if((isset($_REQUEST['module']) && $_REQUEST['module'] == 'Meetings') && (isset($_REQUEST['action']) && $_REQUEST['action'] == 'index')) { - $_REQUEST['return_module'] = 'Calls'; - } - require_once('modules/Calls/Forms.php'); +global $current_user; +if(is_admin($current_user)) +{ + if(!isset($_REQUEST['process'])) + { + global $mod_strings; + echo '
'.$mod_strings['LBL_REPAIR_JS_FILES_PROCESSING']; + echo'
'; + $ss = new Sugar_Smarty(); + $ss->display('modules/Administration/templates/RebuildSprites.tpl'); + } +} + ?> \ No newline at end of file diff --git a/modules/Administration/RepairFieldCasing.php b/modules/Administration/RepairFieldCasing.php index 16c149a7..81ee69ca 100644 --- a/modules/Administration/RepairFieldCasing.php +++ b/modules/Administration/RepairFieldCasing.php @@ -37,69 +37,60 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); //Check if current user has admin access if(is_admin($current_user)) { - global $mod_strings; - + global $mod_strings; + //echo out processing message echo '
'.$mod_strings['LBL_REPAIR_FIELD_CASING_PROCESSING']; - + //store the affected entries $database_entries = array(); $module_entries = array(); - + $query = "SELECT * FROM fields_meta_data"; - $result = $GLOBALS['db']->query($query); + $result = $GLOBALS['db']->query($query); while($row = $GLOBALS['db']->fetchByAssoc($result)) { $name = $row['name']; $id = $row['id']; $module_entries[$row['custom_module']] = true; - + //Only run database SQL where the name or id casing does is not lowercased if($name != strtolower($row['name'])) { - $database_entries[$row['custom_module']][$name] = $row; + $database_entries[$row['custom_module']][$name] = $row; } - } - + } + //If we have database entries to process if(!empty($database_entries)) { - + foreach($database_entries as $module=>$entries) { $table_name = strtolower($module) . '_cstm'; - + foreach($entries as $original_col_name=>$entry) { echo '
'. string_format($mod_strings['LBL_REPAIR_FIELD_CASING_SQL_FIELD_META_DATA'], array($entry['name'])); $update_sql = "UPDATE fields_meta_data SET id = '" . $entry['custom_module'] . strtolower($entry['name']) . "', name = '" . strtolower($entry['name']) . "' WHERE id = '" . $entry['id'] . "'"; - $GLOBALS['db']->query($update_sql); + $GLOBALS['db']->query($update_sql); echo '
'. string_format($mod_strings['LBL_REPAIR_FIELD_CASING_SQL_CUSTOM_TABLE'], array($entry['name'], $table_name)); - - if($GLOBALS['db']->dbType == 'mssql') { - $sql = "SP_RENAME '{$table_name}.{$entry['name']}', '" . strtolower($entry['name']) . "', 'COLUMN'"; - $GLOBALS['db']->query($sql); - } else if($GLOBALS['db']->dbType == 'mysql') { - $entry['name'] = strtolower($entry['name']); - $GLOBALS['db']->alterColumn($table_name, $entry); - } else if($GLOBALS['db']->dbType == 'oci8') { - $sql = "ALTER TABLE \"" . strtoupper($table_name) ."\" RENAME COLUMN \"" . $entry['name'] . "\" TO \"" . strtolower($entry['name']) . "\""; - $GLOBALS['db']->query($sql); - } + + $GLOBALS['db']->query($GLOBALS['db']->renameColumnSQL($table_name, $entry['name'], strtolower($entry['name']))); } } } - + //If we have metadata files to alter if(!empty($module_entries)) { $modules = array_keys($module_entries); $views = array('basic_search', 'advanced_search', 'detailview', 'editview', 'quickcreate'); $class_names = array(); - - require_once ('include/TemplateHandler/TemplateHandler.php') ; + + require_once ('include/TemplateHandler/TemplateHandler.php') ; require_once('modules/ModuleBuilder/parsers/ParserFactory.php'); - - foreach($modules as $module) { + + foreach($modules as $module) { if(isset($GLOBALS['beanList'][$module])) { $class_names[] = $GLOBALS['beanList'][$module]; } - + $repairClass->module_list[] = $module; foreach($views as $view) { try{ @@ -114,7 +105,7 @@ if(is_admin($current_user)) { foreach($panel as $row_id=>$row) { foreach($row as $entry_id=>$entry) { if(is_array($entry) && isset($entry['name'])) { - $parser->_viewdefs['panels'][$panel_id][$row_id][$entry_id]['name'] = strtolower($entry['name']); + $parser->_viewdefs['panels'][$panel_id][$row_id][$entry_id]['name'] = strtolower($entry['name']); } } } @@ -123,30 +114,30 @@ if(is_admin($current_user)) { //For basic_search and advanced_search views, just process the fields foreach($parser->_viewdefs as $entry_id=>$entry) { if(is_array($entry) && isset($entry['name'])) { - $parser->_viewdefs[$entry_id]['name'] = strtolower($entry['name']); - } + $parser->_viewdefs[$entry_id]['name'] = strtolower($entry['name']); + } } } - + //Save the changes $parser->handleSave(false); } //foreach - + //Now clear the cache of the .tpl files TemplateHandler::clearCache($module); - - + + } //foreach - + echo '
'.$mod_strings['LBL_CLEAR_VARDEFS_DATA_CACHE_TITLE']; require_once('modules/Administration/QuickRepairAndRebuild.php'); $repair = new RepairAndClear(); $repair->show_output = false; $repair->module_list = array($class_names); - $repair->clearVardefs(); + $repair->clearVardefs(); } - + echo '
'.$mod_strings['LBL_DIAGNOSTIC_DONE']; - + } ?> diff --git a/modules/Administration/RepairIndex.php b/modules/Administration/RepairIndex.php index cc37e11f..aee9340f 100644 --- a/modules/Administration/RepairIndex.php +++ b/modules/Administration/RepairIndex.php @@ -50,7 +50,7 @@ function compare($table_name, $db_indexes, $var_indexes) { $var_fields_string = implode('',$var_i_def['fields']); $field_list_match = false; if(isset($db_indexes[$var_i_name])) { - $sel_db_index = $db_indexes[$var_i_name]; + $sel_db_index = $db_indexes[$var_i_name]; $db_fields_string = implode('', $db_indexes[$var_i_name]['fields']); if(strcasecmp($var_fields_string, $db_fields_string)==0) { $field_list_match=true; @@ -60,29 +60,29 @@ function compare($table_name, $db_indexes, $var_indexes) { foreach ($db_indexes as $db_i_name=>$db_i_def) { $db_fields_string=implode('',$db_i_def['fields']); if(strcasecmp($var_fields_string , $db_fields_string)==0) { - $sel_db_index=$db_indexes[$db_i_name]; + $sel_db_index=$db_indexes[$db_i_name]; $field_list_match=true; break; } } - } + } - //no matching index in database. + //no matching index in database. if(empty($sel_db_index)) { - $add_index[]=$GLOBALS['db']->helper->add_drop_constraint($table_name,$var_i_def); + $add_index[]=$GLOBALS['db']->add_drop_constraint($table_name,$var_i_def); continue; } if(!$field_list_match) { //drop the db index and create new index based on vardef - $drop_index[]=$GLOBALS['db']->helper->add_drop_constraint($table_name,$sel_db_index,true); - $add_index[]=$GLOBALS['db']->helper->add_drop_constraint($table_name,$var_i_def); + $drop_index[]=$GLOBALS['db']->add_drop_constraint($table_name,$sel_db_index,true); + $add_index[]=$GLOBALS['db']->add_drop_constraint($table_name,$var_i_def); continue; } //check for name match. //it should not occur for indexes of type primary or unique. if( $var_i_def['type'] != 'primary' and $var_i_def['type'] != 'unique' and $var_i_def['name'] != $sel_db_index['name']) { //rename index. - $rename=$GLOBALS['db']->helper->rename_index($sel_db_index,$var_i_def,$table_name); + $rename=$GLOBALS['db']->renameIndexDefs($sel_db_index,$var_i_def,$table_name); if(is_array($rename)) { $change_index=array_merge($change_index,$rename); } else { @@ -90,7 +90,7 @@ function compare($table_name, $db_indexes, $var_indexes) { } continue; } - } + } } //// END LOCAL UTILITY /////////////////////////////////////////////////////////////////////////////// @@ -125,12 +125,12 @@ foreach ($beanFiles as $beanname=>$beanpath) { $focus= new $beanname(); //skips beans based on same tables. user, employee and group are an example. - if(empty($focus->table_name) || isset($processed_tables[$focus->table_name])) { + if(empty($focus->table_name) || isset($processed_tables[$focus->table_name])) { continue; } else { $processed_tables[$focus->table_name]=$focus->table_name; } - + if(!empty($dictionary[$focus->object_name]['indices'])) { $indices=$dictionary[$focus->object_name]['indices']; } else { @@ -145,13 +145,13 @@ foreach ($beanFiles as $beanname=>$beanpath) { if ($definition['type']=='fulltext') { continue; } - + if(empty($definition['db']) or $definition['db'] == $focus->db->dbType) { $var_indices[$definition['name']] = $definition; } } - $db_indices=$focus->db->helper->get_indices($focus->table_name); + $db_indices=$focus->db->get_indices($focus->table_name); compare($focus->table_name,$db_indices,$var_indices); } //// END PROCESS MODULE BEANS @@ -166,7 +166,7 @@ foreach ($dictionary as $rel=>$rel_def) { $indices=$rel_def['indices']; } else { $indices=array(); - } + } //clean vardef defintions.. removed indexes not value for this dbtype. //set index name as the key. @@ -177,7 +177,7 @@ foreach ($dictionary as $rel=>$rel_def) { } } - $db_indices=$focus->db->helper->get_indices($rel_def['table']); + $db_indices=$focus->db->get_indices($rel_def['table']); compare($rel_def['table'],$db_indices,$var_indices); } @@ -209,7 +209,7 @@ if((count($drop_index) > 0 or count($add_index) > 0 or count($change_index) > 0) foreach ($drop_index as $statement) { echo ($_REQUEST['silent']) ? "" : "
".$statement.";"; } - } + } } if(count($add_index) > 0) { @@ -242,7 +242,7 @@ if((count($drop_index) > 0 or count($add_index) > 0 or count($change_index) > 0) } } } - + if(!isset($_REQUEST['mode']) or $_REQUEST['mode'] != 'execute') { echo ($_REQUEST['silent']) ? "" : "


"; echo ($_REQUEST['silent']) ? "" : "Execute Script"; diff --git a/modules/Administration/RepairSeedUsers.php b/modules/Administration/RepairSeedUsers.php index d7f9dee8..53fc0db8 100644 --- a/modules/Administration/RepairSeedUsers.php +++ b/modules/Administration/RepairSeedUsers.php @@ -40,7 +40,7 @@ global $current_user; if(is_admin($current_user)){ if(count($_POST)){ if(!empty($_POST['activate'])){ - + $status = ''; if($_POST['activate'] == 'false'){ $status = 'Inactive'; @@ -53,13 +53,13 @@ if(is_admin($current_user)){ } $query = "SELECT status FROM users WHERE id LIKE 'seed%'"; $result = $GLOBALS['db']->query($query); - $row = $GLOBALS['db']->fetchByAssoc($result, -1, true); + $row = $GLOBALS['db']->fetchByAssoc($result); if(!empty($row['status'])){ $activate = 'false'; if($row['status'] == 'Inactive'){ $activate = 'true'; } - ?> + ?>

@@ -76,12 +76,12 @@ if(is_admin($current_user)){

\ No newline at end of file diff --git a/modules/Administration/SugarSpriteBuilder.php b/modules/Administration/SugarSpriteBuilder.php new file mode 100644 index 00000000..426b9884 --- /dev/null +++ b/modules/Administration/SugarSpriteBuilder.php @@ -0,0 +1,641 @@ + IMAGETYPE_GIF, + IMG_JPG => IMAGETYPE_JPEG, + IMG_PNG => IMAGETYPE_PNG, + ); + + // sprite settings + var $pngCompression = 9; + var $pngFilter = PNG_NO_FILTER; + var $maxWidth = 75; + var $maxHeight = 75; + var $rowCnt = 30; + + // processed image types + var $imageTypes = array(); + + // source files + var $spriteSrc = array(); + var $spriteRepeat = array(); + + // sprite resource images + var $spriteImg; + + // sprite_config collection + var $sprites_config = array(); + + + public function __construct() + { + // check if we have gd installed + if(function_exists('imagecreatetruecolor')) + { + $this->isAvailable = true; + foreach($this->supportedTypeMap as $gd_bit => $imagetype) + { + if(imagetypes() & $gd_bit) { + // swap gd_bit & imagetype + $this->imageTypes[$imagetype] = $gd_bit; + } + } + } + + if(function_exists('logThis') && isset($GLOBALS['path'])) + { + $this->writeToUpgradeLog = true; + } + } + + + /** + * addDirectory + * + * This function is used to create the spriteSrc array + * @param $name String value of the sprite name + * @param $dir String value of the directory associated with the sprite entry + */ + public function addDirectory($name, $dir) { + + // sprite namespace + if(!array_key_exists($name, $this->spriteSrc)) + { + $this->spriteSrc[$name] = array(); + } + + // add files from directory + $this->spriteSrc[$name][$dir] = $this->getFileList($dir); + } + + /** + * getFileList + * + * This method processes files in a directory and adds them to the sprites array + * @param $dir String value of the directory to scan for image files in + */ + private function getFileList($dir) { + $list = array(); + if(is_dir($dir)) { + if($dh = opendir($dir)) { + + // optional sprites_config.php file + $this->loadSpritesConfig($dir); + + while (($file = readdir($dh)) !== false) + { + if ($file != "." && $file != ".." && $file != "sprites_config.php") + { + + // file info & check supported image format + if($info = $this->getFileInfo($dir, $file)) { + + // skip excluded files + if(isset($this->sprites_config[$dir]['exclude']) && array_search($file, $this->sprites_config[$dir]['exclude']) !== false) + { + global $mod_strings; + $msg = string_format($mod_strings['LBL_SPRITES_EXCLUDING_FILE'], array("{$dir}/{$file}")); + $GLOBALS['log']->debug($msg); + $this->logMessage($msg); + } else { + // repeatable sprite ? + $isRepeat = false; + + if(isset($this->sprites_config[$dir]['repeat'])) + { + foreach($this->sprites_config[$dir]['repeat'] as $repeat) + { + if($info['x'] == $repeat['width'] && $info['y'] == $repeat['height']) + { + $id = md5($repeat['width'].$repeat['height'].$repeat['direction']); + $isRepeat = true; + $this->spriteRepeat['repeat_'.$repeat['direction'].'_'.$id][$dir][$file] = $info; + } + } + } + + if(!$isRepeat) + { + $list[$file] = $info; + } + } + } else if(preg_match('/\.(jpg|jpeg|gif|png|bmp|ico)$/i', $file)) { + $GLOBALS['log']->error('Unable to process image file ' . $file); + //$this->logMessage('Unable to process image file ' . $file); + } + } + } + } + closedir($dh); + } + return $list; + } + + + /** + * loadSpritesConfig + * + * This function is used to load the sprites_config.php file. The sprites_config.php file may be used to add entries + * to the sprites_config member variable which may contain a list of array entries of files/directories to exclude from + * being included into the sprites image. + * + * @param $dir String value of the directory containing the custom sprites_config.php file + */ + private function loadSpritesConfig($dir) { + $sprites_config = array(); + if(file_exists("$dir/sprites_config.php")) + { + include("$dir/sprites_config.php"); + if(count($sprites_config)) { + $this->sprites_config = array_merge($this->sprites_config, $sprites_config); + } + } + } + + + /** + * getFileInfo + * + * This is a private helper function to return attributes about an image. If the width, height or type of the + * image file cannot be determined, then we do not process the file. + * + * @return array of file info entries containing file information (x, y, type) if image type is supported + */ + private function getFileInfo($dir, $file) { + $result = false; + $info = @getimagesize($dir.'/'.$file); + if($info) { + + // supported image type ? + if(isset($this->imageTypes[$info[2]])) + { + $w = $info[0]; + $h = $info[1]; + $surface = $w * $h; + + // be sure we have an image size + $addSprite = false; + if($surface) + { + // sprite dimensions + if($w <= $this->maxWidth && $h <= $this->maxHeight) + { + $addSprite = true; + } + } + + if($addSprite) + { + $result = array(); + $result['x'] = $w; + $result['y'] = $h; + $result['type'] = $info[2]; + } + } else { + $msg = "Skipping unsupported image file type ({$info[2]}) for file {$file}"; + $GLOBALS['log']->error($msg); + $this->logMessage($msg."\n"); + } + } + return $result; + } + + + /** + * createSprites + * + * This is the public function to allow the sprites to be built. + * + * @return $result boolean value indicating whether or not sprites were created + */ + public function createSprites() { + + global $mod_strings; + + if(!$this->isAvailable) + { + if(!$this->silentRun) + { + $msg = $mod_strings['LBL_SPRITES_NOT_SUPPORTED']; + $GLOBALS['log']->warn($msg); + $this->logMessage($msg); + } + return false; + } + + // add repeatable sprites + if(count($this->spriteRepeat)) + { + $this->spriteSrc = array_merge($this->spriteSrc, $this->spriteRepeat); + } + + foreach($this->spriteSrc as $name => $dirs) + { + if(!$this->silentRun) + { + $msg = string_format($mod_strings['LBL_SPRITES_CREATING_NAMESPACE'], array($name)); + $GLOBALS['log']->debug($msg); + $this->logMessage($msg); + } + + // setup config for sprite placement algorithm + if(substr($name, 0, 6) == 'repeat') + { + $isRepeat = true; + $type = substr($name, 7, 10) == 'horizontal' ? 'horizontal' : 'vertical'; + $config = array( + 'type' => $type, + ); + } else { + $isRepeat = false; + $config = array( + 'type' => 'boxed', + 'width' => $this->maxWidth, + 'height' => $this->maxHeight, + 'rowcnt' => $this->rowCnt, + ); + } + + // use seperate class to arrange the images + $sp = new SpritePlacement($dirs, $config); + $sp->processSprites(); + + //if(! $this->silentRun) + // echo " (size {$sp->width()}x{$sp->height()})
"; + + // we need a target image size + if($sp->width() && $sp->height()) + { + // init sprite image + $this->initSpriteImg($sp->width(), $sp->height()); + + // add sprites based upon determined coordinates + foreach($dirs as $dir => $files) + { + if(!$this->silentRun) + { + $msg = string_format($mod_strings['LBL_SPRITES_PROCESSING_DIR'], array($dir)); + $GLOBALS['log']->debug($msg); + $this->logMessage($msg); + } + + foreach($files as $file => $info) + { + if($im = $this->loadImage($dir, $file, $info['type'])) + { + // coordinates + $dst_x = $sp->spriteMatrix[$dir.'/'.$file]['x']; + $dst_y = $sp->spriteMatrix[$dir.'/'.$file]['y']; + + imagecopy($this->spriteImg, $im, $dst_x, $dst_y, 0, 0, $info['x'], $info['y']); + imagedestroy($im); + + if(!$this->silentRun) + { + $msg = string_format($mod_strings['LBL_SPRITES_ADDED'], array("{$dir}/{$file}")); + $GLOBALS['log']->debug($msg); + $this->logMessage($msg); + } + } + } + } + + // dir & filenames + if($isRepeat) + { + $outputDir = sugar_cached("sprites/Repeatable"); + $spriteFileName = "{$name}.png"; + $cssFileName = "{$this->fileName}.css"; + $metaFileName = "{$this->fileName}.meta.php"; + $nameSpace = "Repeatable"; + } else { + $outputDir = sugar_cached("sprites/$name"); + $spriteFileName = "{$this->fileName}.png"; + $cssFileName = "{$this->fileName}.css"; + $metaFileName = "{$this->fileName}.meta.php"; + $nameSpace = "{$name}"; + } + + // directory structure + if(!is_dir(sugar_cached("sprites/$nameSpace"))) + { + sugar_mkdir(sugar_cached("sprites/$nameSpace"), 0775, true); + } + + // save sprite image + imagepng($this->spriteImg, "$outputDir/$spriteFileName", $this->pngCompression, $this->pngFilter); + imagedestroy($this->spriteImg); + + /* generate css & metadata */ + + $head = ''; + $body = ''; + $metadata = ''; + + foreach($sp->spriteSrc as $id => $info) + { + // sprite id + $hash_id = md5($id); + + // header + $head .= "span.spr_{$hash_id},\n"; + + // image size + $w = $info['x']; + $h = $info['y']; + + // image offset + $offset_x = $sp->spriteMatrix[$id]['x']; + $offset_y = $sp->spriteMatrix[$id]['y']; + + // sprite css + $body .= "/* {$id} */ +span.spr_{$hash_id} { +width: {$w}px; +height: {$h}px; +background-position: -{$offset_x}px -{$offset_y}px; +}\n"; + + $metadata .= '$sprites["'.$id.'"] = array ("class"=>"'.$hash_id.'","width"=>"'.$w.'","height"=>"'.$h.'");'."\n"; + } + + // common css header + $head = rtrim($head, "\n,")." {background: url('../../../index.php?entryPoint=getImage&imageName={$spriteFileName}&spriteNamespace={$nameSpace}'); no-repeat;display:inline-block;}\n"; + + // append mode for repeatable sprites + $fileMode = $isRepeat ? 'a' : 'w'; + + // save css + $css_content = "\n/* autogenerated sprites - $name */\n".$head.$body; + if($this->cssMinify) + { + $css_content = cssmin::minify($css_content); + } + $fh = fopen("$outputDir/$cssFileName", $fileMode); + fwrite($fh, $css_content); + fclose($fh); + + /* save metadata */ + $add_php_tag = (file_exists("$outputDir/$metaFileName") && $isRepeat) ? false : true; + $fh = fopen("$outputDir/$metaFileName", $fileMode); + if($add_php_tag) + { + fwrite($fh, 'silentRun) + { + $msg = string_format($mod_strings['LBL_SPRITES_ADDED'], array($name)); + $GLOBALS['log']->debug($msg); + $this->logMessage($msg); + } + + } + + } + return true; + } + + + /** + * initSpriteImg + * + * @param w int value representing width of sprite + * @param h int value representing height of sprite + * Private function to initialize creating the sprite canvas image + */ + private function initSpriteImg($w, $h) { + $this->spriteImg = imagecreatetruecolor($w,$h); + $transparent = imagecolorallocatealpha($this->spriteImg, 0, 0, 0, 127); + imagefill($this->spriteImg, 0, 0, $transparent); + imagealphablending($this->spriteImg, false); + imagesavealpha($this->spriteImg, true); + } + + + /** + * loadImage + * + * private function to load image resources + * + * @param $dir String value of directory where image is located + * @param $file String value of file + * @param $type String value of the file type (IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG) + * + */ + private function loadImage($dir, $file, $type) { + $path_file = $dir.'/'.$file; + switch($type) { + case IMAGETYPE_GIF: + return imagecreatefromgif($path_file); + case IMAGETYPE_JPEG: + return imagecreatefromjpeg($path_file); + case IMAGETYPE_PNG: + return imagecreatefrompng($path_file); + default: + return false; + } + } + + /** + * private logMessage + * + * This is a private function used to log messages generated from this class. Depending on whether or not + * silentRun or fromSilentUpgrade is set to true/false then it will either output to screen or write to log file + * + * @param $msg String value of message to log into file or echo into output buffer depending on the context + */ + private function logMessage($msg) + { + if(!$this->silentRun && !$this->fromSilentUpgrade) + { + echo $msg . '
'; + } else if ($this->fromSilentUpgrade && $this->writeToUpgradeLog) { + logThis($msg, $GLOBALS['path']); + } else if(!$this->silentRun) { + echo $msg . "\n"; + } + } +} + + +/** + * SpritePlacement + * + */ +class SpritePlacement +{ + + // occupied space + var $spriteMatrix = array(); + + // minimum surface + var $minSurface = 0; + + // sprite src (flattened array) + var $spriteSrc = array(); + + // placement config array + /* + type = boxed + horizontal + vertical + + required params for + type 1 -> width + -> height + -> rowcnt + + */ + var $config = array(); + + function __construct($spriteSrc, $config) { + + // convert spriteSrc to flat array + foreach($spriteSrc as $dir => $files) { + foreach($files as $file => $info) { + // use full path as identifier + $full_path = $dir.'/'.$file; + $this->spriteSrc[$full_path] = $info; + } + } + + $this->config = $config; + } + + function processSprites() { + + foreach($this->spriteSrc as $id => $info) { + + // dimensions + $x = $info['x']; + $y = $info['y']; + + // update min surface + $this->minSurface += $x * $y; + + // get coordinates where to add this sprite + if($coor = $this->addSprite($x, $y)) { + $this->spriteMatrix[$id] = $coor; + } + } + } + + // returns x/y coordinates to fit the sprite + function addSprite($w, $h) { + $result = false; + + switch($this->config['type']) { + + // boxed + case 'boxed': + + $spriteX = $this->config['width']; + $spriteY = $this->config['height']; + $spriteCnt = count($this->spriteMatrix) + 1; + $y = ceil($spriteCnt / $this->config['rowcnt']); + $x = $spriteCnt - (($y - 1) * $this->config['rowcnt']); + $result = array( + 'x' => ($x * $spriteX) + 1 - $spriteX, + 'y' => ($y * $spriteY) + 1 - $spriteY); + + break; + + // horizontal -> align vertically + case 'horizontal': + $result = array('x' => 1, 'y' => $this->height() + 1); + break; + + // vertical -> align horizontally + case 'vertical': + $result = array('x' => $this->width() + 1, 'y' => 1); + break; + + default: + $GLOBALS['log']->warn(__CLASS__.": Unknown sprite placement algorithm -> {$this->config['type']}"); + break; + } + + return $result; + } + + // calculate total width + function width() { + return $this->getMaxAxis('x'); + } + + // calculate total height + function height() { + return $this->getMaxAxis('y'); + } + + // helper function to get highest axis value + function getMaxAxis($axis) { + $val = 0; + foreach($this->spriteMatrix as $id => $coor) { + $new_val = $coor[$axis] + $this->spriteSrc[$id][$axis] - 1; + if($new_val > $val) { + $val = $new_val; + } + } + return $val; + } +} + +?> \ No newline at end of file diff --git a/modules/Administration/SupportPortal.php b/modules/Administration/SupportPortal.php index 503ee98c..948422d0 100644 --- a/modules/Administration/SupportPortal.php +++ b/modules/Administration/SupportPortal.php @@ -66,6 +66,7 @@ switch ($_REQUEST['view']) { $sugar_smarty = new Sugar_Smarty(); $sugar_smarty->assign('iframeURL', $iframe_url); + $sugar_smarty->assign('langHeader', get_language_header()); echo $sugar_smarty->fetch('modules/Administration/SupportPortal.tpl'); break; @@ -108,6 +109,7 @@ switch ($_REQUEST['view']) { $sugar_smarty->assign('table', "
"); $sugar_smarty->assign('endtable', "
"); $sugar_smarty->assign('charset', $app_strings['LBL_CHARSET']); + $sugar_smarty->assign('langHeader', get_language_header()); echo $sugar_smarty->fetch('modules/Administration/SupportPortal.tpl'); } else { diff --git a/modules/Administration/SupportPortal.tpl b/modules/Administration/SupportPortal.tpl index 121221f6..3ca0c8a9 100644 --- a/modules/Administration/SupportPortal.tpl +++ b/modules/Administration/SupportPortal.tpl @@ -41,7 +41,7 @@ {if $helpFileExists} - + {$title} {$styleSheet} @@ -77,5 +77,5 @@ function createBookmarkLink(title, url){ {else} - + {/if} \ No newline at end of file diff --git a/modules/Administration/Upgrade.php b/modules/Administration/Upgrade.php index ff32648f..75ef0cd7 100644 --- a/modules/Administration/Upgrade.php +++ b/modules/Administration/Upgrade.php @@ -47,10 +47,10 @@ global $gridline; echo getClassicModuleTitle($mod_strings['LBL_MODULE_NAME'], array($mod_strings['LBL_UPGRADE_TITLE']), false); $str1=""; -if ($GLOBALS['db']->dbType=='oci8') { - +if ($GLOBALS['db']->supports('fulltext')) { + $str1=''; - $str1.=SugarThemeRegistry::current()->getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_ORACLE_FULLTEXT'].'" align="absmiddle" border="0"'); + $str1.=SugarThemeRegistry::current()->getImage('Repair','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REPAIR_ORACLE_FULLTEXT']); $str1.=' ' . $mod_strings['LBL_REPAIR_ORACLE_FULLTEXT'] .''; $str1.='' .$mod_strings['LBL_REPAIR_ORACLE_FULLTEXT_DESC'] . ''; } @@ -58,87 +58,93 @@ if ($GLOBALS['db']->dbType=='oci8') {

- + - + - - + - + - +?> - + - + - + - + - + - + - + - + + + + + + + - + - + - + - + - + - + - +
getImage('Repair','alt="'. $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_QUICK_REPAIR_AND_REBUILD']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_EXPAND_DATABASE_COLUMNS'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_EXPAND_DATABASE_COLUMNS']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_HTACCESS'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REBUILD_HTACCESS']); ?>  getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_WEBCONFIG'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REBUILD_WEBCONFIG']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_CONFIG'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REBUILD_CONFIG']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_REL_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REBUILD_REL_TITLE']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_SCHEDULERS_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REBUILD_SCHEDULERS_TITLE']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_DASHLETS_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REBUILD_DASHLETS_TITLE']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_JAVASCRIPT_LANG_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REBUILD_JAVASCRIPT_LANG_TITLE']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_JS_FILES_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REBUILD_JS_FILES_TITLE']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_CONCAT_JS_FILES_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REBUILD_CONCAT_JS_FILES_TITLE']); ?> 
getImage('Rebuild','alt="'. $mod_strings['LBL_REBUILD_JS_MINI_FILES_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Rebuild','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REBUILD_JS_MINI_FILES_TITLE']); ?> 
getImage('Rebuild','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REBUILD_SPRITES_TITLE']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_JS_FILES_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REPAIR_JS_FILES_TITLE']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_FIELD_CASING_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REPAIR_FIELD_CASING_TITLE']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_ROLES'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"',null,null,'.gif',$mod_strings['LBL_REPAIR_ROLES']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_IE'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REPAIR_IE']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_XSS'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REPAIR_XSS']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_ACTIVITIES'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REPAIR_ACTIVITIES']); ?> 
getImage('Repair','alt="'. $mod_strings['LBL_REPAIR_SEED_USERS_TITLE'].'" align="absmiddle" border="0"'); ?> getImage('Repair','align="absmiddle" border="0"', null,null,'.gif',$mod_strings['LBL_REPAIR_SEED_USERS_TITLE']); ?> 

diff --git a/modules/Administration/UpgradeAccess.php b/modules/Administration/UpgradeAccess.php index 8d8a17c1..e9f47a21 100644 --- a/modules/Administration/UpgradeAccess.php +++ b/modules/Administration/UpgradeAccess.php @@ -44,16 +44,16 @@ global $sugar_config; $ignoreCase = (substr_count(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache/2') > 0)?'(?i)':''; $htaccess_file = getcwd() . "/.htaccess"; $contents = ''; -$restrict_str = <<' . $mod_strings['LBL_HT_NO_WRITE'] . '$htaccess_file

\n'; - echo '

' . $mod_strings['LBL_HT_NO_WRITE_2'] . '

\n'; - echo "$redirect_str"; + echo '

' . $mod_strings['LBL_HT_NO_WRITE'] . "{$htaccess_file}

\n"; + echo '

' . $mod_strings['LBL_HT_NO_WRITE_2'] . "

\n"; + echo "{$redirect_str}\n"; } @@ -80,19 +83,11 @@ $uploadDir=''; $uploadHta=''; if (empty($GLOBALS['sugar_config']['upload_dir'])) { - $GLOBALS['sugar_config']['upload_dir']='cache/upload/'; -} -$uploadDir = getcwd()."/".$sugar_config['upload_dir']; -if(file_exists($uploadDir)){ - $uploadHta = $uploadDir.".htaccess"; -} -else{ - mkdir_recursive($uploadDir); - if(is_dir($uploadDir)){ - $uploadHta = $uploadDir.".htaccess"; - } + $GLOBALS['sugar_config']['upload_dir']='upload/'; } +$uploadHta = "upload://.htaccess"; + $denyAll =<< Order Deny,Allow @@ -102,36 +97,28 @@ eoq; if(file_exists($uploadHta) && filesize($uploadHta)) { // file exists, parse to make sure it is current - if(is_writable($uploadHta) && ($fpUploadHta = @sugar_fopen($uploadHta, "r+"))) { + if(is_writable($uploadHta)) { $oldHtaccess = file_get_contents($uploadHta); // use a different regex boundary b/c .htaccess uses the typicals - if(!preg_match("=".$denyAll."=", $oldHtaccess)) { + if(strstr($oldHtaccess, $denyAll) === false) { + $oldHtaccess .= "\n"; $oldHtaccess .= $denyAll; } - - rewind($fpUploadHta); - fwrite($fpUploadHta, $oldHtaccess); - ftruncate($fpUploadHta, ftell($fpUploadHta)); - fclose($fpUploadHta); + if(!file_put_contents($uploadHta, $oldHtaccess)) { + $htaccess_failed = true; + } } else { $htaccess_failed = true; } } else { // no .htaccess yet, create a fill - if($fpUploadHta = @sugar_fopen($uploadHta, "w")) { - fputs($fpUploadHta, $denyAll); - fclose($fpUploadHta); - } else { + if(!file_put_contents($uploadHta, $denyAll)) { $htaccess_failed = true; } } - - - include('modules/Versions/ExpectedVersions.php'); - global $expect_versions; if (isset($expect_versions['htaccess'])) { diff --git a/modules/Administration/UpgradeFields.php b/modules/Administration/UpgradeFields.php index a183d00e..ce595c89 100644 --- a/modules/Administration/UpgradeFields.php +++ b/modules/Administration/UpgradeFields.php @@ -43,10 +43,6 @@ global $db; if (!isset ($db)) { $db = DBManagerFactory:: getInstance(); } -global $dbManager; -if (!isset ($dbManager)) { - $dbManager = DBManagerFactory::getInstance(); -} $result = $db->query('SELECT * FROM fields_meta_data WHERE deleted = 0 ORDER BY custom_module'); $modules = array (); @@ -79,38 +75,20 @@ foreach ($modules as $the_module => $fields) { $mod->custom_fields->createCustomTable(); } - if ($db->dbType == 'oci8') { - } elseif ($db->dbType == 'mssql') { - $def_query="SELECT col.name as field, col_type.name as type, col.is_nullable, col.precision as data_precision, col.max_length as data_length, col.scale data_scale"; - $def_query.=" FROM sys.columns col"; - $def_query.=" join sys.types col_type on col.user_type_id=col_type.user_type_id "; - $def_query.=" where col.object_id = (select object_id(sys.schemas.name + '.' + sys.tables.name)"; - $def_query.=" from sys.tables join sys.schemas on sys.schemas.schema_id = sys.tables.schema_id"; - $def_query.=" where sys.tables.name='".$mod->table_name."_cstm')"; - $result = $db->query($def_query); - } - else { - $result = $db->query("DESCRIBE $mod->table_name"."_cstm"); - } - - while ($row = $db->fetchByAssoc($result)) { + $table = $db->getTableDescription($mod->table_name."_cstm"); + foreach($table as $row) { $col = strtolower(empty ($row['Field']) ? $row['field'] : $row['Field']); $the_field = $mod->custom_fields->getField($col); $type = strtolower(empty ($row['Type']) ? $row['type'] : $row['Type']); - if ($db->dbType == 'oci8' or $db->dbType == 'mssql') { - if ($row['data_precision']!= '' and $row['data_scale']!='') { - $type.='(' . $row['data_precision']; - if (!empty($row['data_scale'])) { - $type.=',' . $row['data_scale']; - } - $type.=')'; - } else { - if ($row['data_length']!= '' && (strtolower($row['type'])=='varchar' or strtolower($row['type'])=='varchar2')) { - $type.='(' . $row['data_length'] . ')'; - - } - } - } + if (!empty($row['data_precision']) && !empty($row['data_scale'])) { + $type.='(' . $row['data_precision']; + if (!empty($row['data_scale'])) { + $type.=',' . $row['data_scale']; + } + $type.=')'; + } elseif(!empty($row['data_length']) && (strtolower($row['type'])=='varchar' or strtolower($row['type'])=='varchar2')) { + $type.='(' . $row['data_length'] . ')'; + } if (!isset ($fields[$col]) && $col != 'id_c') { if (!$simulate) { $db->query("ALTER TABLE $mod->table_name"."_cstm DROP COLUMN $col"); @@ -119,9 +97,8 @@ foreach ($modules as $the_module => $fields) { echo "Dropping Column $col from $mod->table_name"."_cstm for module $the_module
"; } else { if ($col != 'id_c') { - //$db_data_type = $dbManager->helper->getColumnType(strtolower($the_field->data_type)); $db_data_type = strtolower(str_replace(' ' , '', $the_field->get_db_type())); - + $type = strtolower(str_replace(' ' , '', $type)); if (strcmp($db_data_type,$type) != 0) { diff --git a/modules/Administration/UpgradeHistory.php b/modules/Administration/UpgradeHistory.php index 3e02b148..1e2d0a6f 100644 --- a/modules/Administration/UpgradeHistory.php +++ b/modules/Administration/UpgradeHistory.php @@ -66,7 +66,7 @@ class UpgradeHistory extends SugarBean function delete() { - $this->dbManager->query( "delete from " . $this->table_name . " where id = '" . $this->id . "'" ); + $this->db->query( "delete from " . $this->table_name . " where id = " . $this->db->quoted($this->id)); } function UpgradeHistory() diff --git a/modules/Administration/UpgradeWizard.php b/modules/Administration/UpgradeWizard.php index fabe53ab..b6050f00 100644 --- a/modules/Administration/UpgradeWizard.php +++ b/modules/Administration/UpgradeWizard.php @@ -38,7 +38,7 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); if(!is_admin($GLOBALS['current_user'])){ - sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); + sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); } require_once('modules/Administration/UpgradeWizardCommon.php'); require_once('ModuleInstall/PackageManager/PackageManagerDisplay.php'); @@ -49,12 +49,17 @@ $uh = new UpgradeHistory(); function unlinkTempFiles() { global $sugar_config; @unlink($_FILES['upgrade_zip']['tmp_name']); - @unlink(getAbsolutePath($sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'],true)); + @unlink("upload://".$_FILES['upgrade_zip']['name']); } +$base_upgrade_dir = "upload://upgrades"; +$base_tmp_upgrade_dir = sugar_cached('upgrades/temp'); + // make sure dirs exist foreach( $GLOBALS['subdirs'] as $subdir ){ - mkdir_recursive( "$base_upgrade_dir/$subdir" ); + if(!file_exists("$base_upgrade_dir/$subdir")) { + sugar_mkdir("$base_upgrade_dir/$subdir", 0770, true); + } } // get labels and text that are specific to either Module Loader or Upgrade Wizard @@ -97,124 +102,102 @@ if( isset( $_REQUEST['run'] ) && ($_REQUEST['run'] != "") ){ if(isset($_REQUEST['release_id']) && $_REQUEST['release_id'] != ""){ require_once('ModuleInstall/PackageManager.php'); $pm = new PackageManager(); - $tempFile = $pm->download('','',$_REQUEST['release_id'], getAbsolutePath($sugar_config['upload_dir'],true)); + $tempFile = $pm->download('','',$_REQUEST['release_id']); $perform = true; $base_filename = urldecode($tempFile); - } - elseif(!empty($_REQUEST['load_module_from_dir'])){ + } elseif(!empty($_REQUEST['load_module_from_dir'])) { //copy file to proper location then call performSetup - $tempFile = getAbsolutePath($sugar_config['upload_dir'].$_REQUEST['upgrade_zip_escaped'],true); - copy($_REQUEST['load_module_from_dir'].'/'.$_REQUEST['upgrade_zip_escaped'], $tempFile); + copy($_REQUEST['load_module_from_dir'].'/'.$_REQUEST['upgrade_zip_escaped'], "upload://".$_REQUEST['upgrade_zip_escaped']); $perform = true; $base_filename = urldecode( $_REQUEST['upgrade_zip_escaped'] ); - }else if( empty( $_FILES['upgrade_zip']['tmp_name'] ) ){ - echo $mod_strings['ERR_UW_NO_UPLOAD_FILE']; - } - else{ - $ext = end(explode(".", $_FILES['upgrade_zip']['name'])); - if($ext === $_FILES['upgrade_zip']['name'] || $ext != 'zip' || !move_uploaded_file($_FILES['upgrade_zip']['tmp_name'], getAbsolutePath($sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'],true))) { - unlinkTempFiles(); - sugar_die("Invalid Package"); - } else { - $tempFile = getAbsolutePath($sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'],true); - $perform = true; - $base_filename = urldecode( $_REQUEST['upgrade_zip_escaped'] ); - } + } else { + if( empty( $_FILES['upgrade_zip']['tmp_name'] ) ){ + echo $mod_strings['ERR_UW_NO_UPLOAD_FILE']; + } else{ + $upload = new UploadFile('upgrade_zip'); + if(!$upload->confirm_upload() || + strtolower(pathinfo($upload->get_stored_file_name(), PATHINFO_EXTENSION)) != 'zip' || + !$upload->final_move($upload->get_stored_file_name()) + ) { + unlinkTempFiles(); + sugar_die("Invalid Package"); + } else { + $tempFile = "upload://".$upload->get_stored_file_name(); + $perform = true; + $base_filename = urldecode( $_REQUEST['upgrade_zip_escaped'] ); + } + } } - if($perform){ + if($perform) { $manifest_file = extractManifest( $tempFile ); - if(is_file($manifest_file)) - { - //SCAN THE MANIFEST FILE TO MAKE SURE NO COPIES OR ANYTHING ARE HAPPENING IN IT - $ms = new ModuleScanner(); - $fileIssues = $ms->scanFile($manifest_file); - if(!empty($fileIssues)){ - echo '

' . $mod_strings['ML_MANIFEST_ISSUE'] . '


'; - $ms->displayIssues(); - die(); + if(is_file($manifest_file)) + { + //SCAN THE MANIFEST FILE TO MAKE SURE NO COPIES OR ANYTHING ARE HAPPENING IN IT + $ms = new ModuleScanner(); + $fileIssues = $ms->scanFile($manifest_file); + if(!empty($fileIssues)){ + echo '

' . $mod_strings['ML_MANIFEST_ISSUE'] . '


'; + $ms->displayIssues(); + die(); + } + require_once( $manifest_file ); + validate_manifest( $manifest ); + + $upgrade_zip_type = $manifest['type']; + + // exclude the bad permutations + if( $view == "module" ) { + if ($upgrade_zip_type != "module" && $upgrade_zip_type != "theme" && $upgrade_zip_type != "langpack") { + unlinkTempFiles(); + die($mod_strings['ERR_UW_NOT_ACCEPTIBLE_TYPE']); + } + } elseif( $view == "default" ) { + if($upgrade_zip_type != "patch" ) { + unlinkTempFiles(); + die($mod_strings['ERR_UW_ONLY_PATCHES']); + } + } + + $base_filename = pathinfo($tempFile, PATHINFO_BASENAME); + + mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" ); + $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename"; + $target_manifest = remove_file_extension( $target_path ) . "-manifest.php"; + + if( isset($manifest['icon']) && $manifest['icon'] != "" ){ + $icon_location = extractFile( $tempFile ,$manifest['icon'] ); + copy($icon_location, remove_file_extension( $target_path )."-icon.".pathinfo($icon_location, PATHINFO_EXTENSION)); + } + + if(rename( $tempFile , $target_path )) { + copy( $manifest_file, $target_manifest ); + $GLOBALS['ML_STATUS_MESSAGE'] = $base_filename.$mod_strings['LBL_UW_UPLOAD_SUCCESS']; + } else{ + $GLOBALS['ML_STATUS_MESSAGE'] = $mod_strings['ERR_UW_UPLOAD_ERROR']; } - require_once( $manifest_file ); - validate_manifest( $manifest ); - - $upgrade_zip_type = $manifest['type']; - - // exclude the bad permutations - if( $view == "module" ) - { - if ($upgrade_zip_type != "module" && $upgrade_zip_type != "theme" && $upgrade_zip_type != "langpack") - { - unlinkTempFiles(); - die($mod_strings['ERR_UW_NOT_ACCEPTIBLE_TYPE']); - } - } - elseif( $view == "default" ) - { - if($upgrade_zip_type != "patch" ) - { - unlinkTempFiles(); - die($mod_strings['ERR_UW_ONLY_PATCHES']); - } - } - - //$base_filename = urldecode( $_REQUEST['upgrade_zip_escaped'] ); - $base_filename = preg_replace( "#\\\\#", "/", $base_filename ); - $base_filename = basename( $base_filename ); - - mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" ); - $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename"; - $target_manifest = remove_file_extension( $target_path ) . "-manifest.php"; - - if( isset($manifest['icon']) && $manifest['icon'] != "" ){ - $icon_location = extractFile( $tempFile ,$manifest['icon'] ); - $path_parts = pathinfo( $icon_location ); - copy( $icon_location, remove_file_extension( $target_path ) . "-icon." . $path_parts['extension'] ); - } - - if( copy( $tempFile , $target_path ) ){ - copy( $manifest_file, $target_manifest ); - $GLOBALS['ML_STATUS_MESSAGE'] = $base_filename.$mod_strings['LBL_UW_UPLOAD_SUCCESS']; - } - else{ - $GLOBALS['ML_STATUS_MESSAGE'] = $mod_strings['ERR_UW_UPLOAD_ERROR']; - } - } - else - { - unlinkTempFiles(); - die($mod_strings['ERR_UW_NO_MANIFEST']); - } - } - } - else if( $run == $mod_strings['LBL_UW_BTN_DELETE_PACKAGE'] ){ + } else { + unlinkTempFiles(); + die($mod_strings['ERR_UW_NO_MANIFEST']); + } + } + } else if( $run == $mod_strings['LBL_UW_BTN_DELETE_PACKAGE'] ){ if(!empty ($_REQUEST['install_file']) ){ die($mod_strings['ERR_UW_NO_UPLOAD_FILE']); } - + $delete_me = hashToFile($delete_me); - $checkFile = clean_path(trim(strtolower($delete_me))); - - if(false !== strpos($checkFile, '.zip')) { // is zip file? - if(false !== strpos($checkFile, $sugar_config['upload_dir'])) { // is in upload dir? - if(false === strpos($checkFile, "..")) { // no dir navigation - if(!file_exists($checkFile)) { // file exists? - if(unlink($delete_me)) { // successful deletion? - echo "Package $delete_me has been removed.
"; - } else { - die("Problem removing package $delete_me."); - } - } else { - die("File to be deleted does not exist."); - } - } else { - die("Path is trying to navigate folders."); - } - } else { - die("File is not located in SugarCRM's upload cache directory."); - } + $checkFile = strtolower($delete_me); + + if(substr($delete_me, -4) != ".zip" || substr($delete_me, 0, 9) != "upload://" || + strpos($checkFile, "..") !== false || !file_exists($checkFile)) { + die("File is not a zipped archive."); + } + if(unlink($delete_me)) { // successful deletion? + echo "Package $delete_me has been removed.
"; } else { - die("File is not a zipped archive."); + die("Problem removing package $delete_me."); } } } @@ -244,7 +227,7 @@ if(!empty($GLOBALS['sugar_config']['use_common_ml_dir']) && $GLOBALS['sugar_conf //rrs }else{ -$form =<< diff --git a/modules/Administration/UpgradeWizardCommon.php b/modules/Administration/UpgradeWizardCommon.php index 8c7e45fe..0484fff1 100644 --- a/modules/Administration/UpgradeWizardCommon.php +++ b/modules/Administration/UpgradeWizardCommon.php @@ -39,12 +39,8 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/utils/db_utils.php'); - require_once('include/utils/zip_utils.php'); - - - // increase the cuttoff time to 1 hour ini_set("max_execution_time", "3600"); @@ -60,9 +56,10 @@ else{ $form_action = "index.php?module=Administration&view=" . $view . "&action=UpgradeWizard"; -$base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades"; -$base_tmp_upgrade_dir = "$base_upgrade_dir/temp"; -$GLOBALS['subdirs'] = array('full', 'langpack', 'module', 'patch', 'theme', 'temp'); +$base_upgrade_dir = "upload://upgrades"; +$base_tmp_upgrade_dir = sugar_cached('upgrades/temp'); + +$GLOBALS['subdirs'] = array('full', 'langpack', 'module', 'patch', 'theme'); // array of special scripts that are executed during (un)installation-- key is type of script, value is filename if(!defined('SUGARCRM_PRE_INSTALL_FILE')) @@ -83,7 +80,7 @@ $script_files = array( function extractFile( $zip_file, $file_in_zip ){ global $base_tmp_upgrade_dir; if(empty($base_tmp_upgrade_dir)){ - $base_tmp_upgrade_dir = $GLOBALS['sugar_config']['upload_dir'] . "upgrades/temp"; + $base_tmp_upgrade_dir = sugar_cached("upgrades/temp"); } $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir ); unzip_file( $zip_file, $file_in_zip, $my_zip_dir ); @@ -97,7 +94,7 @@ function extractManifest( $zip_file ){ function getInstallType( $type_string ){ // detect file type global $subdirs; - + foreach( $subdirs as $subdir ){ if( preg_match( "#/$subdir/#", $type_string ) ){ return( $subdir ); @@ -108,23 +105,23 @@ function getInstallType( $type_string ){ } function getImageForType( $type ){ - + $icon = ""; switch( $type ){ case "full": - $icon = SugarThemeRegistry::current()->getImage("Upgrade", "" ); + $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_DST_UPGRADE']); break; case "langpack": - $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "" ); + $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGUAGE_PACKS'] ); break; case "module": - $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "" ); + $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULE_LOADER_TITLE']); break; case "patch": - $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "" ); + $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCH_UPGRADES'] ); break; case "theme": - $icon = SugarThemeRegistry::current()->getImage("Themes", "" ); + $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEME_SETTINGS'] ); break; default: break; @@ -153,22 +150,6 @@ function getUITextForMode( $mode ){ return $mod_strings[$mode]; } -/** - * @deprecated - * @todo this function doesn't seemed to be used anymore; trying kill this off - */ -function run_upgrade_wizard_sql( $script ){ - global $unzip_dir; - global $sugar_config; - global $mod_strings; - - $db_type = $sugar_config['dbconfig']['db_type']; - $script = str_replace( "%db_type%", $db_type, $script ); - if( !run_sql_file( "$unzip_dir/$script" ) ){ - die( "{$mod_strings['ERR_UW_RUN_SQL']} $unzip_dir/$script" ); - } -} - function validate_manifest( $manifest ){ // takes a manifest.php manifest array and validates contents global $subdirs; @@ -259,6 +240,6 @@ function getDiffFiles($unzip_dir, $install_file, $is_install = true, $previous_v }//fi }//rof }//fi - return $modified_files; + return $modified_files; } ?> diff --git a/modules/Administration/UpgradeWizard_commit.php b/modules/Administration/UpgradeWizard_commit.php index f3780591..da2471db 100644 --- a/modules/Administration/UpgradeWizard_commit.php +++ b/modules/Administration/UpgradeWizard_commit.php @@ -40,8 +40,8 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('modules/Administration/UpgradeWizardCommon.php'); require_once('modules/Configurator/Configurator.php'); function UWrebuild() { - $log =& $GLOBALS['log']; - $db =& $GLOBALS['db']; + global $log; + global $db; $log->info('Deleting Relationship Cache. Relationships will automatically refresh.'); echo " @@ -106,8 +106,7 @@ function UWrebuild() { unset($_SESSION['rebuild_relationships']); unset($_SESSION['rebuild_extensions']); -$log =& $GLOBALS['log']; -$db =& $GLOBALS['db']; +global $log, $db; // process commands if( !isset($_REQUEST['mode']) || ($_REQUEST['mode'] == "") ){ @@ -125,10 +124,10 @@ if( !isset($_REQUEST['copy_count']) || ($_REQUEST['copy_count'] == "") ){ die($mod_strings['ERR_UW_NO_FILES']); } -if( !isset($_REQUEST['unzip_dir']) || ($_REQUEST['unzip_dir'] == "") ){ +if( empty($_REQUEST['unzip_dir']) || $_REQUEST['unzip_dir'] == "." || $_REQUEST['unzip_dir'] == ".."){ die($mod_strings['ERR_UW_NO_TEMP_DIR']); } -$unzip_dir = $_REQUEST['unzip_dir']; +$unzip_dir = $base_tmp_upgrade_dir. "/". basename($_REQUEST['unzip_dir']); if(empty($_REQUEST['install_file'])){ die($mod_strings['ERR_UW_NO_INSTALL_FILE']); @@ -191,7 +190,7 @@ if($install_type == 'module'){ $file_action = ""; $uh_status = ""; -$rest_dir = clean_path( remove_file_extension($install_file)."-restore"); +$rest_dir = remove_file_extension($install_file)."-restore"; $files_to_handle = array(); @@ -530,8 +529,8 @@ if(isset($lang_changed_string)) print($lang_changed_string); if ($install_type != "module" && $install_type != "langpack"){ if( sizeof( $files_to_handle ) > 0 ){ - echo '
Show Details
-
Hide Details

'; + echo '
' . SugarThemeRegistry::current()->getImage('advanced_search', '', null, null, ".gif", $mod_strings['LBL_ADVANCED_SEARCH']) . ' Show Details
+
' . SugarThemeRegistry::current()->getImage('basic_search', '', null, null, ".gif", $mod_strings['LBL_BASIC_SEARCH']) . ' Hide Details

'; print( "{$mod_strings['LBL_UW_FOLLOWING_FILES']} $file_action:
\n" ); print( "
    \n" ); foreach( $files_to_handle as $file_to_copy ){ diff --git a/modules/Administration/UpgradeWizard_prepare.php b/modules/Administration/UpgradeWizard_prepare.php index f816f646..d9deca88 100644 --- a/modules/Administration/UpgradeWizard_prepare.php +++ b/modules/Administration/UpgradeWizard_prepare.php @@ -52,6 +52,10 @@ if( !isset($_REQUEST['mode']) || ($_REQUEST['mode'] == "") ){ die( "No mode specified." ); } +if(!file_exists($base_tmp_upgrade_dir)) { + mkdir($base_tmp_upgrade_dir, 0755, true); +} + $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir ); $install_file = hashToFile($_REQUEST['install_file']); $hidden_fields = ""; @@ -230,8 +234,7 @@ if(empty($new_studio_mod_files)) { echo $mod_strings['LBL_UW_ENABLE_READY']; else echo $mod_strings['LBL_UW_PATCH_READY']; -} -else { +} else { echo $mod_strings['LBL_UW_PATCH_READY2']; echo ' '.$mod_strings['LBL_UW_CHECK_ALL']; foreach($new_studio_mod_files as $the_file) { @@ -358,7 +361,7 @@ if( $show_files == true ){ $new_studio_mod_files = array(); $new_sugar_mod_files = array(); - $cache_html_files = findAllFilesRelative( "{$GLOBALS['sugar_config']['cache_dir']}layout", array()); + $cache_html_files = findAllFilesRelative( sugar_cached("layout"), array()); foreach($new_files as $the_file) { if(substr(strtolower($the_file), -5, 5) == '.html' && in_array($the_file, $cache_html_files)) @@ -385,9 +388,9 @@ if( $show_files == true ){ echo '

    '; echo '
    - '.' '.$mod_strings['LBL_UW_SHOW_DETAILS'].'
    + '.SugarThemeRegistry::current()->getImage('advanced_search', '', null, null, ".gif", $mod_strings['LBL_ADVANCED_SEARCH']).$mod_strings['LBL_UW_SHOW_DETAILS'].'
    ' - .' '.$mod_strings['LBL_UW_HIDE_DETAILS'].'

    '; + .SugarThemeRegistry::current()->getImage('basic_search', '', null, null, ".gif", $mod_strings['LBL_BASIC_SEARCH']).$mod_strings['LBL_UW_HIDE_DETAILS'].'

    '; echo ' '.$mod_strings['LBL_UW_CHECK_ALL']; echo '
      '; foreach( $new_sugar_mod_files as $the_file ){ @@ -521,12 +524,12 @@ echo ' +
      diff --git a/modules/Administration/templates/ConfigureTabs.tpl b/modules/Administration/templates/ConfigureTabs.tpl index a9ce21a0..76e0b8c6 100644 --- a/modules/Administration/templates/ConfigureTabs.tpl +++ b/modules/Administration/templates/ConfigureTabs.tpl @@ -36,7 +36,7 @@ *} - + diff --git a/modules/Administration/templates/GlobalSearchSettings.tpl b/modules/Administration/templates/GlobalSearchSettings.tpl index 809701d1..fb9a1757 100644 --- a/modules/Administration/templates/GlobalSearchSettings.tpl +++ b/modules/Administration/templates/GlobalSearchSettings.tpl @@ -35,7 +35,7 @@ ********************************************************************************/ *} - + diff --git a/modules/Administration/templates/Languages.tpl b/modules/Administration/templates/Languages.tpl index 075e450d..02ecdc10 100644 --- a/modules/Administration/templates/Languages.tpl +++ b/modules/Administration/templates/Languages.tpl @@ -36,7 +36,7 @@ *} - +{sugar_getscript file="cache/include/javascript/sugar_grp_yui_widgets.js"} {overlib_includes} diff --git a/modules/Administration/templates/RebuildSprites.tpl b/modules/Administration/templates/RebuildSprites.tpl new file mode 100644 index 00000000..444083cf --- /dev/null +++ b/modules/Administration/templates/RebuildSprites.tpl @@ -0,0 +1,80 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} + + \ No newline at end of file diff --git a/modules/Administration/templates/RepairXSS.tpl b/modules/Administration/templates/RepairXSS.tpl index 19662533..068d876c 100644 --- a/modules/Administration/templates/RepairXSS.tpl +++ b/modules/Administration/templates/RepairXSS.tpl @@ -35,8 +35,8 @@ ********************************************************************************/ *} - - + +
      {$mod.LBL_REPAIRXSS_INSTRUCTIONS} diff --git a/modules/Administration/templates/ShortcutBar.tpl b/modules/Administration/templates/ShortcutBar.tpl index 4229db1e..ad19a10c 100644 --- a/modules/Administration/templates/ShortcutBar.tpl +++ b/modules/Administration/templates/ShortcutBar.tpl @@ -35,7 +35,7 @@ ********************************************************************************/ *} - + diff --git a/modules/Administration/templates/themeSettings.tpl b/modules/Administration/templates/themeSettings.tpl index 71b78a32..0947e646 100644 --- a/modules/Administration/templates/themeSettings.tpl +++ b/modules/Administration/templates/themeSettings.tpl @@ -35,7 +35,7 @@ ********************************************************************************/ *} - + diff --git a/modules/Administration/updater_utils.php b/modules/Administration/updater_utils.php index f505e708..35c64126 100644 --- a/modules/Administration/updater_utils.php +++ b/modules/Administration/updater_utils.php @@ -45,7 +45,7 @@ function getSystemInfo($send_usage_info=true){ global $db, $authLevel, $administration, $timedate; $info=array(); $info = getBaseSystemInfo($send_usage_info); - if($send_usage_info){ + if($send_usage_info){ if($authLevel > 0){ if(isset($_SERVER['SERVER_ADDR'])) $info['ip_address'] = $_SERVER['SERVER_ADDR']; @@ -73,32 +73,25 @@ function getSystemInfo($send_usage_info=true){ $info['system_name'] = (!empty($administration->settings['system_name']))?substr($administration->settings['system_name'], 0 ,255):''; - $query="select count(*) count from users where status='Active' and deleted=0 and is_admin='1'"; - $result=$db->query($query, 'fetching admin count', false); - $row = $db->fetchByAssoc($result); - if(!empty($row)) { - $info['admin_users'] = $row['count']; + $result=$db->getOne("select count(*) count from users where status='Active' and deleted=0 and is_admin='1'", false, 'fetching admin count'); + if($result !== false) { + $info['admin_users'] = $result; } + if(empty($authLevel)){ $authLevel = 0; } - $query="select count(*) count from users"; - $result=$db->query($query, 'fetching all users count', false); - $row = $db->fetchByAssoc($result); - if(!empty($row)) { - $info['registered_users'] = $row['count']; - } - $lastMonth = db_convert("'". $timedate->getNow()->modify("-30 days")->asDb(false) . "'", 'datetime'); - if( !$send_usage_info){ - $info['users_active_30_days'] = -1; + $result=$db->getOne("select count(*) count from users", false, 'fetching all users count'); + if($result !== false) { + $info['registered_users'] = $result; } - else{ - $query = "SELECT count( DISTINCT users.id ) user_count FROM tracker, users WHERE users.id = tracker.user_id AND tracker.date_modified >= $lastMonth"; - $result=$db->query($query, 'fetching last 30 users count', false); - $row = $db->fetchByAssoc($result); - $info['users_active_30_days'] = $row['user_count']; + $lastMonth = $db->convert("'". $timedate->getNow()->modify("-30 days")->asDb(false) . "'", 'datetime'); + if( !$send_usage_info) { + $info['users_active_30_days'] = -1; + } else { + $info['users_active_30_days'] = $db->getOne("SELECT count( DISTINCT users.id ) user_count FROM tracker, users WHERE users.id = tracker.user_id AND tracker.date_modified >= $lastMonth", false, 'fetching last 30 users count'); } @@ -107,15 +100,13 @@ function getSystemInfo($send_usage_info=true){ if(!$send_usage_info){ $info['latest_tracker_id'] = -1; }else{ - $query="select id from tracker order by date_modified desc"; - $id=$db->getOne($query,'fetching most recent tracker entry',false); + $id=$db->getOne("select id from tracker order by date_modified desc", false, 'fetching most recent tracker entry'); if ( $id !== false ) $info['latest_tracker_id'] = $id; } - $dbManager = &DBManagerFactory::getInstance(); $info['db_type']=$sugar_config['dbconfig']['db_type']; - $info['db_version']=$dbManager->version(); + $info['db_version']=$db->version(); } if(file_exists('distro.php')){ include('distro.php'); @@ -285,21 +276,32 @@ function check_now($send_usage_info=true, $get_request_data=false, $response_dat */ function compareVersions($ver1, $ver2) { - $ver_arr_1 = preg_split("/[^0-9]/", $ver1); - $ver_arr_2 = preg_split("/[^0-9]/", $ver2); - $count = (count($ver_arr_1) >= count($ver_arr_2)) ? count($ver_arr_1) : count($ver_arr_2); - for ($i = 0; $i < $count; $i++) + if(!preg_match_all("/[0-9]/", $ver1, $matches1)) { - if (!isset($ver_arr_1[$i])) - $ver_arr_1[$i] = 0; - - if (!isset($ver_arr_2[$i])) - $ver_arr_2[$i] = 0; - - if ($ver_arr_1[$i] > $ver_arr_2[$i]) - return true; + return false; } - return false; + + if(!preg_match_all("/[0-9]/", $ver2, $matches2)) + { + return true; + } + + //Now recreate string with only numbers + $ver1 = implode('', $matches1[0]); + $ver2 = implode('', $matches2[0]); + + $len1 = strlen($ver1); + $len2 = strlen($ver2); + + //Now apply padding + if($len1 > $len2) { + $ver2 = str_pad($ver2, $len1, '0'); + } else if($len2 > $len1) { + $ver1 = str_pad($ver1, $len2, '0'); + } + + //Return result + return (int)$ver1 > (int)$ver2; } function set_CheckUpdates_config_setting($value) { diff --git a/modules/Audit/Popup_picker.php b/modules/Audit/Popup_picker.php index 493601ec..8a15d2b2 100644 --- a/modules/Audit/Popup_picker.php +++ b/modules/Audit/Popup_picker.php @@ -97,7 +97,7 @@ class Popup_Picker $printImageURL = SugarThemeRegistry::current()->getImageURL('print.gif'); $titleExtra = << -{$GLOBALS['app_strings']['LNK_PRINT']} +{$GLOBALS['app_strings']['LNK_PRINT']} {$GLOBALS['app_strings']['LNK_PRINT']} diff --git a/modules/Calendar/Cal.css b/modules/Calendar/Cal.css new file mode 100644 index 00000000..cf344896 --- /dev/null +++ b/modules/Calendar/Cal.css @@ -0,0 +1,183 @@ +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + + +#cal-grid { + border-left: 1px solid silver; + width: 100%; + overflow:hidden; +} + +#cal-scrollable { + overflow-y: scroll; + overflow-x: hidden; +} + +#cal-grid .day_col { + width: 14.2%; + float: left; + border-bottom: 0px solid silver; +} +#cal-grid .left_time_col { + width: 52px; + float: left; + border-bottom: 0px solid silver; +} + +#cal-grid .week_block { + width: auto; + margin-left: 52px; + min-width: 290px; +} + +#cal-grid .slot { + height: 14px; + border-right: 1px solid silver; + border-bottom: 1px solid #e5e5e5; + background-color: transparent; +} +#cal-grid .slot_over { + background-color: #D1DCFF; +} + +#cal-grid .left_cell { + height: 14px; + font-size: 10px; + text-align: center; + border-right: 1px solid silver; + border-bottom: 1px solid #e5e5e5; + vertical-align: middle; + line-height: 15px; +} +#cal-grid .day_head { + height: 14px; + text-align: center; + font-size: 13px; + border-bottom: 1px solid silver; + border-top: 1px solid silver; + border-right: 1px solid silver; + white-space: nowrap; +} +#cal-grid .day_head a { + text-decoration: none; +} +#cal-grid .odd { + background-color: transparent; +} +#cal-grid .odd_border { + border-bottom: 1px solid silver; +} + +#cal-grid .slot_active { + background-color: gray; +} + +#cal-grid .today { + font-weight: bold; + background-color: #FCD372; +} + +.act_item { + width: 92%; + min-width: 0px; + font-size: 10px; + position : relative; + vertical-align: top; + display: inline-block; + border: 1px solid; + border-top-width: 1px; + overflow: hidden; + cursor: default; +} + +.act_item.empty { + border-color: transparent; +} + +.act_item, #cal-grid .day_col { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: -moz-none; + -o-user-select: none; + user-select: none; +} + +.act_item .head { + height: 13px; + padding-left: 2px; +} +.act_item .head div { + overflow: hidden; + height: 13px; +} +.act_item .contain { + padding-top: 1px; + padding-left: 2px; + padding-right: 2px; + overflow: hidden; + height: 13px; +} + +.act_item .adicon { + float: right; + color: black; + width: 11px; + font-size: 9px; + height: 11px; + line-height: 11px; + text-align: center; + background-image: url('../../themes/default/images/MoreDetail.png'); + background-repeat: no-repeat; +} + +.act_item .head { + font-size: 10px; + font-weight: bold; +} +.act_item .head div { + font-weight: bold; + font-size: 10px; +} +.act_item .head a, .act_item .head a:visited, .act_item .head a:hover { + text-decoration: none; +} + +#cal-edit-buttons { + padding: 7px 5px 5px 5px; +} + +#cal-grid .owt { + display: none; +} diff --git a/modules/Calendar/Cal.js b/modules/Calendar/Cal.js new file mode 100644 index 00000000..9262caa0 --- /dev/null +++ b/modules/Calendar/Cal.js @@ -0,0 +1,187 @@ +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ +var CAL={};CAL.dropped=0;CAL.records_openable=true;CAL.moved_from_cell="";CAL.deleted_id="";CAL.deleted_module="";CAL.old_caption="";CAL.disable_creating=false;CAL.record_editable=false;CAL.tp=false;CAL.tp1=false;CAL.shared_users={};CAL.shared_users_count=0;CAL.script_evaled=false;CAL.editDialog=false;CAL.settingsDialog=false;CAL.scroll_slot=0;CAL.update_dd=new YAHOO.util.CustomEvent("update_dd");CAL.dom=YAHOO.util.Dom;CAL.get=YAHOO.util.Dom.get;CAL.query=YAHOO.util.Selector.query;CAL.arrange_slot=function(cell_id){if(!cell_id) +return;cellElm=document.getElementById(cell_id);if(cellElm){var total_height=0;var prev_i=0;var first=1;var top=0;var height=0;var cnt=0;var child_cnt=cellElm.childNodes.length;for(var i=0;i20) +return;var depth=level;if(el!=null){if(level==1){ol_group={};ol_group.items=new Array();} +ol_group.items.push({id:el.id,level:level});affected_items.push(el.id);} +for(var i=start;i=slot_count) +break;if(typeof slots[i].childNodes!='undefined'&&typeof slots[i].childNodes[0]!='undefined'){var pos=0;if(i==start){var node=slots[i].childNodes[0];while(node.nextSibling&&contains(affected_items,node.id)){node=node.nextSibling;pos++;}} +var current=slots[i].childNodes[pos];var slots_takes=parseInt(current.getAttribute('duration_coef'));if(contains(affected_items,current.id)) +continue;if(pos==0){var slot_id=current.parentNode.id;if(!contains(affected_slots,slot_id)) +affected_slots.push(slot_id);} +if(slots_takes>0){var k=find_overlapping(current,i,i+slots_takes,level+1,ol_group);if(k>depth) +depth=k;}}} +if(level==1){ol_group.depth=depth;ol.push(ol_group);} +return depth;} +function insert_empty_items(el,count,to_end){var slot=el.parentNode;for(var i=0;i0) +duration_text+=item.duration_minutes+CAL.lbl_mins_abbrev;var start_text=CAL.get_header_text(item.type,item.time_start,item.status,item.record);var time_cell=item.timestamp-item.timestamp%(CAL.t_step*60);var duration_coef;if(item.module_name=='Tasks'){duration_coef=1;duration_text=" ";}else{if((item.duration_minutes
        
      "+start_text+"
      "+""+"
      "+item_text+"
      ";el.className="act_item"+" "+item.type+"_item";el.setAttribute("id",elm_id);el.setAttribute("module_name",item.module_name);el.setAttribute("record",item.record);el.setAttribute("dur",duration_text);el.setAttribute("subj",item.record_name);el.setAttribute("date_start",item.date_start);el.setAttribute("desc",item.description);el.setAttribute("parent_name",item.parent_name);el.setAttribute("parent_type",item.parent_type);el.setAttribute("parent_id",item.parent_id);el.setAttribute("status",item.status);el.setAttribute("detail",item.detail);el.setAttribute("edit",item.edit);el.setAttribute("duration_coef",duration_coef);el.style.backgroundColor=CAL.activity_colors[item.module_name]['body'];el.style.borderColor=CAL.activity_colors[item.module_name]['border'];el.style.height=parseInt(15*duration_coef-1)+"px";if(item.module_name=="Tasks") +el.setAttribute("date_due",item.date_due);YAHOO.util.Event.on(el,"click",function(){if(this.getAttribute('detail')=="1") +CAL.load_form(this.getAttribute('module_name'),this.getAttribute('record'),false);});YAHOO.util.Event.on(el,"mouseover",function(){if(!CAL.records_openable) +return;CAL.disable_creating=true;CAL.tp=setTimeout(function(){var e;if(e=CAL.get(elm_id)) +e.style.zIndex=2;},150);});YAHOO.util.Event.on(el,"mouseout",function(){if(!CAL.records_openable) +return;clearTimeout(CAL.tp);CAL.get(elm_id).style.zIndex='';CAL.disable_creating=false;});var slot;if(slot=CAL.get("t_"+time_cell+suffix)){slot.appendChild(el);CAL.cut_record(item.record+id_suffix);if(duration_coef<1.75&&CAL.mouseover_expand){YAHOO.util.Event.on(elm_id,"mouseover",function(){if(CAL.records_openable) +CAL.expand_record(this.getAttribute("id"));});YAHOO.util.Event.on(elm_id,"mouseout",function(){CAL.unexpand_record(this.getAttribute("id"));});YAHOO.util.Event.on(elm_id,"click",function(){CAL.unexpand_record(this.getAttribute("id"));});} +if(CAL.items_draggable&&item.edit==1){var border='cal-grid';if(CAL.view!="shared"&&CAL.view!="month") +border='cal-scrollable';var dd=new YAHOO.util.DDCAL(elm_id,"cal",{isTarget:false,cont:border});dd.onInvalidDrop=function(e){CAL.arrange_slot(this.el.parentNode.getAttribute("id"));if(CAL.dropped==0){this.el.childNodes[0].innerHTML=CAL.old_caption;} +CAL.records_openable=true;CAL.disable_creating=false;} +dd.onMouseDown=function(e){YAHOO.util.DDM.mode=YAHOO.util.DDM.POINT;YAHOO.util.DDM.clickPixelThresh=20;} +dd.onMouseUp=function(e){YAHOO.util.DDM.mode=YAHOO.util.DDM.INTERSECT;YAHOO.util.DDM.clickPixelThresh=3;} +dd.startDrag=function(x,y){this.el=document.getElementById(this.id);this.el.style.zIndex=5;CAL.dropped=0;CAL.records_openable=false;CAL.disable_creating=true;CAL.old_caption=this.el.childNodes[0].innerHTML;CAL.moved_from_cell=this.el.parentNode.id;this.setDelta(2,2);} +dd.endDrag=function(x,y){this.el=document.getElementById(this.id);this.el.style.zIndex="";var nodes=CAL.query("#cal-grid .slot");CAL.each(nodes,function(i,v){YAHOO.util.Dom.removeClass(nodes[i],"slot_active");});} +dd.onDragDrop=function(e,id){var slot=document.getElementById(id);YAHOO.util.Dom.removeClass(slot,"slot_active");if(CAL.dropped) +return;CAL.dropped=1;this.el.style.position="relative";this.el.style.cssFloat="none";if(CAL.view!='shared'){var box_id=this.id;var slot_id=id;var ex_slot_id=CAL.moved_from_cell;CAL.move_activity(box_id,slot_id,ex_slot_id);}else{var record=this.el.getAttribute("record");var tid=id;var tar=tid.split("_");var timestamp=tar[1];var tid=CAL.moved_from_cell;var tar=tid.split("_");var ex_timestamp=tar[1];for(i=0;i "+SUGAR.language.languages.app_list_strings[type+'_status_dom'][status];return start_text;} +CAL.cut_record=function(id){var el=CAL.get(id);if(!el) +return;var duration_coef=el.getAttribute("duration_coef");var real_celcount=CAL.celcount;if(CAL.view=='day'||CAL.view=='week') +real_celcount=CAL.cells_per_day;var celpos=0;var s=el.parentNode;while(s.previousSibling){celpos++;s=s.previousSibling;} +if(CAL.view=='week') +celpos=celpos+1;if(real_celcount-celpos-duration_coef<0) +duration_coef=real_celcount-celpos+1;el.style.height=parseInt(15*duration_coef-1)+"px";} +CAL.init_edit_dialog=function(params){CAL.editDialog=false;var rd=CAL.get("cal-edit");var content=CAL.get("edit-dialog-content");if(CAL.dashlet&&rd){document.getElementById("content").appendChild(rd);} +rd.style.width=params.width+"px";content.style.height=params.height+"px";content.style.overflow="auto";content.style.padding="0";CAL.editDialog=new YAHOO.widget.Dialog("cal-edit",{draggable:true,visible:false,modal:true,close:true,zIndex:10});var listeners=new YAHOO.util.KeyListener(document,{keys:27},{fn:function(){CAL.editDialog.cancel();}});CAL.editDialog.cfg.queueProperty("keylisteners",listeners);CAL.editDialog.cancelEvent.subscribe(function(e,a,o){CAL.close_edit_dialog();});rd.style.display="block";CAL.editDialog.render();rd.style.overflow="auto";rd.style.overflowX="hidden";rd.style.outline="0 none";rd.style.height="auto";} +CAL.open_edit_dialog=function(params){CAL.get("btn-delete").style.display="";CAL.editDialog.center();CAL.editDialog.show();var nodes=CAL.query("#cal-tabs li a");CAL.each(nodes,function(i,v){YAHOO.util.Event.on(nodes[i],'click',function(){CAL.select_tab(this.getAttribute("tabname"));});});var nodes_li=CAL.query("#cal-tabs li");CAL.each(nodes_li,function(j,v){CAL.dom.removeClass(nodes_li[j],"selected");if(j==0) +CAL.dom.addClass(nodes_li[j],"selected");});var nodes=CAL.query(".yui-nav");CAL.each(nodes,function(i,v){nodes[i].style.overflowX="visible";});} +CAL.close_edit_dialog=function(){CAL.reset_edit_dialog();} +CAL.remove_edit_dialog=function(){var rd_c=CAL.get("cal-edit_c");if(rd_c){rd_c.parentNode.removeChild(rd_c);}} +CAL.reset_edit_dialog=function(){var e;document.getElementById("form_content").innerHTML="";document.forms["CalendarEditView"].elements["current_module"].value="Meetings";CAL.get("radio_call").removeAttribute("disabled");CAL.get("radio_meeting").removeAttribute("disabled");CAL.get("radio_call").checked=false;CAL.get("radio_meeting").checked=true;CAL.get("send_invites").value="";if(e=CAL.get("record")) +e.value="";if(e=CAL.get("list_div_win")) +e.style.display="none";CAL.GR_update_focus("Meetings","");CAL.select_tab("cal-tab-1");QSFieldsArray=new Array();QSProcessedFieldsArray=new Array();} +CAL.select_tab=function(tid){var nodes_li=CAL.query("#cal-tabs li");CAL.each(nodes_li,function(j,v){CAL.dom.removeClass(nodes_li[j],"selected");});CAL.dom.addClass(CAL.get(tid+"-link").parentNode,"selected");var nodes=CAL.query("#cal-tabs .yui-content");CAL.each(nodes,function(i,v){nodes[i].style.display="none";});var nodes=CAL.query("#cal-tabs #"+tid);CAL.each(nodes,function(i,v){nodes[i].style.display="block";});} +CAL.GR_update_user=function(user_id){var callback={success:function(o){res=eval(o.responseText);GLOBAL_REGISTRY.focus.users_arr_hash=undefined;}};var data={"users":user_id};var url="index.php?module=Calendar&action=GetGRUsers&sugar_body_only=true";YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data));} +CAL.GR_update_focus=function(module,record){if(record==""){GLOBAL_REGISTRY["focus"]={"module":module,users_arr:[],fields:{"id":"-1"}};SugarWidgetScheduler.update_time();}else{var callback={success:function(o){res=eval(o.responseText);SugarWidgetScheduler.update_time();if(CAL.record_editable){CAL.get("btn-save").removeAttribute("disabled");CAL.get("btn-delete").removeAttribute("disabled");CAL.get("btn-apply").removeAttribute("disabled");CAL.get("btn-send-invites").removeAttribute("disabled");}}};var url='index.php?module=Calendar&action=GetGR&sugar_body_only=true&type='+module+'&record='+record;YAHOO.util.Connect.asyncRequest('POST',url,callback,false);}} +CAL.toggle_settings=function(){var sd=CAL.get("settings_dialog");if(!CAL.settingsDialog){CAL.settingsDialog=new YAHOO.widget.Dialog("settings_dialog",{fixedcenter:true,draggable:false,visible:false,modal:true,close:true});var listeners=new YAHOO.util.KeyListener(document,{keys:27},{fn:function(){CAL.settingsDialog.cancel();}});CAL.settingsDialog.cfg.queueProperty("keylisteners",listeners);} +CAL.settingsDialog.cancelEvent.subscribe(function(e,a,o){CAL.get("form_settings").reset();});sd.style.display="block";CAL.settingsDialog.render();CAL.settingsDialog.show();} +CAL.toggle_whole_day=function(){var wd=CAL.get("whole_day");if(!wd.value) +wd.value="1";else +wd.value="";setTimeout(function(){if(wd.value){var nodes=CAL.query("#cal-grid .owt");CAL.each(nodes,function(i,v){nodes[i].style.display="block";});}else{var nodes=CAL.query("#cal-grid .owt");CAL.each(nodes,function(i,v){nodes[i].style.display="none";});}},25);} +CAL.fill_invitees=function(){CAL.get("user_invitees").value="";CAL.get("contact_invitees").value="";CAL.get("lead_invitees").value="";CAL.each(GLOBAL_REGISTRY['focus'].users_arr,function(i,v){var field_name="";if(v.module=="User") +field_name="user_invitees";if(v.module=="Contact") +field_name="contact_invitees";if(v.module=="Lead") +field_name="lead_invitees";var str=CAL.get(field_name).value;CAL.get(field_name).value=str+v.fields.id+",";});} +CAL.load_form=function(module_name,record,run_one_time){var e;var to_open=true;if(module_name=="Tasks") +to_open=false;if(to_open&&CAL.records_openable){CAL.get("form_content").style.display="none";CAL.get("btn-delete").setAttribute("disabled","disabled");CAL.get("btn-apply").setAttribute("disabled","disabled");CAL.get("btn-save").setAttribute("disabled","disabled");CAL.get("btn-send-invites").setAttribute("disabled","disabled");CAL.get("title-cal-edit").innerHTML=CAL.lbl_loading;ajaxStatus.showStatus(SUGAR.language.get('app_strings','LBL_LOADING'));CAL.open_edit_dialog();CAL.get("record").value="";var callback={success:function(o){try{res=eval("("+o.responseText+")");}catch(err){alert(CAL.lbl_error_loading);CAL.editDialog.cancel();ajaxStatus.hideStatus();return;} +if(res.success=='yes'){var fc=document.getElementById("form_content");CAL.script_evaled=false;fc.innerHTML=''+res.html;if(!CAL.script_evaled){SUGAR.util.evalScript(res.html);} +CAL.get("record").value=res.record;CAL.get("current_module").value=res.module_name;var mod_name=res.module_name;if(mod_name=="Meetings") +CAL.get("radio_meeting").checked=true;if(mod_name=="Calls") +CAL.get("radio_call").checked=true;if(res.edit==1){CAL.record_editable=true;}else{CAL.record_editable=false;} +CAL.get("radio_call").setAttribute("disabled","disabled");CAL.get("radio_meeting").setAttribute("disabled","disabled");eval(res.gr);SugarWidgetScheduler.update_time();if(CAL.record_editable){CAL.get("btn-save").removeAttribute("disabled");CAL.get("btn-delete").removeAttribute("disabled");CAL.get("btn-apply").removeAttribute("disabled");CAL.get("btn-send-invites").removeAttribute("disabled");} +CAL.get("form_content").style.display="";CAL.get("title-cal-edit").innerHTML=CAL.lbl_edit;ajaxStatus.hideStatus();setTimeout(function(){enableQS(false);disableOnUnloadEditView();},500);}else +alert(CAL.lbl_error_loading);},failure:function(){alert(CAL.lbl_error_loading);}};var url="index.php?module=Calendar&action=QuickEdit&sugar_body_only=true";var data={"current_module":module_name,"record":record};YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data));} +CAL.records_openable=true;} +CAL.remove_shared=function(record_id){var e;var cell_id;if(e=CAL.get(record_id+'____'+"0")) +cell_id=e.parentNode.id;if(typeof cell_id!="undefined"){var cell_id_arr=cell_id.split("_");cell_id="t_"+cell_id_arr[1];} +CAL.each(CAL.shared_users,function(i,v){if(e=CAL.get(record_id+'____'+v)) +e.parentNode.removeChild(e);CAL.arrange_slot(cell_id+'_'+v);});} +CAL.add_item=function(item){if(CAL.view!='shared'){CAL.add_item_to_grid(item);}else{CAL.remove_shared(item.record);record_id=item.record;var timestamp=item.timestamp;CAL.each(item.users,function(i,v){var rec=item;rec.timestamp=timestamp;rec.user_id=v;rec.record=record_id;CAL.add_item_to_grid(rec);CAL.each(rec.arr_rec,function(j,r){rec.record=r.record;rec.timestamp=r.timestamp;CAL.add_item_to_grid(rec);});});} +CAL.arrange_advanced();} +CAL.move_activity=function(box_id,slot_id,ex_slot_id){var u,s;if(u=CAL.get(box_id)){if(s=CAL.get(slot_id)){s.appendChild(u);CAL.arrange_column(document.getElementById(slot_id).parentNode);CAL.arrange_column(document.getElementById(ex_slot_id).parentNode);CAL.update_dd.fire();CAL.cut_record(box_id);var start_text=CAL.get_header_text(CAL.act_types[u.getAttribute('module_name')],s.getAttribute('time'),u.getAttribute('status'),u.getAttribute('record'));var date_field="date_start";if(u.getAttribute('module_name')=="Tasks") +date_field="date_due";u.setAttribute(date_field,s.getAttribute("datetime"));u.childNodes[0].childNodes[1].innerHTML=start_text;}}} +CAL.change_activity_type=function(mod_name){if(typeof CAL.current_params.module_name!="undefined") +if(CAL.current_params.module_name==mod_name) +return;var e,user_name,user_id,date_start;CAL.get("title-cal-edit").innerHTML=CAL.lbl_loading;document.forms["CalendarEditView"].elements["current_module"].value=mod_name;CAL.current_params.module_name=mod_name;QSFieldsArray=new Array();QSProcessedFieldsArray=new Array();CAL.load_create_form(CAL.current_params);} +CAL.load_create_form=function(params){ajaxStatus.showStatus(SUGAR.language.get('app_strings','LBL_LOADING'));var callback={success:function(o){try{res=eval("("+o.responseText+")");}catch(err){alert(CAL.lbl_error_loading);CAL.editDialog.cancel();ajaxStatus.hideStatus();return;} +if(res.success=='yes'){var fc=document.getElementById("form_content");CAL.script_evaled=false;fc.innerHTML=''+res.html;if(!CAL.script_evaled){SUGAR.util.evalScript(res.html);} +CAL.get("record").value="";CAL.get("current_module").value=res.module_name;var mod_name=res.module_name;if(res.edit==1){CAL.record_editable=true;}else{CAL.record_editable=false;} +CAL.get("title-cal-edit").innerHTML=CAL.lbl_create_new;setTimeout(function(){SugarWidgetScheduler.update_time();enableQS(false);disableOnUnloadEditView();},500);ajaxStatus.hideStatus();}else{alert(CAL.lbl_error_loading);ajaxStatus.hideStatus();}},failure:function(){alert(CAL.lbl_error_loading);ajaxStatus.hideStatus();}};var url="index.php?module=Calendar&action=QuickEdit&sugar_body_only=true";var data={"current_module":params.module_name,"assigned_user_id":params.user_id,"assigned_user_name":params.user_name,"date_start":params.date_start};YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data));} +CAL.dialog_create=function(cell){var e,user_id,user_name;CAL.get("title-cal-edit").innerHTML=CAL.lbl_loading;CAL.open_edit_dialog();CAL.get("btn-delete").setAttribute("disabled","disabled");CAL.get("btn-delete").style.display="none";var module_name=CAL.get("current_module").value;if(CAL.view=='shared'){user_name=cell.parentNode.parentNode.parentNode.getAttribute("user_name");user_id=cell.parentNode.parentNode.parentNode.getAttribute("user_id");CAL.GR_update_user(user_id);}else{user_id=CAL.current_user_id;user_name=CAL.current_user_name;CAL.GR_update_user(CAL.current_user_id);} +var params={'module_name':module_name,'user_id':user_id,'user_name':user_name,'date_start':cell.getAttribute("datetime")};CAL.current_params=params;CAL.load_create_form(CAL.current_params);} +CAL.dialog_save=function(){ajaxStatus.showStatus(SUGAR.language.get('app_strings','LBL_SAVING'));CAL.get("title-cal-edit").innerHTML=CAL.lbl_saving;CAL.fill_invitees();var callback={success:function(o){try{res=eval("("+o.responseText+")");}catch(err){alert(CAL.lbl_error_saving);CAL.editDialog.cancel();ajaxStatus.hideStatus();return;} +if(res.success=='yes'){CAL.add_item(res);CAL.editDialog.cancel();CAL.update_vcal();ajaxStatus.hideStatus();}else{alert(CAL.lbl_error_saving);ajaxStatus.hideStatus();}},failure:function(){alert(CAL.lbl_error_saving);ajaxStatus.hideStatus();}};var url="index.php?module=Calendar&action=SaveActivity&sugar_body_only=true";YAHOO.util.Connect.setForm(CAL.get("CalendarEditView"));YAHOO.util.Connect.asyncRequest('POST',url,callback,false);} +CAL.dialog_apply=function(){ajaxStatus.showStatus(SUGAR.language.get('app_strings','LBL_SAVING'));CAL.get("title-cal-edit").innerHTML=CAL.lbl_saving;CAL.fill_invitees();var e;if(e=CAL.get("radio_call")) +e.setAttribute("disabled","disabled");if(e=CAL.get("radio_meeting")) +e.setAttribute("disabled","disabled");var callback={success:function(o){try{res=eval("("+o.responseText+")");}catch(err){alert(CAL.lbl_error_saving);CAL.editDialog.cancel();ajaxStatus.hideStatus();return;} +if(res.success=='yes'){var e;CAL.get("record").value=res.record;CAL.add_item(res);CAL.update_vcal();CAL.get("title-cal-edit").innerHTML=CAL.lbl_edit;if(e=CAL.get("send_invites")) +e.removeAttribute("checked");ajaxStatus.hideStatus();CAL.get("btn-delete").removeAttribute("disabled");CAL.get("btn-delete").style.display="";}else{alert(CAL.lbl_error_saving);ajaxStatus.hideStatus();}},failure:function(){alert(CAL.lbl_error_saving);ajaxStatus.hideStatus();}};var url="index.php?module=Calendar&action=SaveActivity&sugar_body_only=true";YAHOO.util.Connect.setForm(CAL.get("CalendarEditView"));YAHOO.util.Connect.asyncRequest('POST',url,callback,false);} +CAL.dialog_remove=function(){CAL.deleted_id=CAL.get("record").value;CAL.deleted_module=CAL.get("current_module").value;var delete_recurring=false;var callback={success:function(o){try{res=eval("("+o.responseText+")");}catch(err){alert(CAL.lbl_error_saving);CAL.editDialog.cancel();ajaxStatus.hideStatus();return;} +var e,cell_id;if(e=CAL.get(CAL.deleted_id)) +cell_id=e.parentNode.id;if(CAL.view=='shared') +CAL.remove_shared(CAL.deleted_id);if(e=CAL.get(CAL.deleted_id)) +e.parentNode.removeChild(e);CAL.arrange_advanced();},failure:function(){alert(CAL.lbl_error_saving);}};var data={"current_module":CAL.deleted_module,"record":CAL.deleted_id,"delete_recurring":delete_recurring};var url="index.php?module=Calendar&action=Remove&sugar_body_only=true";YAHOO.util.Connect.asyncRequest('POST',url,callback,CAL.toURI(data));CAL.editDialog.cancel();} +CAL.show_additional_details=function(id){var obj=CAL.get(id);var record=obj.getAttribute("record");mod=obj.getAttribute("module_name");var atype=CAL.act_types[mod];var subj=obj.getAttribute("subj");var date_start=obj.getAttribute("date_start");var duration=obj.getAttribute("dur");var desc=obj.getAttribute("desc");var detail=parseInt(obj.getAttribute("detail"));var edit=parseInt(obj.getAttribute("edit"));var date_str="";if(date_start!="") +date_str+=''+CAL.lbl_start+': '+date_start;if(mod=="Tasks"){var date_due=obj.getAttribute("date_due");if(date_due!=""){if(date_str!="") +date_str+="
      ";date_str+=''+CAL.lbl_due+': '+date_due;}} +var related="";if(obj.getAttribute("parent_id")!=''&&obj.getAttribute("parent_name")!='') +related=""+CAL.lbl_related+": "+obj.getAttribute("parent_name")+""+"
      ";if(desc!='') +desc=''+CAL.lbl_desc+':
      '+desc+'
      ';if(subj=='') +return"";var date_lbl=CAL.lbl_start;if(duration!=""){var duration_text=''+CAL.lbl_duration+': '+duration+'
      ';if(mod=="Tasks"){date_lbl=CAL.lbl_due;duration_text="";}}else +duration_text="";var caption="
      "+CAL.lbl_title+"
      ";if(edit){caption+="";} +if(detail){caption+="";} +caption+="
      ";var body=''+CAL.lbl_name+': '+subj+'
      '+date_str+'
      '+duration_text+related+desc;return overlib(body,CAPTION,caption,DELAY,200,STICKY,MOUSEOFF,200,WIDTH,300,CLOSETEXT,'',CLOSETITLE,SUGAR.language.get('app_strings','LBL_ADDITIONAL_DETAILS_CLOSE_TITLE'),CLOSECLICK,FGCLASS,'olFgClass',CGCLASS,'olCgClass',BGCLASS,'olBgClass',TEXTFONTCLASS,'olFontClass',CAPTIONFONTCLASS,'olCapFontClass ecCapFontClass',CLOSEFONTCLASS,'olCloseFontClass');} +CAL.toggle_shared_edit=function(id){if(document.getElementById(id).style.display=='none'){document.getElementById(id).style.display='inline' +if(document.getElementById(id+"link")!=undefined){document.getElementById(id+"link").style.display='none';}}else{document.getElementById(id).style.display='none' +if(document.getElementById(id+"link")!=undefined){document.getElementById(id+"link").style.display='inline';}}} +CAL.goto_date_call=function(){var date_string=CAL.get("goto_date").value;var date_arr=[];date_arr=date_string.split("/");window.location.href="index.php?module=Calendar&view="+CAL.view+"&day="+date_arr[1]+"&month="+date_arr[0]+"&year="+date_arr[2];} +CAL.toURI=function(a){t=[];for(x in a){if(!(a[x].constructor.toString().indexOf('Array')==-1)){for(i in a[x]) +t.push(x+"[]="+encodeURIComponent(a[x][i]));}else +t.push(x+"="+encodeURIComponent(a[x]));} +return t.join("&");} +CAL.each=function(object,callback){if(typeof object=="undefined") +return;var name,i=0,length=object.length,isObj=(length===undefined)||(typeof(object)==="function");if(isObj){for(name in object){if(callback.call(object[name],name,object[name])===false){break;}}}else{for(;istart_time->ts == $act1->start_time->ts) - { - return 0; - } - - return ($act0->start_time->ts < $act1->start_time->ts) ? -1 : 1; -} - -class Calendar -{ - var $view = 'month'; +require_once('modules/Calendar/CalendarUtils.php'); +require_once('modules/Calendar/CalendarActivity.php'); + +class Calendar { + + public $view = 'week'; // current view + public $dashlet = false; // if is displayed in dashlet + public $date_time; // current date + + public $show_tasks = true; + public $show_calls = true; + + public $time_step = 60; // time step of each slot in minutes + + public $acts_arr = array(); // Array of activities objects + public $items = array(); // Array of activities data to be displayed + public $shared_ids = array(); // ids of users for shared view + + + public $cells_per_day; // entire 24h day count of slots + public $grid_start_ts; // start timestamp of calendar grid + + public $day_start_time; // working day start time in format '11:00' + public $day_end_time; // working day end time in format '11:00' + public $scroll_slot; // first slot of working day + public $celcount; // count of slots in a working day + /** - * Current date - * @var SugarDateTime - */ - var $date_time; - var $slices_arr = array(); - // for monthly calendar view, if you want to see all the - // days in the grid, otherwise you only see that months - var $show_only_current_slice = false; - var $show_activities = true; - var $show_tasks = true; - var $activity_focus; - var $show_week_on_month_view = true; - var $use_24 = 1; - var $toggle_appt = true; - var $slice_hash = array(); - var $shared_users_arr = array(); - - function __construct($view,$time_arr=array()) - { - global $current_user, $timedate; - global $sugar_config; - if ( $current_user->getPreference('time')) - { - $time = $current_user->getPreference('time'); - } - else - { - $time = $sugar_config['default_time_format']; - } - - if( substr_count($time, 'h') > 0) - { - $this->use_24 = 0; - } - - if (!( $view == 'day' || $view == 'month' || $view == 'year' || $view == 'week' || $view == 'shared') ) - { - sugar_die ("view needs to be one of: day, week, month, shared, or year"); - } - - $this->view = $view; - - if ( isset($time_arr['activity_focus'])) - { - $this->activity_focus = new CalendarActivity($time_arr['activity_focus']); - $this->date_time = $this->activity_focus->start_time; - } - else - { - if(!empty($time_arr)) { - // FIXME: what format? - $this->date_time = $timedate->fromTimeArray($time_arr); - } else { - $this->date_time = $timedate->getNow(); - } - } - - $timedate->tzUser($this->date_time, $current_user); - $GLOBALS['log']->debug("CALENDATE: ".$this->date_time->format('r')); - $this->create_slices(); - - } - function add_shared_users($shared_users_arr) - { - $this->shared_users_arr = $shared_users_arr; - } - - function get_view_name($view) - { - if ($view == 'month') - { - return "MONTH"; - } - else if ($view == 'week') - { - return "WEEK"; - } - else if ($view == 'day') - { - return "DAY"; - } - else if ($view == 'year') - { - return "YEAR"; - } - else if ($view == 'shared') - { - return "SHARED"; - } - else - { - sugar_die ("get_view_name: view ".$this->view." not supported"); - } - } - - function isDayView() { - return $this->view == 'day'; - } - - function get_slices_arr() - { - return $this->slices_arr; - } - - - function create_slices() - { - global $current_user; - - if ( $this->view == 'month') - { - $days_in_month = $this->date_time->days_in_month; - - $first_day_of_month = $this->date_time->get_day_by_index_this_month(0); - $num_of_prev_days = $first_day_of_month->day_of_week; - // do 42 slices (6x7 grid) - - for($i=0;$i < 42;$i++) - { - $slice = new Slice('day',$this->date_time->get_day_by_index_this_month($i-$num_of_prev_days)); - $this->slice_hash[$slice->start_time->get_mysql_date()] = $slice; - array_push($this->slices_arr, $slice->start_time->get_mysql_date()); - } - - } - else if ( $this->view == 'week' || $this->view == 'shared') - { - $days_in_week = 7; - - for($i=0;$i<$days_in_week;$i++) - { - $slice = new Slice('day',$this->date_time->get_day_by_index_this_week($i)); - $this->slice_hash[$slice->start_time->get_mysql_date()] = $slice; - array_push($this->slices_arr, $slice->start_time->get_mysql_date()); - } - } - else if ( $this->view == 'day') - { - $hours_in_day = 24; - - for($i=0;$i<$hours_in_day;$i++) - { - $slice = new Slice('hour',$this->date_time->get_datetime_by_index_today($i)); - $this->slice_hash[$slice->start_time->get_mysql_date().":".$slice->start_time->hour ] = $slice; - $this->slices_arr[] = $slice->start_time->get_mysql_date().":".$slice->start_time->hour; - } - } - else if ( $this->view == 'year') - { - - for($i=0;$i<12;$i++) - { - $slice = new Slice('month',$this->date_time->get_day_by_index_this_year($i)); - $this->slice_hash[$slice->start_time->get_mysql_date()] = $slice; - array_push($this->slices_arr, $slice->start_time->get_mysql_date()); - } - } - else - { - sugar_die("not a valid view:".$this->view); - } - - } - - function add_activities($user,$type='sugar') { - global $timedate; - if ( $this->view == 'week' || $this->view == 'shared') { - $end_date_time = $this->date_time->get("+7 days"); - } else { - $end_date_time = $this->date_time; - } - - $acts_arr = array(); - if($type == 'vfb') { - $acts_arr = CalendarActivity::get_freebusy_activities($user, $this->date_time, $end_date_time); - } else { - $acts_arr = CalendarActivity::get_activities($user->id, $this->show_tasks, $this->date_time, $end_date_time, $this->view); - } - - // loop thru each activity for this user - foreach ($acts_arr as $act) { - // get "hashed" time slots for the current activity we are looping through - $start = $timedate->tzUser($act->start_time); - $end = $timedate->tzUser($act->end_time); - $hash_list = SugarDateTime::getHashList($this->view, $start, $end); - - for($j=0;$j < count($hash_list); $j++) { - if(!isset($this->slice_hash[$hash_list[$j]]) || !isset($this->slice_hash[$hash_list[$j]]->acts_arr[$user->id])) { - $this->slice_hash[$hash_list[$j]]->acts_arr[$user->id] = array(); - } - $this->slice_hash[$hash_list[$j]]->acts_arr[$user->id][] = $act; - } - } - } - - function occurs_within_slice($slice, $act) - { - // if activity starts within this slice - // OR activity ends within this slice - // OR activity starts before and ends after this slice - if ( ( $act->start_time->ts >= $slice->start_time->ts && - $act->start_time->ts <= $slice->end_time->ts ) - || - ( $act->end_time->ts >= $slice->start_time->ts && - $act->end_time->ts <= $slice->end_time->ts ) - || - ( $act->start_time->ts <= $slice->start_time->ts && - $act->end_time->ts >= $slice->end_time->ts ) - ) - { - return true; - } - - return false; - - } - - function get_previous_date_str() - { - if ($this->view == 'month') - { - $day = $this->date_time->get("-1 month")->get_day_begin(1); - } - else if ($this->view == 'week' || $this->view == 'shared') - { - // first day last week - $day = $this->date_time->get("-7 days")->get_day_by_index_this_week(0)->get_day_begin(); - } - else if ($this->view == 'day') - { - $day = $this->date_time->get("yesterday")->get_day_begin(); - } - else if ($this->view == 'year') - { - $day = $this->date_time->get("-1 year")->get_day_begin(); - } - else - { - return "get_previous_date_str: notdefined for this view"; - } - return $day->get_date_str(); - } - - function get_next_date_str() - { - if ($this->view == 'month') - { - $day = $this->date_time->get("+1 month")->get_day_begin(1); - } - else - if ($this->view == 'week' || $this->view == 'shared' ) - { - $day = $this->date_time->get("+7 days")->get_day_by_index_this_week(0)->get_day_begin(); - } - else - if ($this->view == 'day') - { - $day = $this->date_time->get("tomorrow")->get_day_begin(); - } - else - if ($this->view == 'year') - { - $day = $this->date_time->get("+1 year")->get_day_begin(); - } - else - { - sugar_die("get_next_date_str: not defined for view"); - } - return $day->get_date_str(); - } - - function get_start_slice_idx() - { - - if ($this->isDayView()) - { - $start_at = 8; + * constructor + * @param string $view + * @param array $time_arr + */ + function __construct($view = "day", $time_arr = array()){ + global $current_user, $timedate; + + $this->view = $view; - for($i=0;$i < 8; $i++) - { - if (count($this->slice_hash[$this->slices_arr[$i]]->acts_arr) > 0) - { - $start_at = $i; - break; - } + if(!in_array($this->view,array('day','week','month','year','shared'))) + $this->view = 'week'; + + $date_arr = array(); + if(!empty($_REQUEST['day'])) + $_REQUEST['day'] = intval($_REQUEST['day']); + if(!empty($_REQUEST['month'])) + $_REQUEST['month'] = intval($_REQUEST['month']); + + if (!empty($_REQUEST['day'])) + $date_arr['day'] = $_REQUEST['day']; + if (!empty($_REQUEST['month'])) + $date_arr['month'] = $_REQUEST['month']; + if (!empty($_REQUEST['week'])) + $date_arr['week'] = $_REQUEST['week']; + + if (!empty($_REQUEST['year'])){ + if ($_REQUEST['year'] > 2037 || $_REQUEST['year'] < 1970){ + print("Sorry, calendar cannot handle the year you requested"); + print("
      Year must be between 1970 and 2037"); + exit; } - return $start_at; - } - else - { - return 0; + $date_arr['year'] = $_REQUEST['year']; + } + + if(empty($_REQUEST['day'])) + $_REQUEST['day'] = ""; + if(empty($_REQUEST['week'])) + $_REQUEST['week'] = ""; + if(empty($_REQUEST['month'])) + $_REQUEST['month'] = ""; + if(empty($_REQUEST['year'])) + $_REQUEST['year'] = ""; + + // if date is not set in request use current date + if(empty($date_arr) || !isset($date_arr['year']) || !isset($date_arr['month']) || !isset($date_arr['day']) ){ + $today = $timedate->getNow(true); + $date_arr = array( + 'year' => $today->year, + 'month' => $today->month, + 'day' => $today->day, + ); } + + $current_date_db = $date_arr['year']."-".str_pad($date_arr['month'],2,"0",STR_PAD_LEFT)."-".str_pad($date_arr['day'],2,"0",STR_PAD_LEFT); + $this->date_time = $GLOBALS['timedate']->fromString($current_date_db); + + $this->show_tasks = $current_user->getPreference('show_tasks'); + if(is_null($this->show_tasks)) + $this->show_tasks = SugarConfig::getInstance()->get('calendar.show_tasks_by_default',true); + $this->show_calls = $current_user->getPreference('show_calls'); + if(is_null($this->show_calls)) + $this->show_calls = SugarConfig::getInstance()->get('calendar.show_calls_by_default',true); + + $this->day_start_time = $current_user->getPreference('day_start_time'); + if(is_null($this->day_start_time)) + $this->day_start_time = SugarConfig::getInstance()->get('calendar.default_day_start',"08:00"); + $this->day_end_time = $current_user->getPreference('day_end_time'); + if(is_null($this->day_end_time)) + $this->day_end_time = SugarConfig::getInstance()->get('calendar.default_day_end',"19:00"); + + if($this->view == "day"){ + $this->time_step = SugarConfig::getInstance()->get('calendar.day_timestep',15); + }else if($this->view == "week" || $this->view == "shared"){ + $this->time_step = SugarConfig::getInstance()->get('calendar.week_timestep',30); + }else if($this->view == "month"){ + $this->time_step = SugarConfig::getInstance()->get('calendar.month_timestep',60); + }else{ + $this->time_step = 60; + } + $this->cells_per_day = 24 * (60 / $this->time_step); + $this->calculate_grid_start_ts(); + + $this->calculate_day_range(); } - function get_end_slice_idx() - { - if ( $this->view == 'month') - { - return $this->date_time->days_in_month - 1; - } - else if ( $this->view == 'week' || $this->view == 'shared') - { - return 6; - } - else if ($this->isDayView()) - { - $end_at = 18; - - for($i=$end_at;$i < 23; $i++) - { - if (count($this->slice_hash[$this->slices_arr[$i+1]]->acts_arr) > 0) - { - $end_at = $i + 1; - } + + /** + * Load activities data to array + */ + public function load_activities(){ + $field_list = CalendarUtils::get_fields(); + + foreach($this->acts_arr as $user_id => $acts){ + foreach($acts as $act){ + $item = array(); + $item['user_id'] = $user_id; + $item['module_name'] = $act->sugar_bean->module_dir; + $item['type'] = strtolower($act->sugar_bean->object_name); + $item['assigned_user_id'] = $act->sugar_bean->assigned_user_id; + $item['id'] = $act->sugar_bean->id; + $item['name'] = $act->sugar_bean->name; + $item['status'] = $act->sugar_bean->status; + + if(isset($act->sugar_bean->duration_hours)){ + $item['duration_hours'] = $act->sugar_bean->duration_hours; + $item['duration_minutes'] = $act->sugar_bean->duration_minutes; + } + + $item['detail'] = 0; + $item['edit'] = 0; + + if($act->sugar_bean->ACLAccess('DetailView')) + $item['detail'] = 1; + if($act->sugar_bean->ACLAccess('Save')) + $item['edit'] = 1; + + if(empty($act->sugar_bean->id)){ + $item['detail'] = 0; + $item['edit'] = 0; + } + + if($item['detail'] == 1){ + if(isset($field_list[$item['module_name']])){ + foreach($field_list[$item['module_name']] as $field){ + if(!isset($item[$field])){ + $item[$field] = $act->sugar_bean->$field; + if($act->sugar_bean->field_defs[$field]['type'] == 'text'){ + $t = $item[$field]; + if(strlen($t) > 300){ + $t = substr($t, 0, 300); + $t .= "..."; + } + $t = str_replace("\r\n","
      ",$t); + $t = str_replace("\r","
      ",$t); + $t = str_replace("\n","
      ",$t); + $item[$field] = $t; + } + } + } + } + } + + if(!isset($item['duration_hours']) || empty($item['duration_hours'])) + $item['duration_hours'] = 0; + if(!isset($item['duration_minutes']) || empty($item['duration_minutes'])) + $item['duration_minutes'] = 0; + + $item = array_merge($item,CalendarUtils::get_time_data($act->sugar_bean)); + + $this->items[] = $item; } - - - return $end_at; - - } - else - { - return 1; } } - - -} - -class Slice -{ - var $view = 'day'; - var $start_time; - var $end_time; - var $acts_arr = array(); - - function Slice($view,$time) - { - $this->view = $view; - $this->start_time = $time; - - if ( $view == 'day') - { - $this->end_time = $this->start_time->get_day_end_time(); - } - if ( $view == 'hour') - { - $this->end_time = $this->start_time->get_hour_end_time(); + + /** + * Get javascript objects of activities to be displayed on calendar + * @return string + */ + public function get_activities_js(){ + $field_list = CalendarUtils::get_fields(); + $a_str = ""; + $ft = true; + foreach($this->items as $act){ + if(!$ft) + $a_str .= ","; + $a_str .= "{"; + $a_str .= ' + "type" : "'.$act["type"].'", + "module_name" : "'.$act["module_name"].'", + "record" : "'.$act["id"].'", + "user_id" : "'.$act["user_id"].'", + "timestamp" : "'.$act["timestamp"].'", + "time_start" : "'.$act["time_start"].'", + "record_name": "'.$act["name"].'",'. + ''; + foreach($field_list[$act['module_name']] as $field){ + if(!isset($act[$field])) + $act[$field] = ""; + $a_str .= ' "'. $field . '" : "'.$act[$field].'", + '; + } + $a_str .= ' + "detail" : "'.$act["detail"].'", + "edit" : "'.$act["edit"].'" + '; + $a_str .= "}"; + $ft = false; + } + return $a_str; + } + + /** + * initialize ids of shared users + */ + public function init_shared(){ + global $current_user; + + + $user_ids = $current_user->getPreference('shared_ids'); + if(!empty($user_ids) && count($user_ids) != 0 && !isset($_REQUEST['shared_ids'])) { + $this->shared_ids = $user_ids; + }else if(isset($_REQUEST['shared_ids']) && count($_REQUEST['shared_ids']) > 0){ + $this->shared_ids = $_REQUEST['shared_ids']; + $current_user->setPreference('shared_ids', $_REQUEST['shared_ids']); + }else{ + $this->shared_ids = array($current_user->id); } - - } - function get_view() - { - return $this->view; } - -} - -// global to switch on the offet - -$DO_USER_TIME_OFFSET = false; - -class CalendarActivity -{ - var $sugar_bean; - var $start_time; - var $end_time; - - function CalendarActivity($args) - { - // if we've passed in an array, then this is a free/busy slot - // and does not have a sugarbean associated to it - global $DO_USER_TIME_OFFSET; - global $timedate; - - if ( is_array ( $args )) - { - $this->start_time = clone $args[0]; - $this->end_time = clone $args[1]; - $this->sugar_bean = null; - $timedate->tzGMT($this->start_time); - $timedate->tzGMT($this->end_time); - return; - } - - // else do regular constructor.. - - $sugar_bean = $args; - $this->sugar_bean = $sugar_bean; - - - if ($sugar_bean->object_name == 'Task') - { - $this->start_time = $timedate->fromUser($this->sugar_bean->date_due); - if ( empty($this->start_time)) - { - return null; - } - - $this->end_time = $timedate->fromUser($this->sugar_bean->date_due); - } - else - { - $this->start_time = $timedate->fromUser($this->sugar_bean->date_start); - if ( empty($this->start_time)) - { - return null; - } - $hours = $this->sugar_bean->duration_hours; - if(empty($hours)) { - $hours = 0; - } - $mins = $this->sugar_bean->duration_minutes; - if(empty($mins)) { - $mins = 0; - } - $this->end_time = $this->start_time->get("+$hours hours $mins minutes"); - } - // Convert it back to database time so we can properly manage it for getting the proper start and end dates - $timedate->tzGMT($this->start_time); - $timedate->tzGMT($this->end_time); + + /** + * Calculate timestamp the calendar grid should be started from + */ + protected function calculate_grid_start_ts(){ + + if($this->view == "week" || $this->view == "shared"){ + $week_start = CalendarUtils::get_first_day_of_week($this->date_time); + $this->grid_start_ts = $week_start->format('U') + $week_start->getOffset(); + }else if($this->view == "month"){ + $month_start = $this->date_time->get_day_by_index_this_month(0); + $week_start = CalendarUtils::get_first_day_of_week($month_start); + $this->grid_start_ts = $week_start->format('U') + $week_start->getOffset(); // convert to timestamp, ignore tz + }else if($this->view == "day"){ + $this->grid_start_ts = $this->date_time->format('U') + $this->date_time->getOffset(); + }else + $this->grid_start_ts = 0; } + + /** + * calculate count of timeslots per visible day, calculates day start and day end in minutes + */ + function calculate_day_range(){ + + list($hour_start,$minute_start) = explode(":",$this->day_start_time); + list($hour_end,$minute_end) = explode(":",$this->day_end_time); - function get_occurs_within_where_clause($table_name, $rel_table, $start_ts_obj, $end_ts_obj, $field_name='date_start', $view) - { + $this->d_start_minutes = $hour_start * 60 + $minute_start; + $this->d_end_minutes = $hour_end * 60 + $minute_end; + + $this->scroll_slot = intval($hour_start * (60 / $this->time_step) + ($minute_start / $this->time_step)); + $this->celcount = (($hour_end * 60 + $minute_end) - ($hour_start * 60 + $minute_start)) / $this->time_step; + } + + /** + * loads array of objects + * @param User $user user object + * @param string $type + */ + public function add_activities($user,$type='sugar'){ global $timedate; - // ensure we're working with user TZ - $start_ts_obj = $timedate->tzUser($start_ts_obj); - $end_ts_obj = $timedate->tzUser($end_ts_obj); - switch ($view) { - case 'month': - //C.L. For the start date, go back 6 days since 99 hours is the max duration (6 days) - $start = $start_ts_obj->get("-6 days")->get_day_begin(); - $end = $end_ts_obj->get("first day of next month")->get_day_begin(); - break; - case 'freebusy': //bug: 44586, for freebusy, don't modify the start/end dates - $start = $start_ts_obj; - $end = $end_ts_obj; - break; - default: - // Date for the past 5 days as that is the maximum duration of a single activity - $start = $start_ts_obj->get("-5 days")->get_day_begin(); - $end = $start_ts_obj->get("+5 days")->get_day_end(); - break; - } - - $field_date = $table_name.'.'.$field_name; - $start_day = $GLOBALS['db']->convert("'{$start->asDb()}'",'datetime'); - $end_day = $GLOBALS['db']->convert("'{$end->asDb()}'",'datetime'); - - $where = "($field_date >= $start_day AND $field_date < $end_day"; - if($rel_table != '') { - $where .= " AND $rel_table.accept_status != 'decline'"; - } + $start_date_time = $this->date_time; + if($this->view == 'week' || $this->view == 'shared'){ + $start_date_time = CalendarUtils::get_first_day_of_week($this->date_time); + $end_date_time = $start_date_time->get("+7 days"); + }else if($this->view == 'month'){ + $start_date_time = $this->date_time->get_day_by_index_this_month(0); + $end_date_time = $start_date_time->get("+".$start_date_time->format('t')." days"); + $start_date_time = CalendarUtils::get_first_day_of_week($start_date_time); + $end_date_time = CalendarUtils::get_first_day_of_week($end_date_time)->get("+7 days"); + }else{ + $end_date_time = $this->date_time->get("+1 day"); + } - $where .= ")"; - return $where; + $acts_arr = array(); + if($type == 'vfb'){ + $acts_arr = CalendarActivity::get_freebusy_activities($user, $start_date_time, $end_date_time); + }else{ + $acts_arr = CalendarActivity::get_activities($user->id, $this->show_tasks, $start_date_time, $end_date_time, $this->view,$this->show_calls); + } + + $this->acts_arr[$user->id] = $acts_arr; } - function get_freebusy_activities($user_focus, $start_date_time, $end_date_time) - { - $act_list = array(); - $vcal_focus = new vCal(); - $vcal_str = $vcal_focus->get_vcal_freebusy($user_focus); - - $lines = explode("\n",$vcal_str); - $utc = new DateTimeZone("UTC"); - foreach ($lines as $line) - { - if ( preg_match('/^FREEBUSY.*?:([^\/]+)\/([^\/]+)/i',$line,$matches)) - { - $dates_arr = array(SugarDateTime::createFromFormat(vCal::UTC_FORMAT, $matches[1], $utc), - SugarDateTime::createFromFormat(vCal::UTC_FORMAT, $matches[2], $utc)); - $act_list[] = new CalendarActivity($dates_arr); - } - } - usort($act_list,'sort_func_by_act_date'); - return $act_list; - } - - - function get_activities($user_id, $show_tasks, $view_start_time, $view_end_time, $view) { - global $current_user; - $act_list = array(); - $seen_ids = array(); - - - // get all upcoming meetings, tasks due, and calls for a user - if(ACLController::checkAccess('Meetings', 'list', $current_user->id == $user_id)) { - $meeting = new Meeting(); - - if($current_user->id == $user_id) { - $meeting->disable_row_level_security = true; - } - - $where = CalendarActivity::get_occurs_within_where_clause($meeting->table_name, $meeting->rel_users_table, $view_start_time, $view_end_time, 'date_start', $view); - $focus_meetings_list = build_related_list_by_user_id($meeting,$user_id,$where); - foreach($focus_meetings_list as $meeting) { - if(isset($seen_ids[$meeting->id])) { - continue; - } - - $seen_ids[$meeting->id] = 1; - $act = new CalendarActivity($meeting); - - if(!empty($act)) { - $act_list[] = $act; - } - } - } - - if(ACLController::checkAccess('Calls', 'list',$current_user->id == $user_id)) { - $call = new Call(); - - if($current_user->id == $user_id) { - $call->disable_row_level_security = true; - } - - $where = CalendarActivity::get_occurs_within_where_clause($call->table_name, $call->rel_users_table, $view_start_time, $view_end_time, 'date_start', $view); - $focus_calls_list = build_related_list_by_user_id($call,$user_id,$where); - - foreach($focus_calls_list as $call) { - if(isset($seen_ids[$call->id])) { - continue; - } - $seen_ids[$call->id] = 1; - - $act = new CalendarActivity($call); - if(!empty($act)) { - $act_list[] = $act; - } - } - } - - - if($show_tasks) { - if(ACLController::checkAccess('Tasks', 'list',$current_user->id == $user_id)) { - $task = new Task(); - - $where = CalendarActivity::get_occurs_within_where_clause('tasks', '', $view_start_time, $view_end_time, 'date_due', $view); - $where .= " AND tasks.assigned_user_id='$user_id' "; - - $focus_tasks_list = $task->get_full_list("", $where,true); - - if(!isset($focus_tasks_list)) { - $focus_tasks_list = array(); - } - - foreach($focus_tasks_list as $task) { - $act = new CalendarActivity($task); - if(!empty($act)) { - $act_list[] = $act; - } - } - } + /** + * Get date string of next or previous calendar grid + * @param string $direction next or previous + * @return string + */ + public function get_neighbor_date_str($direction){ + if($direction == "previous") + $sign = "-"; + else + $sign = "+"; + + if($this->view == 'month'){ + $day = $this->date_time->get($sign."1 month")->get_day_begin(1); + }else if($this->view == 'week' || $this->view == 'shared'){ + $day = CalendarUtils::get_first_day_of_week($this->date_time); + $day = $day->get($sign."7 days"); + }else if($this->view == 'day'){ + $day = $this->date_time->get($sign."1 day")->get_day_begin(); + }else if($this->view == 'year'){ + $day = $this->date_time->get($sign."1 year")->get_day_begin(); + }else{ + return "get_neighbor_date_str: notdefined for this view"; } - - usort($act_list,'sort_func_by_act_date'); - return $act_list; + return $day->get_date_str(); } + } + +?> diff --git a/modules/Calendar/CalendarActivity.php b/modules/Calendar/CalendarActivity.php new file mode 100644 index 00000000..c2662d63 --- /dev/null +++ b/modules/Calendar/CalendarActivity.php @@ -0,0 +1,231 @@ +start_time = clone $args[0]; + $this->end_time = clone $args[1]; + $this->sugar_bean = null; + $timedate->tzGMT($this->start_time); + $timedate->tzGMT($this->end_time); + return; + } + + // else do regular constructor.. + + $sugar_bean = $args; + $this->sugar_bean = $sugar_bean; + + + if ($sugar_bean->object_name == 'Task'){ + $this->start_time = $timedate->fromUser($this->sugar_bean->date_due); + if ( empty($this->start_time)){ + return null; + } + $this->end_time = $timedate->fromUser($this->sugar_bean->date_due); + }else{ + $this->start_time = $timedate->fromUser($this->sugar_bean->date_start); + if ( empty($this->start_time)){ + return null; + } + $hours = $this->sugar_bean->duration_hours; + if(empty($hours)){ + $hours = 0; + } + $mins = $this->sugar_bean->duration_minutes; + if(empty($mins)){ + $mins = 0; + } + $this->end_time = $this->start_time->get("+$hours hours $mins minutes"); + } + // Convert it back to database time so we can properly manage it for getting the proper start and end dates + $timedate->tzGMT($this->start_time); + $timedate->tzGMT($this->end_time); + } + + /** + * Get where clause for fetching entried from DB + * @param string $table_name t + * @param string $rel_table table for accept status, not used in Tasks + * @param SugarDateTime $start_ts_obj start date + * @param SugarDateTime $end_ts_obj end date + * @param string $field_name date field in table + * @param string $view view; not used for now, left for compatibility + * @return string + */ + function get_occurs_within_where_clause($table_name, $rel_table, $start_ts_obj, $end_ts_obj, $field_name='date_start', $view){ + global $timedate; + + $start = clone $start_ts_obj; + $end = clone $end_ts_obj; + + $field_date = $table_name.'.'.$field_name; + $start_day = $GLOBALS['db']->convert("'{$start->asDb()}'",'datetime'); + $end_day = $GLOBALS['db']->convert("'{$end->asDb()}'",'datetime'); + + $where = "($field_date >= $start_day AND $field_date < $end_day"; + if($rel_table != ''){ + $where .= " AND $rel_table.accept_status != 'decline'"; + } + + $where .= ")"; + return $where; + } + + function get_freebusy_activities($user_focus, $start_date_time, $end_date_time){ + $act_list = array(); + $vcal_focus = new vCal(); + $vcal_str = $vcal_focus->get_vcal_freebusy($user_focus); + + $lines = explode("\n",$vcal_str); + $utc = new DateTimeZone("UTC"); + foreach ($lines as $line){ + if ( preg_match('/^FREEBUSY.*?:([^\/]+)\/([^\/]+)/i',$line,$matches)){ + $dates_arr = array(SugarDateTime::createFromFormat(vCal::UTC_FORMAT, $matches[1], $utc), + SugarDateTime::createFromFormat(vCal::UTC_FORMAT, $matches[2], $utc)); + $act_list[] = new CalendarActivity($dates_arr); + } + } + return $act_list; + } + + /** + * Get array of activities + * @param string $user_id + * @param boolean $show_tasks + * @param SugarDateTime $view_start_time start date + * @param SugarDateTime $view_end_time end date + * @param string $view view; not used for now, left for compatibility + * @param boolean $show_calls + * @return array + */ + function get_activities($user_id, $show_tasks, $view_start_time, $view_end_time, $view, $show_calls = true){ + global $current_user; + $act_list = array(); + $seen_ids = array(); + + + // get all upcoming meetings, tasks due, and calls for a user + if(ACLController::checkAccess('Meetings', 'list', $current_user->id == $user_id)) { + $meeting = new Meeting(); + + if($current_user->id == $user_id) { + $meeting->disable_row_level_security = true; + } + + $where = CalendarActivity::get_occurs_within_where_clause($meeting->table_name, $meeting->rel_users_table, $view_start_time, $view_end_time, 'date_start', $view); + $focus_meetings_list = build_related_list_by_user_id($meeting,$user_id,$where); + foreach($focus_meetings_list as $meeting) { + if(isset($seen_ids[$meeting->id])) { + continue; + } + + $seen_ids[$meeting->id] = 1; + $act = new CalendarActivity($meeting); + + if(!empty($act)) { + $act_list[] = $act; + } + } + } + + if($show_calls){ + if(ACLController::checkAccess('Calls', 'list',$current_user->id == $user_id)) { + $call = new Call(); + + if($current_user->id == $user_id) { + $call->disable_row_level_security = true; + } + + $where = CalendarActivity::get_occurs_within_where_clause($call->table_name, $call->rel_users_table, $view_start_time, $view_end_time, 'date_start', $view); + $focus_calls_list = build_related_list_by_user_id($call,$user_id,$where); + + foreach($focus_calls_list as $call) { + if(isset($seen_ids[$call->id])) { + continue; + } + $seen_ids[$call->id] = 1; + + $act = new CalendarActivity($call); + if(!empty($act)) { + $act_list[] = $act; + } + } + } + } + + + if($show_tasks){ + if(ACLController::checkAccess('Tasks', 'list',$current_user->id == $user_id)) { + $task = new Task(); + + $where = CalendarActivity::get_occurs_within_where_clause('tasks', '', $view_start_time, $view_end_time, 'date_due', $view); + $where .= " AND tasks.assigned_user_id='$user_id' "; + + $focus_tasks_list = $task->get_full_list("", $where,true); + + if(!isset($focus_tasks_list)) { + $focus_tasks_list = array(); + } + + foreach($focus_tasks_list as $task) { + $act = new CalendarActivity($task); + if(!empty($act)) { + $act_list[] = $act; + } + } + } + } + return $act_list; + } +} + +?> diff --git a/modules/Calendar/CalendarDisplay.php b/modules/Calendar/CalendarDisplay.php new file mode 100644 index 00000000..cd6fc09b --- /dev/null +++ b/modules/Calendar/CalendarDisplay.php @@ -0,0 +1,450 @@ + array( + 'border' => '#1C5FBD', + 'body' => '#D2E5FC', + ), + 'Calls' => array( + 'border' => '#DE4040', + 'body' => '#FCDCDC', + ), + 'Tasks' => array( + 'border' => '#015900', + 'body' => '#B1F5AE', + ), + ); + + /** + * constructor + * @param Calendar $cal + * @param string $dashlet_id for dashlet mode + */ + function __construct(&$cal,$dashlet_id = ""){ + $this->cal = &$cal; + $this->dashlet_id = $dashlet_id; + } + + /** + * main displaying function of Calendar + */ + public function display(){ + + global $timedate; + + $cal = &$this->cal; + $ss = new Sugar_Smarty(); + + $ss->assign('APP',$GLOBALS['app_strings']); + $ss->assign('APPLIST',$GLOBALS['app_list_strings']); + $ss->assign('MOD',$GLOBALS['cal_strings']); + + $ss->assign('view',$cal->view); + $ss->assign('t_step',$cal->time_step); + $ss->assign('current_user_id',$GLOBALS['current_user']->id); + $ss->assign('current_user_name',$GLOBALS['current_user']->name); + $ss->assign('time_format',$GLOBALS['timedate']->get_user_time_format()); + $ss->assign('items_draggable',SugarConfig::getInstance()->get('calendar.items_draggable',true)); + $ss->assign('mouseover_expand',SugarConfig::getInstance()->get('calendar.mouseover_expand',true)); + $ss->assign('item_text','name'); + $ss->assign('cells_per_day',$cal->cells_per_day); + $ss->assign('img_edit_inline',SugarThemeRegistry::current()->getImageURL('edit_inline.gif',false)); + $ss->assign('img_view_inline',SugarThemeRegistry::current()->getImageURL('view_inline.gif',false)); + $ss->assign('img_close',SugarThemeRegistry::current()->getImageURL('close.gif',false)); + $ss->assign('dashlet',$cal->dashlet); + + $ss->assign('grid_start_ts',$cal->grid_start_ts); + $ss->assign('celcount',$cal->celcount); + + if(count($cal->shared_ids)){ + $ss->assign('shared_ids',$cal->shared_ids); + $ss->assign('shared_users_count',count($cal->shared_ids)); + } + $ss->assign('activity_colors',$this->activity_colors); + + $ss->assign('scroll_slot',$this->cal->scroll_slot); + + $ss->assign('editview_width',SugarConfig::getInstance()->get('calendar.editview_width',800)); + $ss->assign('editview_height',SugarConfig::getInstance()->get('calendar.editview_height',600)); + $ss->assign('a_str',$cal->get_activities_js()); + + $ss->assign('sugar_body_only',(isset($_REQUEST['to_pdf']) && $_REQUEST['to_pdf'] || isset($_REQUEST['sugar_body_only']) && $_REQUEST['sugar_body_only'])); + require_once('include/json_config.php'); + global $json; + $json = getJSONobj(); + $json_config = new json_config(); + $ss->assign('GRjavascript',$json_config->get_static_json_server(false, true, 'Meetings')); + + // form + $user_default_date_start = $timedate->asUser($timedate->getNow()); + $ss->assign('user_default_date_start',$user_default_date_start); + // end form + + if($_REQUEST['module'] == "Calendar"){ + $this->load_settings_template($ss); + $settings = "custom/modules/Calendar/tpls/settings.tpl"; + if(!file_exists($settings)) + $settings = "modules/Calendar/tpls/settings.tpl"; + $ss->assign("settings",$settings); + } + + $main = "custom/modules/Calendar/tpls/main.tpl"; + if(!file_exists($main)) + $main = "modules/Calendar/tpls/main.tpl"; + $form_tpl = "custom/modules/Calendar/tpls/form.tpl"; + if(!file_exists($form_tpl)) + $form_tpl = "modules/Calendar/tpls/form.tpl"; + + $ss->assign("form",$form_tpl); + + echo $ss->fetch($main); + + // drid + $grid = new CalendarGrid($cal); + echo $grid->display(); + // end grid + } + + /** + * load settings popup template + */ + protected function load_settings_template(&$ss){ + + list($d_start_hour,$d_start_min) = explode(":",$this->cal->day_start_time); + list($d_end_hour,$d_end_min) = explode(":",$this->cal->day_end_time); + + require_once("include/utils.php"); + global $app_strings,$app_list_strings,$beanList; + global $timedate; + + $user_default_date_start = $timedate->asUser($timedate->getNow()); + if(!isset($time_separator)) + $time_separator = ":"; + $date_format = $timedate->get_cal_date_format(); + $time_format = $timedate->get_user_time_format(); + $TIME_FORMAT = $time_format; + $t23 = strpos($time_format, '23') !== false ? '%H' : '%I'; + if(!isset($match[2]) || $match[2] == '') { + $CALENDAR_FORMAT = $date_format . ' ' . $t23 . $time_separator . "%M"; + }else{ + $pm = $match[2] == "pm" ? "%P" : "%p"; + $CALENDAR_FORMAT = $date_format . ' ' . $t23 . $time_separator . "%M" . $pm; + } + $hours_arr = array (); + $num_of_hours = 24; + $start_at = 0; + $TIME_MERIDIEM = ""; + $time_pref = $timedate->get_time_format(); + $start_m = ""; + if(strpos($time_pref, 'a') || strpos($time_pref, 'A')){ + $num_of_hours = 12; + $start_at = 1; + $start_m = 'am'; + if($d_start_hour == 0){ + $d_start_hour = 12; + $start_m = 'am'; + }else + if($d_start_hour == 12) + $start_m = 'pm'; + if($d_start_hour > 12){ + $d_start_hour = $d_start_hour - 12; + $start_m = 'pm'; + } + $end_m = 'am'; + if($d_end_hour == 0){ + $d_end_hour = 12; + $end_m = 'am'; + }else + if($d_end_hour == 12) + $end_m = 'pm'; + + if($d_end_hour > 12){ + $d_end_hour = $d_end_hour - 12; + $end_m = 'pm'; + } + if(strpos($time_pref, 'A')){ + $start_m = strtoupper($start_m); + $end_m = strtoupper($end_m); + } + $options = strpos($time_pref, 'a') ? $app_list_strings['dom_meridiem_lowercase'] : $app_list_strings['dom_meridiem_uppercase']; + $TIME_START_MERIDIEM = get_select_options_with_id($options, $start_m); + $TIME_END_MERIDIEM = get_select_options_with_id($options, $end_m); + $TIME_START_MERIDIEM = ""; + $TIME_END_MERIDIEM = ""; + }else{ + $TIME_START_MERIDIEM = $TIME_END_MERIDIEM = ""; + } + for($i = $start_at; $i <= $num_of_hours; $i ++){ + $i = $i.""; + if (strlen($i) == 1) + $i = "0".$i; + $hours_arr[$i] = $i; + } + $TIME_START_HOUR_OPTIONS = get_select_options_with_id($hours_arr, $d_start_hour); + $TIME_START_MINUTES_OPTIONS = get_select_options_with_id(array('0'=>'00','15'=>'15','30'=>'30','45'=>'45'), $d_start_min); + $TIME_END_HOUR_OPTIONS = get_select_options_with_id($hours_arr, $d_end_hour); + $TIME_END_MINUTES_OPTIONS = get_select_options_with_id(array('0'=>'00','15'=>'15','30'=>'30','45'=>'45'), $d_end_min); + + $ss->assign('day',$_REQUEST['day']); + $ss->assign('week',$_REQUEST['week']); + $ss->assign('month',$_REQUEST['month']); + $ss->assign('year',$_REQUEST['year']); + $ss->assign('TIME_START_HOUR_OPTIONS',$TIME_START_HOUR_OPTIONS); + $ss->assign('TIME_START_MINUTES_OPTIONS',$TIME_START_MINUTES_OPTIONS); + $ss->assign('TIME_START_MERIDIEM',$TIME_START_MERIDIEM); + $ss->assign('TIME_END_HOUR_OPTIONS',$TIME_END_HOUR_OPTIONS); + $ss->assign('TIME_END_MINUTES_OPTIONS',$TIME_END_MINUTES_OPTIONS); + $ss->assign('TIME_END_MERIDIEM',$TIME_END_MERIDIEM); + $ss->assign('show_calls',$this->cal->show_calls); + $ss->assign('show_tasks',$this->cal->show_tasks); + } + + /** + * Get date info string (legacy from old calendar) + * @return string + */ + public function get_date_info($view, $date_time){ + $str = ""; + + global $current_user; + $dateFormat = $current_user->getUserDateTimePreferences(); + + if($view == 'month'){ + for($i=0; $iyear; + break; + case "m": + $str .= " ".$date_time->get_month_name(); + break; + } + } + }else + if($view == 'week' || $view == 'shared') { + $first_day = $date_time; + + $first_day = CalendarUtils::get_first_day_of_week($date_time); + $last_day = $first_day->get("+6 days"); + + for($i=0; $iyear; + break; + case "m": + $str .= " ".$first_day->get_month_name(); + break; + case "d": + $str .= " ".$first_day->get_day(); + break; + } + } + $str .= " - "; + for($i=0; $iyear; + break; + case "m": + $str .= " ".$last_day->get_month_name(); + break; + case "d": + $str .= " ".$last_day->get_day(); + break; + } + } + }else if($view == 'day'){ + $str .= $date_time->get_day_of_week()." "; + + for($i=0; $iyear; + break; + case "m": + $str .= " ".$date_time->get_month_name(); + break; + case "d": + $str .= " ".$date_time->get_day(); + break; + } + } + }else if($view == 'year') { + $str .= $date_time->year; + }else{ + sugar_die("echo_date_info: date not supported"); + } + return $str; + } + + /** + * Get link to next date range + * @return string + */ + protected function get_next_calendar(){ + global $cal_strings,$image_path; + $str = ""; + if($_REQUEST['module'] == "Calendar"){ + $str .= ""; + + }else{ + $str .= ""; + } + $str .= $cal_strings["LBL_NEXT_".strtoupper($this->cal->view)]; + + $str .= "  ".SugarThemeRegistry::current()->getImage("calendar_next", 'align="absmiddle" border="0"' ,null,null,'.gif', '') . ""; //setting alt tag blank on purpose for 508 compliance + return $str; + } + + /** + * Get link to previous date range + * @return string + */ + protected function get_previous_calendar(){ + global $cal_strings,$image_path; + $str = ""; + if($_REQUEST['module'] == "Calendar"){ + $str .= ""; + }else{ + $str .= ""; + } + $str .= SugarThemeRegistry::current()->getImage('calendar_previous','align="absmiddle" border="0"', null, null, '.gif', ''); //setting alt tag blank on purpose for 508 compliance + $str .= "  ".$cal_strings["LBL_PREVIOUS_".strtoupper($this->cal->view)] . ""; + return $str; + } + + /** + * display header + * @param boolean $controls display ui contol elements + */ + public function display_calendar_header($controls = true){ + global $cal_strings; + + $ss = new Sugar_Smarty(); + $ss->assign("MOD",$cal_strings); + $ss->assign("view",$this->cal->view); + + if($controls){ + $current_date = str_pad($this->cal->date_time->month,2,'0',STR_PAD_LEFT)."/".str_pad($this->cal->date_time->day,2,'0',STR_PAD_LEFT)."/".$this->cal->date_time->year; + + $tabs = array('day', 'week', 'month', 'year', 'shared'); + $tabs_params = array(); + foreach($tabs as $tab){ + $tabs_params[$tab]['title'] = $cal_strings["LBL_".strtoupper($tab)]; + $tabs_params[$tab]['id'] = $tab . "_tab"; + $tabs_params[$tab]['link'] = "window.location.href='".ajaxLink("index.php?module=Calendar&action=index&view=". $tab . $this->cal->date_time->get_date_str())."'"; + } + $ss->assign('controls',$controls); + $ss->assign('tabs',$tabs); + $ss->assign('tabs_params',$tabs_params); + $ss->assign('current_date',$current_date); + $ss->assign('start_weekday',$GLOBALS['current_user']->get_first_day_of_week()); + $ss->assign('cal_img',SugarThemeRegistry::current()->getImageURL("jscalendar.gif",false)); + } + + $ss->assign('previous',$this->get_previous_calendar()); + $ss->assign('next',$this->get_next_calendar()); + + $ss->assign('date_info',$this->get_date_info($this->cal->view,$this->cal->date_time)); + + $header = "custom/modules/Calendar/tpls/header.tpl"; + if(!file_exists($header)) + $header = "modules/Calendar/tpls/header.tpl"; + echo $ss->fetch($header); + } + + /** + * display footer + */ + public function display_calendar_footer(){ + global $cal_strings; + + $ss = new Sugar_Smarty(); + $ss->assign("MOD",$cal_strings); + $ss->assign("view",$this->cal->view); + + $ss->assign('previous',$this->get_previous_calendar()); + $ss->assign('next',$this->get_next_calendar()); + + $footer = "custom/modules/Calendar/tpls/footer.tpl"; + if(!file_exists($footer)) + $footer = "modules/Calendar/tpls/footer.tpl"; + echo $ss->fetch($footer); + } + + /** + * display title + */ + public function display_title(){ + global $mod_strings; + echo get_module_title("Calendar","»".$mod_strings['LBL_MODULE_TITLE'], false); + } + + /** + * display html used in shared view + */ + public function display_shared_html(){ + global $app_strings,$cal_strings,$action; + + $ss = new Sugar_Smarty(); + $ss->assign("APP",$app_strings); + $ss->assign("MOD",$cal_strings); + $ss->assign("UP",SugarThemeRegistry::current()->getImage('uparrow_big', 'border="0" style="margin-bottom: 1px;"', null, null, '.gif', $app_strings['LBL_SORT'])); + $ss->assign("DOWN",SugarThemeRegistry::current()->getImage('downarrow_big', 'border="0" style="margin-top: 1px;"', null, null, '.gif', $app_strings['LBL_SORT'])); + + if(empty($_REQUEST['edit_shared'])){ + $ss->assign("style","display: none"); + } + + + $ss->assign("users_options",get_select_options_with_id(get_user_array(false), $this->cal->shared_ids)); + + $tpl = "modules/Calendar/tpls/shared_users.tpl"; + echo $ss->fetch($tpl); + } + +} + +?> diff --git a/modules/Calendar/CalendarGrid.php b/modules/Calendar/CalendarGrid.php new file mode 100644 index 00000000..719132bd --- /dev/null +++ b/modules/Calendar/CalendarGrid.php @@ -0,0 +1,408 @@ +cal = &$cal; + $today = $GLOBALS['timedate']->getNow(true)->get_day_begin(); + $this->today_ts = $today->format('U') + $today->getOffset(); + $this->startday = $current_user->get_first_day_of_week(); + + $weekday_names = array(); + for($i = 0; $i < 7; $i++){ + $j = $i + $this->startday; + if($j >= 7) + $j = $j - 7; + $weekday_names[$i] = $GLOBALS['app_list_strings']['dom_cal_day_short'][$j+1]; + } + + $this->weekday_names = $weekday_names; + + $this->scrollable = false; + if(in_array($this->cal->view,array('day','week'))){ + $this->scrollable = true; + if($this->cal->time_step < 30) + $this->scroll_height = 480; + else + $this->scroll_height = $this->cal->celcount * 15 + 1; + } + + $this->time_step = $this->cal->time_step; + $this->time_format = $GLOBALS['timedate']->get_time_format(); + $this->date_time_format = $GLOBALS['timedate']->get_date_time_format(); + + } + + + /** Get html of calendar grid + * @return string + */ + public function display(){ + $action = "display_".strtolower($this->cal->view); + return $this->$action(); + } + + /** Get html of time column + * @param integer $start timestamp + * @return string + */ + protected function get_time_column($start){ + $str = ""; + $head_content = " "; + if($this->cal->view == 'month'){ + if($this->startday == 0) + $wf = 1; + else + $wf = 0; + $head_content = "fromTimestamp($start)->format('j')."&month=".$GLOBALS['timedate']->fromTimestamp($start)->format('n')."&year=".$GLOBALS['timedate']->fromTimestamp($start)->format('Y'))."'>".$GLOBALS['timedate']->fromTimestamp($start + $wf*3600*24)->format('W').""; + } + $str .= "
      "; + if(!$this->scrollable) + $str .= "
      ".$head_content."
      "; + for($i = 0; $i < 24; $i++){ + for($j = 0; $j < 60; $j += $this->time_step){ + + if($j == 0){ + $innerText = $GLOBALS['timedate']->fromTimestamp($start + $i * 3600)->format($this->time_format); + }else{ + $innerText = " "; + } + if($j == 60 - $this->time_step && $this->time_step < 60){ + $class = " odd_border"; + }else{ + $class = ""; + } + if($this->scrollable || !$this->check_owt($i,$j,$this->cal->d_start_minutes,$this->cal->d_end_minutes)) + $str .= "
      ".$innerText."
      "; + } + } + $str .= "
      "; + return $str; + } + + /** + * Get html of day slots column + * @param integer $start timestamp + * @param integer $day number of day in week + * @param string $prefix prefix for id of timeslot used in shared view + * @return string + */ + protected function get_day_column($start,$day = 0,$prefix = ""){ + $curr_time = $start; + $str = ""; + $str .= "
      "; + $str .= $this->get_day_head($start,$day); + for($i = 0; $i < 24; $i++){ + for($j = 0; $j < 60; $j += $this->time_step){ + $timestr = $GLOBALS['timedate']->fromTimestamp($curr_time)->format($this->time_format); + if($j == 60 - $this->time_step && $this->time_step < 60){ + $class = " odd_border"; + }else{ + $class = ""; + } + if($this->scrollable || !$this->check_owt($i,$j,$this->cal->d_start_minutes,$this->cal->d_end_minutes)) + $str .= "
      fromTimestamp($curr_time)->format($this->date_time_format)."'>
      "; + $curr_time += $this->time_step*60; + } + } + $str .= "
      "; + return $str; + } + + /** + * Get html of day head + * @param integer $start timestamp + * @param integer $day number of day in week + * @param bulean $force force display header + * @return string + */ + protected function get_day_head($start,$day = 0,$force = false){ + $str = ""; + if(!$this->scrollable || $force){ + $headstyle = ""; + if($this->today_ts == $start) + $headstyle = " today"; + $str .= ""; + } + return $str; + } + + /** + * Get true if out of working day + * @param integer $i hours + * @param integer $j minutes + * @param integer $r_start start of working day in minutes + * @param integer $r_end end of working day in minutes + * @return boolean + */ + protected function check_owt($i,$j,$r_start,$r_end){ + if($i*60+$j < $r_start || $i*60+$j >= $r_end) + return true; + } + + /** + * Get html of week calendar grid + * @return string + */ + protected function display_week(){ + + $current_date = $this->cal->date_time; + $week_start = CalendarUtils::get_first_day_of_week($current_date); + $week_start_ts = $week_start->format('U') + $week_start->getOffset(); // convert to timestamp, ignore tz + + $str = ""; + $str .= ""; + + return $str; + } + + /** + * Get html of day calendar grid + * @return string + */ + protected function display_day(){ + + $current_date = $this->cal->date_time; + $day_start_ts = $current_date->format('U') + $current_date->getOffset(); // convert to timestamp, ignore tz + + + $str = ""; + $str .= ""; + + return $str; + } + + /** + * Get html of month calendar grid + * @return string + */ + protected function display_month(){ + + $current_date = $this->cal->date_time; + $month_start = $current_date->get_day_by_index_this_month(0); + $month_end = $month_start->get("+".$month_start->format('t')." days"); + $week_start = CalendarUtils::get_first_day_of_week($month_start); + $week_start_ts = $week_start->format('U') + $week_start->getOffset(); // convert to timestamp, ignore tz + $month_end_ts = $month_end->format('U') + $month_end->getOffset(); + + $str = ""; + $str .= ""; + + return $str; + } + + /** + * Get html of week shared grid + * @return string + */ + protected function display_shared(){ + + $current_date = $this->cal->date_time; + $week_start = CalendarUtils::get_first_day_of_week($current_date); + $week_start_ts = $week_start->format('U') + $week_start->getOffset(); // convert to timestamp, ignore tz + + $str = ""; + $str .= ""; + + return $str; + } + + /** + * Get html of year calendar + * @return string + */ + protected function display_year(){ + + $weekEnd1 = 0 - $this->startday; + $weekEnd2 = -1 - $this->startday; + if($weekEnd1 < 0) + $weekEnd1 += 7; + if($weekEnd2 < 0) + $weekEnd2 += 7; + + $year_start = $GLOBALS['timedate']->fromString($this->cal->date_time->year.'-01-01'); + + $str = ""; + $str .= '
@@ -263,8 +246,10 @@ $form =<< eoq; } + $hidden_fields = ""; $hidden_fields .= ""; + $form2 = PackageManagerDisplay::buildPackageDisplay($form, $hidden_fields, $form_action, array('module')); $form3 =<<"; + $icon = ""; } $upgrades_available++; @@ -360,7 +345,6 @@ print( "\n" ); */ $GLOBALS['log']->info( "Upgrade Wizard view"); - ?>
'; + + for($m = 0; $m < 12; $m++){ + + $month_start = $year_start->get("+".$m." months"); + $month_start_ts = $month_start->format('U') + $month_start->getOffset(); + $month_end = $month_start->get("+".$month_start->format('t')." days"); + $week_start = CalendarUtils::get_first_day_of_week($month_start); + $week_start_ts = $week_start->format('U') + $week_start->getOffset(); // convert to timestamp, ignore tz + $month_end_ts = $month_end->format('U') + $month_end->getOffset(); + $table_id = "daily_cal_table".$m; //bug 47471 + + if($m % 3 == 0) + $str .= ""; + $str .= ''; + if(($m - 2) % 3 == 0) + $str .= ""; + } + $str .= "
'; + $str .= ''.$GLOBALS['app_list_strings']['dom_cal_month_long'][$m+1].''; + $str .= ''; + $str .= ''; + for($d = 0; $d < 7; $d++) + $str .= ''; + $str .= ''; + $curr_time_global = $week_start_ts; + $w = 0; + while($curr_time_global < $month_end_ts){ + $str .= ''; + for($d = 0; $d < 7; $d++){ + $curr_time = $week_start_ts + $d*86400 + $w*60*60*24*7; + + if($curr_time < $month_start_ts || $curr_time >= $month_end_ts) + $monC = ""; + else + $monC = ''.$GLOBALS['timedate']->fromTimestamp($curr_time)->format('j').''; + + if($d == $weekEnd1 || $d == $weekEnd2) + $str .= ""; + } + $str .= ""; + $curr_time_global += 60*60*24*7; + $w++; + } + $str .= '
'.$this->weekday_names[$d].'
"; + else + $str .= ""; + $str .= $monC; + $str .= "
'; + $str .= '
"; + + return $str; + } +} + +?> diff --git a/modules/Calendar/CalendarUtils.php b/modules/Calendar/CalendarUtils.php new file mode 100644 index 00000000..54b11f3f --- /dev/null +++ b/modules/Calendar/CalendarUtils.php @@ -0,0 +1,124 @@ +get_first_day_of_week(); + if($date->day_of_week < $fdow) + $date = $date->get('-7 days'); + return $date->get_day_by_index_this_week($fdow); + } + + + /** + * Get list of needed fields for modules + * @return array + */ + static function get_fields(){ + return array( + 'Meetings' => array( + 'name', + 'date_start', + 'duration_hours', + 'duration_minutes', + 'status', + 'description', + 'parent_type', + 'parent_name', + 'parent_id', + ), + 'Calls' => array( + 'name', + 'date_start', + 'duration_hours', + 'duration_minutes', + 'status', + 'description', + 'parent_type', + 'parent_name', + 'parent_id', + ), + 'Tasks' => array( + 'name', + 'date_start', + 'date_due', + 'status', + 'description', + 'parent_type', + 'parent_name', + 'parent_id', + ), + ); + } + + /** + * Get array of needed time data + * @param SugarBean $bean + * @return array + */ + static function get_time_data($bean){ + $arr = array(); + + $date_field = "date_start"; + if($bean->object_name == 'Task') + $date_field = "date_due"; + + $timestamp = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$bean->$date_field,new DateTimeZone('UTC'))->format('U'); + $arr['timestamp'] = $timestamp; + $arr['time_start'] = $GLOBALS['timedate']->fromTimestamp($arr['timestamp'])->format($GLOBALS['timedate']->get_time_format()); + + + return $arr; + } +} diff --git a/modules/Calendar/small_month.php b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.en_us.lang.php similarity index 77% rename from modules/Calendar/small_month.php rename to modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.en_us.lang.php index 25a5f05e..ab1d1a81 100644 --- a/modules/Calendar/small_month.php +++ b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.en_us.lang.php @@ -1,6 +1,5 @@ \ No newline at end of file +$dashletStrings['CalendarDashlet'] = array( + 'LBL_TITLE' => 'Calendar', + 'LBL_DESCRIPTION' => 'Calendar dashlet', + 'LBL_CONFIGURE_TITLE' => 'Title', + 'LBL_CONFIGURE_VIEW' => 'View', + 'LBL_SAVE_BUTTON_LABEL' => 'Save', + + 'LBL_VIEW_DAY' => 'Day', + 'LBL_VIEW_WEEK' => 'Week', + 'LBL_VIEW_MONTH' => 'Month', + +); +?> diff --git a/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.meta.php b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.meta.php new file mode 100644 index 00000000..1e4135b1 --- /dev/null +++ b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.meta.php @@ -0,0 +1,47 @@ + 'LBL_TITLE', // array index in language pack + 'description' => 'LBL_DESCRIPTION', // array index in language pack + 'icon' => 'icon_Calendar_32.gif', + 'category' => 'Module Views', +); +?> diff --git a/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.php b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.php new file mode 100644 index 00000000..c0d71496 --- /dev/null +++ b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashlet.php @@ -0,0 +1,122 @@ +loadLanguage('CalendarDashlet','modules/Calendar/Dashlets/'); + + parent::Dashlet($id); + + $this->isConfigurable = true; + $this->hasScript = true; + + if(empty($def['title'])) + $this->title = $this->dashletStrings['LBL_TITLE']; + else + $this->title = $def['title']; + + if(!empty($def['view'])) + $this->view = $def['view']; + + } + + function display(){ + ob_start(); + + if(isset($GLOBALS['cal_strings'])) + return parent::display() . "Only one Calendar dashlet is allowed."; + + require_once('modules/Calendar/Calendar.php'); + require_once('modules/Calendar/CalendarDisplay.php'); + require_once("modules/Calendar/CalendarGrid.php"); + + global $cal_strings, $current_language; + $cal_strings = return_module_language($current_language, 'Calendar'); + + if(!ACLController::checkAccess('Calendar', 'list', true)) + ACLController::displayNoAccess(true); + + $cal = new Calendar($this->view); + $cal->dashlet = true; + $cal->add_activities($GLOBALS['current_user']); + $cal->load_activities(); + + $display = new CalendarDisplay($cal,$this->id); + $display->display_calendar_header(false); + $display->display(); + + $str = ob_get_contents(); + ob_end_clean(); + + return parent::display() . $str; + } + + + function displayOptions() { + global $app_strings,$mod_strings; + $ss = new Sugar_Smarty(); + $ss->assign('MOD', $this->dashletStrings); + $ss->assign('title', $this->title); + $ss->assign('view', $this->view); + $ss->assign('id', $this->id); + + return parent::displayOptions() . $ss->fetch('modules/Calendar/Dashlets/CalendarDashlet/CalendarDashletOptions.tpl'); + } + + function saveOptions($req) { + global $sugar_config, $timedate, $current_user, $theme; + $options = array(); + $options['title'] = $_REQUEST['title']; + $options['view'] = $_REQUEST['view']; + + return $options; + } + + function displayScript(){ + return ""; + } + + +} + +?> diff --git a/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashletOptions.tpl b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashletOptions.tpl new file mode 100644 index 00000000..d939c90c --- /dev/null +++ b/modules/Calendar/Dashlets/CalendarDashlet/CalendarDashletOptions.tpl @@ -0,0 +1,72 @@ +{* + +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + + +*} + + +
+ + + + + + + + + + + + + + + + + + +
{$MOD.LBL_CONFIGURE_TITLE} + +
{$MOD.LBL_CONFIGURE_VIEW} + +
+ +
+ +
diff --git a/modules/Calendar/DateTimeUtil.php b/modules/Calendar/DateTimeUtil.php deleted file mode 100644 index 3d6213cc..00000000 --- a/modules/Calendar/DateTimeUtil.php +++ /dev/null @@ -1,637 +0,0 @@ -adjustmentForUserTimeZone()*60; - $time_arr['sec'] = $gmtdiff; - return new DateTimeUtil($time_arr,true); - } - - function get_time_end( $start_time, $duration_hours,$duration_minutes) - { - if ( empty($duration_hours)) - { - $duration_hours = "00"; - } - if ( empty($duration_minutes)) - { - $duration_minutes = "00"; - } - - $added_seconds = ($duration_hours * 60 * 60 + $duration_minutes * 60 ) - 1; - - $time_arr = array(); - $time_arr['year'] = $start_time->year; - $time_arr['month'] = $start_time->month; - $time_arr['day'] = $start_time->day; - $time_arr['hour'] = $start_time->hour; - $time_arr['min'] = $start_time->min; - $time_arr['sec'] = $added_seconds; - return new DateTimeUtil($time_arr,true); - - } - - function get_date_str() - { - - $arr = array(); - if ( isset( $this->hour)) - { - array_push( $arr, "hour=".$this->hour); - } - if ( isset( $this->day)) - { - array_push( $arr, "day=".$this->day); - } - if ( isset( $this->month)) - { - array_push( $arr, "month=".$this->month); - } - if ( isset( $this->year)) - { - array_push( $arr, "year=".$this->year); - } - return ("&".implode('&',$arr)); - } - - function get_tomorrow() - { - $date_arr = array('day'=>($this->day + 1), - 'month'=>$this->month, - 'year'=>$this->year); - - return new DateTimeUtil($date_arr,true); - } - function get_yesterday() - { - $date_arr = array('day'=>($this->day - 1), - 'month'=>$this->month, - 'year'=>$this->year); - - return new DateTimeUtil($date_arr,true); - } - - function get_mysql_date() - { - return $this->year."-".$this->zmonth."-".$this->zday; - } - function get_mysql_time() - { - return $this->hour.":".$this->min; - } - - function parse_utc_date_time($str) - { - preg_match('/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/',$str,$matches); - - $date_arr = array( - 'year'=>$matches[1], - 'month'=>$matches[2], - 'day'=>$matches[3], - 'hour'=>$matches[4], - 'min'=>$matches[5]); - - $date_time = new DateTimeUtil($date_arr,true); - - $date_arr = array('ts'=>$date_time->ts + $date_time->tz_offset); - - return new DateTimeUtil($date_arr,true); - } - - function get_utc_date_time() - { - return gmdate('Ymd\THi', $this->ts)."00Z"; - } - - function get_first_day_of_last_year() - { - $date_arr = array('day'=>1, - 'month'=>1, - 'year'=>($this->year - 1)); - - return new DateTimeUtil($date_arr,true); - - } - function get_first_day_of_next_year() - { - $date_arr = array('day'=>1, - 'month'=>1, - 'year'=>($this->year + 1)); - - return new DateTimeUtil($date_arr,true); - - } - - function get_first_day_of_next_week() - { - $first_day = $this->get_day_by_index_this_week(0); - $date_arr = array('day'=>($first_day->day + 7), - 'month'=>$first_day->month, - 'year'=>$first_day->year); - - return new DateTimeUtil($date_arr,true); - - } - function get_first_day_of_last_week() - { - $first_day = $this->get_day_by_index_this_week(0); - $date_arr = array('day'=>($first_day->day - 7), - 'month'=>$first_day->month, - 'year'=>$first_day->year); - - return new DateTimeUtil($date_arr,true); - } - function get_first_day_of_last_month() - { - if ($this->month == 1) - { - $month = 12; - $year = $this->year - 1; - } - else - { - $month = $this->month - 1; - $year = $this->year ; - } - $date_arr = array('day'=>1, - 'month'=>$month, - 'year'=>$year); - - return new DateTimeUtil($date_arr,true); - - } - function get_first_day_of_this_month() - { - $month = $this->month; - $year = $this->year ; - $date_arr = array('day'=>1, - 'month'=>$month, - 'year'=>$year); - - return new DateTimeUtil($date_arr,true); - - } - function get_first_day_of_next_month() - { - $date_arr = array('day'=>1, - 'month'=>($this->month + 1), - 'year'=>$this->year); - return new DateTimeUtil($date_arr,true); - } - - - function fill_in_details() - { - global $mod_strings, $timedate; - $hour = 0; - $min = 0; - $sec = 0; - $day = 1; - $month = 1; - $year = 1970; - - if ( isset($this->sec)) - { - $sec = $this->sec; - } - if ( isset($this->min)) - { - $min = $this->min; - } - if ( isset($this->hour)) - { - $hour = $this->hour; - } - if ( isset($this->day)) - { - $day= $this->day; - } - if ( isset($this->month)) - { - $month = $this->month; - } - if ( isset($this->year)) - { - $year = $this->year; - } - else - { - sugar_die ("fill_in_details: year was not set"); - } - $this->ts = mktime($hour,$min,$sec,$month,$day,$year)+$timedate->adjustmentForUserTimeZone()*60; - $this->load_ts($this->ts); - - } - - function load_ts($timestamp) - { - // global $mod_list_strings; - global $current_language; - $mod_list_strings = return_mod_list_strings_language($current_language,"Calendar"); - if ( empty($timestamp)) - { - - $timestamp = time(); - } - - $this->ts = $timestamp; - global $timedate; - - $tdiff = $timedate->adjustmentForUserTimeZone(); - $date_str = date('i:G:H:j:d:t:w:z:L:W:n:m:Y:Z',$timestamp-$tdiff*60); - list( - $this->min, - $this->hour, - $this->zhour, - $this->day, - $this->zday, - $this->days_in_month, - $this->day_of_week, - $this->day_of_year, - $is_leap, - $this->week, - $this->month, - $this->zmonth, - $this->year, - $this->tz_offset) - = explode(':',$date_str); - $this->tz_offset = date('Z') - $tdiff * 60; - - $this->day_of_week_short =$mod_list_strings['dom_cal_weekdays'][$this->day_of_week]; - $this->day_of_week_long=$mod_list_strings['dom_cal_weekdays_long'][$this->day_of_week]; - $this->month_short=$mod_list_strings['dom_cal_month'][$this->month]; - $this->month_long=$mod_list_strings['dom_cal_month_long'][$this->month]; - - $this->days_in_year = 365; - - if ($is_leap == 1) - { - $this->days_in_year += 1; - } - - - } - - function DateTimeUtil($time,$fill_in_details) - { - if (! isset( $time) || count($time) == 0 ) - { - $this->load_ts(null); - } - else if ( isset( $time['ts'])) - { - $this->load_ts($time['ts']); - } - else if ( isset( $time['date_str'])) - { - list($this->year,$this->month,$this->day)= - explode("-",$time['date_str']); - if ($fill_in_details == true) - { - $this->fill_in_details(); - } - } - else - { - if ( isset($time['sec'])) - { - $this->sec = $time['sec']; - } - if ( isset($time['min'])) - { - $this->min = $time['min']; - } - if ( isset($time['hour'])) - { - $this->hour = $time['hour']; - } - if ( isset($time['day'])) - { - $this->day = $time['day']; - } - if ( isset($time['week'])) - { - $this->week = $time['week']; - } - if ( isset($time['month'])) - { - $this->month = $time['month']; - } - if ( isset($time['year']) && $time['year'] >= 1970) - { - $this->year = $time['year']; - } - else - { - return null; - } - - if ($fill_in_details == true) - { - $this->fill_in_details(); - } - - } - } - - function dump_date_info() - { - echo "min:".$this->min."
\n"; - echo "hour:".$this->hour."
\n"; - echo "day:".$this->day."
\n"; - echo "month:".$this->month."
\n"; - echo "year:".$this->year."
\n"; - } - - function get_hour() - { - $hour = $this->hour; - if ($this->hour > 12) - { - $hour -= 12; - } - else if ($this->hour == 0) - { - $hour = 12; - } - return $hour; - } - - function get_24_hour() - { - return $this->hour; - } - - function get_am_pm() - { - if ($this->hour >=12) - { - return "PM"; - } - return "AM"; - } - - function get_day() - { - return $this->day; - } - - function get_month() - { - return $this->month; - } - - function get_day_of_week_short() - { - return $this->day_of_week_short; - } - function get_day_of_week() - { - return $this->day_of_week_long; - } - - - function get_month_name() - { - return $this->month_long; - } - - function get_datetime_by_index_today($hour_index) - { - $arr = array(); - - if ( $hour_index < 0 || $hour_index > 23 ) - { - sugar_die("hour is outside of range"); - } - - $arr['hour'] = $hour_index; - $arr['min'] = 0; - $arr['day'] = $this->day; - - $arr['month'] = $this->month; - $arr['year'] = $this->year; - - return new DateTimeUtil($arr,true); - } - - function get_hour_end_time() - { - $arr = array(); - $arr['hour'] = $this->hour; - $arr['min'] = 59; - $arr['sec'] = 59; - $arr['day'] = $this->day; - - $arr['month'] = $this->month; - $arr['year'] = $this->year; - - return new DateTimeUtil($arr,true); - } - - function get_day_end_time() - { - $arr = array(); - $arr['hour'] = 23; - $arr['min'] = 59; - $arr['sec'] = 59; - $arr['day'] = $this->day; - - $arr['month'] = $this->month; - $arr['year'] = $this->year; - - return new DateTimeUtil($arr,true); - } - - function get_day_by_index_this_week($day_index) - { - $arr = array(); - - if ( $day_index < 0 || $day_index > 6 ) - { - sugar_die("day is outside of week range"); - } - - $arr['day'] = $this->day + - ($day_index - $this->day_of_week); - - $arr['month'] = $this->month; - $arr['year'] = $this->year; - - return new DateTimeUtil($arr,true); - } - function get_day_by_index_this_year($month_index) - { - $arr = array(); - $arr['month'] = $month_index+1; - $arr['year'] = $this->year; - // wp: Find the last day of the month requested, ensure that is the ceiling of the day param - $arr['day'] = min(strftime("%d", mktime(0, 0, 0, $arr['month']+1, 0, $arr['year'])), $this->day); - - return new DateTimeUtil($arr,true); - } - - function get_day_by_index_this_month($day_index) - { - $arr = array(); - $arr['day'] = $day_index + 1; - $arr['month'] = $this->month; - $arr['year'] = $this->year; - - return new DateTimeUtil($arr,true); - } - - function getHashList($view, &$start_time, &$end_time) - { - $hash_list = array(); - - if (version_compare(phpversion(), '5.0') < 0) - $new_time = $start_time; - else - $new_time = clone($start_time); - - $arr = array(); - - if ( $view != 'day') - { - $end_time = $end_time->get_day_end_time(); - } - - - if (empty($new_time->ts)) - { - return; - } - - if ( $new_time->ts == $end_time->ts) - { - $end_time->ts+=1; - } - - while( $new_time->ts < $end_time->ts) - { - - $arr['month'] = $new_time->month; - $arr['year'] = $new_time->year; - $arr['day'] = $new_time->day; - $arr['hour'] = $new_time->hour; - if ( $view == 'day') - { - $hash_list[] = $new_time->get_mysql_date().":".$new_time->hour; - $arr['hour'] += 1; - } - else - { - $hash_list[] = $new_time->get_mysql_date(); - $arr['day'] += 1; - } - $new_time = new DateTimeUtil($arr,true); - } - return $hash_list; - } - -} - -?> diff --git a/modules/Calendar/Menu.php b/modules/Calendar/Menu.php index 169307c9..99bf6d91 100644 --- a/modules/Calendar/Menu.php +++ b/modules/Calendar/Menu.php @@ -1,5 +1,6 @@ diff --git a/modules/Calendar/TasksListView.html b/modules/Calendar/TasksListView.html deleted file mode 100644 index 13a802cd..00000000 --- a/modules/Calendar/TasksListView.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - -{PAGINATION} - - - - - - - - - - - - - - - -
{MOD.LBL_LIST_STATUS}{arrow_start}{status_arrow}{arrow_end}{MOD.LBL_LIST_SUBJECT}{arrow_start}{name_arrow}{arrow_end}{MOD.LBL_LIST_DUE_DATE}{arrow_start}{date_due_arrow}{arrow_end}
{TASK.STATUS}{TASK.NAME}{TASK.DATE_DUE}
- diff --git a/modules/Calendar/TasksListView.php b/modules/Calendar/TasksListView.php deleted file mode 100644 index b3c525df..00000000 --- a/modules/Calendar/TasksListView.php +++ /dev/null @@ -1,144 +0,0 @@ -setPreference('ListViewDisplayColumns', array(), 0, 'Calendar'); - -$savedDisplayColumns = $current_user->getPreference('ListViewDisplayColumns', 'Calendar'); // get user defined display columns - -$json = getJSONobj(); -$seedTask = new Task(); - -// setup listview smarty -$lv = new ListViewSmarty(); - -$displayColumns = array(); -// check $_REQUEST if new display columns from post -if(!empty($_REQUEST['displayColumns'])) { - foreach(explode('|', $_REQUEST['displayColumns']) as $num => $col) { - if(!empty($listViewDefs['Tasks'][$col])) - $displayColumns[$col] = $listViewDefs['Tasks'][$col]; - } -} -elseif(!empty($savedDisplayColumns)) { // use user defined display columns from preferences - $displayColumns = $savedDisplayColumns; -} -else { // use columns defined in listviewdefs for default display columns - foreach($listViewDefs['Calendar'] as $col => $params) { - if(!empty($params['default']) && $params['default']) - $displayColumns[$col] = $params; - } -} -$params = array('massupdate' => false); // setup ListViewSmarty params -if(!empty($_REQUEST['orderBy'])) { // order by coming from $_REQUEST - $params['orderBy'] = $_REQUEST['orderBy']; - $params['overrideOrder'] = true; - if(!empty($_REQUEST['sortOrder'])) $params['sortOrder'] = $_REQUEST['sortOrder']; -} -$params['orderBy'] = ''; -$lv->displayColumns = $displayColumns; - -// use the stored query if there is one -if (!isset($where)) $where = ""; -require_once('modules/MySettings/StoreQuery.php'); -$storeQuery = new StoreQuery(); -if(!isset($_REQUEST['query'])){ - $storeQuery->loadQuery('Calendar'); - $storeQuery->populateRequest(); -}else{ - $storeQuery->saveFromGet('Calendar'); -} -global $timedate; - -//jc: bug 14616 - dates need to specificy the end of the current date in order to get tasks -// that are scheduled to start today -$today = $timedate->getNow(true)->get_day_end_time()->asDb(); -//end bug 14616 - -$where = "(tasks.assigned_user_id='$current_user->id' and tasks.status<>'Completed' and tasks.status<>'Deferred'"; -$where .= "and (tasks.date_start is NULL or tasks.date_start <= '$today'))"; - -$lv->export = false; -$lv->delete = false; -$lv->select = false; -$lv->mailMerge = false; -$lv->multiSelect = false; -$lv->showMassupdateFields = false; -$lv->setup($seedTask, 'include/ListView/ListViewNoMassUpdate.tpl', $where, $params); -echo getClassicModuleTitle($current_module_strings['LBL_MODULE_NAME'], array($current_module_strings['LBL_LIST_FORM_TITLE']), false); - - -echo $lv->display(); -//Fake Mass Update -$form = "
"; -echo $form; -?> diff --git a/modules/Calendar/views/view.list.php b/modules/Calendar/action_view_map.php similarity index 86% rename from modules/Calendar/views/view.list.php rename to modules/Calendar/action_view_map.php index 703cfb81..cd43972a 100644 --- a/modules/Calendar/views/view.list.php +++ b/modules/Calendar/action_view_map.php @@ -1,4 +1,5 @@ +$action_view_map['saveactivity'] = 'saveactivity'; +$action_view_map['reschedule'] = 'reschedule'; +$action_view_map['remove'] = 'remove'; +$action_view_map['getgr'] = 'getgr'; +$action_view_map['getgrusers'] = 'getgrusers'; +$action_view_map['quickedit'] = 'quickedit'; +$action_view_map['savesettings'] = 'savesettings'; diff --git a/modules/Calendar/index.php b/modules/Calendar/index.php index a6729bd9..52d8cf8e 100644 --- a/modules/Calendar/index.php +++ b/modules/Calendar/index.php @@ -1,4 +1,5 @@ get('calendar.default_view','week'); } -if ( isset($_REQUEST['week'])) -{ - $date_arr['week'] = $_REQUEST['week']; -} +$cal = new Calendar($_REQUEST['view']); -if ( isset($_REQUEST['year'])) -{ - if ($_REQUEST['year'] > 2037 || $_REQUEST['year'] < 1970) - { - print("Sorry, calendar cannot handle the year you requested"); - print("
Year must be between 1970 and 2037"); - exit; +if(in_array($cal->view,array('day','week','month'))){ + $cal->add_activities($GLOBALS['current_user']); +}else if($cal->view == 'shared'){ + $cal->init_shared(); + global $shared_user; + $shared_user = new User(); + foreach($cal->shared_ids as $member){ + $shared_user->retrieve($member); + $cal->add_activities($shared_user); } - $date_arr['year'] = $_REQUEST['year']; } -// today adjusted for user's timezone -$args['calendar'] = new Calendar($_REQUEST['view'], $date_arr); -if ($_REQUEST['view'] == 'day' || $_REQUEST['view'] == 'week' || $_REQUEST['view'] == 'month') -{ - global $current_user; - $args['calendar']->add_activities($current_user); +if(in_array($cal->view, array("day","week","month","shared"))){ + $cal->load_activities(); } -$args['view'] = $_REQUEST['view']; -?> - - - - - - - - -
- - - -
+?> diff --git a/modules/Calendar/language/en_us.lang.php b/modules/Calendar/language/en_us.lang.php index 1940d213..e0ea6a07 100644 --- a/modules/Calendar/language/en_us.lang.php +++ b/modules/Calendar/language/en_us.lang.php @@ -35,108 +35,165 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * "Powered by SugarCRM". ********************************************************************************/ -/********************************************************************************* + +$mod_strings = array ( - * Description: Defines the English language pack for the base application. - * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. - * All Rights Reserved. - * Contributor(s): ______________________________________.. - ********************************************************************************/ + 'LBL_MODULE_NAME' => 'Calendar', + 'LBL_MODULE_TITLE' => 'Calendar', + 'LNK_NEW_CALL' => 'Log Call', + 'LNK_NEW_MEETING' => 'Schedule Meeting', + 'LNK_NEW_APPOINTMENT' => 'Create Appointment', + 'LNK_NEW_TASK' => 'Create Task', + 'LNK_CALL_LIST' => 'Calls', + 'LNK_MEETING_LIST' => 'Meetings', + 'LNK_TASK_LIST' => 'Tasks', + 'LNK_VIEW_CALENDAR' => 'Today', + 'LNK_IMPORT_CALLS' => 'Import Calls', + 'LNK_IMPORT_MEETINGS' => 'Import Meetings', + 'LNK_IMPORT_TASKS' => 'Import Tasks', + 'LBL_MONTH' => 'Month', + 'LBL_DAY' => 'Day', + 'LBL_YEAR' => 'Year', + 'LBL_WEEK' => 'Week', + 'LBL_PREVIOUS_MONTH' => 'Previous Month', + 'LBL_PREVIOUS_DAY' => 'Previous Day', + 'LBL_PREVIOUS_YEAR' => 'Previous Year', + 'LBL_PREVIOUS_WEEK' => 'Previous Week', + 'LBL_NEXT_MONTH' => 'Next Month', + 'LBL_NEXT_DAY' => 'Next Day', + 'LBL_NEXT_YEAR' => 'Next Year', + 'LBL_NEXT_WEEK' => 'Next Week', + 'LBL_AM' => 'AM', + 'LBL_PM' => 'PM', + 'LBL_SCHEDULED' => 'Scheduled', + 'LBL_BUSY' => 'Busy', + 'LBL_CONFLICT' => 'Conflict', + 'LBL_USER_CALENDARS' => 'User Calendars', + 'LBL_SHARED' => 'Shared', + 'LBL_PREVIOUS_SHARED' => 'Previous', + 'LBL_NEXT_SHARED' => 'Next', + 'LBL_SHARED_CAL_TITLE' => 'Shared Calendar', + 'LBL_USERS' => 'Users', + 'LBL_REFRESH' => 'Refresh', + 'LBL_EDIT_USERLIST' => 'User List', + 'LBL_SELECT_USERS' => 'Select users for calendar display', + 'LBL_FILTER_BY_TEAM' => 'Filter user list by team:', + 'LBL_ASSIGNED_TO_NAME' => 'Assigned to', + 'LBL_DATE' => 'Start Date & Time', + 'LBL_CREATE_MEETING' => 'Schedule Meeting', + 'LBL_CREATE_CALL' => 'Log Call', + 'LBL_HOURS_ABBREV' => 'h', + 'LBL_MINS_ABBREV' => 'm', + + 'LBL_YES' => 'Yes', + 'LBL_NO' => 'No', + 'LBL_SETTINGS' => 'Settings', + 'LBL_CREATE_NEW_RECORD' => 'Create Activity', + 'LBL_LOADING' => 'Loading ......', + 'LBL_SAVING' => 'Saving ......', + 'LBL_CONFIRM_REMOVE' => 'Are you sure you want to remove the record?', + 'LBL_EDIT_RECORD' => 'Edit Activity', + 'LBL_ERROR_SAVING' => 'Error while saving', + 'LBL_ERROR_LOADING' => 'Error while loading', + 'LBL_GOTO_DATE' => 'Goto Date', + 'NOTICE_DURATION_TIME' => 'Duration time must be greater than 0', + 'LBL_STYLE_BASIC' => 'Basic', + 'LBL_STYLE_ADVANCED' => 'Advanced', + + 'LBL_INFO_TITLE' => 'Additional Details', + 'LBL_INFO_DESC' => 'Description', + 'LBL_INFO_START_DT' => 'Start Date Time', + 'LBL_INFO_DUE_DT' => 'Due Date Time', + 'LBL_INFO_DURATION' => 'Duration', + 'LBL_INFO_NAME' => 'Subject', + 'LBL_INFO_RELATED_TO' => 'Related to', + + 'LBL_NO_USER' => 'No match for field: Assigned to', + 'LBL_SUBJECT' => 'Subject', + 'LBL_DURATION' => 'Duration', + 'LBL_STATUS' => 'Status', + 'LBL_DATE_TIME' => 'Date and Time', + + + 'LBL_SETTINGS_TITLE' => 'Settings', + 'LBL_SETTINGS_TIME_STARTS'=>'Start time:', + 'LBL_SETTINGS_TIME_ENDS'=>'End time:', + 'LBL_SETTINGS_CALENDAR_STYLE' => 'Calendar Style:', + 'LBL_SETTINGS_CALLS_SHOW' => 'Show Calls:', + 'LBL_SETTINGS_TASKS_SHOW' => 'Show Tasks:', + + 'LBL_SAVE_BUTTON' => 'Save', + 'LBL_DELETE_BUTTON' => 'Delete', + 'LBL_APPLY_BUTTON' => 'Apply', + 'LBL_SEND_INVITES' => 'Send Invites', + 'LBL_CANCEL_BUTTON' => 'Cancel', + 'LBL_CLOSE_BUTTON' => 'Close', + + 'LBL_GENERAL_TAB' => 'Details', + 'LBL_PARTICIPANTS_TAB' =>'Invitees', -$mod_strings = array ( - 'LBL_MODULE_NAME'=>'Calendar', - 'LBL_MODULE_TITLE'=>'Calendar', - 'LBL_MODULE_ACTION'=>'View', - 'LNK_NEW_CALL' => 'Log Call', - 'LNK_NEW_MEETING' => 'Schedule Meeting', - 'LNK_NEW_APPOINTMENT' => 'Create Appointment', - 'LNK_NEW_TASK' => 'Create Task', - 'LNK_CALL_LIST' => 'View Calls', - 'LNK_MEETING_LIST' => 'View Meetings', - 'LNK_TASK_LIST' => 'View Tasks', - 'LNK_VIEW_CALENDAR' => 'View Calendar', - 'LNK_IMPORT_CALLS'=>'Import Calls', - 'LNK_IMPORT_MEETINGS'=>'Import Meetings', - 'LNK_IMPORT_TASKS'=>'Import Tasks', - 'LBL_MONTH' => 'Month', - 'LBL_DAY' => 'Day', - 'LBL_YEAR' => 'Year', - 'LBL_WEEK' => 'Week', - 'LBL_PREVIOUS_MONTH' => 'Previous Month', - 'LBL_PREVIOUS_DAY' => 'Previous Day', - 'LBL_PREVIOUS_YEAR' => 'Previous Year', - 'LBL_PREVIOUS_WEEK' => 'Previous Week', - 'LBL_NEXT_MONTH' => 'Next Month', - 'LBL_NEXT_DAY' => 'Next Day', - 'LBL_NEXT_YEAR' => 'Next Year', - 'LBL_NEXT_WEEK' => 'Next Week', - 'LBL_AM' => 'AM', - 'LBL_PM' => 'PM', - 'LBL_SCHEDULED' => 'Scheduled', - 'LBL_BUSY' => 'Busy', - 'LBL_CONFLICT' => 'Conflict', - 'LBL_USER_CALENDARS' => 'User Calendars', - 'LBL_SHARED' => 'Shared', - 'LBL_PREVIOUS_SHARED' => 'Previous', - 'LBL_NEXT_SHARED' => 'Next', - 'LBL_SHARED_CAL_TITLE' => 'Shared Calendar', - 'LBL_USERS' => 'User', - 'LBL_REFRESH' => 'Refresh', - 'LBL_EDIT' => 'Edit', - 'LBL_SELECT_USERS' => 'Select users for calendar display', - 'LBL_FILTER_BY_TEAM' => 'Filter user list by team:', - 'LBL_ASSIGNED_TO_NAME' => 'Assigned to', - 'LBL_DATE' => 'Start Date & Time' ); $mod_list_strings = array( -'dom_cal_weekdays'=>array( -"Sun", -"Mon", -"Tue", -"Wed", -"Thu", -"Fri", -"Sat", -), -'dom_cal_weekdays_long'=>array( -"Sunday", -"Monday", -"Tuesday", -"Wednesday", -"Thursday", -"Friday", -"Saturday", -), -'dom_cal_month'=>array( -"", -"Jan", -"Feb", -"Mar", -"Apr", -"May", -"Jun", -"Jul", -"Aug", -"Sep", -"Oct", -"Nov", -"Dec", -), -'dom_cal_month_long'=>array( -"", -"January", -"February", -"March", -"April", -"May", -"June", -"July", -"August", -"September", -"October", -"November", -"December", -) + 'repeat_types' => + array( + '' => 'None', + 'Daily' => 'Daily', + 'Weekly' => 'Weekly', + 'Monthly' => 'Monthly', + 'Yearly' => 'Yearly', + ), + 'dom_cal_weekdays'=> + array( + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + ), + 'dom_cal_weekdays_long'=> + array( + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ), + 'dom_cal_month'=> + array( + "", + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ), + 'dom_cal_month_long'=> + array( + "", + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ), ); ?> diff --git a/modules/Calendar/templates/template_shared_calendar.php b/modules/Calendar/templates/template_shared_calendar.php deleted file mode 100644 index fef3d15a..00000000 --- a/modules/Calendar/templates/template_shared_calendar.php +++ /dev/null @@ -1,183 +0,0 @@ -$args['activity_focus']); -$calendar = new Calendar("day",$date_arr); -$calendar->show_tasks = false; -$calendar->toggle_appt = false; -foreach($args['users'] as $user) -{ -/* - if ($user->id != $current_user->id) - { -*/ - $calendar->add_activities($user,'vfb'); -/* - } -*/ -} -?> -

- - -

-
-

date_time);?>

-
- - - -get_start_slice_idx(); - $end_slice_idx = $calendar->get_end_slice_idx(); - $cur_slice_idx = 1; - $slice_args = array(); - for($cur_slice_idx=$start_slice_idx;$cur_slice_idx<=$end_slice_idx;$cur_slice_idx++) - { - $slice_args['slice'] = $calendar->slice_hash[$calendar->slices_arr[$cur_slice_idx]]; - $slice_args['calendar'] = $calendar; - //print_r($cur_time); - ?> - - - - - - -slice_hash[$calendar->slices_arr[$cur_slice_idx]]; - - // if this current activitiy occurs within this time slice - if ( Calendar::occurs_within_slice($cur_slice,$calendar->activity_focus)) - { -/* - $got_conflict = 0; - if ( isset($cur_slice->acts_arr[$curr_user->id]) ) - { - foreach( $cur_slice->acts_arr[$curr_user->id] as $act) - { - if ($act->sugar_bean->id != $calendar->activity_focus->sugar_bean->id) - { - $got_conflict = 1; - } - } - } -*/ - - if (isset($cur_slice->acts_arr[$curr_user->id]) && count($cur_slice->acts_arr[$curr_user->id]) > 1) - { -?> - - - - -acts_arr[$curr_user->id])) - { - ?> - - - - - - - - -
-full_name; ?>    
- - - - - - - - - - - -
<?php echo $mod_strings['LBL_SCHEDULED']; ?>   <?php echo $mod_strings['LBL_BUSY']; ?>   <?php echo $mod_strings['LBL_CONFLICT']; ?>  
-

- diff --git a/modules/Calendar/templates/templates_calendar.php b/modules/Calendar/templates/templates_calendar.php deleted file mode 100644 index 452ce165..00000000 --- a/modules/Calendar/templates/templates_calendar.php +++ /dev/null @@ -1,876 +0,0 @@ - - '; - } - -?> - - - - -
- -selected="selected" value=" get_view_name($tab)]; ?> " id="_tab_id" title="get_view_name($tab)]; ?>" onclick="window.location.href='index.php?module=Calendar&action=index&view=date_time->get_date_str(); ?>'">  - -
- - -start_time->month; - $cal_arr['year'] = $args['slice']->start_time->year; - $newargs['calendar'] = new Calendar('month', $cal_arr); - $newargs['calendar']->show_only_current_slice = true; - $newargs['calendar']->show_activities = false; - $newargs['calendar']->show_week_on_month_view = false; - template_calendar_month($newargs); -?> -acts_arr[$current_user->id])) { - return; - } - foreach($args['slice']->acts_arr[$current_user->id] as $act) { - $fields = array(); - foreach($act->sugar_bean->field_name_map as $field) { - if(!empty($act->sugar_bean->$field['name'])) - $fields[strtoupper($field['name'])] = $act->sugar_bean->$field['name']; - } - - $extra = "id=\"adspan_{$act->sugar_bean->id}\" " - . "onmouseover=\"return SUGAR.util.getAdditionalDetails( '{$act->sugar_bean->module_dir}','{$act->sugar_bean->id}', 'adspan_{$act->sugar_bean->id}');\" " - . "onmouseout=\"return SUGAR.util.clearAdditionalDetailsCall()\" onmouseout=\"return nd(1000);\" "; - - - $count ++; - echo '
'; - if($act->sugar_bean->object_name == 'Call') { - if ( isset($app_list_strings['call_status_dom'][$act->sugar_bean->status]) ) { - $callStatus = $app_list_strings['call_status_dom'][$act->sugar_bean->status]; - } - else { - $callStatus = ''; - } - echo ' - '; - } else if($act->sugar_bean->object_name == 'Meeting') { - if ( isset($app_list_strings['meeting_status_dom'][$act->sugar_bean->status]) ) { - $meetingStatus = $app_list_strings['meeting_status_dom'][$act->sugar_bean->status]; - } - else { - $meetingStatus = ''; - } - $out = ' - "; - echo $out; - - } else if($act->sugar_bean->object_name == 'Task') { - if ( isset($app_list_strings['task_status_dom'][$act->sugar_bean->status]) ) - { - $taskStatus = $app_list_strings['task_status_dom'][$act->sugar_bean->status]; - } - else - { - $taskStatus = ''; - } - - echo ' - '; - } - echo '
' . SugarThemeRegistry::current()->getImage('Calls','alt="'.$callStatus.': '.$act->sugar_bean->name.'"') . '' . $callStatus . ': ' . $act->sugar_bean->name . '' . SugarThemeRegistry::current()->getImage('Meetings','alt="'.$meetingStatus.': '.$act->sugar_bean->name.'"') . '' . $meetingStatus . ': ' . $act->sugar_bean->name .''; - - /////////////////////////////////////////////////////////////// - //// MEETING INTEGRATION - if(method_exists($act->sugar_bean, 'hasIntegratedMeeting')) { - if($act->sugar_bean->hasIntegratedMeeting()) { - $out .= $act->sugar_bean->miIcon; - } - } - //// END MEETING INTEGRATION - /////////////////////////////////////////////////////////////// - $out .= "' . SugarThemeRegistry::current()->getImage('Tasks','alt="'.$taskStatus.': '.$act->sugar_bean->name.'"') . ''.$taskStatus.': ' . $act->sugar_bean->name . '
'; - } - } - - function template_echo_slice_activities_shared($args) { - global $app_list_strings; - - global $shared_user, $timedate; - $count = 0; - if(empty($args['slice']->acts_arr[$shared_user->id])) { - return; - } - - $out = ''; - - foreach($args['slice']->acts_arr[$shared_user->id] as $act) { - $count ++; - echo "
- "; - - if($act->sugar_bean->object_name == 'Call') { - echo ""; - - if(empty($act->sugar_bean->name)) { - echo ""; - } else { - echo ""; - } - } else if($act->sugar_bean->object_name == 'Meeting') { - echo ""; - - if(empty($act->sugar_bean->name)) { - echo ""; - } else { - echo ""; - echo $out; - } - } else if($act->sugar_bean->object_name == 'Task') { - echo ""; - - if(empty($act->sugar_bean->name)) { - echo ""; - } else { - echo ""; - } - } - echo "
" . SugarThemeRegistry::current()->getImage('Calls','alt=\"'.$app_list_strings['call_status_dom'][$act->sugar_bean->status].': '.$act->sugar_bean->name.'\"') . ""; - echo $timedate->getTimePart($act->sugar_bean->date_start); - echo "
- sugar_bean->id."\">". - $app_list_strings['call_status_dom'][$act->sugar_bean->status].": ". - $act->sugar_bean->name."
(". - $timedate->getTimePart($act->sugar_bean->date_start).")
". - SugarThemeRegistry::current()->getImage('Meetings','alt=\"'.$app_list_strings['meeting_status_dom'][$act->sugar_bean->status].': '.$act->sugar_bean->name.'\"'); - echo "". - $timedate->getTimePart($act->sugar_bean->date_start); - echo "
- sugar_bean->id."\">". - $app_list_strings['meeting_status_dom'][$act->sugar_bean->status].":". - $act->sugar_bean->name."
(". - $timedate->getTimePart($act->sugar_bean->date_start).")
"; - - // MEETING INTEGRATION - if($act->sugar_bean->hasIntegratedMeeting()) { - $out .= $act->sugar_bean->miIcon; - } - // END MEETING INTEGRATION - - $out .= "
". - SugarThemeRegistry::current()->getImage('Tasks','alt="'.$app_list_strings['task_status_dom'][$act->sugar_bean->status].': '.$act->sugar_bean->name.'"'); - echo "". - $timedate->getTimePart($act->sugar_bean->date_due); - echo "
- sugar_bean->id."\">". - $app_list_strings['task_status_dom'][$act->sugar_bean->status].': '.$act->sugar_bean->name."
(". - $timedate->getTimePart($act->sugar_bean->date_due).")
"; - } - } - - ///////////////////////////////// - // template - ///////////////////////////////// - function template_cal_day_slice($args) { - /* - echo "cale:".$args['calendar']->view; - echo "cal1:".$args['calendar']->date_time->month; - echo "cal3:".$args['slice']->date_time->month; - */ - if($args['calendar']->show_only_current_slice == false || $args['calendar']->date_time->month == $args['slice']->start_time->month) { - template_echo_slice_date($args); - - if($args['calendar']->show_activities == true) { - template_echo_slice_activities($args); - } - - } - } - - ///////////////////////////////// - // template - ///////////////////////////////// - function template_calendar($args) { - global $timedate; - if(isset($args['size']) && $args['size'] == 'small') { - $args['calendar']->show_activities = false; - $args['calendar']->show_week_on_month_view = false; - } - - $newargs = array(); - $newargs['view'] = $args['view']; - $newargs['calendar'] = $args['calendar']; - if(!isset($args['size']) || $args['size'] != 'small') { - template_cal_tabs($newargs); - } - - if(isset($_REQUEST['view']) && $_REQUEST['view'] == 'shared') { - global $ids; - global $current_user; - global $mod_strings; - global $app_list_strings, $current_language, $currentModule, $action, $app_strings; - $current_module_strings = return_module_language($current_language, 'Calendar'); - - $ids = array(); - $user_ids = $current_user->getPreference('shared_ids'); - //get list of user ids for which to display data - if(!empty($user_ids) && count($user_ids) != 0 && !isset($_REQUEST['shared_ids'])) { - $ids = $user_ids; - } - elseif(isset($_REQUEST['shared_ids']) && count($_REQUEST['shared_ids']) > 0) { - $ids = $_REQUEST['shared_ids']; - $current_user->setPreference('shared_ids', $_REQUEST['shared_ids']); - } else { - //$ids = get_user_array(false); - //$ids = array_keys($ids); - $ids = array($current_user->id); - - } - - - //get team id for which to display user list - - $tools = ''; - - echo get_form_header($mod_strings['LBL_SHARED_CAL_TITLE'], $tools, false); - if(empty($_SESSION['shared_ids'])) - $_SESSION['shared_ids'] = ""; - - echo " - - -

"; - - if(isset($_REQUEST['edit']) && $_REQUEST['edit']) - echo " "; - - echo " - - - - - - - - - - -
- - - - - - -
"; - - if(!isset($args['size']) || $args['size'] != 'small') { - template_get_previous_calendar($args); - } - - echo " - "; - - if(isset( $args['size']) && $args['size'] = 'small') - { - ?> - - -

-date_time); ?> -

-"; - } -?> - -
-
-view == 'month') { - template_calendar_month($args); - } else - if($args['calendar']->view == 'year') { - template_calendar_year($args); - } else - if($args['calendar']->view == 'shared') { - - global $current_user, $shared_user; - $shared_args = array(); - foreach($args as $key => $val) { - $shared_args[$key] = $val; - } - $shared_args['calendar'] = $args['calendar']; - $shared_user = new User(); - foreach($ids as $member) { - $shared_user->retrieve($member); - $shared_args['calendar']->show_tasks = true; - $shared_args['calendar']->add_activities($shared_user); - $shared_args['show_link'] = 'off'; - if(($shared_user->id == $current_user->id)) - $shared_args['show_link'] = 'on'; - echo '
'.$shared_user->full_name.'
'; - template_calendar_horizontal($shared_args); - } - } else { - template_calendar_vertical($args); - } -?> -
- - - - - -
- -
- - - get_start_slice_idx(); - $end_slice_idx = $args['calendar']->get_end_slice_idx(); - $cur_slice_idx = 1; - for($cur_slice_idx = $start_slice_idx; $cur_slice_idx <= $end_slice_idx; $cur_slice_idx ++) { - $calendar = $args['calendar']; - $args['slice'] = $calendar->slice_hash[$calendar->slices_arr[$cur_slice_idx]]; -?> - - - - -
-"; - - // need to change these values after we find out what activities - // occur outside of these values - $start_slice_idx = $args['calendar']->get_start_slice_idx(); - $end_slice_idx = $args['calendar']->get_end_slice_idx(); - $cur_slice_idx = 1; - for($cur_slice_idx = $start_slice_idx; $cur_slice_idx <= $end_slice_idx; $cur_slice_idx ++) { - $calendar = $args['calendar']; - $args['slice'] = $calendar->slice_hash[$calendar->slices_arr[$cur_slice_idx]]; - - template_cal_horizontal_slice($args); - } - - echo ""; -} - -function template_cal_vertical_slice($args) { - global $timedate; -?> - - - - - - - - - - -"; - - if($args['show_link'] == 'on') { - template_echo_slice_date($args); - } else { - template_echo_slice_date_nolink($args); - } - - template_echo_slice_activities_shared($args); - - echo ""; -} - -function template_calendar_year($args) { - $count = 0; -?> - - - - -
- - - -slice_hash[$args['calendar']->slices_arr[$count]]; -?> - - - - - - -
-
- - - - - get_start_slice_idx(); - $end_slice_idx = $args['calendar']->get_end_slice_idx(); - $cur_slice_idx = 1; - */ - $count = 0; - if($args['calendar']->slice_hash[$args['calendar']->slices_arr[35]]->start_time->month != $args['calendar']->date_time->month) { - $rows = 5; - } else { - $rows = 6; - } -?> - -slice_hash[$args['calendar']->slices_arr[$i]]; -?> - - - - - -slice_hash[$args['calendar']->slices_arr[$count]]; -?> - - - - - - -
start_time->get_day_of_week_short(); ?>
class="weekEnd">
-start_time->get_mysql_date() == $timedate->nowDbDate()) { - return true; - } - return false; -} - -function template_echo_daily_view_hour($args) { - - $slice = $args['slice']; - $hour = $slice->start_time->get_hour(); - return $hour; - -} - -function template_echo_daily_view_24_hour($args) { - - $slice = $args['slice']; - $hour = $slice->start_time->get_24_hour(); - return $hour; - -} - -function template_echo_slice_date($args) { - global $mod_strings; - global $timedate; - $slice = $args['slice']; - - if($slice->view != 'hour') { - if($slice->start_time->get_day_of_week_short() == 'Sun' || $slice->start_time->get_day_of_week_short() == 'Sat') { - echo "get_view().$slice->start_time->get_date_str()."\" "; - } else { - echo "get_view().$slice->start_time->get_date_str()."\" "; - } - } - - if($slice->view == 'day' &&($args['calendar']->view == 'week')) { - echo ">"; - echo $slice->start_time->get_day_of_week_short(); - echo " "; - echo $slice->start_time->get_day(); - } - elseif($args['calendar']->view == 'shared') { - echo ">"; - echo $slice->start_time->get_day_of_week_short(); - echo " "; - echo $slice->start_time->get_day(); - } else - if($slice->view == 'day') { - echo ">"; - if($slice->start_time->get_month() == $args['calendar']->date_time->get_month()) { - echo $slice->start_time->get_day(); - } - //echo $slice->start_time->get_day(); - } else - if($slice->view == 'month') { - echo ">"; - echo $slice->start_time->get_month_name(); - } else - if($slice->view == 'hour') { - if($args['calendar']->toggle_appt == true) { - echo ''; - } - //Bug 13324, We are now using the users time format instead of a custom AM/PM setting - echo $timedate->to_display_time($slice->start_time->get_24_hour() . ":00:00", true, false); - } else { - sugar_die("template_echo_slice_date: view not supported"); - } - - echo ""; -} - -function template_echo_slice_date_nolink($args) { - global $mod_strings; - $slice = $args['slice']; - echo $slice->start_time->get_day_of_week_short(); - echo " "; - echo $slice->start_time->get_day(); -} - -function template_echo_date_info($view, $date_time) { - global $current_user; - $dateFormat = $current_user->getUserDateTimePreferences(); - - if($view == 'month') { - for($i=0; $iyear; - break; - case "m": - echo " ".$date_time->get_month_name(); - break; - } - } - } else - if($view == 'week' || $view == 'shared') { - $first_day = $date_time->get_day_by_index_this_week(0); - $last_day = $date_time->get_day_by_index_this_week(6); - - for($i=0; $iyear; - break; - case "m": - echo " ".$first_day->get_month_name(); - break; - case "d": - echo " ".$first_day->get_day(); - break; - } - } - echo " - "; - for($i=0; $iyear; - break; - case "m": - echo " ".$last_day->get_month_name(); - break; - case "d": - echo " ".$last_day->get_day(); - break; - } - } - } else - if($view == 'day') { - echo $date_time->get_day_of_week()." "; - - for($i=0; $iyear; - break; - case "m": - echo " ".$date_time->get_month_name(); - break; - case "d": - echo " ".$date_time->get_day(); - break; - } - } - } else - if($view == 'year') { - echo $date_time->year; - } else { - sugar_die("echo_date_info: date not supported"); - } -} - -function template_get_next_calendar($args) { - - global $mod_strings; -?> -get_view_name($args['calendar']->view)]; ?> getImage('calendar_next','alt="'. $mod_strings["LBL_NEXT_".$args['calendar']->get_view_name($args['calendar']->view)].'" align="absmiddle" border="0"'); ?> - -getImage('calendar_previous','alt="'. $mod_strings["LBL_PREVIOUS_".$args['calendar']->get_view_name($args['calendar']->view)].'" align="absmiddle" border="0"'); ?>  get_view_name($args['calendar']->view)]; ?> - \ No newline at end of file diff --git a/modules/Calendar/tpls/empty.tpl b/modules/Calendar/tpls/empty.tpl new file mode 100644 index 00000000..57a1302e --- /dev/null +++ b/modules/Calendar/tpls/empty.tpl @@ -0,0 +1,37 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} diff --git a/modules/Calendar/tpls/footer.tpl b/modules/Calendar/tpls/footer.tpl new file mode 100644 index 00000000..77764165 --- /dev/null +++ b/modules/Calendar/tpls/footer.tpl @@ -0,0 +1,41 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} +
+
{$previous}
{$next}
+
+
diff --git a/tests/modules/UpgradeWizard/SugarMerge/Bug37921Test.php b/modules/Calendar/tpls/form.tpl old mode 100755 new mode 100644 similarity index 54% rename from tests/modules/UpgradeWizard/SugarMerge/Bug37921Test.php rename to modules/Calendar/tpls/form.tpl index bcdfde87..7c5c9e8d --- a/tests/modules/UpgradeWizard/SugarMerge/Bug37921Test.php +++ b/modules/Calendar/tpls/form.tpl @@ -1,4 +1,4 @@ - + + + + + + + -class Bug37921Test extends Sugar_PHPUnit_Framework_TestCase { +
+ {literal} + + {/literal} + + {literal} + + {/literal} + +
-var $merge; - -function setUp() { - SugarTestMergeUtilities::setupFiles(array('Notes'), array('searchdefs'), 'tests/modules/UpgradeWizard/SugarMerge/od_metadata_files'); -} - - -function tearDown() { - SugarTestMergeUtilities::teardownFiles(); -} - - -function test_elster_notes_searchdefs_merge() { - require_once 'modules/UpgradeWizard/SugarMerge/SearchMerge.php'; - $this->merge = new SearchMerge(); - $this->merge->merge('Notes', 'tests/modules/UpgradeWizard/SugarMerge/metadata_files/551/modules/Notes/metadata/searchdefs.php', 'modules/Notes/metadata/searchdefs.php', 'custom/modules/Notes/metadata/searchdefs.php'); - $this->assertTrue(file_exists('custom/modules/Notes/metadata/searchdefs.php.suback.php')); - require('custom/modules/Notes/metadata/searchdefs.php'); - $fields = array(); - - - foreach($searchdefs['Notes']['layout']['basic_search'] as $col_key=>$col) { - $id = is_array($col) && isset($col['name']) ? $col['name'] : $col; - if(!empty($id) && !is_array($id)) { - $fields[$id] = $col; - } - } - - $this->assertTrue(count($fields) == 2, "Assert that there are 2 fields in the basic_search layout for Notes metadata"); - - $fields = array(); - foreach($searchdefs['Notes']['layout']['advanced_search'] as $col_key=>$col) { - $id = is_array($col) && isset($col['name']) ? $col['name'] : $col; - if(!empty($id)) { - $fields[$id] = $col; - } - } - $this->assertTrue(count($fields) == 7, "Assert that there are 7 fields in the advanced_search layout for Notes metadata"); -} +
+ + + +
+ + + diff --git a/modules/Calendar/tpls/header.tpl b/modules/Calendar/tpls/header.tpl new file mode 100644 index 00000000..6134f20d --- /dev/null +++ b/modules/Calendar/tpls/header.tpl @@ -0,0 +1,91 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} + +{if $controls} + +
+ +
+{foreach name=tabs from=$tabs key=k item=tab} + +{/foreach} +
+ +
+ {if $view != 'year'} + + Enter Date + + + + {/if} + +
+ +
+ +{/if} + + +
+
{$previous}
+

{$date_info}

+
{$next}
+
+
diff --git a/modules/Calendar/tpls/main.tpl b/modules/Calendar/tpls/main.tpl new file mode 100644 index 00000000..744538d1 --- /dev/null +++ b/modules/Calendar/tpls/main.tpl @@ -0,0 +1,321 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} + + + + + + +{if $settings} +{include file=$settings} +{/if} + + + + + + + + + + +{if $view == 'day'} + +{/if} + diff --git a/modules/Calendar/tpls/settings.tpl b/modules/Calendar/tpls/settings.tpl new file mode 100644 index 00000000..203e1a4d --- /dev/null +++ b/modules/Calendar/tpls/settings.tpl @@ -0,0 +1,115 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} + diff --git a/modules/Calendar/tpls/shared_users.tpl b/modules/Calendar/tpls/shared_users.tpl new file mode 100644 index 00000000..abeaee22 --- /dev/null +++ b/modules/Calendar/tpls/shared_users.tpl @@ -0,0 +1,128 @@ +{* +/********************************************************************************* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo. If the display of the logo is not reasonably feasible for + * technical reasons, the Appropriate Legal Notices must display the words + * "Powered by SugarCRM". + ********************************************************************************/ + +*} + +
+
+
+ + + +
+
+ + + + + + + + + +
{$MOD.LBL_SELECT_USERS}
+ + + + + + + + + +
{$MOD.LBL_USERS}: + + + {$UP}
+ {$DOWN} +
+ + +
+
+
+
diff --git a/modules/Calendar/views/view.getgr.php b/modules/Calendar/views/view.getgr.php new file mode 100644 index 00000000..4ebcd077 --- /dev/null +++ b/modules/Calendar/views/view.getgr.php @@ -0,0 +1,62 @@ +display(); + } + + function display(){ + error_reporting(0); + require_once('include/json_config.php'); + global $json; + $json = getJSONobj(); + $json_config = new json_config(); + $GRjavascript = $json_config->getFocusData($_REQUEST['type'], $_REQUEST['record']); + ob_clean(); + echo $GRjavascript; + } + +} + +?> diff --git a/modules/Calendar/views/view.getgrusers.php b/modules/Calendar/views/view.getgrusers.php new file mode 100644 index 00000000..5366fc49 --- /dev/null +++ b/modules/Calendar/views/view.getgrusers.php @@ -0,0 +1,76 @@ +display(); + } + + function display(){ + $users_arr = array(); + require_once("modules/Users/User.php"); + + $user_ids = explode(",", trim($_REQUEST['users'],',')); + $user_ids = array_unique($user_ids); + + require_once('include/json_config.php'); + global $json; + $json = getJSONobj(); + $json_config = new json_config(); + + foreach($user_ids as $u_id){ + if(empty($u_id)) + continue; + $bean = new User(); + $bean->retrieve($u_id); + array_push($users_arr, $json_config->populateBean($bean)); + } + + $GRjavascript = "\n" . $json_config->global_registry_var_name."['focus'].users_arr = " . $json->encode($users_arr) . ";\n"; + ob_clean(); + echo $GRjavascript; + } + +} + +?> diff --git a/modules/Calendar/views/view.quickedit.php b/modules/Calendar/views/view.quickedit.php new file mode 100644 index 00000000..3ae4a50e --- /dev/null +++ b/modules/Calendar/views/view.quickedit.php @@ -0,0 +1,125 @@ +bean = new $beanList[$module](); + if(!empty($_REQUEST['record'])) + $this->bean->retrieve($_REQUEST['record']); + + if(!$this->bean->ACLAccess('DetailView')) { + $json_arr = array( + 'success' => 'no', + ); + echo json_encode($json_arr); + die; + } + + if($this->bean->ACLAccess('Save')){ + $this->editable = 1; + }else{ + $this->editable = 0; + } + + } + + public function display(){ + require_once("modules/Calendar/CalendarUtils.php"); + + $module = $_REQUEST['current_module']; + + $_REQUEST['module'] = $module; + + $base = 'modules/' . $module . '/metadata/'; + $source = 'custom/'.$base.'quickcreatedefs.php'; + if (!file_exists($source)){ + $source = $base . 'quickcreatedefs.php'; + if (!file_exists($source)){ + $source = 'custom/' . $base . 'editviewdefs.php'; + if (!file_exists($source)){ + $source = $base . 'editviewdefs.php'; + } + } + } + + $tpl = "custom/include/EditView/EditView.tpl"; + if(!file_exists($tpl)) + $tpl = "include/EditView/EditView.tpl"; + $this->ev = new EditView(); + $this->ev->view = "QuickCreate"; + $this->ev->ss = new Sugar_Smarty(); + $this->ev->formName = "CalendarEditView"; + $this->ev->setup($module,$this->bean,$source,$tpl); + $this->ev->defs['templateMeta']['form']['headerTpl'] = "modules/Calendar/tpls/empty.tpl"; + $this->ev->defs['templateMeta']['form']['footerTpl'] = "modules/Calendar/tpls/empty.tpl"; + $this->ev->process(false, "CalendarEditView"); + + if(!empty($this->bean->id)){ + require_once('include/json_config.php'); + global $json; + $json = getJSONobj(); + $json_config = new json_config(); + $GRjavascript = $json_config->getFocusData($module, $this->bean->id); + }else{ + $GRjavascript = ""; + } + + $json_arr = array( + 'success' => 'yes', + 'module_name' => $this->bean->module_dir, + 'record' => $this->bean->id, + 'edit' => $this->editable, + 'html'=> $this->ev->display(false, true), + 'gr' => $GRjavascript, + ); + + ob_clean(); + echo json_encode($json_arr); + } +} + +?> diff --git a/modules/Calendar/views/view.remove.php b/modules/Calendar/views/view.remove.php new file mode 100644 index 00000000..831aa5bc --- /dev/null +++ b/modules/Calendar/views/view.remove.php @@ -0,0 +1,77 @@ +display(); + } + + function display(){ + require_once("modules/Calls/Call.php"); + require_once("modules/Meetings/Meeting.php"); + require_once("modules/Calendar/CalendarUtils.php"); + + global $beanFiles,$beanList; + $module = $_REQUEST['current_module']; + require_once($beanFiles[$beanList[$module]]); + $bean = new $beanList[$module](); + + $bean->retrieve($_REQUEST['record']); + + if(!$bean->ACLAccess('delete')){ + die; + } + + $bean->mark_deleted($_REQUEST['record']); + + $json_arr = array( + 'success' => 'yes', + ); + + ob_clean(); + echo json_encode($json_arr); + } + +} + +?> diff --git a/modules/Calendar/views/view.reschedule.php b/modules/Calendar/views/view.reschedule.php new file mode 100644 index 00000000..d4d12279 --- /dev/null +++ b/modules/Calendar/views/view.reschedule.php @@ -0,0 +1,84 @@ +display(); + } + + function display(){ + require_once("modules/Calls/Call.php"); + require_once("modules/Meetings/Meeting.php"); + + global $beanFiles,$beanList; + $module = $_REQUEST['current_module']; + require_once($beanFiles[$beanList[$module]]); + $bean = new $beanList[$module](); + + $bean->retrieve($_REQUEST['record']); + + if(!$bean->ACLAccess('Save')){ + die; + } + + $field = "date_start"; + if($module == "Tasks") + $field = "date_due"; + + $_POST[$field] = $_REQUEST['datetime']; + + require_once('include/formbase.php'); + $bean = populateFromPost("",$bean); + + $bean->save(); + + $json_arr = array( + 'success' => 'yes', + ); + ob_clean(); + echo json_encode($json_arr); + } + +} + +?> diff --git a/modules/Calendar/views/view.saveactivity.php b/modules/Calendar/views/view.saveactivity.php new file mode 100644 index 00000000..5ad0d644 --- /dev/null +++ b/modules/Calendar/views/view.saveactivity.php @@ -0,0 +1,558 @@ +display(); + } + + function display(){ + require_once("modules/Calendar/CalendarUtils.php"); + + $field_list = CalendarUtils::get_fields(); + + global $beanFiles,$beanList; + $module = $_REQUEST['current_module']; + require_once($beanFiles[$beanList[$module]]); + $bean = new $beanList[$module](); + $type = strtolower($beanList[$module]); + $table_name = $bean->table_name; + + + if(!empty($_REQUEST['record'])) + $bean->retrieve($_REQUEST['record']); + + if(!$bean->ACLAccess('Save')) { + $json_arr = array( + 'success' => 'no', + ); + echo json_encode($json_arr); + die; + } + + require_once('include/formbase.php'); + + $bean = populateFromPost("",$bean); + + + if(!$_REQUEST['reminder_checked']) + $bean->reminder_time = -1; + + + if(empty($_REQUEST['record']) && strpos($_POST['user_invitees'],$bean->assigned_user_id) === false) + $_POST['user_invitees'] .= ",".$bean->assigned_user_id; + // fill invites and save the entry + $this->save_activity($bean); + + + if($r_id = $bean->id){ + + $u = new User(); + $u->retrieve($bean->assigned_user_id); + + $arr_rec = array(); + + $bean->retrieve($r_id); + + if(isset($bean->parent_name)) + $bean->parent_name = $_REQUEST['parent_name']; + + $bean->fill_in_additional_parent_fields(); + + + global $timedate; + + $date_field = "date_start"; + if($_REQUEST['current_module'] == "Tasks") + $date_field = "date_due"; + + $timestamp = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$bean->$date_field,new DateTimeZone('UTC'))->format('U'); + + if($_REQUEST['current_module'] == 'Calls') + $users = $bean->get_call_users(); + if($_REQUEST['current_module'] == 'Meetings') + $users = $bean->get_meeting_users(); + $user_ids = array(); + foreach($users as $u) + $user_ids[] = $u->id; + + + $field_arr = array(); + foreach($field_list[$_REQUEST['current_module']] as $field){ + $field_arr[$field] = $bean->$field; + if($bean->field_defs[$field]['type'] == 'text'){ + $t = $field_arr[$field]; + if(strlen($t) > 300){ + $t = substr($t, 0, 300); + $t .= "..."; + } + $t = str_replace("\r\n","
",$t); + $t = str_replace("\r","
",$t); + $t = str_replace("\n","
",$t); + $t = html_entity_decode($t,ENT_QUOTES); + $field_arr[$field] = $t; + } + } + + $json_arr = array( + 'success' => 'yes', + 'type' => $type, + 'module_name' => $bean->module_dir, + 'user_id' => $GLOBALS['current_user']->id, + + 'detail' => 1, + 'edit' => 1, + 'record_name' => html_entity_decode($bean->name,ENT_QUOTES), + 'record' => $bean->id, + + 'users' => $user_ids, + + ); + + $json_arr = array_merge($json_arr,$field_arr); + $json_arr = array_merge($json_arr,CalendarUtils::get_time_data($bean)); + + }else{ + $json_arr = array( + 'success' => 'no', + ); + } + + ob_clean(); + echo json_encode($json_arr); + + } + + + private function save_activity(&$bean,$notify = true){ + + + if($_REQUEST['current_module'] == 'Meetings'){ + + + if(!empty($_POST['user_invitees'])) { + $userInvitees = explode(',', trim($_POST['user_invitees'], ',')); + } else { + $userInvitees = array(); + } + + // Calculate which users to flag as deleted and which to add + $deleteUsers = array(); + $bean->load_relationship('users'); + // Get all users for the meeting + $q = 'SELECT mu.user_id, mu.accept_status FROM meetings_users mu WHERE mu.meeting_id = \''.$bean->id.'\''; + $r = $bean->db->query($q); + $acceptStatusUsers = array(); + while($a = $bean->db->fetchByAssoc($r)) { + if(!in_array($a['user_id'], $userInvitees)) { + $deleteUsers[$a['user_id']] = $a['user_id']; + } else { + $acceptStatusUsers[$a['user_id']] = $a['accept_status']; + } + } + + if(count($deleteUsers) > 0) { + $sql = ''; + foreach($deleteUsers as $u) { + $sql .= ",'" . $u . "'"; + } + $sql = substr($sql, 1); + // We could run a delete SQL statement here, but will just mark as deleted instead + $sql = "UPDATE meetings_users set deleted = 1 where user_id in ($sql) AND meeting_id = '". $bean->id . "'"; + $bean->db->query($sql); + } + + // Get all contacts for the meeting + if(!empty($_POST['contact_invitees'])) { + $contactInvitees = explode(',', trim($_POST['contact_invitees'], ',')); + } else { + $contactInvitees = array(); + } + + $deleteContacts = array(); + $bean->load_relationship('contacts'); + $q = 'SELECT mu.contact_id, mu.accept_status FROM meetings_contacts mu WHERE mu.meeting_id = \''.$bean->id.'\''; + $r = $bean->db->query($q); + $acceptStatusContacts = array(); + while($a = $bean->db->fetchByAssoc($r)) { + if(!in_array($a['contact_id'], $contactInvitees)) { + $deleteContacts[$a['contact_id']] = $a['contact_id']; + } else { + $acceptStatusContacts[$a['contact_id']] = $a['accept_status']; + } + } + + if(count($deleteContacts) > 0) { + $sql = ''; + foreach($deleteContacts as $u) { + $sql .= ",'" . $u . "'"; + } + $sql = substr($sql, 1); + // We could run a delete SQL statement here, but will just mark as deleted instead + $sql = "UPDATE meetings_contacts set deleted = 1 where contact_id in ($sql) AND meeting_id = '". $bean->id . "'"; + $bean->db->query($sql); + } + + if(!empty($_POST['lead_invitees'])) { + $leadInvitees = explode(',', trim($_POST['lead_invitees'], ',')); + } else { + $leadInvitees = array(); + } + + $deleteLeads = array(); + $bean->load_relationship('leads'); + $q = 'SELECT mu.lead_id, mu.accept_status FROM meetings_leads mu WHERE mu.meeting_id = \''.$bean->id.'\''; + $r = $bean->db->query($q); + $acceptStatusLeads = array(); + while($a = $bean->db->fetchByAssoc($r)) { + if(!in_array($a['lead_id'], $leadInvitees)) { + $deleteLeads[$a['lead_id']] = $a['lead_id']; + } else { + $acceptStatusLeads[$a['lead_id']] = $a['accept_status']; + } + } + + if(count($deleteLeads) > 0) { + $sql = ''; + foreach($deleteLeads as $u) { + $sql .= ",'" . $u . "'"; + } + $sql = substr($sql, 1); + // We could run a delete SQL statement here, but will just mark as deleted instead + $sql = "UPDATE meetings_leads set deleted = 1 where lead_id in ($sql) AND meeting_id = '". $bean->id . "'"; + $bean->db->query($sql); + } + //// END REMOVE + /////////////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////////////// + //// REBUILD INVITEE RELATIONSHIPS + $bean->users_arr = array(); + $bean->users_arr = $userInvitees; + $bean->contacts_arr = array(); + $bean->contacts_arr = $contactInvitees; + $bean->leads_arr = array(); + $bean->leads_arr = $leadInvitees; + + if(!empty($_POST['parent_id']) && $_POST['parent_type'] == 'Contacts') { + $bean->contacts_arr[] = $_POST['parent_id']; + } + + if(!empty($_POST['parent_id']) && $_POST['parent_type'] == 'Leads') { + $bean->leads_arr[] = $_POST['parent_id']; + } + + + $bean->save($notify); + + + // Process users + $existing_users = array(); + if(!empty($_POST['existing_invitees'])) { + $existing_users = explode(",", trim($_POST['existing_invitees'], ',')); + } + + foreach($bean->users_arr as $user_id) { + if(empty($user_id) || isset($existing_users[$user_id]) || isset($deleteUsers[$user_id])) { + continue; + } + + if(!isset($acceptStatusUsers[$user_id])) { + $bean->users->add($user_id); + } else { + // update query to preserve accept_status + $qU = 'UPDATE meetings_users SET deleted = 0, accept_status = \''.$acceptStatusUsers[$user_id].'\' '; + $qU .= 'WHERE meeting_id = \''.$bean->id.'\' '; + $qU .= 'AND user_id = \''.$user_id.'\''; + $bean->db->query($qU); + } + } + + // Process contacts + $existing_contacts = array(); + if(!empty($_POST['existing_contact_invitees'])) { + $existing_contacts = explode(",", trim($_POST['existing_contact_invitees'], ',')); + } + + foreach($bean->contacts_arr as $contact_id) { + if(empty($contact_id) || isset($exiting_contacts[$contact_id]) || isset($deleteContacts[$contact_id])) { + continue; + } + + if(!isset($acceptStatusContacts[$contact_id])) { + $bean->contacts->add($contact_id); + } else { + // update query to preserve accept_status + $qU = 'UPDATE meetings_contacts SET deleted = 0, accept_status = \''.$acceptStatusContacts[$contact_id].'\' '; + $qU .= 'WHERE meeting_id = \''.$bean->id.'\' '; + $qU .= 'AND contact_id = \''.$contact_id.'\''; + $bean->db->query($qU); + } + } + + // Process leads + $existing_leads = array(); + if(!empty($_POST['existing_lead_invitees'])) { + $existing_leads = explode(",", trim($_POST['existing_lead_invitees'], ',')); + } + + foreach($bean->leads_arr as $lead_id) { + if(empty($lead_id) || isset($exiting_leads[$lead_id]) || isset($deleteLeads[$lead_id])) { + continue; + } + + if(!isset($acceptStatusLeads[$lead_id])) { + $bean->leads->add($lead_id); + } else { + // update query to preserve accept_status + $qU = 'UPDATE meetings_leads SET deleted = 0, accept_status = \''.$acceptStatusLeads[$lead_id].'\' '; + $qU .= 'WHERE meeting_id = \''.$bean->id.'\' '; + $qU .= 'AND lead_id = \''.$lead_id.'\''; + $bean->db->query($qU); + } + } + + }else if($_REQUEST['current_module'] == 'Calls'){ + + if(!empty($_POST['user_invitees'])) { + $userInvitees = explode(',', trim($_POST['user_invitees'], ',')); + }else { + $userInvitees = array(); + } + + // Calculate which users to flag as deleted and which to add + $deleteUsers = array(); + $bean->load_relationship('users'); + // Get all users for the call + $q = 'SELECT mu.user_id, mu.accept_status FROM calls_users mu WHERE mu.call_id = \''.$bean->id.'\''; + $r = $bean->db->query($q); + $acceptStatusUsers = array(); + while($a = $bean->db->fetchByAssoc($r)) { + if(!in_array($a['user_id'], $userInvitees)) { + $deleteUsers[$a['user_id']] = $a['user_id']; + } else { + $acceptStatusUsers[$a['user_id']] = $a['accept_status']; + } + } + + if(count($deleteUsers) > 0) { + $sql = ''; + foreach($deleteUsers as $u) { + // make sure we don't delete the assigned user + if ( $u != $bean->assigned_user_id ) + $sql .= ",'" . $u . "'"; + } + $sql = substr($sql, 1); + // We could run a delete SQL statement here, but will just mark as deleted instead + $sql = "UPDATE calls_users set deleted = 1 where user_id in ($sql) AND call_id = '". $bean->id . "'"; + $bean->db->query($sql); + } + + // Get all contacts for the call + if(!empty($_POST['contact_invitees'])) { + $contactInvitees = explode(',', trim($_POST['contact_invitees'], ',')); + } else { + $contactInvitees = array(); + } + + $deleteContacts = array(); + $bean->load_relationship('contacts'); + $q = 'SELECT mu.contact_id, mu.accept_status FROM calls_contacts mu WHERE mu.call_id = \''.$bean->id.'\''; + $r = $bean->db->query($q); + $acceptStatusContacts = array(); + while($a = $bean->db->fetchByAssoc($r)) { + if(!in_array($a['contact_id'], $contactInvitees)) { + $deleteContacts[$a['contact_id']] = $a['contact_id']; + }else{ + $acceptStatusContacts[$a['contact_id']] = $a['accept_status']; + } + } + + if(count($deleteContacts) > 0) { + $sql = ''; + foreach($deleteContacts as $u) { + $sql .= ",'" . $u . "'"; + } + $sql = substr($sql, 1); + // We could run a delete SQL statement here, but will just mark as deleted instead + $sql = "UPDATE calls_contacts set deleted = 1 where contact_id in ($sql) AND call_id = '". $bean->id . "'"; + $bean->db->query($sql); + } + + if(!empty($_POST['lead_invitees'])) { + $leadInvitees = explode(',', trim($_POST['lead_invitees'], ',')); + } else { + $leadInvitees = array(); + } + + // Calculate which leads to flag as deleted and which to add + $deleteLeads = array(); + $bean->load_relationship('leads'); + // Get all leads for the call + $q = 'SELECT mu.lead_id, mu.accept_status FROM calls_leads mu WHERE mu.call_id = \''.$bean->id.'\''; + $r = $bean->db->query($q); + $acceptStatusLeads = array(); + while($a = $bean->db->fetchByAssoc($r)) { + if(!in_array($a['lead_id'], $leadInvitees)) { + $deleteLeads[$a['lead_id']] = $a['lead_id']; + } else { + $acceptStatusLeads[$a['user_id']] = $a['accept_status']; + } + } + + if(count($deleteLeads) > 0) { + $sql = ''; + foreach($deleteLeads as $u) { + // make sure we don't delete the assigned user + if ( $u != $bean->assigned_user_id ) + $sql .= ",'" . $u . "'"; + } + $sql = substr($sql, 1); + // We could run a delete SQL statement here, but will just mark as deleted instead + $sql = "UPDATE calls_leads set deleted = 1 where lead_id in ($sql) AND call_id = '". $bean->id . "'"; + $bean->db->query($sql); + } + //// END REMOVE + /////////////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////////////// + //// REBUILD INVITEE RELATIONSHIPS + $bean->users_arr = array(); + $bean->users_arr = $userInvitees; + $bean->contacts_arr = array(); + $bean->contacts_arr = $contactInvitees; + $bean->leads_arr = array(); + $bean->leads_arr = $leadInvitees; + + if(!empty($_POST['parent_id']) && $_POST['parent_type'] == 'Contacts') { + $bean->contacts_arr[] = $_POST['parent_id']; + } + + if(!empty($_POST['parent_id']) && $_POST['parent_type'] == 'Leads') { + $bean->leads_arr[] = $_POST['parent_id']; + } + + + $bean->save($notify); + + + // Process users + $existing_users = array(); + if(!empty($_POST['existing_invitees'])) { + $existing_users = explode(",", trim($_POST['existing_invitees'], ',')); + } + + foreach($bean->users_arr as $user_id) { + if(empty($user_id) || isset($existing_users[$user_id]) || isset($deleteUsers[$user_id])) { + continue; + } + + if(!isset($acceptStatusUsers[$user_id])) { + $bean->users->add($user_id); + } else { + // update query to preserve accept_status + $qU = 'UPDATE calls_users SET deleted = 0, accept_status = \''.$acceptStatusUsers[$user_id].'\' '; + $qU .= 'WHERE call_id = \''.$bean->id.'\' '; + $qU .= 'AND user_id = \''.$user_id.'\''; + $bean->db->query($qU); + } + } + + // Process contacts + $existing_contacts = array(); + if(!empty($_POST['existing_contact_invitees'])) { + $existing_contacts = explode(",", trim($_POST['existing_contact_invitees'], ',')); + } + + foreach($bean->contacts_arr as $contact_id) { + if(empty($contact_id) || isset($exiting_contacts[$contact_id]) || isset($deleteContacts[$contact_id])) { + continue; + } + + if(!isset($acceptStatusContacts[$contact_id])) { + $bean->contacts->add($contact_id); + } else { + // update query to preserve accept_status + $qU = 'UPDATE calls_contacts SET deleted = 0, accept_status = \''.$acceptStatusContacts[$contact_id].'\' '; + $qU .= 'WHERE call_id = \''.$bean->id.'\' '; + $qU .= 'AND contact_id = \''.$contact_id.'\''; + $bean->db->query($qU); + } + } + + // Process leads + $existing_leads = array(); + if(!empty($_POST['existing_lead_invitees'])) { + $existing_contacts = explode(",", trim($_POST['existing_lead_invitees'], ',')); + } + + foreach($bean->leads_arr as $lead_id) { + if(empty($lead_id) || isset($existing_leads[$lead_id]) || isset($deleteLeads[$lead_id])) { + continue; + } + + if(!isset($acceptStatusLeads[$lead_id])) { + $bean->leads->add($lead_id); + } else { + // update query to preserve accept_status + $qU = 'UPDATE calls_leads SET deleted = 0, accept_status = \''.$acceptStatusLeads[$lead_id].'\' '; + $qU .= 'WHERE call_id = \''.$bean->id.'\' '; + $qU .= 'AND lead_id = \''.$lead_id.'\''; + $bean->db->query($qU); + } + } + + }else if($_REQUEST['current_module'] == 'Tasks'){ + if (!isset($GLOBALS['check_notify'])){ + $GLOBALS['check_notify'] = false; + } + $bean->save($GLOBALS['check_notify']); + } + } + + +} + +?> diff --git a/tests/modules/UpgradeWizard/Bug42643Test.php b/modules/Calendar/views/view.savesettings.php old mode 100755 new mode 100644 similarity index 55% rename from tests/modules/UpgradeWizard/Bug42643Test.php rename to modules/Calendar/views/view.savesettings.php index aad4c93a..dddcb3a3 --- a/tests/modules/UpgradeWizard/Bug42643Test.php +++ b/modules/Calendar/views/view.savesettings.php @@ -34,48 +34,56 @@ * "Powered by SugarCRM". ********************************************************************************/ - -require_once('modules/UpgradeWizard/uw_utils.php'); +require_once('include/MVC/View/SugarView.php'); -class Bug42643Test extends Sugar_PHPUnit_Framework_TestCase -{ - var $has_notification_studio_file = false; - var $studio_file = 'modules/Help/Forms.php'; - var $backup_file; +class CalendarViewSaveSettings extends SugarView { + + function CalendarViewSettings(){ + parent::SugarView(); + } + + function process(){ + $this->display(); + } - public function setUp() - { + function display(){ + global $current_user; + + $db_start = $this->to_db_time($_REQUEST['day_start_hours'],$_REQUEST['day_start_minutes'],$_REQUEST['day_start_meridiem']); + $db_end = $this->to_db_time($_REQUEST['day_end_hours'],$_REQUEST['day_end_minutes'],$_REQUEST['day_end_meridiem']); - if(file_exists($this->studio_file)) - { - //This really shouldn't be happening, but just in case... - $this->has_notification_studio_file = true; - $this->backup_file = $this->studio_file . '.' . gmmktime() . '.bak'; - copy($this->studio_file, $this->backup_file); - } else { - //Create the test file - write_array_to_file("test", array(), $this->studio_file); - } + $current_user->setPreference('day_start_time', $db_start, 0, 'global', $current_user); + $current_user->setPreference('day_end_time', $db_end, 0, 'global', $current_user); + + $current_user->setPreference('show_tasks', $_REQUEST['show_tasks'], 0, 'global', $current_user); + $current_user->setPreference('show_calls', $_REQUEST['show_calls'], 0, 'global', $current_user); + + if(isset($_REQUEST['day']) && !empty($_REQUEST['day'])) + header("Location: index.php?module=Calendar&action=index&view=".$_REQUEST['view']."&hour=0&day=".$_REQUEST['day']."&month=".$_REQUEST['month']."&year=".$_REQUEST['year']); + else + header("Location: index.php?module=Calendar&action=index"); } - public function tearDown() - { - if($this->has_notification_studio_file) - { - copy($this->backup_file, $this->studio_file); - unlink($this->backup_file); - } else { - if(file_exists($this->studio_file)) - { - unlink($this->studio_file); - } + private function to_db_time($hours,$minutes,$mer){ + $hours = intval($hours); + $minutes = intval($minutes); + $mer = strtolower($mer); + if(!empty($mer)){ + if(($mer) == 'am') + if($hours == 12) + $hours = $hours - 12; + if(($mer) == 'pm') + if($hours != 12) + $hours = $hours + 12; } - } - - public function testUnlinkUpgradeFilesPre614() - { - $this->assertTrue(file_exists($this->studio_file), 'Assert the ' . $this->studio_file . ' exists'); - unlinkUpgradeFiles('610'); - $this->assertFalse(file_exists($this->studio_file), 'Assert the ' . $this->studio_file . ' no longer exists'); + if($hours < 10) + $hours = "0".$hours; + if($minutes < 10) + $minutes = "0".$minutes; + return $hours . ":". $minutes; } -} \ No newline at end of file + + +} + +?> diff --git a/modules/Calls/Call.php b/modules/Calls/Call.php index b0c3ab2f..31e327e8 100644 --- a/modules/Calls/Call.php +++ b/modules/Calls/Call.php @@ -229,24 +229,13 @@ class Call extends SugarBean } $query .= " FROM calls "; - /* - if ( $this->db->dbType == 'mssql' ) - { - $query .= ", calls.date_start "; - if ( preg_match("/contacts/",$where)){ - $query .= ", contacts.first_name, contacts.last_name"; - $query .= ", contacts.assigned_user_id contact_name_owner"; - } - $query .= " FROM calls "; - } - */ if ( preg_match("/contacts/",$where)){ $query .= "LEFT JOIN calls_contacts ON calls.id=calls_contacts.call_id LEFT JOIN contacts ON calls_contacts.contact_id=contacts.id "; } - if ( preg_match("/calls_users\.user_id/",$where)) + if ( preg_match('/calls_users\.user_id/',$where)) { $query .= "LEFT JOIN calls_users ON calls.id=calls_users.call_id and calls_users.deleted=0 "; @@ -409,7 +398,7 @@ class Call extends SugarBean $action = "index"; $setCompleteUrl = ""; - $call_fields['SET_COMPLETE'] = $setCompleteUrl . SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Calls')." border='0'").""; + $call_fields['SET_COMPLETE'] = $setCompleteUrl . SugarThemeRegistry::current()->getImage("close_inline","title='".translate('LBL_LIST_CLOSE','Calls')."' border='0'", null,null,'.gif', translate('LBL_LIST_CLOSE','Calls')) . ""; } global $timedate; $today = $timedate->nowDb(); diff --git a/modules/Calls/CallFormBase.php b/modules/Calls/CallFormBase.php index 9e1daa4c..452f6897 100644 --- a/modules/Calls/CallFormBase.php +++ b/modules/Calls/CallFormBase.php @@ -43,7 +43,9 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * Contributor(s): ______________________________________.. ********************************************************************************/ -class CallFormBase{ +require_once('include/SugarObjects/forms/FormBase.php'); + +class CallFormBase extends FormBase { function getFormBody($prefix, $mod='', $formname='',$cal_date='',$cal_time=''){ if(!ACLController::checkAccess('Calls', 'edit', true)){ @@ -274,10 +276,10 @@ function handleSave($prefix,$redirect=true,$useRequired=false) { $return_id = $focus->id; }else{ - if(empty($_REQUEST['return_module']) && empty($_REQUEST['return_action']) && $focus->status == 'Held'){ - //if we are closing the call, and the request does not have a return module AND return action set, then - //the request is coming from a dashlet or subpanel close icon and there is no need to process user invitees, - //just save the current values. + if($focus->status == 'Held' && $this->isEmptyReturnModuleAndAction() && !$this->isSaveFromDCMenu()){ + //if we are closing the meeting, and the request does not have a return module AND return action set and it is not a save + //being triggered by the DCMenu (shortcut bar) then the request is coming from a dashlet or subpanel close icon and there is no + //need to process user invitees, just save the current values. $focus->save(true); }else{ /////////////////////////////////////////////////////////////////////////// @@ -581,7 +583,7 @@ $form .= <<$lbl_date $lbl_required_symbol $ntc_date_format - {$app_strings['LBL_ENTER_DATE']} + {$app_strings['LBL_ENTER_DATE']} diff --git a/modules/Calls/Dashlets/MyCallsDashlet/MyCallsDashlet.php b/modules/Calls/Dashlets/MyCallsDashlet/MyCallsDashlet.php index 902b75e1..af3d150f 100644 --- a/modules/Calls/Dashlets/MyCallsDashlet/MyCallsDashlet.php +++ b/modules/Calls/Dashlets/MyCallsDashlet/MyCallsDashlet.php @@ -125,14 +125,9 @@ class MyCallsDashlet extends DashletGeneric { { $this->lvs->data['data'][$rowNum]['SET_ACCEPT_LINKS'] = ""; + SugarThemeRegistry::current()->getImage("accept_inline","border='0'",null,null,'.gif',$app_list_strings['dom_meeting_accept_options']['accept']). " id."&object_type=Call&object_id=".$this->lvs->data['data'][$rowNum]['ID'] . "&accept_status=tentative', null, null, SUGAR.mySugar.retrieveDashlet, '{$this->id}');\">". + SugarThemeRegistry::current()->getImage("tentative_inline","border='0'", null,null,'.gif',$app_list_strings['dom_meeting_accept_options']['tentative'])." id."&object_type=Call&object_id=".$this->lvs->data['data'][$rowNum]['ID'] . "&accept_status=decline', null, null, SUGAR.mySugar.retrieveDashlet, '{$this->id}');\">". + SugarThemeRegistry::current()->getImage("decline_inline","border='0'", null,null,'.gif',$app_list_strings['dom_meeting_accept_options']['decline'])."
"; } else { diff --git a/modules/Calls/metadata/editviewdefs.php b/modules/Calls/metadata/editviewdefs.php index cb7d11c9..f95777bf 100644 --- a/modules/Calls/metadata/editviewdefs.php +++ b/modules/Calls/metadata/editviewdefs.php @@ -34,16 +34,16 @@ * "Powered by SugarCRM". ********************************************************************************/ -$viewdefs ['Calls'] = +$viewdefs ['Calls'] = array ( - 'EditView' => + 'EditView' => array ( - 'templateMeta' => + 'templateMeta' => array ( 'maxColumns' => '2', - 'form' => + 'form' => array ( - 'hidden' => + 'hidden' => array ( 0 => '', 1 => '', @@ -51,52 +51,52 @@ array ( 3 => '', 4 => '', ), - 'buttons' => + 'buttons' => array ( - 0 => + 0 => array ( 'customCode' => '', ), 1 => 'CANCEL', - 2 => + 2 => array ( 'customCode' => '', ), - 3 => + 3 => array ( 'customCode' => '{if $fields.status.value != "Held"}{/if}', ), ), 'footerTpl' => 'modules/Calls/tpls/footer.tpl', ), - 'widths' => + 'widths' => array ( - 0 => + 0 => array ( 'label' => '10', 'field' => '30', ), - 1 => + 1 => array ( 'label' => '10', 'field' => '30', ), ), - 'javascript' => ' + 'javascript' => '{sugar_getscript file="cache/include/javascript/sugar_grp_jsolait.js"} ', 'useTabs' => false, ), - 'panels' => + 'panels' => array ( - 'lbl_call_information' => + 'lbl_call_information' => array ( array ( 'name' => 'name', array ( 'name' => 'status', - 'fields' => + 'fields' => array ( array ( 'name' => 'direction', @@ -110,7 +110,7 @@ function formSubmitCheck(){ldelim}if(check_form(\'EditView\') && isValidDuration array ( array ( 'name' => 'date_start', - 'displayParams' => + 'displayParams' => array ( 'updateCallback' => 'SugarWidgetScheduler.update_time();', ), @@ -126,7 +126,7 @@ function formSubmitCheck(){ldelim}if(check_form(\'EditView\') && isValidDuration 'name' => 'duration_hours', 'label' => 'LBL_DURATION', 'customCode' => '{literal}{/literal}{$fields.duration_minutes.value} {$MOD.LBL_HOURS_MINUTES}', - + ), array ( 'name' => 'reminder_time', @@ -142,7 +142,7 @@ function formSubmitCheck(){ldelim}if(check_form(\'EditView\') && isValidDuration ), ), ), - 'LBL_PANEL_ASSIGNMENT' => + 'LBL_PANEL_ASSIGNMENT' => array ( array ( array ( diff --git a/modules/Calls/metadata/quickcreatedefs.php b/modules/Calls/metadata/quickcreatedefs.php index a0ec512c..29715a41 100644 --- a/modules/Calls/metadata/quickcreatedefs.php +++ b/modules/Calls/metadata/quickcreatedefs.php @@ -34,16 +34,16 @@ * "Powered by SugarCRM". ********************************************************************************/ -$viewdefs ['Calls'] = +$viewdefs ['Calls'] = array ( - 'QuickCreate' => + 'QuickCreate' => array ( - 'templateMeta' => + 'templateMeta' => array ( 'maxColumns' => '2', - 'form' => + 'form' => array ( - 'hidden' => + 'hidden' => array ( 0 => '', 1 => '', @@ -51,62 +51,62 @@ array ( 3 => '', 4 => '', ), - 'buttons' => + 'buttons' => array ( - 0 => + 0 => array ( 'customCode' => '', ), 1 => 'CANCEL', - 2 => + 2 => array ( 'customCode' => '', ), - 3 => + 3 => array ( 'customCode' => '{if $fields.status.value != "Held"}{/if}', ), ), 'footerTpl' => 'modules/Calls/tpls/footer.tpl', ), - 'widths' => + 'widths' => array ( - 0 => + 0 => array ( 'label' => '10', 'field' => '30', ), - 1 => + 1 => array ( 'label' => '10', 'field' => '30', ), ), - 'javascript' => ' - -', + 'javascript' => ''. + '{sugar_getscript file="cache/include/javascript/sugar_grp_jsolait.js"}' . + '', 'useTabs' => false, ), - 'panels' => + 'panels' => array ( - 'default' => + 'default' => array ( array ( array ( 'name' => 'name', - 'displayParams' => + 'displayParams' => array ( 'required' => true, ), ), array ( 'name' => 'status', - 'displayParams' => + 'displayParams' => array ( 'required' => true, ), - 'fields' => + 'fields' => array ( array ( 'name' => 'direction', @@ -122,7 +122,7 @@ array ( array ( 'name' => 'date_start', 'type' => 'datetimecombo', - 'displayParams' => + 'displayParams' => array ( 'required' => true, 'updateCallback' => 'SugarWidgetScheduler.update_time();', @@ -140,7 +140,7 @@ array ( 'name' => 'duration_hours', 'label' => 'LBL_DURATION', 'customCode' => '{literal}{/literal}{$fields.duration_minutes.value} {$MOD.LBL_HOURS_MINUTES}', - 'displayParams' => + 'displayParams' => array ( 'required' => true, ), @@ -150,9 +150,9 @@ array ( 'customCode' => '{if $fields.reminder_checked.value == "1"}{assign var="REMINDER_TIME_DISPLAY" value="inline"}{assign var="REMINDER_CHECKED" value="checked"}{else}{assign var="REMINDER_TIME_DISPLAY" value="none"}{assign var="REMINDER_CHECKED" value=""}{/if}
{$fields.reminder_time.value}
', 'label' => 'LBL_REMINDER', ), - + ), - + array ( array ( 'name' => 'assigned_user_name', diff --git a/modules/Calls/tpls/QuickCreate.tpl b/modules/Calls/tpls/QuickCreate.tpl index 7d58ce47..684f0de0 100644 --- a/modules/Calls/tpls/QuickCreate.tpl +++ b/modules/Calls/tpls/QuickCreate.tpl @@ -105,7 +105,7 @@ CL: Bug fix for 9291 and 9427 - parent_id should be parent_type, not the module - {$USER_DATEFORMAT}  + {sugar_getimage name="jscalendar" ext=".gif" alt=$USER_DATEFORMAT other_attributes='align="absmiddle" id="jscal_trigger" '}  {$TIME_SEPARATOR} @@ -131,8 +131,8 @@ CL: Bug fix for 9291 and 9427 - parent_id should be parent_type, not the module \ No newline at end of file + diff --git a/modules/Calls/tpls/footer.tpl b/modules/Calls/tpls/footer.tpl index 864e6258..8c888a73 100644 --- a/modules/Calls/tpls/footer.tpl +++ b/modules/Calls/tpls/footer.tpl @@ -80,7 +80,7 @@ var callsLoader = new YAHOO.util.YUILoader({ callsLoader.addModule({ name :"sugar_grp_jsolait", type : "js", - fullpath: "include/javascript/sugar_grp_jsolait.js", + fullpath: "cache/include/javascript/sugar_grp_jsolait.js", varName: "global_rpcClient", requires: [] }); diff --git a/modules/CampaignLog/CampaignLog.php b/modules/CampaignLog/CampaignLog.php index 02137e90..ae550655 100644 --- a/modules/CampaignLog/CampaignLog.php +++ b/modules/CampaignLog/CampaignLog.php @@ -35,17 +35,6 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * "Powered by SugarCRM". ********************************************************************************/ -/********************************************************************************* - - * Description: - ********************************************************************************/ - - - - - - - class CampaignLog extends SugarBean { @@ -80,22 +69,19 @@ class CampaignLog extends SugarBean { //make sure that both items in array are set to some value, else return null if(!(isset($temp_array['TARGET_TYPE']) && $temp_array['TARGET_TYPE']!= '') || !(isset($temp_array['TARGET_ID']) && $temp_array['TARGET_ID']!= '')) { //needed values to construct query are empty/null, so return null - $GLOBALS['log']->debug("CampaignLog.php:get_list_view_data duntion: temp_array['TARGET_TYPE'] and/or temp_array['TARGET_ID'] are empty, return null"); + $GLOBALS['log']->debug("CampaignLog.php:get_list_view_data: temp_array['TARGET_TYPE'] and/or temp_array['TARGET_ID'] are empty, return null"); $emptyArr = array(); return $emptyArr; } - if ( ( $this->db->dbType == 'mysql' ) or ( $this->db->dbType == 'oci8' ) ) - { - $query="select first_name, last_name, CONCAT(CONCAT(first_name, ' '), last_name) name from ".strtolower($temp_array['TARGET_TYPE']) . " where id ='{$temp_array['TARGET_ID']}'"; - } - if($this->db->dbType == 'mssql') - { - $query="select first_name, last_name, (first_name + ' ' + last_name) name from ".strtolower($temp_array['TARGET_TYPE']) . " where id ='{$temp_array['TARGET_ID']}'"; - } + + $table = strtolower($temp_array['TARGET_TYPE']); + if($temp_array['TARGET_TYPE']=='Accounts'){ - $query="select name from ".strtolower($temp_array['TARGET_TYPE']) . " where id ='{$temp_array['TARGET_ID']}'"; + $query = "select name from $table where id = ".$this->db->quoted($temp_array['TARGET_ID']); + }else{ + $query = "select first_name, last_name, ".$this->db->concat($table, array('first_name', 'last_name'))." name from $table" . + " where id = ".$this->db->quoted($temp_array['TARGET_ID']); } - $result=$this->db->query($query); $row=$this->db->fetchByAssoc($result); @@ -117,7 +103,7 @@ class CampaignLog extends SugarBean { { $temp_array['MARKETING_NAME'] = $row['name']; } - + return $temp_array; } diff --git a/modules/CampaignLog/Popup_picker.html b/modules/CampaignLog/Popup_picker.html index 9a4b0d46..19a2217b 100644 --- a/modules/CampaignLog/Popup_picker.html +++ b/modules/CampaignLog/Popup_picker.html @@ -40,7 +40,7 @@ --> - + diff --git a/modules/CampaignTrackers/EditView.php b/modules/CampaignTrackers/EditView.php index 72de8457..2ef5b0be 100644 --- a/modules/CampaignTrackers/EditView.php +++ b/modules/CampaignTrackers/EditView.php @@ -113,7 +113,7 @@ if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($ if(!empty($_REQUEST['record'])){ $record = $_REQUEST['record']; } - $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); } if (!empty($focus->is_optout) && $focus->is_optout == 1) { $xtpl->assign("IS_OPTOUT_CHECKED","checked"); diff --git a/modules/CampaignTrackers/language/en_us.lang.php b/modules/CampaignTrackers/language/en_us.lang.php index 78ebecf4..a2058674 100644 --- a/modules/CampaignTrackers/language/en_us.lang.php +++ b/modules/CampaignTrackers/language/en_us.lang.php @@ -69,6 +69,7 @@ $mod_strings = array ( 'LBL_EDIT_TRACKER_KEY'=>'Tracker Key:', 'LBL_EDIT_OPT_OUT'=>'Opt-out Link?', 'LNK_CAMPAIGN_LIST'=>'Campaigns', + 'LBL_EDIT_LAYOUT' => 'Edit Layout' /*for 508 compliance fix*/, ); ?> diff --git a/modules/Campaigns/Campaign.php b/modules/Campaigns/Campaign.php index 74495fc7..574738af 100644 --- a/modules/Campaigns/Campaign.php +++ b/modules/Campaigns/Campaign.php @@ -40,16 +40,9 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * Description: ********************************************************************************/ - - - - - - - class Campaign extends SugarBean { var $field_name_map; - + // Stored fields var $id; var $date_entered; @@ -76,7 +69,7 @@ class Campaign extends SugarBean { var $tracker_count; var $refer_url; var $impressions; - + // These are related var $assigned_user_name; @@ -86,42 +79,37 @@ class Campaign extends SugarBean { var $object_name = "Campaign"; var $module_dir = 'Campaigns'; var $importable = true; - + // This is used to retrieve related fields from form posts. var $additional_column_fields = array( 'assigned_user_name', 'assigned_user_id', ); var $relationship_fields = Array('prospect_list_id'=>'prospect_lists'); - - function Campaign() { - global $sugar_config; - parent::SugarBean(); - } var $new_schema = true; - + function list_view_parse_additional_sections(&$listTmpl) { global $locale; - + // take $assigned_user_id and get the Username value to assign $assId = $this->getFieldValue('assigned_user_id'); - + $query = "SELECT first_name, last_name FROM users WHERE id = '".$assId."'"; $result = $this->db->query($query); $user = $this->db->fetchByAssoc($result); - + //_ppd($user); if(!empty($user)) { $fullName = $locale->getLocaleFormattedName($user->first_name, $user->last_name); $listTmpl->assign('ASSIGNED_USER_NAME', $fullName); } } - + function get_summary_text() { - return "$this->name"; + return $this->name; } function create_export_query(&$order_by, &$where, $relate_link_join='') @@ -164,12 +152,12 @@ class Campaign extends SugarBean { $prospect_clause = " and prospect_list_id = '$prospect_list_id' "; else $prospect_clause = ''; - + $query = "DELETE FROM $this->rel_prospect_list_table WHERE campaign_id='$campaign_id' AND deleted = '0' " . $prospect_clause; $this->db->query($query, true, "Error clearing campaign to prospect_list relationship: "); } - - + + function mark_relationships_deleted($id) { @@ -183,9 +171,9 @@ class Campaign extends SugarBean { function fill_in_additional_detail_fields() { - parent::fill_in_additional_detail_fields(); + parent::fill_in_additional_detail_fields(); //format numbers. - + //don't need additional formatting here. //$this->budget=format_number($this->budget); //$this->expected_cost=format_number($this->expected_cost); @@ -193,7 +181,7 @@ class Campaign extends SugarBean { //$this->expected_revenue=format_number($this->expected_revenue); } - + function update_currency_id($fromid, $toid){ } @@ -208,14 +196,16 @@ class Campaign extends SugarBean { $temp_array['TRACK_CAMPAIGN_IMAGE'] = SugarThemeRegistry::current()->getImageURL('view_status.gif'); $temp_array['LAUNCH_WIZARD_TITLE'] = translate("LBL_TO_WIZARD_TITLE",'Campaigns'); $temp_array['LAUNCH_WIZARD_IMAGE'] = SugarThemeRegistry::current()->getImageURL('edit_wizard.gif'); - + $temp_array['TRACK_VIEW_ALT_TEXT'] = translate("LBL_TRACK_BUTTON_TITLE",'Campaigns'); + $temp_array['LAUNCH_WIZ_ALT_TEXT'] = translate("LBL_TO_WIZARD_TITLE",'Campaigns'); + return $temp_array; } /** builds a generic search based on the query string using or do not include any $this-> because this is called on without having the class instantiated */ - function build_generic_where_clause ($the_query_string) + function build_generic_where_clause ($the_query_string) { $where_clauses = Array(); $the_query_string = $this->db->quote($the_query_string); @@ -233,7 +223,7 @@ class Campaign extends SugarBean { } function save($check_notify = FALSE) { - + //US DOLLAR if(isset($this->amount) && !empty($this->amount)){ @@ -242,9 +232,9 @@ class Campaign extends SugarBean { $this->amount_usdollar = $currency->convertToDollar($this->amount); } - + $this->unformat_all_fields(); - + return parent::save($check_notify); } @@ -252,6 +242,8 @@ class Campaign extends SugarBean { function mark_deleted($id){ $query = "update contacts set campaign_id = null where campaign_id = '{$id}' "; + $this->db->query($query); + $query = "update accounts set campaign_id = null where campaign_id = '{$id}' "; $this->db->query($query); return parent::mark_deleted($id); } @@ -271,34 +263,34 @@ class Campaign extends SugarBean { //get arguments being passed in $args = func_get_args(); $mkt_id =''; - + $this->load_relationship('log_entries'); $query_array = $this->log_entries->getQuery(true); - + //if one of the arguments is marketing ID, then we need to filter by it foreach($args as $arg){ if(isset($arg['EMAIL_MARKETING_ID_VALUE'])){ $mkt_id = $arg['EMAIL_MARKETING_ID_VALUE']; } - + if(isset($arg['group_by'])) { $query_array['group_by'] = $arg['group_by']; - } + } } - - - - if (empty($type)) + + + + if (empty($type)) $type[0]='targeted'; $query_array['select'] ="SELECT campaign_log.* "; $query_array['where'] = $query_array['where']. " AND activity_type='{$type[0]}' AND archived=0"; //add filtering by marketing id, if it exists if (!empty($mkt_id)) $query_array['where'] = $query_array['where']. " AND marketing_id ='$mkt_id' "; - - //B.F. #37943 - if( isset($query_array['group_by']) && $this->db->dbType != 'mysql' ) - { + + //B.F. #37943 + if( isset($query_array['group_by'])) + { //perform the inner join with the group by if a marketing id is defined, which means we need to filter out duplicates. //if no marketing id is specified then we are displaying results from multiple marketing emails and it is understood there might be duplicate target entries if (!empty($mkt_id)){ @@ -308,14 +300,13 @@ class Campaign extends SugarBean { on campaign_log.id = secondary.id "; } unset($query_array['group_by']); - } - else if(isset($query_array['group_by'])) { + } else if(isset($query_array['group_by'])) { $query_array['where'] = $query_array['where'] . ' GROUP BY ' . $query_array['group_by']; unset($query_array['group_by']); } - + $query = (implode(" ",$query_array)); - return $query; + return $query; } @@ -325,19 +316,19 @@ class Campaign extends SugarBean { $mkt_id =''; $this->load_relationship('queueitems'); - $query_array = $this->queueitems->getQuery(true); - + $query_array = $this->queueitems->getQuery(true); + //if one of the arguments is marketing ID, then we need to filter by it foreach($args as $arg){ if(isset($arg['EMAIL_MARKETING_ID_VALUE'])){ $mkt_id = $arg['EMAIL_MARKETING_ID_VALUE']; } - + if(isset($arg['group_by'])) { $query_array['group_by'] = $arg['group_by']; } } - + //add filtering by marketing id, if it exists, and if where key is not empty if (!empty($mkt_id) && !empty($query_array['where'])){ $query_array['where'] = $query_array['where']. " AND marketing_id ='$mkt_id' "; @@ -345,9 +336,9 @@ class Campaign extends SugarBean { //get select query from email man $man = new EmailMan(); - $listquery= $man->create_queue_items_query('',str_replace(array("WHERE","where"),"",$query_array['where']),null,$query_array); + $listquery= $man->create_queue_items_query('',str_replace(array("WHERE","where"),"",$query_array['where']),null,$query_array); return $listquery; - + } // function get_prospect_list_entries() { // $this->load_relationship('prospectlists'); @@ -355,18 +346,18 @@ class Campaign extends SugarBean { // // $query=<< \ No newline at end of file diff --git a/modules/Campaigns/CampaignDiagnostic.php b/modules/Campaigns/CampaignDiagnostic.php index 7e14b442..95c81d71 100644 --- a/modules/Campaigns/CampaignDiagnostic.php +++ b/modules/Campaigns/CampaignDiagnostic.php @@ -106,18 +106,18 @@ while ($mbox_row = $focus->db->fetchByAssoc($mbox_res)){$mbox[] = $mbox_row;} //if the array is not empty, then set "good" message if(isset($mbox) && count($mbox)>0){ $mboxTable .= ""; - $mboxTable .= "" - . " " - . " " - . " " - . " "; + $mboxTable .= "" + . " " + . " " + . " " + . " "; foreach($mbox as $details){ $mboxTable .= ""; - $mboxTable .= ""; - $mboxTable .= ""; - $mboxTable .= ""; - $mboxTable .= ""; + $mboxTable .= ""; + $mboxTable .= ""; + $mboxTable .= ""; + $mboxTable .= ""; } }else{ @@ -140,18 +140,18 @@ if (strstr($focus->settings['notify_fromaddress'], 'example.com')){ $email_health =$email_health +1; }else{ $conf_msg .= ""; - $conf_msg .= "" - . " " - . " "; + $conf_msg .= "" + . " " + . " "; if($focus->settings['mail_sendtype']=='SMTP'){ - $conf_msg .= " " - . " "; + $conf_msg .= " " + . " "; }else{$conf_msg .= "";} - $conf_msg .= ""; + $conf_msg .= ""; $conf_msg .= ""; $conf_msg .= ""; if($focus->settings['mail_sendtype']=='SMTP'){ @@ -197,8 +197,8 @@ while ($sched_row = $focus->db->fetchByAssoc($sched_res)){$scheds[] = $sched_row foreach ($scheds as $funct){ if( ($funct['job']==$check_sched1) || ($funct['job']==$check_sched2)){ $sched_mes = 'use'; - $sched_mes_body .= ""; - $sched_mes_body .= ""; + $sched_mes_body .= ""; + $sched_mes_body .= ""; if($funct['job']==$check_sched1){ $check_sched1 ="found"; }else{ @@ -212,8 +212,8 @@ foreach ($scheds as $funct){ $show_admin_link = false; if($sched_mes == 'use'){ $sched_mes = "
".$mod_strings['LBL_SCHEDULER_CHECK_GOOD']."

" .count($mbox) ." ". $mod_strings['LBL_MAILBOX_CHECK1_GOOD']." .
".$mod_strings['LBL_MAILBOX_NAME']."".$mod_strings['LBL_LOGIN']."".$mod_strings['LBL_MAILBOX']."".$mod_strings['LBL_SERVER_URL']."".$mod_strings['LBL_LIST_STATUS']."
".$mod_strings['LBL_MAILBOX_NAME']."".$mod_strings['LBL_LOGIN']."".$mod_strings['LBL_MAILBOX']."".$mod_strings['LBL_SERVER_URL']."".$mod_strings['LBL_LIST_STATUS']."
".$details['name']."".$details['email_user']."".$details['mailbox']."".$details['server_url']."".$details['status']."
".$details['email_user']."".$details['mailbox']."".$details['server_url']."".$details['status']."
".$mod_strings['LBL_MAILBOX_CHECK2_GOOD']."
".$mod_strings['LBL_WIZ_FROM_NAME']."".$mod_strings['LBL_WIZ_FROM_ADDRESS']."".$mod_strings['LBL_MAIL_SENDTYPE']."
".$mod_strings['LBL_WIZ_FROM_NAME']."".$mod_strings['LBL_WIZ_FROM_ADDRESS']."".$mod_strings['LBL_MAIL_SENDTYPE']."".$mod_strings['LBL_MAIL_SMTPSERVER']."".$mod_strings['LBL_MAIL_SMTPUSER']."
".$mod_strings['LBL_MAIL_SMTPSERVER']."".$mod_strings['LBL_MAIL_SMTPUSER']."
".$focus->settings['notify_fromname']."
".$focus->settings['notify_fromname']."".$focus->settings['notify_fromaddress']."".$focus->settings['mail_sendtype']."
".$funct['name']."".$funct['status']."
".$funct['name']."".$funct['status']."
"; - $sched_mes .= "" - . " "; + $sched_mes .= "" + . " "; }else{ $sched_mes = "
".$mod_strings['LBL_SCHEDULER_NAME']."".$mod_strings['LBL_SCHEDULER_STATUS']."
".$mod_strings['LBL_SCHEDULER_NAME']."".$mod_strings['LBL_SCHEDULER_STATUS']."
"; @@ -259,19 +259,25 @@ if(!isset($_REQUEST['inline']) || $_REQUEST['inline'] != 'inline'){ * @return string HTML img tag */ function define_image($num, $total) -{ +{ global $mod_strings; //if health number is equal to total number then all checks failed, set red image if($num == $total){ //red - return " "; + return SugarThemeRegistry::current()->getImage('red_camp', "align='absmiddle'", null, null, ".gif", $mod_strings['LBL_INVALID']); + + }elseif($num == 0){ //if health number is zero, then all checks passed, set green image //green - return " "; + return SugarThemeRegistry::current()->getImage('green_camp', "align='absmiddle'", null, null, ".gif", $mod_strings['LBL_VALID']); + + }else{ //if health number is between total and num params, then some checks failed but not all, set yellow image //yellow - return " "; + return SugarThemeRegistry::current()->getImage('yellow_camp', "align='absmiddle'", null, null, ".gif", $mod_strings['LBL_ALERT']); + + } } diff --git a/modules/Campaigns/Charts1.php b/modules/Campaigns/Charts1.php index 909313a0..e814025d 100644 --- a/modules/Campaigns/Charts1.php +++ b/modules/Campaigns/Charts1.php @@ -49,9 +49,9 @@ require_once('include/charts/Charts.php'); class charts { - - /* @function: - * + + /* @function: + * * @param array targets: translated list of all activity types, targeted, bounced etc.. * @param string campaign_id: chart for this campaign. */ @@ -59,22 +59,22 @@ class charts { $focus = new Campaign(); $leadSourceArr = array(); - + $query = "SELECT activity_type,target_type, count(*) hits "; $query.= " FROM campaign_log "; $query.= " WHERE campaign_id = '$campaign_id' AND archived=0 AND deleted=0"; $query.= " GROUP BY activity_type, target_type"; $query.= " ORDER BY activity_type, target_type"; - + $result = $focus->db->query($query); - while($row = $focus->db->fetchByAssoc($result, -1, false)) { - + while($row = $focus->db->fetchByAssoc($result, false)) { + if (isset($leadSourceArr[$row['activity_type']]['value'])) { $leadSourceArr[$row['activity_type']]['value']=0; } - + $leadSourceArr[$row['activity_type']]['value']= $leadSourceArr[$row['activity_type']]['value'] + $row['hits']; - + if (!empty($row['target_type'])) { $leadSourceArr[$row['activity_type']]['bars'][$row['target_type']]['value']=$row['hits']; } @@ -85,22 +85,21 @@ class charts { $leadSourceArr[$key]['value']=0; } } - + //use the new template. $xtpl=new XTemplate ('modules/Campaigns/chart.tpl'); $xtpl->assign("GRAPHTITLE",'Campaign Response by Recipient Activity'); $xtpl->assign("Y_DEFAULT_ALT_TEXT",'Rollover a bar to view details.'); - + //process rows foreach ($leadSourceArr as $key=>$values) { if (isset($values['bars'])) { foreach ($values['bars'] as $bar_id=>$bar_value) { $xtpl->assign("Y_BAR_ID",$bar_id); - } + } } - + } } }// end charts class ?> - \ No newline at end of file diff --git a/modules/Campaigns/Delete.php b/modules/Campaigns/Delete.php index 21e320e1..e13165c1 100644 --- a/modules/Campaigns/Delete.php +++ b/modules/Campaigns/Delete.php @@ -53,57 +53,19 @@ $focus->retrieve($_REQUEST['record']); if (isset($_REQUEST['mode']) and $_REQUEST['mode']=='Test') { //deletes all data associated with the test run. + $query = "UPDATE emails SET emails.deleted=1 WHERE id IN ( + SELECT related_id FROM campaign_log INNER JOIN prospect_lists + ON campaign_log.list_id = prospect_lists.id + AND prospect_lists.list_type='test' + AND campaign_log.campaign_id = '{$focus->id}')"; + $focus->db->query($query); - //delete from emails table. - if ($focus->db->dbType=='mysql') { - - $query="update emails "; - $query.="inner join campaign_log on campaign_log.related_id = emails.id and campaign_log.campaign_id = '{$focus->id}' "; - $query.="inner join prospect_lists on campaign_log.list_id = prospect_lists.id and prospect_lists.list_type='test' "; - $query.="set emails.deleted=1 "; - } elseif ($focus->db->dbType=='mssql') { - $query="update emails "; - $query.="set emails.deleted=1 "; - $query.="where id in ( "; - $query.="select related_id from campaign_log "; - $query.="inner join prospect_lists on campaign_log.list_id = prospect_lists.id "; - $query.="and prospect_lists.list_type='test' "; - $query.="and campaign_log.campaign_id = '{$focus->id}' ) "; - } else { - } - $focus->db->query($query); - - //delete from message queue. - if ($focus->db->dbType=='mysql') { - $query="delete emailman.* from emailman "; - $query.="inner join prospect_lists on emailman.list_id = prospect_lists.id and prospect_lists.list_type='test' "; - $query.="WHERE emailman.campaign_id = '{$focus->id}' "; - } elseif ($focus->db->dbType=='mssql') { - $query="delete from emailman "; - $query.="where list_id in ( "; - $query.=" select prospect_list_id from prospect_list_campaigns "; - $query.=" inner join prospect_lists on prospect_list_campaigns.prospect_list_id = prospect_lists.id "; - $query.=" where prospect_lists.list_type='test' and prospect_list_campaigns.campaign_id = '{$focus->id}' ) "; - } else { - } - $focus->db->query($query); - - //delete from campaign_log - if ($focus->db->dbType=='mysql') { - $query="update campaign_log "; - $query.="inner join prospect_lists on campaign_log.list_id = prospect_lists.id and prospect_lists.list_type='test' "; - $query.="set campaign_log.deleted=1 "; - $query.="where campaign_log.campaign_id='{$focus->id}' "; - } elseif ($focus->db->dbType=='mssql') { - $query="update campaign_log "; - $query.="set campaign_log.deleted=1 "; - $query.="where list_id in ( "; - $query.=" select id from prospect_lists "; - $query.=" where prospect_lists.list_type='test') "; - $query.="and campaign_log.campaign_id='{$focus->id}' "; - } else { - } - $focus->db->query($query); + $query="DELETE FROM emailman WHERE list_id IN ( + SELECT prospect_list_id FROM prospect_list_campaigns INNER JOIN prospect_lists + ON prospect_list_campaigns.prospect_list_id = prospect_lists.id + AND prospect_lists.list_type='test' + AND prospect_list_campaigns.campaign_id = '{$focus->id}')"; + $focus->db->query($query); } else { if(!$focus->ACLAccess('Delete')){ ACLController::displayNoAccess(true); diff --git a/modules/Campaigns/GenerateWebToLeadForm.php b/modules/Campaigns/GenerateWebToLeadForm.php index 3cae9b7c..3357f5e0 100644 --- a/modules/Campaigns/GenerateWebToLeadForm.php +++ b/modules/Campaigns/GenerateWebToLeadForm.php @@ -105,8 +105,10 @@ if(!empty($_REQUEST['assigned_user_id'])){ $xtpl->assign("APP", $app_strings); $Web_To_Lead_Form_html = ''; $Web_To_Lead_Form_html .=''; - $Web_To_Lead_Form_html .= ""; - $Web_To_Lead_Form_html .= ''; + + $Web_To_Lead_Form_html .= ""; + $Web_To_Lead_Form_html .= ''; + $Web_To_Lead_Form_html .=""; $Web_To_Lead_Form_html .= "
$field_label"; } if(isset($lead->field_defs[$colsFirstField]['isMultiSelect']) && $lead->field_defs[$colsFirstField]['isMultiSelect'] ==1){ - $Web_To_Lead_Form_html .= ""; + $Web_To_Lead_Form_html .= ""; }elseif(ifRadioButton($lead->field_defs[$colsFirstField]['name'])){ $Web_To_Lead_Form_html .=""; } + $Web_To_Lead_Form_html .= " @@ -110,40 +110,40 @@ - + - + - + - + - + - + - + - + - - - + + - - - + + +
"; foreach($app_list_strings[$field_options] as $field_option_key => $field_option){ @@ -268,6 +270,7 @@ for($i= 0; $i<$columns;$i++){ else{ $Web_To_Lead_Form_html .= "$field_label + @@ -56,7 +56,7 @@
{MOD.LBL_CAMPAIGN_TYPE} - @@ -75,6 +75,17 @@
+ diff --git a/modules/Campaigns/ProcessBouncedEmails.php b/modules/Campaigns/ProcessBouncedEmails.php index 42bbcee2..ebdbabe4 100644 --- a/modules/Campaigns/ProcessBouncedEmails.php +++ b/modules/Campaigns/ProcessBouncedEmails.php @@ -142,6 +142,12 @@ function campaign_process_bounced_emails(&$email, &$email_header) global $sugar_config; $emailFromAddress = $email_header->fromaddress; $email_description = $email->raw_source; + + //if raw_source is empty, try using the description instead + if (empty($email_description)){ + $email_description = $email->description; + } + $email_description .= retrieveErrorReportAttachment($email); if (preg_match('/MAILER-DAEMON|POSTMASTER/i',$emailFromAddress)) @@ -195,7 +201,7 @@ function campaign_process_bounced_emails(&$email, &$email_header) { //todo mark the email address as invalid. search for prospects/leads/contact associated //with this email address and set the invalid_email flag... also make email available. - $GLOBALS['log']->info("Warning: Invalid identifier for campaign log $identifier"); + $GLOBALS['log']->info("Warning: Empty identifier for campaign log."); return FALSE; } } diff --git a/modules/Campaigns/QueueCampaign.php b/modules/Campaigns/QueueCampaign.php index 0b3b0c44..3cc5c34d 100644 --- a/modules/Campaigns/QueueCampaign.php +++ b/modules/Campaigns/QueueCampaign.php @@ -76,10 +76,7 @@ if (isset($_REQUEST['from_wiz'])) { if (!empty($campaign->status) && $campaign->status == 'sending') { $err_messages[]=$mod_strings['ERR_SENDING_NOW']; } -if ($campaign->db->dbType=='oci8') { -} else { - $current_date= "'".$timedate->nowDb()."'"; -} +$current_date = $campaign->db->now(); //start scheduling now..... foreach ($_POST['mass'] as $message_id) { @@ -105,15 +102,12 @@ foreach ($_POST['mass'] as $message_id) { global $timedate; $mergedvalue=$timedate->merge_date_time($marketing->date_start,$marketing->time_start); - - if ($campaign->db->dbType=='oci8') { + if($test) { + $send_date_time = $timedate->getNow()->get("-60 seconds")->asDb(); } else { - if ($test) { - $send_date_time="'".$timedate->getNow()->get("-60 seconds")->asDb() ."'"; - } else { - $send_date_time= "'".$timedate->to_db($mergedvalue)."'"; - } + $send_date_time = $timedate->to_db($mergedvalue); } + $send_date_time = $campaign->db->convert($campaign->db->quoted($send_date_time), "datetime"); //find all prospect lists associated with this email marketing message. if ($marketing->all_prospect_lists == 1) { @@ -140,58 +134,39 @@ foreach ($_POST['mass'] as $message_id) { } $result=$campaign->db->query($query); while (($row=$campaign->db->fetchByAssoc($result))!=null ) { - - $prospect_list_id=$row['prospect_list_id']; //delete all messages for the current campaign and current email marketing message. $delete_emailman_query="delete from emailman where campaign_id='{$campaign->id}' and marketing_id='{$message_id}' and list_id='{$prospect_list_id}'"; $campaign->db->query($delete_emailman_query); + $auto = $campaign->db->getAutoIncrementSQL("emailman", "id"); $insert_query= "INSERT INTO emailman (date_entered, user_id, campaign_id, marketing_id,list_id, related_id, related_type, send_date_time"; - if ($campaign->db->dbType=='oci8') { - } + $insert_query.= empty($auto)?"":",id"; $insert_query.=')'; - $insert_query.= " SELECT $current_date,'{$current_user->id}',plc.campaign_id,'{$message_id}',plp.prospect_list_id, plp.related_id, plp.related_type,{$send_date_time} "; - if ($campaign->db->dbType=='oci8') { - } - $insert_query.= "FROM prospect_lists_prospects plp "; + $insert_query.= " SELECT $current_date,'{$current_user->id}',plc.campaign_id,'{$message_id}',plp.prospect_list_id, plp.related_id, plp.related_type,{$send_date_time}"; + $insert_query.= empty($auto)?"":",$auto"; + $insert_query.= " FROM prospect_lists_prospects plp "; $insert_query.= "INNER JOIN prospect_list_campaigns plc ON plc.prospect_list_id = plp.prospect_list_id "; $insert_query.= "WHERE plp.prospect_list_id = '{$prospect_list_id}' "; $insert_query.= "AND plp.deleted=0 "; $insert_query.= "AND plc.deleted=0 "; $insert_query.= "AND plc.campaign_id='{$campaign->id}'"; - if ($campaign->db->dbType=='oci8') { - } $campaign->db->query($insert_query); } } //delete all entries from the emailman table that belong to the exempt list. +//TODO:SM: may want to move this to query clause above instead if (!$test) { - //id based exempt list treatment. - if ($campaign->db->dbType =='mysql') { - - $delete_query = "DELETE emailman.* FROM emailman "; - $delete_query.= "INNER JOIN prospect_lists_prospects plp on plp.related_id = emailman.related_id and plp.related_type = emailman.related_type "; - $delete_query.= "INNER JOIN prospect_lists pl ON pl.id = plp.prospect_list_id "; - $delete_query .= "INNER JOIN prospect_list_campaigns plc on plp.prospect_list_id = plc.prospect_list_id "; - $delete_query.= "WHERE plp.deleted=0 "; - $delete_query.= "AND plc.campaign_id = '{$campaign->id}'"; - $delete_query.= "AND pl.list_type = 'exempt' "; - $delete_query.= "AND emailman.campaign_id='{$campaign->id}'"; - $campaign->db->query($delete_query); - - }elseif($campaign->db->dbType =='mssql'){ - $delete_query = "DELETE FROM emailman "; - $delete_query .= "WHERE emailman.campaign_id='".$campaign->id."' "; - $delete_query .= "and emailman.related_id in "; - $delete_query .= "(select prospect_lists_prospects.related_id from prospect_lists_prospects where prospect_lists_prospects.deleted = 0 and prospect_lists_prospects.prospect_list_id in (select prospect_lists.id from prospect_lists where prospect_lists.list_type = 'exempt' and prospect_lists_prospects.prospect_list_id in(select prospect_list_campaigns.prospect_list_id from prospect_list_campaigns where prospect_list_campaigns.campaign_id = '".$campaign->id."'))) "; - $delete_query .= "and emailman.related_type in "; - $delete_query .= "(select prospect_lists_prospects.related_type from prospect_lists_prospects where prospect_lists_prospects.deleted = 0 and prospect_lists_prospects.prospect_list_id in (select prospect_lists.id from prospect_lists where prospect_lists.list_type = 'exempt' and prospect_lists_prospects.prospect_list_id in(select prospect_list_campaigns.prospect_list_id from prospect_list_campaigns where prospect_list_campaigns.campaign_id = '".$campaign->id."'))) "; - $campaign->db->query($delete_query); - } + $delete_query = "DELETE FROM emailman WHERE emailman.campaign_id='{$campaign->id}' AND (emailman.related_id, emailman.related_type) IN + (SELECT plp.related_id, plp.related_type FROM prospect_lists_prospects plp + INNER JOIN prospect_lists pl ON pl.id = plp.prospect_list_id + INNER JOIN prospect_list_campaigns plc ON plp.prospect_list_id = plc.prospect_list_id + WHERE plp.deleted = 0 AND plc.deleted = 0 AND pl.deleted = 0 AND pl.list_type = 'exempt' AND plc.campaign_id = '{$campaign->id}') + "; + $campaign->db->query($delete_query); } $return_module=isset($_REQUEST['return_module'])?$_REQUEST['return_module']:'Campaigns'; diff --git a/modules/Campaigns/RemoveMe.php b/modules/Campaigns/RemoveMe.php index 4d4bce39..5b6dbde2 100644 --- a/modules/Campaigns/RemoveMe.php +++ b/modules/Campaigns/RemoveMe.php @@ -44,12 +44,19 @@ if (!empty($_REQUEST['remove'])) clean_string($_REQUEST['remove'], "STANDARD"); if (!empty($_REQUEST['from'])) clean_string($_REQUEST['from'], "STANDARD"); if(!empty($_REQUEST['identifier'])) { - $keys=log_campaign_activity($_REQUEST['identifier'],'removed'); + global $beanFiles, $beanList, $current_user; + + //user is most likely not defined, retrieve admin user so that team queries are bypassed + if(empty($current_user) || empty($current_user->id)){ + $current_user = new User(); + $current_user->retrieve('1'); + } + + $keys=log_campaign_activity($_REQUEST['identifier'],'removed'); global $current_language; $mod_strings = return_module_language($current_language, 'Campaigns'); - global $beanFiles, $beanList; if (!empty($keys) && $keys['target_type'] == 'Users'){ //Users cannot opt out of receiving emails, print out warning message. echo $mod_strings['LBL_USERS_CANNOT_OPTOUT']; diff --git a/modules/Campaigns/RoiDetailView.php b/modules/Campaigns/RoiDetailView.php index ff40d139..b8f91409 100644 --- a/modules/Campaigns/RoiDetailView.php +++ b/modules/Campaigns/RoiDetailView.php @@ -179,7 +179,8 @@ $campaign_id = $focus->id; global $current_user; if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($_SESSION['editinplace'])){ - $smarty->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $smarty->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'", null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); + } $detailView->processListNavigation($xtpl, "CAMPAIGN", $offset, $focus->is_AuditEnabled()); diff --git a/modules/Campaigns/Subscriptions.tpl b/modules/Campaigns/Subscriptions.tpl index d047f298..b440ff44 100644 --- a/modules/Campaigns/Subscriptions.tpl +++ b/modules/Campaigns/Subscriptions.tpl @@ -39,7 +39,7 @@ - +
@@ -78,7 +78,7 @@ diff --git a/modules/Campaigns/TrackDetailView.php b/modules/Campaigns/TrackDetailView.php index 2f5eed6b..b9317948 100644 --- a/modules/Campaigns/TrackDetailView.php +++ b/modules/Campaigns/TrackDetailView.php @@ -80,13 +80,13 @@ if(isset($focus->campaign_type) && $focus->campaign_type == "NewsLetter"){ echo getClassicModuleTitle($mod_strings['LBL_MODULE_NAME'], array($mod_strings['LBL_NEWSLETTER'],$focus->name), true); } else{ echo getClassicModuleTitle($mod_strings['LBL_MODULE_NAME'], array($mod_strings['LBL_MODULE_NAME'],$focus->name), true); -} - +} + $GLOBALS['log']->info("Campaign detail view"); $smarty = new Sugar_Smarty(); $smarty->assign("MOD", $mod_strings); $smarty->assign("APP", $app_strings); - + $smarty->assign("GRIDLINE", $gridline); $smarty->assign("PRINT_URL", "index.php?".$GLOBALS['request_string']); $smarty->assign("ID", $focus->id); @@ -96,29 +96,29 @@ if(isset($focus->campaign_type) && $focus->campaign_type == "NewsLetter"){ $smarty->assign("TYPE", $app_list_strings['campaign_type_dom'][$focus->campaign_type]); $smarty->assign("START_DATE", $focus->start_date); $smarty->assign("END_DATE", $focus->end_date); - + $smarty->assign("BUDGET", $focus->budget); $smarty->assign("ACTUAL_COST", $focus->actual_cost); $smarty->assign("EXPECTED_COST", $focus->expected_cost); $smarty->assign("EXPECTED_REVENUE", $focus->expected_revenue); - - + + $smarty->assign("OBJECTIVE", nl2br($focus->objective)); $smarty->assign("CONTENT", nl2br($focus->content)); $smarty->assign("DATE_MODIFIED", $focus->date_modified); $smarty->assign("DATE_ENTERED", $focus->date_entered); - + $smarty->assign("CREATED_BY", $focus->created_by_name); $smarty->assign("MODIFIED_BY", $focus->modified_by_name); $smarty->assign("TRACKER_URL", $sugar_config['site_url'] . '/campaign_tracker.php?track=' . $focus->tracker_key); $smarty->assign("TRACKER_COUNT", intval($focus->tracker_count)); $smarty->assign("TRACKER_TEXT", $focus->tracker_text); $smarty->assign("REFER_URL", $focus->refer_url); - + if(isset($focus->campaign_type) && $focus->campaign_type == "Email" || $focus->campaign_type == "NewsLetter") { $smarty->assign("TRACK_DELETE_BUTTON",""); } - + $currency = new Currency(); if(isset($focus->currency_id) && !empty($focus->currency_id)) { @@ -127,14 +127,13 @@ if(isset($focus->campaign_type) && $focus->campaign_type == "NewsLetter"){ $smarty->assign("CURRENCY", $currency->iso4217 .' '.$currency->symbol ); }else $smarty->assign("CURRENCY", $currency->getDefaultISO4217() .' '.$currency->getDefaultCurrencySymbol() ); }else{ - + $smarty->assign("CURRENCY", $currency->getDefaultISO4217() .' '.$currency->getDefaultCurrencySymbol() ); - + } global $current_user; if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($_SESSION['editinplace'])){ - - $smarty->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $smarty->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); } global $xtpl; @@ -143,20 +142,20 @@ if(isset($focus->campaign_type) && $focus->campaign_type == "NewsLetter"){ $detailView->processListNavigation($xtpl, "CAMPAIGN", $offset, $focus->is_AuditEnabled()); // adding custom fields: require_once('modules/DynamicFields/templates/Files/DetailView.php'); - + //if this is a newsletter, we need to build dropdown $selected_marketing_id = ''; if(isset($focus->campaign_type)){ //we need to build the dropdown of related marketing values - $options_str = ""; $latest_marketing_id = ''; if(isset($_REQUEST['mkt_id'])) $selected_marketing_id = $_REQUEST['mkt_id']; - + $options_str .= ''; //query for all email marketing records related to this campaign $latest_marketing_query = "select id, name, date_modified from email_marketing where campaign_id = '$focus->id' order by date_modified desc"; - + //build string with value(s) retrieved $result =$focus->db->query($latest_marketing_query); if ($row = $focus->db->fetchByAssoc($result)){ @@ -165,7 +164,7 @@ if(isset($focus->campaign_type) && $focus->campaign_type == "NewsLetter"){ if($focus->campaign_type == 'NewsLetter') { $latest_marketing_id = $row['id']; } - + //fill in first option value $options_str .= ''; // if the marketing is not empty, but not same as selected marketing id, then.. - //.. do not set this option to render as "selected" + //.. do not set this option to render as "selected" }else{ $options_str .='>'. $row['name'] .''; } @@ -189,10 +188,10 @@ if(isset($focus->campaign_type) && $focus->campaign_type == "NewsLetter"){ $options_str .=' selected>'. $row['name'] .''; }else{ $options_str .=' >'. $row['name'] .''; - } + } } $options_str .=""; - //populate the dropdown + //populate the dropdown $smarty->assign("FILTER_LABEL", $mod_strings['LBL_FILTER_CHART_BY']); $smarty->assign("MKT_DROP_DOWN",$options_str); } @@ -205,13 +204,13 @@ $cache_file_name_roi = $current_user->getUserPrivGuid()."_campaign_response_b $chart= new campaign_charts(); //if marketing id has been selected, then set "latest_marketing_id" to the selected value - //latest marketing id will be passed in to filter the charts and subpanels - + //latest marketing id will be passed in to filter the charts and subpanels + if(!empty($selected_marketing_id)){$latest_marketing_id = $selected_marketing_id;} if(empty($latest_marketing_id) || $latest_marketing_id === 'all'){ - $smarty->assign("MY_CHART", $chart->campaign_response_by_activity_type($app_list_strings['campainglog_activity_type_dom'],$app_list_strings['campainglog_target_type_dom'],$focus->id,$sugar_config['tmp_dir'].$cache_file_name,true)); - }else{ - $smarty->assign("MY_CHART", $chart->campaign_response_by_activity_type($app_list_strings['campainglog_activity_type_dom'],$app_list_strings['campainglog_target_type_dom'],$focus->id,$sugar_config['tmp_dir'].$cache_file_name,true,$latest_marketing_id)); + $smarty->assign("MY_CHART", $chart->campaign_response_by_activity_type($app_list_strings['campainglog_activity_type_dom'],$app_list_strings['campainglog_target_type_dom'],$focus->id,sugar_cached("xml/$cache_file_name"),true)); + }else{ + $smarty->assign("MY_CHART", $chart->campaign_response_by_activity_type($app_list_strings['campainglog_activity_type_dom'],$app_list_strings['campainglog_target_type_dom'],$focus->id,sugar_cached("xml/$cache_file_name"),true,$latest_marketing_id)); } //end chart @@ -233,39 +232,39 @@ $subpanel = new SubPanelTiles($focus, 'Campaigns'); //get array of layout defs $layoutDefsArr= $subpanel->subpanel_definitions->layout_defs; - //iterate through layout defs for processing of subpanels. If a marketing Id is specified, then we need to... + //iterate through layout defs for processing of subpanels. If a marketing Id is specified, then we need to... //.. filter the subpanels by it so they match the chart rendered in code above. foreach($layoutDefsArr as $subpanels_name => $subpanels){ - //process each subpanel definition + //process each subpanel definition foreach($subpanels as $subpane_key => $subpane){ - - //see if "function_parameters" key exists in subpanel properties array - if (isset($subpane['function_parameters'])){ + + //see if "function_parameters" key exists in subpanel properties array + if (isset($subpane['function_parameters'])){ //if a function_parameters property key exists, then process further $functionParamsArr = $subpane['function_parameters'];//$panelProperty; - //Check the array of function parameters and see if + //Check the array of function parameters and see if //one exists for market value id. if (isset($functionParamsArr['EMAIL_MARKETING_ID_VALUE'])){ //We found the property, lets fill in the marketing id value... //.. into the subpanel object, using the keys of the array that.. //.. we used to get to thi property - $subpanel->subpanel_definitions->layout_defs[$subpanels_name][$subpane_key]['function_parameters']['EMAIL_MARKETING_ID_VALUE'] = $latest_marketing_id; + $subpanel->subpanel_definitions->layout_defs[$subpanels_name][$subpane_key]['function_parameters']['EMAIL_MARKETING_ID_VALUE'] = $latest_marketing_id; } }//end if (isset($subpane['function_parameters'])){ }//end foreach($subpanels as $subpane_key => $subpane){ - + }//_pp($subpanel->subpanel_definitions->layout_defs); }//end else $alltabs=$subpanel->subpanel_definitions->get_available_tabs(); if (!empty($alltabs)) { - + foreach ($alltabs as $name) { if ($name == 'prospectlists' || $name=='emailmarketing' || $name == 'tracked_urls') { - $subpanel->subpanel_definitions->exclude_tab($name); - } + $subpanel->subpanel_definitions->exclude_tab($name); + } } } echo $subpanel->display(); diff --git a/modules/Campaigns/TrackDetailView.tpl b/modules/Campaigns/TrackDetailView.tpl index f9daec91..284d4f76 100644 --- a/modules/Campaigns/TrackDetailView.tpl +++ b/modules/Campaigns/TrackDetailView.tpl @@ -168,6 +168,5 @@ var toggle = 0; - +{sugar_getscript file="modules/Campaigns/DetailView.js"} {$SUBPANEL} - \ No newline at end of file diff --git a/modules/Campaigns/WebToLeadCapture.php b/modules/Campaigns/WebToLeadCapture.php index 10b1394b..8f1fb6e6 100644 --- a/modules/Campaigns/WebToLeadCapture.php +++ b/modules/Campaigns/WebToLeadCapture.php @@ -170,15 +170,16 @@ if (isset($_POST['campaign_id']) && !empty($_POST['campaign_id'])) { } $redirect_url = $redirect_url.$query_string; - + + // Check if the headers have been sent, or if the redirect url is greater than 2083 characters (IE max URL length) // and use a javascript form submission if that is the case. if(headers_sent() || strlen($redirect_url) > 2083){ - echo 'SugarCRM'; + echo 'SugarCRM'; echo ''; foreach($_POST as $param => $value) { - if($param != 'redirect_url' || $param != 'submit') { + if($param != 'redirect_url' ||$param != 'submit') { echo ''; } } @@ -207,7 +208,7 @@ if (isset($_POST['campaign_id']) && !empty($_POST['campaign_id'])) { if (!empty($_POST['redirect'])) { if(headers_sent()){ - echo 'SugarCRM'; + echo 'SugarCRM'; echo ''; echo ''; echo ''; diff --git a/modules/Campaigns/WebToLeadCreation.html b/modules/Campaigns/WebToLeadCreation.html index ec5f2fb0..aa1d6fe2 100644 --- a/modules/Campaigns/WebToLeadCreation.html +++ b/modules/Campaigns/WebToLeadCreation.html @@ -39,8 +39,8 @@ ********************************************************************************/ --> - - + + {JAVASCRIPT} - - + +
{$MOD.LBL_ALREADY_SUBSCRIBED_HEADER} {$MOD.LBL_UNSUBSCRIBED_HEADER} -Help
diff --git a/modules/Campaigns/WebToLeadForm.html b/modules/Campaigns/WebToLeadForm.html index 2cbc339e..c657bb58 100644 --- a/modules/Campaigns/WebToLeadForm.html +++ b/modules/Campaigns/WebToLeadForm.html @@ -45,9 +45,9 @@ {JAVASCRIPT} - - - + + + - +{sugar_getscript file="modules/Campaigns/wizard.js"} +{sugar_getscript file="modules/InboundEmail/InboundEmail.js"} {$WIZ_JAVASCRIPT} {$DIV_JAVASCRIPT} {$JAVASCRIPT} - \ No newline at end of file diff --git a/modules/Campaigns/WizardHome.php b/modules/Campaigns/WizardHome.php index 9e51c79f..5a291333 100644 --- a/modules/Campaigns/WizardHome.php +++ b/modules/Campaigns/WizardHome.php @@ -396,9 +396,13 @@ function create_target_summary ($focus){ $pl_tbl .= ""; $pl_tbl .= ""; $pl_tbl .= ""; + $pl_tbl .= SugarThemeRegistry::current()->getImage('view_inline', 'border=0', null, null, ".gif", $mod_strings['LBL_VIEW_INLINE']).""; + + } } }else{ diff --git a/modules/Campaigns/WizardMarketing.html b/modules/Campaigns/WizardMarketing.html index 8edb2868..4c64c82b 100644 --- a/modules/Campaigns/WizardMarketing.html +++ b/modules/Campaigns/WizardMarketing.html @@ -87,13 +87,13 @@
$type".$pl_focus->get_entry_count().""; - $pl_tbl .= " "; + $pl_tbl .= SugarThemeRegistry::current()->getImage('edit_inline', 'border=0', null, null, ".gif", $mod_strings['LBL_EDIT_INLINE']) . " "; + + $pl_tbl .= ""; - $pl_tbl .= "
- - - - - - - + + + + + + +
{$MOD.LBL_WIZARD_MARKETING_MESSAGE}
 
 
{$MOD.LBL_MRKT_NAME} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_MRKT_NAME} {$APP.LBL_REQUIRED_SYMBOL} {$MOD.LBL_STATUS_TEXT} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_STATUS_TEXT} {$APP.LBL_REQUIRED_SYMBOL}
{$MOD.LBL_FROM_MAILBOX_NAME}{$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_FROM_MAILBOX_NAME}{$APP.LBL_REQUIRED_SYMBOL} {$MOD.LBL_START_DATE_TIME} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_START_DATE_TIME} {$APP.LBL_REQUIRED_SYMBOL}
{$CALENDAR_DATEFORMAT}  {$TIME_MERIDIEM}
{$USER_DATEFORMAT}{$TIME_FORMAT}
{$MOD.LBL_FROM_NAME} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_FROM_NAME} {$APP.LBL_REQUIRED_SYMBOL} {$MOD.LBL_FROM_ADDR} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_FROM_ADDR} {$APP.LBL_REQUIRED_SYMBOL}
{$MOD.LBL_REPLY_NAME}{$MOD.LBL_REPLY_NAME} {$MOD.LBL_REPLY_ADDR}{$MOD.LBL_REPLY_ADDR}
{$MOD.LBL_MESSAGE_FOR} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_ALL_PROSPECT_LISTS}{$MOD.LBL_TEMPLATE} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_MESSAGE_FOR} {$APP.LBL_REQUIRED_SYMBOL}{$MOD.LBL_TEMPLATE} {$APP.LBL_REQUIRED_SYMBOL} - +     @@ -152,9 +152,9 @@
      
@@ -324,14 +324,14 @@ {$MOD.LBL_WIZARD_SENDMAIL_MESSAGE}
  - {$MOD.LBL_SAVE_EXIT_BUTTON_LABEL} + {$MOD.LBL_SAVE_EXIT_BUTTON_LABEL}  
{$WARNING_MESSAGE}
-  
{$MOD.LBL_SEND_AS_TEST}
+  
{$MOD.LBL_SEND_AS_TEST}
-  
{$MOD.LBL_SEND_EMAIL}
+  
{$MOD.LBL_SEND_EMAIL}
@@ -368,8 +368,8 @@ function determine_back(){
- - +{sugar_getscript file="modules/Campaigns/wizard.js"} +{sugar_getscript file="cache/include/javascript/sugar_grp_overlib.js"} {$WIZ_JAVASCRIPT} {$DIV_JAVASCRIPT} diff --git a/modules/Campaigns/WizardNewsletter.html b/modules/Campaigns/WizardNewsletter.html index 0eb1eee4..7f919244 100644 --- a/modules/Campaigns/WizardNewsletter.html +++ b/modules/Campaigns/WizardNewsletter.html @@ -50,7 +50,7 @@ - + @@ -94,8 +94,8 @@ - - +{sugar_getscript file="modules/Campaigns/wizard.js"} +{sugar_getscript file="cache/include/javascript/sugar_grp_overlib.js"} {$WIZ_JAVASCRIPT} diff --git a/modules/Campaigns/WizardNewsletter.php b/modules/Campaigns/WizardNewsletter.php index c94084f4..cbd44df6 100644 --- a/modules/Campaigns/WizardNewsletter.php +++ b/modules/Campaigns/WizardNewsletter.php @@ -206,7 +206,8 @@ if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($ if(!empty($_REQUEST['record'])){ $record = $_REQUEST['record']; } - $ss->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $ss->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); + } echo $currency->getJavascript(); @@ -297,7 +298,9 @@ global $odd_bg, $even_bg, $hilite_bg; $trkr_html .= ""; $trkr_html .= ""; $trkr_html .= "
id."'); \" > "; - $trkr_html .= "rem". $mod_strings['LBL_REMOVE']."
"; + $trkr_html .= SugarThemeRegistry::current()->getImage('delete_inline', "border='0' align='absmiddle'", 12, 12, ".gif", $mod_strings['LBL_DELETE'])."
"; + + } $trkr_count =$trkr_count+1; @@ -439,7 +442,9 @@ if(count($prospect_lists)>0){ $trgt_html .= "".$app_list_strings['prospect_list_type_dom'][$pl_focus->list_type]; $trgt_html .= ""; $trgt_html .= "id."'); \" > "; - $trgt_html .= "rem". $mod_strings['LBL_REMOVE']."
"; + $trgt_html .= SugarThemeRegistry::current()->getImage('delete_inline', "border='0' align='absmiddle'", 12, 12, ".gif", $mod_string['LBL_DELETE'])."
"; + + $trgt_count =$trgt_count +1; diff --git a/modules/Campaigns/language/en_us.lang.php b/modules/Campaigns/language/en_us.lang.php index 7f437436..8c01d6d5 100644 --- a/modules/Campaigns/language/en_us.lang.php +++ b/modules/Campaigns/language/en_us.lang.php @@ -424,6 +424,14 @@ $mod_strings = array ( 'LBL_MONTH' => "Month", 'LBL_YEAR' => "Year", 'LBL_DAY' => "Day", + 'LBL_EDIT_LAYOUT' => 'Edit Layout' /*for 508 compliance fix*/, + 'LBL_INVALID' => 'Invalid' /*for 508 compliance fix*/, + 'LBL_VALID' => 'Valid' /*for 508 compliance fix*/, + 'LBL_ALERT' => 'Alert' /*for 508 compliance fix*/, + 'LBL_EDIT_INLINE' => 'Edit' /*for 508 compliance fix*/, + 'LBL_DELETE_INLINE' => 'Delete' /*for 508 compliance fix*/, + 'LBL_DELETE' => 'Remove' /*for 508 compliance fix*/, + 'LBL_VIEW_INLINE' => 'View', ); diff --git a/modules/Campaigns/metadata/listviewdefs.php b/modules/Campaigns/metadata/listviewdefs.php index 9413894a..ad7f8282 100644 --- a/modules/Campaigns/metadata/listviewdefs.php +++ b/modules/Campaigns/metadata/listviewdefs.php @@ -68,7 +68,7 @@ $listViewDefs['Campaigns'] = array( 'width' => '1', 'label' => ' ', 'link' => true, - 'customCode' => ' ', + 'customCode' => ' {$TRACK_VIEW_ALT_TEXT} ', 'default' => true, 'studio' => false, 'nowrap' => true, @@ -77,7 +77,7 @@ $listViewDefs['Campaigns'] = array( 'width' => '1', 'label' => ' ', 'link' => true, - 'customCode' => ' ', + 'customCode' => ' {$LAUNCH_WIZ_ALT_TEXT} ', 'default' => true, 'studio' => false, 'nowrap' => true, diff --git a/modules/Campaigns/tpls/WizardCampaignBudget.tpl b/modules/Campaigns/tpls/WizardCampaignBudget.tpl index 9ffe2be3..62cce340 100644 --- a/modules/Campaigns/tpls/WizardCampaignBudget.tpl +++ b/modules/Campaigns/tpls/WizardCampaignBudget.tpl @@ -46,36 +46,36 @@ {$MOD.LBL_WIZARD_BUDGET_MESSAGE}
    - {$MOD.LBL_CAMPAIGN_BUDGET} - - {$MOD.LBL_CAMPAIGN_ACTUAL_COST} - + {$MOD.LBL_CAMPAIGN_BUDGET} + + {$MOD.LBL_CAMPAIGN_ACTUAL_COST} + - {$MOD.LBL_CAMPAIGN_EXPECTED_REVENUE} - - {$MOD.LBL_CAMPAIGN_EXPECTED_COST} - + {$MOD.LBL_CAMPAIGN_EXPECTED_REVENUE} + + {$MOD.LBL_CAMPAIGN_EXPECTED_COST} + - {$MOD.LBL_CURRENCY} - - {$MOD.LBL_CAMPAIGN_IMPRESSIONS} - + {$MOD.LBL_CURRENCY} + + {$MOD.LBL_CAMPAIGN_IMPRESSIONS} + -   +     -   +     {$MOD.LBL_CAMPAIGN_OBJECTIVE} - + -   +     -   +     diff --git a/modules/Campaigns/tpls/WizardCampaignHeader.tpl b/modules/Campaigns/tpls/WizardCampaignHeader.tpl index 71b11b65..9e3ec414 100644 --- a/modules/Campaigns/tpls/WizardCampaignHeader.tpl +++ b/modules/Campaigns/tpls/WizardCampaignHeader.tpl @@ -51,39 +51,39 @@ {$MOD.LBL_WIZARD_HEADER_MESSAGE}
    - {$MOD.LBL_NAME} {$APP.LBL_REQUIRED_SYMBOL} - - {$APP.LBL_ASSIGNED_TO} - - {$MOD.LBL_NAME} {$APP.LBL_REQUIRED_SYMBOL} + + {$APP.LBL_ASSIGNED_TO} + + - {$MOD.LBL_CAMPAIGN_STATUS} {$APP.LBL_REQUIRED_SYMBOL} - + {$MOD.LBL_CAMPAIGN_STATUS} {$APP.LBL_REQUIRED_SYMBOL} + - {$MOD.LBL_CAMPAIGN_START_DATE} - {$APP.LBL_ENTER_DATE} {$USER_DATEFORMAT} - {$MOD.LBL_CAMPAIGN_TYPE} + {$MOD.LBL_CAMPAIGN_START_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$APP.LBL_ENTER_DATE other_attributes='align="absmiddle" id="start_date_trigger" '} {$USER_DATEFORMAT} + {$MOD.LBL_CAMPAIGN_TYPE} <{$SHOULD_TYPE_BE_DISABLED} id='campaign_type' title='{$MOD.LBL_CAMPAIGN_TYPE}' name='wiz_step1_campaign_type' >{$CAMPAIGN_TYPE_OPTIONS} - {$MOD.LBL_CAMPAIGN_END_DATE} {$APP.LBL_REQUIRED_SYMBOL} - {$APP.LBL_ENTER_DATE} {$USER_DATEFORMAT} - {$FREQUENCY_LABEL} - <{$HIDE_FREQUENCY_IF_NEWSLETTER} tabindex='1' id='frequency' name='wiz_step1_frequency' title='{$MOD.LBL_CAMPAIGN_FREQUENCY}'>{$FREQ_OPTIONS} + {$MOD.LBL_CAMPAIGN_END_DATE} {$APP.LBL_REQUIRED_SYMBOL} + {sugar_getimage name="jscalendar" ext=".gif" alt=$APP.LBL_ENTER_DATE other_attributes='align="absmiddle" id="end_date_trigger" '} {$USER_DATEFORMAT} + {$FREQUENCY_LABEL} + <{$HIDE_FREQUENCY_IF_NEWSLETTER} id='frequency' name='wiz_step1_frequency' title='{$MOD.LBL_CAMPAIGN_FREQUENCY}'>{$FREQ_OPTIONS} -   -   -   +   +   +     {$MOD.LBL_CAMPAIGN_CONTENT} - +   diff --git a/modules/Campaigns/tpls/WizardCampaignTargetList.tpl b/modules/Campaigns/tpls/WizardCampaignTargetList.tpl index 4dc62988..04117ee3 100644 --- a/modules/Campaigns/tpls/WizardCampaignTargetList.tpl +++ b/modules/Campaigns/tpls/WizardCampaignTargetList.tpl @@ -43,47 +43,47 @@

{$MOD.LBL_WIZ_NEWSLETTER_TITLE_STEP4}

- {$MOD.LBL_WIZARD_SUBSCRIPTION_MESSAGE}
+ {$MOD.LBL_WIZARD_SUBSCRIPTION_MESSAGE}
-   +   - + Help {$MOD.LBL_SUBSCRIPTION_LIST_NAME} {$MOD.LBL_DEFAULT_LOCATION}
{$MOD.LBL_CUSTOM_LOCATION} - + -   - + Help {$MOD.LBL_UNSUBSCRIPTION_LIST_NAME} {$MOD.LBL_DEFAULT_LOCATION}
{$MOD.LBL_CUSTOM_LOCATION} - + - - +   - - + + Help {$MOD.LBL_TEST_LIST_NAME} {$MOD.LBL_DEFAULT_LOCATION}
@@ -93,14 +93,14 @@ -
-     -   +   +     diff --git a/modules/Campaigns/tpls/WizardCampaignTargetListForNonNewsLetter.tpl b/modules/Campaigns/tpls/WizardCampaignTargetListForNonNewsLetter.tpl index b878d579..ca44ca62 100644 --- a/modules/Campaigns/tpls/WizardCampaignTargetListForNonNewsLetter.tpl +++ b/modules/Campaigns/tpls/WizardCampaignTargetListForNonNewsLetter.tpl @@ -52,7 +52,7 @@

{$MOD.LBL_TARGET_LISTS}

- {$MOD.LBL_WIZARD_TARGET_MESSAGE1}
+ {$MOD.LBL_WIZARD_TARGET_MESSAGE1}
  @@ -60,22 +60,22 @@ -
-   +     {$MOD.LBL_WIZARD_TARGET_MESSAGE2}
- {$MOD.LBL_TARGET_NAME} - + {$MOD.LBL_TARGET_NAME} + - + {$MOD.LBL_TARGET_TYPE} @@ -92,9 +92,9 @@ {$MOD.LBL_TRACKERS_ADDED} - - - +
{$MOD.LBL_TARGET_NAME}{$MOD.LBL_TARGET_TYPE} 
+ +
{$MOD.LBL_TARGET_NAME}{$MOD.LBL_TARGET_TYPE}   
@@ -154,7 +154,8 @@ {/literal} //display the html - var trgt_html = "
"+trgt_name_html+""+trgt_type_html+""+trgt_id_html+" rem{$MOD.LBL_REMOVE}
"; + {capture assign='alt_remove' }{sugar_translate label='LBL_DELETE' module='CAMPAIGNS'}{/capture} + var trgt_html = ""; document.getElementById('added_targets').innerHTML = document.getElementById('added_targets').innerHTML + trgt_html; //add values to array in string, seperated by "@@" characters diff --git a/modules/Campaigns/tpls/WizardCampaignTracker.tpl b/modules/Campaigns/tpls/WizardCampaignTracker.tpl index 3873f59e..c9bc4f40 100644 --- a/modules/Campaigns/tpls/WizardCampaignTracker.tpl +++ b/modules/Campaigns/tpls/WizardCampaignTracker.tpl @@ -58,13 +58,13 @@ - - + + - +
{$MOD.LBL_EDIT_TRACKER_NAME}  {$MOD.LBL_EDIT_OPT_OUT_} {$MOD.LBL_EDIT_OPT_OUT_}  
{$MOD.LBL_EDIT_TRACKER_URL} 
 
@@ -74,9 +74,9 @@ - - - + + +
{$MOD.LBL_EDIT_OPT_OUT}{$MOD.LBL_EDIT_TRACKER_NAME}{$MOD.LBL_EDIT_TRACKER_URL}{$MOD.LBL_EDIT_OPT_OUT}{$MOD.LBL_EDIT_TRACKER_NAME}{$MOD.LBL_EDIT_TRACKER_URL}
@@ -125,7 +125,8 @@ var trkr_url_html = ""; var trkr_opt_html = ""; //display the html - var trkr_html = "
"+trkr_opt_html+""+trkr_name_html+""+trkr_url_html+" rem{$MOD.LBL_REMOVE}
"; + {capture assign='alt_remove' }{sugar_translate label='LBL_DELETE' module='CAMPAIGNS'}{/capture} + var trkr_html = ""; document.getElementById('added_trackers').innerHTML = document.getElementById('added_trackers').innerHTML + trkr_html; //add values to array in string, seperated by "@@" characters diff --git a/modules/Campaigns/tpls/WizardHomeStart.tpl b/modules/Campaigns/tpls/WizardHomeStart.tpl index 1a959b03..ebcb06a2 100644 --- a/modules/Campaigns/tpls/WizardHomeStart.tpl +++ b/modules/Campaigns/tpls/WizardHomeStart.tpl @@ -67,19 +67,20 @@
- - - - - +

{$MOD.LBL_CHOOSE_CAMPAIGN_TYPE}

{$MOD.LBL_HOME_START_MESSAGE}

  - {$MOD.LBL_NEWSLETTER}
- {$MOD.LBL_EMAIL}
- {$MOD.LBL_OTHER_TYPE_CAMPAIGN}
+

{$MOD.LBL_CHOOSE_CAMPAIGN_TYPE}

+
{$MOD.LBL_HOME_START_MESSAGE} +

+
+
+
+

+

- + diff --git a/modules/Campaigns/tpls/WizardNewsletter.tpl b/modules/Campaigns/tpls/WizardNewsletter.tpl index 4a274a90..e4bd85da 100644 --- a/modules/Campaigns/tpls/WizardNewsletter.tpl +++ b/modules/Campaigns/tpls/WizardNewsletter.tpl @@ -50,7 +50,7 @@ - +

@@ -68,7 +68,7 @@
- +
@@ -95,9 +95,9 @@ - - - + + + {$WIZ_JAVASCRIPT} diff --git a/modules/Campaigns/utils.php b/modules/Campaigns/utils.php index 25661fac..0c7750c0 100644 --- a/modules/Campaigns/utils.php +++ b/modules/Campaigns/utils.php @@ -49,16 +49,16 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * */ function get_message_scope_dom($campaign_id, $campaign_name,$db=null, $mod_strings=array()) { - + //find prospect list attached to this campaign.. - $query = "SELECT prospect_list_id, prospect_lists.name "; + $query = "SELECT prospect_list_id, prospect_lists.name "; $query .= "FROM prospect_list_campaigns "; $query .= "INNER join prospect_lists on prospect_lists.id = prospect_list_campaigns.prospect_list_id "; - $query .= "WHERE prospect_lists.deleted = 0 "; - $query .= "AND prospect_list_campaigns.deleted=0 "; + $query .= "WHERE prospect_lists.deleted = 0 "; + $query .= "AND prospect_list_campaigns.deleted=0 "; $query .= "AND campaign_id='".$campaign_id."'"; $query.=" and prospect_lists.list_type not like 'exempt%'"; - + if (empty($db)) { $db = DBManagerFactory::getInstance(); } @@ -66,15 +66,15 @@ function get_message_scope_dom($campaign_id, $campaign_name,$db=null, $mod_strin global $current_language; $mod_strings = return_module_language($current_language, 'Campaigns'); } - + //add campaign to the result array. //$return_array[$campaign_id]= $campaign_name . ' (' . $mod_strings['LBL_DEFAULT'] . ')'; - + $result=$db->query($query); while(($row=$db->fetchByAssoc($result))!= null) { $return_array[$row['prospect_list_id']]=$row['name']; } - if (empty($return_array)) $return_array=array(); + if (empty($return_array)) $return_array=array(); else return $return_array; } /** @@ -88,7 +88,7 @@ function get_campaign_mailboxes(&$emails, $get_name=true) { if (!class_exists('InboundEmail')) { require('modules/InboundEmail/InboundEmail.php'); } - $query = "select id,name,stored_options from inbound_email where mailbox_type='bounce' and status='Active' and deleted='0'"; + $query = "select id,name,stored_options from inbound_email where mailbox_type='bounce' and status='Active' and deleted='0'"; $db = DBManagerFactory::getInstance(); $result=$db->query($query); while(($row=$db->fetchByAssoc($result))!= null) { @@ -100,24 +100,24 @@ function get_campaign_mailboxes(&$emails, $get_name=true) { $emails[$row['id']]=InboundEmail::get_stored_options('from_addr','nobody@example.com',$row['stored_options']); } - if (empty($return_array)) $return_array=array(''=>''); + if (empty($return_array)) $return_array=array(''=>''); return $return_array; - + } function get_campaign_mailboxes_with_stored_options() { $ret = array(); - + if(!class_exists('InboundEmail')) { require('modules/InboundEmail/InboundEmail.php'); } - - $q = "SELECT id, name, stored_options FROM inbound_email WHERE mailbox_type='bounce' AND status='Active' AND deleted='0'"; - + + $q = "SELECT id, name, stored_options FROM inbound_email WHERE mailbox_type='bounce' AND status='Active' AND deleted='0'"; + $db = DBManagerFactory::getInstance(); - + $r = $db->query($q); - + while($a = $db->fetchByAssoc($r)) { $ret[$a['id']] = unserialize(base64_decode($a['stored_options'])); } @@ -127,7 +127,7 @@ function get_campaign_mailboxes_with_stored_options() { function log_campaign_activity($identifier, $activity, $update=true, $clicked_url_key=null) { $return_array = array(); - + $db = DBManagerFactory::getInstance(); @@ -136,37 +136,37 @@ function log_campaign_activity($identifier, $activity, $update=true, $clicked_ur if($identifier == 'BANNER' && isset($clicked_url_key) && !empty($clicked_url_key)) { // create md5 encrypted string using the client ip, this will be used for tracker id purposes - $enc_id = 'BNR'.md5($_SERVER['REMOTE_ADDR']); - + $enc_id = 'BNR'.md5($_SERVER['REMOTE_ADDR']); + //default the identifier to ip address $identifier = $enc_id; - + //if user has chosen to not use this mode of id generation, then replace identifier with plain guid. //difference is that guid will generate a new campaign log for EACH CLICK!! //encrypted generation will generate 1 campaign log and update the hit counter for each click if(isset($sugar_config['campaign_banner_id_generation']) && $sugar_config['campaign_banner_id_generation'] != 'md5'){ - $identifier = create_guid(); + $identifier = create_guid(); } - //retrieve campaign log. - $trkr_query = "select * from campaign_log where target_tracker_key='$identifier ' and related_id = '$clicked_url_key'"; + //retrieve campaign log. + $trkr_query = "select * from campaign_log where target_tracker_key='$identifier' and related_id = '$clicked_url_key'"; $current_trkr=$db->query($trkr_query); $row=$db->fetchByAssoc($current_trkr); - //if campaign log is not retrieved (this is a new ip address or we have chosen to create + //if campaign log is not retrieved (this is a new ip address or we have chosen to create //unique entries for each click - if($row==null || empty($row)){ + if($row==null || empty($row)){ + - //retrieve campaign id $trkr_query = "select ct.campaign_id from campaign_trkrs ct, campaigns c where c.id = ct.campaign_id and ct.id = '$clicked_url_key'"; $current_trkr=$db->query($trkr_query); $row=$db->fetchByAssoc($current_trkr); - - + + //create new campaign log with minimal info. Note that we are creating new unique id //as target id, since we do not link banner/web campaigns to any users - + $data['target_id']="'" . create_guid() . "'"; $data['target_type']= "'Prospects'"; $data['id']="'" . create_guid() . "'"; @@ -177,35 +177,35 @@ function log_campaign_activity($identifier, $activity, $update=true, $clicked_ur $data['hits']=1; if (!empty($clicked_url_key)) { $data['related_id']="'".$clicked_url_key."'"; - $data['related_type']="'".'CampaignTrackers'."'"; + $data['related_type']="'".'CampaignTrackers'."'"; } - + //values for return array.. $return_array['target_id']=$data['target_id']; - $return_array['target_type']=$data['target_type']; - + $return_array['target_type']=$data['target_type']; + //create insert query for new campaign log - $insert_query="INSERT into campaign_log (" . implode(",",array_keys($data)) . ")"; - $insert_query.=" VALUES (" . implode(",",array_values($data)) . ")"; + $insert_query="INSERT into campaign_log (" . implode(",",array_keys($data)) . ")"; + $insert_query.=" VALUES (" . implode(",",array_values($data)) . ")"; $db->query($insert_query); }else{ //campaign log already exists, so just set the return array and update hits column $return_array['target_id']= $row['target_id']; - $return_array['target_type']= $row['target_type']; + $return_array['target_type']= $row['target_type']; $query1="update campaign_log set hits=hits+1 where id='{$row['id']}'"; $current=$db->query($query1); - - + + } - //return array and exit + //return array and exit return $return_array; } - - - + + + $query1="select * from campaign_log where target_tracker_key='$identifier' and activity_type='$activity'"; if (!empty($clicked_url_key)) { $query1.=" AND related_id='$clicked_url_key'"; @@ -213,19 +213,19 @@ function log_campaign_activity($identifier, $activity, $update=true, $clicked_ur $current=$db->query($query1); $row=$db->fetchByAssoc($current); - if ($row==null) { + if ($row==null) { $query="select * from campaign_log where target_tracker_key='$identifier' and activity_type='targeted'"; $targeted=$db->query($query); $row=$db->fetchByAssoc($targeted); - + //if activity is removed and target type is users, then a user is trying to opt out - //of emails. This is not possible as Users Table does not have opt out column. + //of emails. This is not possible as Users Table does not have opt out column. if ($row && (strtolower($row['target_type']) == 'users' && $activity == 'removed' )) { $return_array['target_id']= $row['target_id']; - $return_array['target_type']= $row['target_type']; + $return_array['target_type']= $row['target_type']; return $return_array; } - elseif ($row){ + elseif ($row){ $data['id']="'" . create_guid() . "'"; $data['campaign_id']="'" . $row['campaign_id'] . "'"; $data['target_tracker_key']="'" . $identifier . "'"; @@ -238,39 +238,39 @@ function log_campaign_activity($identifier, $activity, $update=true, $clicked_ur $data['hits']=1; if (!empty($clicked_url_key)) { $data['related_id']="'".$clicked_url_key."'"; - $data['related_type']="'".'CampaignTrackers'."'"; + $data['related_type']="'".'CampaignTrackers'."'"; } //values for return array.. $return_array['target_id']=$row['target_id']; - $return_array['target_type']=$row['target_type']; - $insert_query="INSERT into campaign_log (" . implode(",",array_keys($data)) . ")"; - $insert_query.=" VALUES (" . implode(",",array_values($data)) . ")"; + $return_array['target_type']=$row['target_type']; + $insert_query="INSERT into campaign_log (" . implode(",",array_keys($data)) . ")"; + $insert_query.=" VALUES (" . implode(",",array_values($data)) . ")"; $db->query($insert_query); } } else { - + $return_array['target_id']= $row['target_id']; - $return_array['target_type']= $row['target_type']; - + $return_array['target_type']= $row['target_type']; + $query1="update campaign_log set hits=hits+1 where id='{$row['id']}'"; $current=$db->query($query1); - + } //check to see if this is a removal action if ($row && $activity == 'removed' ) { //retrieve campaign and check it's type, we are looking for newsletter Campaigns $query = "SELECT campaigns.* FROM campaigns WHERE campaigns.id = '".$row['campaign_id']."' "; $result = $db->query($query); - if(!empty($result)) + if(!empty($result)) { $c_row = $db->fetchByAssoc($result); - + //if type is newsletter, then add campaign id to return_array for further processing. if(isset($c_row['campaign_type']) && $c_row['campaign_type'] == 'NewsLetter'){ $return_array['campaign_id']=$c_row['id']; } } - } + } return $return_array; } @@ -282,30 +282,27 @@ function log_campaign_activity($identifier, $activity, $update=true, $clicked_ur * @see campaign_log_lead_or_contact_entry() */ function campaign_log_lead_entry($campaign_id, $parent_bean,$child_bean,$activity_type){ - - campaign_log_lead_or_contact_entry($campaign_id, $parent_bean,$child_bean,$activity_type); - } - - - -function campaign_log_lead_or_contact_entry($campaign_id, $parent_bean,$child_bean,$activity_type){ - global $timedate; - + campaign_log_lead_or_contact_entry($campaign_id, $parent_bean,$child_bean,$activity_type); +} - //create campaign tracker id and retrieve related bio bean - $tracker_id = create_guid(); - //create new campaign log record. - $campaign_log = new CampaignLog(); - $campaign_log->campaign_id = $campaign_id; - $campaign_log->target_tracker_key = $tracker_id; - $campaign_log->related_id = $parent_bean->id; - $campaign_log->related_type = $parent_bean->module_dir; - $campaign_log->target_id = $child_bean->id; - $campaign_log->target_type = $child_bean->module_dir; - $campaign_log->activity_date = $timedate->now(); - $campaign_log->activity_type = $activity_type; - //save the campaign log entry - $campaign_log->save(); + +function campaign_log_lead_or_contact_entry($campaign_id, $parent_bean,$child_bean,$activity_type){ + global $timedate; + + //create campaign tracker id and retrieve related bio bean + $tracker_id = create_guid(); + //create new campaign log record. + $campaign_log = new CampaignLog(); + $campaign_log->campaign_id = $campaign_id; + $campaign_log->target_tracker_key = $tracker_id; + $campaign_log->related_id = $parent_bean->id; + $campaign_log->related_type = $parent_bean->module_dir; + $campaign_log->target_id = $child_bean->id; + $campaign_log->target_type = $child_bean->module_dir; + $campaign_log->activity_date = $timedate->now(); + $campaign_log->activity_type = $activity_type; + //save the campaign log entry + $campaign_log->save(); } @@ -313,14 +310,14 @@ function get_campaign_urls($campaign_id) { $return_array=array(); if (!empty($campaign_id)) { - + $db = DBManagerFactory::getInstance(); $query1="select * from campaign_trkrs where campaign_id='$campaign_id' and deleted=0"; $current=$db->query($query1); while (($row=$db->fetchByAssoc($current)) != null) { $return_array['{'.$row['tracker_name'].'}']=$row['tracker_name'] . ' : ' . $row['tracker_url']; - } + } } return $return_array; } @@ -328,23 +325,23 @@ function get_campaign_urls($campaign_id) { /** * Queries for the list */ -function get_subscription_lists_query($focus, $additional_fields = null) { +function get_subscription_lists_query($focus, $additional_fields = null) { //get all prospect lists belonging to Campaigns of type newsletter $all_news_type_pl_query = "select c.name, pl.list_type, plc.campaign_id, plc.prospect_list_id"; - if(is_array($additional_fields) && !empty($additional_fields)) $all_news_type_pl_query .= ', ' . implode(', ', $additional_fields); - $all_news_type_pl_query .= " from prospect_list_campaigns plc , prospect_lists pl, campaigns c "; - - + if(is_array($additional_fields) && !empty($additional_fields)) $all_news_type_pl_query .= ', ' . implode(', ', $additional_fields); + $all_news_type_pl_query .= " from prospect_list_campaigns plc , prospect_lists pl, campaigns c "; + + $all_news_type_pl_query .= "where plc.campaign_id = c.id "; $all_news_type_pl_query .= "and plc.prospect_list_id = pl.id "; $all_news_type_pl_query .= "and c.campaign_type = 'NewsLetter' and pl.deleted = 0 and c.deleted=0 and plc.deleted=0 "; $all_news_type_pl_query .= "and (pl.list_type like 'exempt%' or pl.list_type ='default') "; - + $all_news_type_list =$focus->db->query($all_news_type_pl_query); - //build array of all newsletter campaigns + //build array of all newsletter campaigns $news_type_list_arr = array(); - while ($row = $focus->db->fetchByAssoc($all_news_type_list)){$news_type_list_arr[] = $row;} + while ($row = $focus->db->fetchByAssoc($all_news_type_list)){$news_type_list_arr[] = $row;} //now get all the campaigns that the current user is assigned to $all_plp_current = "select prospect_list_id from prospect_lists_prospects where related_id = '$focus->id' and deleted = 0 "; @@ -353,18 +350,18 @@ function get_subscription_lists_query($focus, $additional_fields = null) { $current_plp =$focus->db->query($all_plp_current ); $current_plp_arr = array(); while ($row = $focus->db->fetchByAssoc($current_plp)){$current_plp_arr[] = $row;} - + return array('current_plp_arr' => $current_plp_arr, 'news_type_list_arr' => $news_type_list_arr); } /* - * This function takes in a bean from a lead, propsect, or contact and returns an array containing - * all subscription lists that the bean is a part of, and all the subscriptions that the bean is not + * This function takes in a bean from a lead, propsect, or contact and returns an array containing + * all subscription lists that the bean is a part of, and all the subscriptions that the bean is not * a part of. The array elements have the key names of "subscribed" and "unsusbscribed". These elements contain an array - * of the corresponding list. In other words, the "subscribed" element holds another array that holds the subscription information. - * + * of the corresponding list. In other words, the "subscribed" element holds another array that holds the subscription information. + * * The subscription information is a concatenated string that holds the prospect list id and the campaign id, seperated by at "@" character. * To parse these information string into something more usable, use the "process subscriptions()" function - * + * * */ function get_subscription_lists($focus, $descriptions = false) { $subs_arr = array(); @@ -374,13 +371,13 @@ function get_subscription_lists($focus, $descriptions = false) { $news_type_list_arr = $results['news_type_list_arr']; $current_plp_arr = $results['current_plp_arr']; - - //For each prospect list of type 'NewsLetter', check to see if current user is already in list, + + //For each prospect list of type 'NewsLetter', check to see if current user is already in list, foreach($news_type_list_arr as $news_list){ $match = 'false'; //perform this check against each prospect list this user belongs to - foreach($current_plp_arr as $current_list_key => $current_list){//echo " new entry from current lists user is subscribed to-------------"; + foreach($current_plp_arr as $current_list_key => $current_list){//echo " new entry from current lists user is subscribed to-------------"; //compare current user list id against newsletter id if ($news_list['prospect_list_id'] == $current_list['prospect_list_id']){ //if id's match, user is subscribed to this list, check to see if this is an exempt list, @@ -396,7 +393,7 @@ function get_subscription_lists($focus, $descriptions = false) { //non exempt list has not been processed yet, so just add to exempt array $unsubs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; } - $match = 'false';//although match is false, this is an exempt array, so + $match = 'false';//although match is false, this is an exempt array, so //it will not be added a second time down below }else{ //this list is not exempt, and user is subscribed, so add to subscribed array, and unset from the unsubs_arr @@ -404,7 +401,7 @@ function get_subscription_lists($focus, $descriptions = false) { $temp = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; if(!array_search($temp,$unsubs_arr)){ $subs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; - $match = 'true'; + $match = 'true'; //unset($unsubs_arr[$news_list['name']]); } } @@ -414,10 +411,10 @@ function get_subscription_lists($focus, $descriptions = false) { } //if this newsletter id never matched a user subscription.. //..then add to available(unsubscribed) NewsLetters if list is not of type exempt - if(($match == 'false') && (strpos($news_list['list_type'], 'exempt') === false)){ - $unsubs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; + if(($match == 'false') && (strpos($news_list['list_type'], 'exempt') === false)){ + $unsubs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; } - + } $return_array['unsubscribed'] = $unsubs_arr; $return_array['subscribed'] = $subs_arr; @@ -432,21 +429,21 @@ function get_subscription_lists_keyed($focus) { $unsubs_arr = array(); $results = get_subscription_lists_query($focus, array('c.content', 'c.frequency')); - + $news_type_list_arr = $results['news_type_list_arr']; $current_plp_arr = $results['current_plp_arr']; - - //For each prospect list of type 'NewsLetter', check to see if current user is already in list, + + //For each prospect list of type 'NewsLetter', check to see if current user is already in list, foreach($news_type_list_arr as $news_list){ $match = false; - + $news_list_data = array('prospect_list_id' => $news_list['prospect_list_id'], 'campaign_id' => $news_list['campaign_id'], 'description' => $news_list['content'], 'frequency' => $news_list['frequency']); //perform this check against each prospect list this user belongs to - foreach($current_plp_arr as $current_list_key => $current_list){//echo " new entry from current lists user is subscribed to-------------"; + foreach($current_plp_arr as $current_list_key => $current_list){//echo " new entry from current lists user is subscribed to-------------"; //compare current user list id against newsletter id if ($news_list['prospect_list_id'] == $current_list['prospect_list_id']){ //if id's match, user is subscribed to this list, check to see if this is an exempt list, @@ -463,14 +460,14 @@ function get_subscription_lists_keyed($focus) { //non exempt list has not been processed yet, so just add to exempt array $unsubs_arr[$news_list['name']] = $news_list_data; } - $match = false;//although match is false, this is an exempt array, so + $match = false;//although match is false, this is an exempt array, so //it will not be added a second time down below }else{ //this list is not exempt, and user is subscribed, so add to subscribed array //as long as this list is not in exempt array if(!array_key_exists($news_list['name'],$unsubs_arr)){ $subs_arr[$news_list['name']] = $news_list_data; - $match = 'true'; + $match = 'true'; } } }else{ @@ -479,14 +476,14 @@ function get_subscription_lists_keyed($focus) { } //if this newsletter id never matched a user subscription.. //..then add to available(unsubscribed) NewsLetters if list is not of type exempt - if(($match == false) && ($news_list['list_type'] != 'exempt')){ - $unsubs_arr[$news_list['name']] = $news_list_data; + if(($match == false) && ($news_list['list_type'] != 'exempt')){ + $unsubs_arr[$news_list['name']] = $news_list_data; } - + } $return_array['unsubscribed'] = $unsubs_arr; - $return_array['subscribed'] = $subs_arr; + $return_array['subscribed'] = $subs_arr; return $return_array; } @@ -494,20 +491,20 @@ function get_subscription_lists_keyed($focus) { /* * This function will take an array of strings that have been created by the "get_subscription_lists()" method - * and parses it into an array. The returned array has it's key's labeled in a specific fashion. - * - * Each string produces a campaign and a prospect id. The keys are appended with a number specifying the order + * and parses it into an array. The returned array has it's key's labeled in a specific fashion. + * + * Each string produces a campaign and a prospect id. The keys are appended with a number specifying the order * it was process in. So an input array containing 3 strings will have the following key values: * "prospect_list0", "campaign0" * "prospect_list1", "campaign1" - * "prospect_list2", "campaign2" - * + * "prospect_list2", "campaign2" + * * */ function process_subscriptions($subscription_string_to_parse) { $subs_change = array(); - //parse through and build list of id's'. We are retrieving the campaign_id and - //the prospect_list id from the selected subscriptions + //parse through and build list of id's'. We are retrieving the campaign_id and + //the prospect_list id from the selected subscriptions $i = 0; foreach($subscription_string_to_parse as $subs_changes){ $subs_changes = trim($subs_changes); @@ -523,57 +520,57 @@ function process_subscriptions($subscription_string_to_parse) { /*This function is used by the Manage Subscriptions page in order to add the user - * to the default prospect lists of the passed in campaign - * Takes in campaign and prospect list id's we are subscribing to. + * to the default prospect lists of the passed in campaign + * Takes in campaign and prospect list id's we are subscribing to. * It also takes in a bean of the user (lead,target,prospect) we are subscribing * */ function subscribe($campaign, $prospect_list, $focus, $default_list = false) { $relationship = strtolower($focus->getObjectName()).'s'; //--grab all the lists for the passed in campaign id - $pl_qry ="select id, list_type from prospect_lists where id in (select prospect_list_id from prospect_list_campaigns "; + $pl_qry ="select id, list_type from prospect_lists where id in (select prospect_list_id from prospect_list_campaigns "; $pl_qry .= "where campaign_id = '$campaign') and deleted = 0 "; $GLOBALS['log']->debug("In Campaigns Util: subscribe function, about to run query: ".$pl_qry ); $pl_qry_result = $focus->db->query($pl_qry); - - //build the array of all prospect_lists + + //build the array of all prospect_lists $pl_arr = array(); while ($row = $focus->db->fetchByAssoc($pl_qry_result)){$pl_arr[] = $row;} - + //--grab all the prospect_lists this user belongs to $curr_pl_qry ="select prospect_list_id, related_id from prospect_lists_prospects "; $curr_pl_qry .="where related_id = '$focus->id' and deleted = 0 "; $GLOBALS['log']->debug("In Campaigns Util: subscribe function, about to run query: ".$curr_pl_qry ); $curr_pl_qry_result = $focus->db->query($curr_pl_qry); - + //build the array of all prospect lists that this current user belongs to $curr_pl_arr = array(); while ($row = $focus->db->fetchByAssoc($curr_pl_qry_result)){$curr_pl_arr[] = $row;} - + //search through prospect lists for this campaign and identifiy the "unsubscription list" $exempt_id = ''; foreach($pl_arr as $subscription_list){ if(strpos($subscription_list['list_type'], 'exempt')!== false){ $exempt_id = $subscription_list['id']; } - + if($subscription_list['list_type'] == 'default' && $default_list) { $prospect_list = $subscription_list['id']; } - } - + } + //now that we have exempt (unsubscription) list id, compare against user list id's if(!empty($exempt_id)){ $exempt_array['exempt_id'] = $exempt_id; - + foreach($curr_pl_arr as $curr_subscription_list){ if($curr_subscription_list['prospect_list_id'] == $exempt_id){ //--if we are in here then user is subscribing to a list in which they are exempt. // we need to remove the user from this unsubscription list. //Begin by retrieving unsubscription prospect list $exempt_subscription_list = new ProspectList(); - - + + $exempt_result = $exempt_subscription_list->retrieve($exempt_id); if($exempt_result == null) {//error happened while retrieving this list @@ -582,19 +579,19 @@ function process_subscriptions($subscription_string_to_parse) { //load realationships and delete user from unsubscription list $exempt_subscription_list->load_relationship($relationship); $exempt_subscription_list->$relationship->delete($exempt_id,$focus->id); - + } - } - } - + } + } + //Now we need to check if user is already in subscription list $already_here = 'false'; //for each list user is subscribed to, compare id's with current list id' foreach($curr_pl_arr as $user_list){ if(in_array($prospect_list, $user_list)){ //if user already exists, then set flag to true - $already_here = 'true'; - } + $already_here = 'true'; + } } if($already_here ==='true'){ //do nothing, user is already subscribed @@ -615,26 +612,26 @@ function process_subscriptions($subscription_string_to_parse) { /*This function is used by the Manage Subscriptions page in order to add the user - * to the exempt prospect lists of the passed in campaign - * Takes in campaign and focus parameters. + * to the exempt prospect lists of the passed in campaign + * Takes in campaign and focus parameters. * */ function unsubscribe($campaign, $focus) { $relationship = strtolower($focus->getObjectName()).'s'; - //--grab all the list for this campaign id - $pl_qry ="select id, list_type from prospect_lists where id in (select prospect_list_id from prospect_list_campaigns "; + //--grab all the list for this campaign id + $pl_qry ="select id, list_type from prospect_lists where id in (select prospect_list_id from prospect_list_campaigns "; $pl_qry .= "where campaign_id = '$campaign') and deleted = 0 "; $pl_qry_result = $focus->db->query($pl_qry); //build the array with list information $pl_arr = array(); $GLOBALS['log']->debug("In Campaigns Util, about to run query: ".$pl_qry); while ($row = $focus->db->fetchByAssoc($pl_qry_result)){$pl_arr[] = $row;} - + //retrieve lists that this user belongs to $curr_pl_qry ="select prospect_list_id, related_id from prospect_lists_prospects "; $curr_pl_qry .="where related_id = '$focus->id' and deleted = 0 "; $GLOBALS['log']->debug("In Campaigns Util, unsubscribe function about to run query: ".$curr_pl_qry ); $curr_pl_qry_result = $focus->db->query($curr_pl_qry); - + //build the array with current user list information $curr_pl_arr = array(); while ($row = $focus->db->fetchByAssoc($curr_pl_qry_result)){$curr_pl_arr[] = $row;} @@ -652,18 +649,18 @@ function process_subscriptions($subscription_string_to_parse) { if(in_array($v['id'], $user_list)){ $already_here = 'true'; } - - break 2; + + break 2; } - } + } } - + //unsubscribe subscripted newsletter foreach($pl_arr as $subscription_list){ //create a new instance of the prospect list $exempt_list = new ProspectList(); $exempt_list->retrieve($subscription_list['id']); - $exempt_list->load_relationship($relationship); + $exempt_list->load_relationship($relationship); //if list type is default, then delete the relationship //if list type is exempt, then add the relationship to unsubscription list if($subscription_list['list_type'] == 'exempt') { @@ -672,16 +669,16 @@ function process_subscriptions($subscription_string_to_parse) { //if list type is default or test, then delete the relationship //$exempt_list->$relationship->delete($subscription_list['id'],$focus->id); } - - } + + } if($already_here =='true'){ //do nothing, user is already exempted - + }else{ //user is not exempted yet , so add to unsubscription list - - + + $exempt_result = $exempt_list->retrieve($exempt_id); if($exempt_result == null) {//error happened while retrieving this list @@ -691,13 +688,13 @@ function process_subscriptions($subscription_string_to_parse) { $exempt_list->load_relationship($relationship); $exempt_list->$relationship->add($focus->id); } - + } - - + + /* - *This function will return a string to the newsletter wizard if campaign check - *does not return 100% healthy. + *This function will return a string to the newsletter wizard if campaign check + *does not return 100% healthy. */ function diagnose() { @@ -708,27 +705,27 @@ function process_subscriptions($subscription_string_to_parse) { //monitored mailbox section $focus = new Administration(); $focus->retrieveSettings(); //retrieve all admin settings. - - - //run query for mail boxes of type 'bounce' + + + //run query for mail boxes of type 'bounce' $email_health = 0; $email_components = 2; $mbox_qry = "select * from inbound_email where deleted ='0' and mailbox_type = 'bounce'"; $mbox_res = $focus->db->query($mbox_qry); - + $mbox = array(); while ($mbox_row = $focus->db->fetchByAssoc($mbox_res)){$mbox[] = $mbox_row;} //if the array is not empty, then set "good" message if(isset($mbox) && count($mbox)>0){ //everything is ok, do nothing - + }else{ //if array is empty, then increment health counter $email_health =$email_health +1; $msg .= "". $mod_strings['LBL_MAILBOX_CHECK1_BAD'].""; } - - + + if (strstr($focus->settings['notify_fromaddress'], 'example.com')){ //if "from_address" is the default, then set "bad" message and increment health counter $email_health =$email_health +1; @@ -736,7 +733,7 @@ function process_subscriptions($subscription_string_to_parse) { }else{ //do nothing, address has been changed } - //if health counter is above 1, then show admin link + //if health counter is above 1, then show admin link if($email_health>0){ if (is_admin($current_user)){ $msg.=""; }else{ $msg.="".$mod_strings['LBL_NON_ADMIN_ERROR_MSG'].""; - - } - - } - - - // proceed with scheduler components - - //create and run the scheduler queries + + } + + } + + + // proceed with scheduler components + + //create and run the scheduler queries $sched_qry = "select job, name, status from schedulers where deleted = 0 and status = 'Active'"; $sched_res = $focus->db->query($sched_qry); $sched_health = 0; @@ -767,7 +764,7 @@ function process_subscriptions($subscription_string_to_parse) { $sched_mes = ''; $sched_mes_body = ''; $scheds = array(); - + while ($sched_row = $focus->db->fetchByAssoc($sched_res)){$scheds[] = $sched_row;} //iterate through and see which jobs were found foreach ($scheds as $funct){ @@ -776,8 +773,8 @@ function process_subscriptions($subscription_string_to_parse) { $check_sched1 ="found"; }else{ $check_sched2 ="found"; - } - + } + } } //determine if error messages need to be displayed for schedulers @@ -789,51 +786,51 @@ function process_subscriptions($subscription_string_to_parse) { $sched_health =$sched_health +1; $msg.= "".$mod_strings['LBL_SCHEDULER_CHECK2_BAD'].""; } - //if health counter is above 1, then show admin link + //if health counter is above 1, then show admin link if($sched_health>0){ global $current_user; if (is_admin($current_user)){ $msg.="".$mod_strings['LBL_SCHEDULER_LINK'].""; }else{ $msg.="".$mod_strings['LBL_NON_ADMIN_ERROR_MSG'].""; - } - - } + } + + } //determine whether message should be returned if(($sched_health + $email_health)>0){ - $msg .= " "; + $msg .= " "; }else{ $msg = ''; } - return $msg; + return $msg; } - - + + /** * Handle campaign log entry creation for mail-merge activity. The function will be called by the soap component. - * + * * @param String campaign_id Primary key of the campaign * @param array targets List of keys for entries from prospect_lists_prosects table */ function campaign_log_mail_merge($campaign_id, $targets) { - + $campaign= new Campaign(); $campaign->retrieve($campaign_id); - + if (empty($campaign->id)) { $GLOBALS['log']->debug('set_campaign_merge: Invalid campaign id'. $campaign_id); } else { foreach ($targets as $target_list_id) { - $pl_query = "select * from prospect_lists_prospects where id='$target_list_id'"; + $pl_query = "select * from prospect_lists_prospects where id='".$GLOBALS['db']->quote($target_list_id)."'"; $result=$GLOBALS['db']->query($pl_query); $row=$GLOBALS['db']->fetchByAssoc($result); if (!empty($row)) { write_mail_merge_log_entry($campaign_id,$row); } - } + } } - + } /** * Function creates a campaign_log entry for campaigns processesed using the mail-merge feature. If any entry @@ -842,80 +839,67 @@ function process_subscriptions($subscription_string_to_parse) { * @param array $pl_row A row of data from prospect_lists_prospects table. */ function write_mail_merge_log_entry($campaign_id,$pl_row) { - + //Update the log entry if it exists. - $update="update campaign_log set hits=hits+1 where campaign_id='$campaign_id' and target_tracker_key='" . $pl_row['id'] . "'"; + $update="update campaign_log set hits=hits+1 where campaign_id='".$GLOBALS['db']->quote($campaign_id)."' and target_tracker_key='" . $GLOBALS['db']->quote($pl_row['id']) . "'"; $result=$GLOBALS['db']->query($update); - + //get affected row count... $count=$GLOBALS['db']->getAffectedRowCount(); if ($count==0) { $data=array(); - + $data['id']="'" . create_guid() . "'"; - $data['campaign_id']="'" . $campaign_id . "'"; - $data['target_tracker_key']="'" . $pl_row['id'] . "'"; - $data['target_id']="'" . $pl_row['related_id'] . "'"; - $data['target_type']="'" . $pl_row['related_type'] . "'"; + $data['campaign_id']="'" . $GLOBALS['db']->quote($campaign_id) . "'"; + $data['target_tracker_key']="'" . $GLOBALS['db']->quote($pl_row['id']) . "'"; + $data['target_id']="'" . $GLOBALS['db']->quote($pl_row['related_id']) . "'"; + $data['target_type']="'" . $GLOBALS['db']->quote($pl_row['related_type']) . "'"; $data['activity_type']="'targeted'"; $data['activity_date']="'" . TimeDate::getInstance()->nowDb() . "'"; - $data['list_id']="'" . $pl_row['prospect_list_id'] . "'"; + $data['list_id']="'" . $GLOBALS['db']->quote($pl_row['prospect_list_id']) . "'"; $data['hits']=1; - - $insert_query="INSERT into campaign_log (" . implode(",",array_keys($data)) . ")"; - $insert_query.=" VALUES (" . implode(",",array_values($data)) . ")"; - $GLOBALS['db']->query($insert_query); + + $insert_query="INSERT into campaign_log (" . implode(",",array_keys($data)) . ")"; + $insert_query.=" VALUES (" . implode(",",array_values($data)) . ")"; + $GLOBALS['db']->query($insert_query); } -} +} function track_campaign_prospects($focus){ - $delete_query="delete from campaign_log where campaign_id='{$focus->id}' and activity_type='targeted'"; + $delete_query="delete from campaign_log where campaign_id='".$GLOBALS['db']->quote($focus->id)."' and activity_type='targeted'"; $focus->db->query($delete_query); $query="SELECT prospect_lists.id prospect_list_id from prospect_lists "; $query.=" INNER JOIN prospect_list_campaigns plc ON plc.prospect_list_id = prospect_lists.id"; - $query.=" WHERE plc.campaign_id='{$focus->id}'"; + $query.=" WHERE plc.campaign_id='".$GLOBALS['db']->quote($focus->id)."'"; $query.=" AND prospect_lists.deleted=0"; $query.=" AND plc.deleted=0"; - $query.=" AND prospect_lists.list_type!='test' AND prospect_lists.list_type not like 'exempt%'"; + $query.=" AND prospect_lists.list_type!='test' AND prospect_lists.list_type not like 'exempt%'"; $result=$focus->db->query($query); while (($row=$focus->db->fetchByAssoc($result))!=null ) { $prospect_list_id=$row['prospect_list_id']; - - if ($focus->db->dbType=='oci8') { - } - else if ($focus->db->dbType=='mssql') { - $current_date= "'".TimeDate::getInstance()->nowDb()."'"; - $guid = "NEWID()"; - } - else { - $current_date= "'".TimeDate::getInstance()->nowDb()."'"; - $guid = "UUID()"; - } + $guid = create_guid(); + $current_date = $focus->db->now(); $insert_query= "INSERT INTO campaign_log (id,activity_date, campaign_id, target_tracker_key,list_id, target_id, target_type, activity_type"; - $insert_query.=')'; - $insert_query.= " SELECT $guid,$current_date,plc.campaign_id,$guid,plp.prospect_list_id, plp.related_id, plp.related_type,'targeted' "; + $insert_query.=')'; + $insert_query.= " SELECT '{$guid}',$current_date,plc.campaign_id,'{$guid}',plp.prospect_list_id, plp.related_id, plp.related_type,'targeted' "; $insert_query.= "FROM prospect_lists_prospects plp "; - $insert_query.= "INNER JOIN prospect_list_campaigns plc ON plc.prospect_list_id = plp.prospect_list_id "; + $insert_query.= "INNER JOIN prospect_list_campaigns plc ON plc.prospect_list_id = plp.prospect_list_id "; $insert_query.= "WHERE plp.prospect_list_id = '{$prospect_list_id}' "; $insert_query.= "AND plp.deleted=0 "; $insert_query.= "AND plc.deleted=0 "; $insert_query.= "AND plc.campaign_id='{$focus->id}'"; -/* - if ($focus->db->dbType=='oci8') { - } - */ $focus->db->query($insert_query); } global $mod_strings; - //return success message + //return success message return $mod_strings['LBL_DEFAULT_LIST_ENTRIES_WERE_PROCESSED']; } - + function create_campaign_log_entry($campaign_id, $focus, $rel_name, $rel_bean, $target_id = ''){ global $timedate; - + $target_ids = array(); //check if this is specified for one target/contact/prospect/lead (from contact/lead detail subpanel) if(!empty($target_id)){ @@ -924,11 +908,11 @@ function write_mail_merge_log_entry($campaign_id,$pl_row) { //this is specified for all, so load target/prospect relationships (mark as sent button) $focus->load_relationship($rel_name); $target_ids = $focus->$rel_name->get(); - + } if(count($target_ids)>0){ - - + + //retrieve the target beans and create campaign log entry foreach($target_ids as $id){ //perform duplicate check @@ -938,10 +922,10 @@ function write_mail_merge_log_entry($campaign_id,$pl_row) { //process if this is not a duplicate campaign log entry if(empty($row)){ - //create campaign tracker id and retrieve related bio bean - $tracker_id = create_guid(); + //create campaign tracker id and retrieve related bio bean + $tracker_id = create_guid(); $rel_bean->retrieve($id); - + //create new campaign log record. $campaign_log = new CampaignLog(); $campaign_log->campaign_id = $campaign_id; @@ -949,15 +933,15 @@ function write_mail_merge_log_entry($campaign_id,$pl_row) { $campaign_log->target_id = $rel_bean->id; $campaign_log->target_type = $rel_bean->module_dir; $campaign_log->activity_type = 'targeted'; - $campaign_log->activity_date=$timedate->now(); + $campaign_log->activity_date=$timedate->now(); //save the campaign log entry $campaign_log->save(); } - } + } } - + } - + /* * This function will return an array that has been formatted to work as a Quick Search Object for prospect lists */ @@ -965,22 +949,22 @@ function write_mail_merge_log_entry($campaign_id,$pl_row) { global $app_strings; //if source has not been specified, then search across all prospect lists if(empty($source)){ - $qsProspectList = array('method' => 'query', - 'modules'=> array('ProspectLists'), + $qsProspectList = array('method' => 'query', + 'modules'=> array('ProspectLists'), 'group' => 'and', 'field_list' => array('name', 'id'), - 'populate_list' => array('prospect_list_name', 'prospect_list_id'), + 'populate_list' => array('prospect_list_name', 'prospect_list_id'), 'conditions' => array( array('name'=>'name','op'=>'like_custom','end'=>'%','value'=>'') ), 'order' => 'name', 'limit' => '30', 'no_match_text' => $app_strings['ERR_SQS_NO_MATCH']); }else{ - //source has been specified use it to tell quicksearch.js which html input to use to get filter value - $qsProspectList = array('method' => 'query', - 'modules'=> array('ProspectLists'), + //source has been specified use it to tell quicksearch.js which html input to use to get filter value + $qsProspectList = array('method' => 'query', + 'modules'=> array('ProspectLists'), 'group' => 'and', - 'field_list' => array('name', 'id'), - 'populate_list' => array($return_field_name, $return_field_id), + 'field_list' => array('name', 'id'), + 'populate_list' => array($return_field_name, $return_field_id), 'conditions' => array( array('name'=>'name','op'=>'like_custom','end'=>'%','value'=>''), //this condition has the source parameter defined, meaning the query will take the value specified below @@ -989,11 +973,11 @@ function write_mail_merge_log_entry($campaign_id,$pl_row) { 'order' => 'name', 'limit' => '30', 'no_match_text' => $app_strings['ERR_SQS_NO_MATCH']); - + } - + return $qsProspectList; } - - + + ?> diff --git a/modules/Campaigns/views/view.modulelistmenu.php b/modules/Campaigns/views/view.modulelistmenu.php index b705cbec..9a16820e 100644 --- a/modules/Campaigns/views/view.modulelistmenu.php +++ b/modules/Campaigns/views/view.modulelistmenu.php @@ -45,7 +45,8 @@ class CampaignsViewModulelistmenu extends ViewModulelistmenu foreach ( $history as $key => $row ) { $history[$key]['item_summary_short'] = getTrackerSubstring($row['item_summary']); $history[$key]['image'] = SugarThemeRegistry::current() - ->getImage($row['module_name'],'border="0" align="absmiddle" alt="'.$row['item_summary'].'"'); + ->getImage($row['module_name'],'border="0" align="absmiddle"', null,null,'.gif',$row['item_summary']); + } $this->ss->assign('LAST_VIEWED',$history); diff --git a/modules/Cases/Case.php b/modules/Cases/Case.php index f51892b6..47f49471 100644 --- a/modules/Cases/Case.php +++ b/modules/Cases/Case.php @@ -229,7 +229,7 @@ class aCase extends Basic { $temp_array['STATUS'] = empty($this->status)? "" : $app_list_strings['case_status_dom'][$this->status]; $temp_array['ENCODED_NAME'] = $this->name; $temp_array['CASE_NUMBER'] = $this->case_number; - $temp_array['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Cases')." border='0'").""; + $temp_array['SET_COMPLETE'] = "".SugarThemeRegistry::current()->getImage("close_inline","title=".translate('LBL_LIST_CLOSE','Cases')." border='0'",null,null,'.gif',translate('LBL_LIST_CLOSE','Cases')).""; //$temp_array['ACCOUNT_NAME'] = $this->account_name; //overwrites the account_name value returned from the cases table. return $temp_array; } diff --git a/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageConfigure.tpl b/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageConfigure.tpl index a4d2ac8b..85ecd333 100644 --- a/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageConfigure.tpl +++ b/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageConfigure.tpl @@ -61,14 +61,14 @@ {$LBL_DATE_START}
{$user_date_format} - {$LBL_ENTER_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$LBL_ENTER_DATE other_attributes='align="absmiddle" id="date_start_trigger" '} {$LBL_DATE_END}
{$user_date_format} - {$LBL_ENTER_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$LBL_ENTER_DATE other_attributes='align="absmiddle" id="date_end_trigger" '} diff --git a/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageDashlet.php b/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageDashlet.php index aa367ee6..6f196218 100644 --- a/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageDashlet.php +++ b/modules/Charts/Dashlets/MyPipelineBySalesStageDashlet/MyPipelineBySalesStageDashlet.php @@ -128,8 +128,8 @@ class MyPipelineBySalesStageDashlet extends DashletGenericChart $xmlFile = $sugarChart->getXMLFileName($this->id); $sugarChart->saveXMLFile($xmlFile, $sugarChart->generateXML()); - - return $this->getTitle('') . + + return $this->getTitle('') . '
' .$sugarChart->display($this->id, $xmlFile, '100%', '480', false) . '

'. $this->processAutoRefresh(); } @@ -166,11 +166,11 @@ class MyPipelineBySalesStageDashlet extends DashletGenericChart } $result = $db->query($query); - $row = $db->fetchByAssoc($result, -1, false); + $row = $db->fetchByAssoc($result, false); while($row != null){ $temp_data[] = $row; - $row = $db->fetchByAssoc($result, -1, false); + $row = $db->fetchByAssoc($result, false); } // reorder and set the array based on the order of selected_datax @@ -231,8 +231,8 @@ class MyPipelineBySalesStageDashlet extends DashletGenericChart sum(amount_usdollar/1000) AS total FROM users,opportunities "; $query .= " WHERE opportunities.assigned_user_id IN ('{$GLOBALS['current_user']->id}') " . - " AND opportunities.date_closed >= ". db_convert("'".$this->mypbss_date_start."'",'datetime'). - " AND opportunities.date_closed <= ".db_convert("'".$this->mypbss_date_end."'",'datetime') . + " AND opportunities.date_closed >= ". db_convert("'".$this->mypbss_date_start."'",'date'). + " AND opportunities.date_closed <= ".db_convert("'".$this->mypbss_date_end."'",'date') . " AND opportunities.assigned_user_id = users.id AND opportunities.deleted=0 "; if ( count($this->mypbss_sales_stages) > 0 ) $query .= " AND opportunities.sales_stage IN ('" . implode("','",$this->mypbss_sales_stages) . "') "; diff --git a/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthConfigure.tpl b/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthConfigure.tpl index dc151ff9..dc707e03 100644 --- a/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthConfigure.tpl +++ b/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthConfigure.tpl @@ -61,14 +61,14 @@ {$LBL_DATE_START}
{$user_date_format} - {$LBL_ENTER_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$LBL_ENTER_DATE other_attributes='align="absmiddle" id="date_start_trigger" '} {$LBL_DATE_END}
{$user_date_format} - {$LBL_ENTER_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$LBL_ENTER_DATE other_attributes='align="absmiddle" id="date_end_trigger" '} diff --git a/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthDashlet.php b/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthDashlet.php index 129a787a..548d113a 100644 --- a/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthDashlet.php +++ b/modules/Charts/Dashlets/OutcomeByMonthDashlet/OutcomeByMonthDashlet.php @@ -124,8 +124,8 @@ class OutcomeByMonthDashlet extends DashletGenericChart $query = "SELECT sales_stage,". db_convert('opportunities.date_closed','date_format',array("'%Y-%m'"),array("'YYYY-MM'"))." as m, ". "sum(amount_usdollar/1000) as total, count(*) as opp_count FROM opportunities "; - $query .= " WHERE opportunities.date_closed >= ".db_convert("'".$this->obm_date_start."'",'datetime') . - " AND opportunities.date_closed <= ".db_convert("'".$this->obm_date_end."'",'datetime') . + $query .= " WHERE opportunities.date_closed >= ".db_convert("'".$this->obm_date_start."'",'date') . + " AND opportunities.date_closed <= ".db_convert("'".$this->obm_date_end."'",'date') . " AND opportunities.deleted=0"; if (count($this->obm_ids) > 0) $query .= " AND opportunities.assigned_user_id IN ('" . implode("','",$this->obm_ids) . "')"; diff --git a/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageConfigure.tpl b/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageConfigure.tpl index 2f1633f0..76e346df 100644 --- a/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageConfigure.tpl +++ b/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageConfigure.tpl @@ -61,14 +61,14 @@ {$LBL_DATE_START}
{$user_date_format} - {$LBL_ENTER_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$LBL_ENTER_DATE other_attributes='align="absmiddle" id="date_start_trigger" '} {$LBL_DATE_END}
{$user_date_format} - {$LBL_ENTER_DATE} + {sugar_getimage name="jscalendar" ext=".gif" alt=$LBL_ENTER_DATE other_attributes='align="absmiddle" id="date_end_trigger" '} diff --git a/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageDashlet.php b/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageDashlet.php index 24c51343..2626e49e 100644 --- a/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageDashlet.php +++ b/modules/Charts/Dashlets/PipelineBySalesStageDashlet/PipelineBySalesStageDashlet.php @@ -41,100 +41,100 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/Dashlets/DashletGenericChart.php'); -class PipelineBySalesStageDashlet extends DashletGenericChart +class PipelineBySalesStageDashlet extends DashletGenericChart { public $pbss_date_start; public $pbss_date_end; public $pbss_sales_stages = array(); - + /** * @see DashletGenericChart::$_seedName */ protected $_seedName = 'Opportunities'; - + /** * @see DashletGenericChart::__construct() */ public function __construct( - $id, + $id, array $options = null - ) + ) { global $timedate; - - if(empty($options['pbss_date_start'])) - $options['pbss_date_start'] = date($timedate->get_db_date_time_format(), time()); - + + if(empty($options['pbss_date_start'])) + $options['pbss_date_start'] = $timedate->nowDbDate(); + if(empty($options['pbss_date_end'])) - $options['pbss_date_end'] = date($timedate->get_db_date_time_format(), strtotime("+6 months", time())); - - if(empty($options['title'])) + $options['pbss_date_end'] = $timedate->asDbDate($timedate->getNow()->modify("+6 months")); + + if(empty($options['title'])) $options['title'] = translate('LBL_PIPELINE_FORM_TITLE', 'Home'); - + parent::__construct($id,$options); } - + /** * @see DashletGenericChart::displayOptions() */ public function displayOptions() { global $app_list_strings; - + if (!empty($this->pbss_sales_stages) && count($this->pbss_sales_stages) > 0) foreach ($this->pbss_sales_stages as $key) $selected_datax[] = $key; else $selected_datax = array_keys($app_list_strings['sales_stage_dom']); - + $this->_searchFields['pbss_sales_stages']['options'] = $app_list_strings['sales_stage_dom']; $this->_searchFields['pbss_sales_stages']['input_name0'] = $selected_datax; - + return parent::displayOptions(); } - + /** * @see DashletGenericChart::display() */ - public function display() + public function display() { global $current_user, $sugar_config; - + require_once('include/SugarCharts/SugarChartFactory.php'); $sugarChart = SugarChartFactory::getInstance(); - $sugarChart->base_url = array( + $sugarChart->base_url = array( 'module' => 'Opportunities', 'action' => 'index', 'query' => 'true', 'searchFormTab' => 'advanced_search', ); - $sugarChart->url_params = array( ); + $sugarChart->url_params = array( ); $sugarChart->group_by = $this->constructGroupBy(); $sugarChart->setData($this->getChartData($this->constructQuery())); $sugarChart->is_currency = true; $sugarChart->thousands_symbol = translate('LBL_OPP_THOUSANDS', 'Charts'); - + $currency_symbol = $sugar_config['default_currency_symbol']; if ($current_user->getPreference('currency')){ - + $currency = new Currency(); $currency->retrieve($current_user->getPreference('currency')); $currency_symbol = $currency->symbol; } $subtitle = translate('LBL_OPP_SIZE', 'Charts') . " " . $currency_symbol . "1" . translate('LBL_OPP_THOUSANDS', 'Charts'); - + $pipeline_total_string = translate('LBL_TOTAL_PIPELINE', 'Charts') . $sugarChart->currency_symbol . format_number($sugarChart->getTotal(), 0, 0, array('convert'=>true)) . $sugarChart->thousands_symbol; $sugarChart->setProperties($pipeline_total_string, $subtitle, 'horizontal group by chart'); - + $xmlFile = $sugarChart->getXMLFileName($this->id); $sugarChart->saveXMLFile($xmlFile, $sugarChart->generateXML()); - - return $this->getTitle('') . '
' . $sugarChart->display($this->id, $xmlFile, '100%', '480', false) . '
'. $this->processAutoRefresh(); + + return $this->getTitle('') . '
' . $sugarChart->display($this->id, $xmlFile, '100%', '480', false) . '
'. $this->processAutoRefresh(); } /** * awu: Bug 16794 - this function is a hack to get the correct sales stage order until - * i can clean it up later + * i can clean it up later * * @param $query string * @return array @@ -144,14 +144,14 @@ class PipelineBySalesStageDashlet extends DashletGenericChart ) { global $app_list_strings, $db; - + $data = array(); $temp_data = array(); $selected_datax = array(); - + $user_sales_stage = $this->pbss_sales_stages; $tempx = $user_sales_stage; - + //set $datax using selected sales stage keys if (count($tempx) > 0) { foreach ($tempx as $key) { @@ -163,18 +163,18 @@ class PipelineBySalesStageDashlet extends DashletGenericChart $datax = $app_list_strings['sales_stage_dom']; $selected_datax = array_keys($app_list_strings['sales_stage_dom']); } - + $result = $db->query($query); - while($row = $db->fetchByAssoc($result, -1, false)) + while($row = $db->fetchByAssoc($result, false)) $temp_data[] = $row; - // reorder and set the array based on the order of selected_datax + // reorder and set the array based on the order of selected_datax foreach($selected_datax as $sales_stage){ foreach($temp_data as $key => $value){ if ($value['sales_stage'] == $sales_stage){ $value['sales_stage'] = $app_list_strings['sales_stage_dom'][$value['sales_stage']]; $value['key'] = $sales_stage; - $value['value'] = $value['sales_stage']; + $value['value'] = $value['sales_stage']; $data[] = $value; unset($temp_data[$key]); } @@ -182,11 +182,11 @@ class PipelineBySalesStageDashlet extends DashletGenericChart } return $data; } - + /** * @see DashletGenericChart::constructQuery() */ - protected function constructQuery() + protected function constructQuery() { $query = " SELECT opportunities.sales_stage, users.user_name, @@ -194,8 +194,8 @@ class PipelineBySalesStageDashlet extends DashletGenericChart count(*) AS opp_count, sum(amount_usdollar/1000) AS total FROM users,opportunities "; - $query .= " WHERE opportunities.date_closed >= ". db_convert("'".$this->pbss_date_start."'",'datetime'). - " AND opportunities.date_closed <= ".db_convert("'".$this->pbss_date_end."'",'datetime') . + $query .= " WHERE opportunities.date_closed >= ". db_convert("'".$this->pbss_date_start."'",'date'). + " AND opportunities.date_closed <= ".db_convert("'".$this->pbss_date_end."'",'date') . " AND opportunities.assigned_user_id = users.id AND opportunities.deleted=0 "; if ( count($this->pbss_sales_stages) > 0 ) $query .= " AND opportunities.sales_stage IN ('" . implode("','",$this->pbss_sales_stages) . "') "; @@ -203,7 +203,7 @@ class PipelineBySalesStageDashlet extends DashletGenericChart return $query; } - + /** * @see DashletGenericChart::constructGroupBy() */ diff --git a/modules/Charts/DynamicAction.php b/modules/Charts/DynamicAction.php index 2dc7f3d1..fbca1007 100644 --- a/modules/Charts/DynamicAction.php +++ b/modules/Charts/DynamicAction.php @@ -38,14 +38,11 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); if(isset($_GET['DynamicAction']) && $_GET['DynamicAction'] == "saveImage") { - $cache = $GLOBALS['sugar_config']['cache_dir']."images/"; - - + $cache = sugar_cached("images/"); + $filename = $_POST['filename']; $image = str_replace(" ", "+", $_POST["imageStr"]); $data = substr($image, strpos($image, ",")); file_put_contents($cache.$filename, base64_decode($data)); - - } \ No newline at end of file diff --git a/modules/Charts/code/Chart_lead_source_by_outcome.php b/modules/Charts/code/Chart_lead_source_by_outcome.php index cbea37ba..4feaa7a9 100644 --- a/modules/Charts/code/Chart_lead_source_by_outcome.php +++ b/modules/Charts/code/Chart_lead_source_by_outcome.php @@ -138,11 +138,11 @@ $id_md5 = substr(md5($current_user->id),0,9); $seps = array("-", "/"); $dates = array(date($GLOBALS['timedate']->dbDayFormat), $GLOBALS['timedate']->dbDayFormat); $dateFileNameSafe = str_replace($seps, "_", $dates); -$cache_file_name = $current_user->getUserPrivGuid()."_lead_source_by_outcome_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; +$cache_file_name = sugar_cached("xml/").$current_user->getUserPrivGuid()."_lead_source_by_outcome_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; $GLOBALS['log']->debug("cache file name is: $cache_file_name"); -$tools=''; +$tools=''; ?> ".$this->gen_xml($datax, $ids, $sugar_config['tmp_dir'].$cache_file_name, $refresh,$current_module_strings)."

"; +echo "

".$this->gen_xml($datax, $ids, $cache_file_name, $refresh,$current_module_strings)."

"; echo "

".$current_module_strings['LBL_LEAD_SOURCE_BY_OUTCOME_DESC']."

"; - if (file_exists($sugar_config['tmp_dir'].$cache_file_name)) { + if (file_exists($cache_file_name)) { global $timedate; - $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($sugar_config['tmp_dir'].$cache_file_name))); + $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($cache_file_name))); } else { $file_date = ''; @@ -254,8 +254,7 @@ global $timedate; //Now do the db queries //query for opportunity data that matches $datay and $user - $result = $opp->db->query($query) - or sugar_die("Error selecting sugarbean: ".mysql_error()); + $result = $opp->db->query($query, true); //build pipeline by sales stage data $total = 0; $div = 1; @@ -275,7 +274,7 @@ global $timedate; } $fileContents = ' '."\n"; $leadSourceArr = array(); - while($row = $opp->db->fetchByAssoc($result, -1, false)) + while($row = $opp->db->fetchByAssoc($result, false)) { if($row['total']*$div<=100){ $sum = round($row['total']*$div, 2); diff --git a/modules/Charts/code/Chart_my_pipeline_by_sales_stage.php b/modules/Charts/code/Chart_my_pipeline_by_sales_stage.php index a6007f30..25365a64 100644 --- a/modules/Charts/code/Chart_my_pipeline_by_sales_stage.php +++ b/modules/Charts/code/Chart_my_pipeline_by_sales_stage.php @@ -155,12 +155,12 @@ $id_md5 = substr(md5($current_user->id),0,9); $seps = array("-", "/"); $dates = array($dateStartDisplay, $dateEndDisplay); $dateFileNameSafe = str_replace($seps, "_", $dates); -$cache_file_name = $current_user->getUserPrivGuid()."_".$theme."_my_pipeline_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; +$cache_file_name = sugar_cached("xml/").$current_user->getUserPrivGuid()."_".$theme."_my_pipeline_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; $GLOBALS['log']->debug("cache file name is: $cache_file_name"); -$tools=''; +$tools=''; ?> @@ -179,12 +179,12 @@ $tools='

get_user_date_format();?> - <?php echo $app_strings['LBL_ENTER_DATE']; ?> + getImage('jscalendar', 'id="date_start_trigger" align="absmiddle"', null, null, ".gif", $app_strings['LBL_ENTER_DATE']); ?>
get_user_date_format();?> - <?php echo $app_strings['LBL_ENTER_DATE']; ?> + getImage('jscalendar', 'id="date_end_trigger" align="absmiddle"', null, null, ".gif", $app_strings['LBL_ENTER_DATE']); ?> @@ -210,12 +210,12 @@ Calendar.setup ({ ".gen_xml_pipeline_by_sales_stage($datax, $dateXml[0], $dateXml[1], $ids, $sugar_config['tmp_dir'].$cache_file_name, $refresh,'hBarS',$current_module_strings)."

"; +echo "

".gen_xml_pipeline_by_sales_stage($datax, $dateXml[0], $dateXml[1], $ids, $cache_file_name, $refresh,'hBarS',$current_module_strings)."

"; echo "

".$current_module_strings['LBL_PIPELINE_FORM_TITLE_DESC']."

"; - if (file_exists($sugar_config['tmp_dir'].$cache_file_name)) { - $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($sugar_config['tmp_dir'].$cache_file_name))); + if (file_exists($cache_file_name)) { + $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($cache_file_name))); } else { $file_date = ''; @@ -295,8 +295,7 @@ echo get_validate_chart_js(); $query .= "WHERE " .$where; $query .= " GROUP BY opportunities.sales_stage,users.user_name,opportunities.assigned_user_id"; - $result = $opp->db->query($query) - or sugar_die("Error selecting sugarbean: ".mysql_error()); + $result = $opp->db->query($query, true); //build pipeline by sales stage data $total = 0; $div = 1; @@ -319,7 +318,7 @@ echo get_validate_chart_js(); $usernameArr = array(); $rowTotalArr = array(); $rowTotalArr[] = 0; - while($row = $opp->db->fetchByAssoc($result, -1, false)) + while($row = $opp->db->fetchByAssoc($result, false)) { if($row['total']*$div<=100){ $sum = round($row['total']*$div, 2); diff --git a/modules/Charts/code/Chart_outcome_by_month.php b/modules/Charts/code/Chart_outcome_by_month.php index 92fa3986..21da0df0 100644 --- a/modules/Charts/code/Chart_outcome_by_month.php +++ b/modules/Charts/code/Chart_outcome_by_month.php @@ -150,13 +150,13 @@ $seps = array("-", "/"); $dates = array($date_start, $date_end); $dateFileNameSafe = str_replace($seps, "_", $dates); -$cache_file_name = $current_user->getUserPrivGuid()."_outcome_by_month_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; +$cache_file_name = sugar_cached("xml/").$current_user->getUserPrivGuid()."_outcome_by_month_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; $GLOBALS['log']->debug("cache file name is: $cache_file_name"); global $app_strings; -$tools='
'; +$tools=''; ?> order . '">' . get_form_header($current_module_strings['LBL_YEAR_BY_OUTCOME'],$tools,false) . '';?> @@ -189,7 +189,7 @@ if (empty($_SESSION['obm_ids'])) $_SESSION['obm_ids'] = "";

".$this->gen_xml($date_start, $date_end, $ids, $sugar_config['tmp_dir'].$cache_file_name, $refresh,$current_module_strings)."

"; +echo "

".$this->gen_xml($date_start, $date_end, $ids, $cache_file_name, $refresh,$current_module_strings)."

"; echo "

".$current_module_strings['LBL_MONTH_BY_OUTCOME_DESC']."

"; @@ -198,8 +198,8 @@ echo "

".$current_module_strings['L asUser($timedate->fromTimestamp(filemtime($sugar_config['tmp_dir'].$cache_file_name))); + if (file_exists($cache_file_name)) { + $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($cache_file_name))); } else { $file_date = ''; @@ -261,8 +261,7 @@ echo get_validate_chart_js(); //query for opportunity data that matches $datay and $user //_pp($query); - $result = $opp->db->query($query) - or sugar_die("Error selecting sugarbean: ".mysql_error()); + $result = $opp->db->query($query, true); //build pipeline by sales stage data $total = 0; $div = 1; @@ -282,7 +281,7 @@ echo get_validate_chart_js(); } $months = array(); $monthArr = array(); - while($row = $opp->db->fetchByAssoc($result, -1, false)) + while($row = $opp->db->fetchByAssoc($result, false)) { if($row['total']*$div<=100){ $sum = round($row['total']*$div, 2); @@ -457,4 +456,4 @@ echo get_validate_chart_js(); } -?> \ No newline at end of file +?> diff --git a/modules/Charts/code/Chart_pipeline_by_lead_source.php b/modules/Charts/code/Chart_pipeline_by_lead_source.php index 5875c626..6de0f2fa 100644 --- a/modules/Charts/code/Chart_pipeline_by_lead_source.php +++ b/modules/Charts/code/Chart_pipeline_by_lead_source.php @@ -142,11 +142,11 @@ $id_md5 = substr(md5($current_user->id),0,9); $seps = array("-", "/"); $dates = array(date($GLOBALS['timedate']->dbDayFormat), $GLOBALS['timedate']->dbDayFormat); $dateFileNameSafe = str_replace($seps, "_", $dates); -$cache_file_name = $current_user->getUserPrivGuid()."_pipeline_by_lead_source_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; +$cache_file_name = sugar_cached("xml/").$current_user->getUserPrivGuid()."_pipeline_by_lead_source_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; $GLOBALS['log']->debug("cache file name is: $cache_file_name"); global $currentModule,$action; -$tools='

'; +$tools=''; ?> ".$this->gen_xml($datax, $ids, $sugar_config['tmp_dir'].$cache_file_name, $refresh,$current_module_strings)."

"; +echo "

".$this->gen_xml($datax, $ids, $cache_file_name, $refresh,$current_module_strings)."

"; echo "

".$current_module_strings['LBL_LEAD_SOURCE_FORM_DESC']."

"; - if (file_exists($sugar_config['tmp_dir'].$cache_file_name)) { + if (file_exists($cache_file_name)) { global $timedate; - $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($sugar_config['tmp_dir'].$cache_file_name))); + $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($cache_file_name))); } else { $file_date = ''; @@ -267,10 +267,9 @@ global $timedate; $subtitle = $current_module_strings['LBL_OPP_SIZE'].' '.$symbol.'1'.$current_module_strings['LBL_OPP_THOUSANDS']; $fileContents = ''; $fileContents .= ' '."\n"; - $result = $opp->db->query($query) - or sugar_die("Error selecting sugarbean: ".mysql_error()); + $result = $opp->db->query($query, true); $leadSourceArr = array(); - while($row = $opp->db->fetchByAssoc($result, -1, false)) + while($row = $opp->db->fetchByAssoc($result, false)) { if($row['lead_source'] == ''){ $leadSource = $current_module_strings['NTC_NO_LEGENDS']; diff --git a/modules/Charts/code/Chart_pipeline_by_sales_stage.php b/modules/Charts/code/Chart_pipeline_by_sales_stage.php index dcf1ac99..284b5e3f 100644 --- a/modules/Charts/code/Chart_pipeline_by_sales_stage.php +++ b/modules/Charts/code/Chart_pipeline_by_sales_stage.php @@ -200,11 +200,11 @@ if (isset($ids)) { $GLOBALS['log']->debug("ids is:"); $GLOBALS['log']->debug($ids); -$cache_file_name = $current_user->getUserPrivGuid()."_lead_source_by_outcome_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; +$cache_file_name = sugar_cached("xml/").$current_user->getUserPrivGuid()."_lead_source_by_outcome_".$dateFileNameSafe[0]."_".$dateFileNameSafe[1].".xml"; $GLOBALS['log']->debug("cache file name is: $cache_file_name"); -$tools=''; +$tools=''; echo '' . get_form_header($current_module_strings['LBL_SALES_STAGE_FORM_TITLE'], $tools , false) . ''; ?> @@ -228,11 +228,11 @@ $puser_date_start = $current_user->getPreference('user_date_start'); - + - + @@ -263,11 +263,11 @@ Calendar.setup ({ ".$this->gen_xml($datax, $dateXml[0], $dateXml[1], $ids, $sugar_config['tmp_dir'].$cache_file_name, $refresh,'hBarF',$current_module_strings)."

"; +echo "

".$this->gen_xml($datax, $dateXml[0], $dateXml[1], $ids, $cache_file_name, $refresh,'hBarF',$current_module_strings)."

"; echo "

".$current_module_strings['LBL_SALES_STAGE_FORM_DESC']."

"; - if (file_exists($sugar_config['tmp_dir'].$cache_file_name)) { - $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($sugar_config['tmp_dir'].$cache_file_name))); + if (file_exists($cache_file_name)) { + $file_date = $timedate->asUser($timedate->fromTimestamp(filemtime($cache_file_name))); } else { $file_date = ''; @@ -353,8 +353,7 @@ echo get_validate_chart_js(); - $result = $opp->db->query($query) - or sugar_die("Error selecting sugarbean: ".mysql_error()); + $result = $opp->db->query($query, true); //build pipeline by sales stage data $total = 0; $div = 1; @@ -377,7 +376,7 @@ echo get_validate_chart_js(); $usernameArr = array(); $rowTotalArr = array(); $rowTotalArr[] = 0; - while($row = $opp->db->fetchByAssoc($result, -1, false)) + while($row = $opp->db->fetchByAssoc($result, false)) { if($row['total']*$div<=100){ $sum = round($row['total']*$div, 2); diff --git a/modules/Configurator/Configurator.php b/modules/Configurator/Configurator.php index cdd08e51..a34948cf 100644 --- a/modules/Configurator/Configurator.php +++ b/modules/Configurator/Configurator.php @@ -185,7 +185,7 @@ class Configurator { function saveImages() { if (!empty ($_POST['company_logo'])) { - $this->saveCompanyLogo($_POST['company_logo']); + $this->saveCompanyLogo("upload://".$_POST['company_logo']); } } diff --git a/modules/Configurator/UploadFileCheck.php b/modules/Configurator/UploadFileCheck.php index c67581b3..682c1524 100644 --- a/modules/Configurator/UploadFileCheck.php +++ b/modules/Configurator/UploadFileCheck.php @@ -38,6 +38,7 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); require_once('include/JSON.php'); require_once('include/entryPoint.php'); +require_once 'include/upload_file.php'; global $sugar_config; $supportedExtensions = array('jpg', 'png', 'jpeg'); @@ -49,32 +50,27 @@ if($json->decode(html_entity_decode($_REQUEST['forQuotes']))){ }else{ $returnArray['forQuotes']="company"; } +$upload_ok = false; if(isset($_FILES['file_1'])){ - $uploadTmpDir=$sugar_config['tmp_dir'].'tmp_logo_'.$returnArray['forQuotes'].'_upload'; - $file_name = $uploadTmpDir . DIRECTORY_SEPARATOR . cleanFileName(basename($_FILES['file_1']['name'])); - if(file_exists($uploadTmpDir)) - rmdir_recursive($uploadTmpDir); - - mkdir_recursive( $uploadTmpDir,null,true ); - if (!empty($_FILES['file_1']['error'])){ - rmdir_recursive($uploadTmpDir); - $returnArray['data']='not_recognize'; - echo $json->encode($returnArray); - sugar_cleanup(); - exit(); - } - if (!move_uploaded_file($_FILES['file_1']['tmp_name'], $file_name)){ - rmdir_recursive($uploadTmpDir); - die("Possible file upload attack!\n"); + $upload = new UploadFile('file_1'); + if($upload->confirm_upload()) { + $dir = "upload://tmp_logo_{$returnArray['forQuotes']}_upload"; + UploadStream::ensureDir($dir); + $file_name = $dir."/".$upload->get_stored_file_name(); + if($upload->final_move($file_name)) { + $upload_ok = true; + } } -}else{ +} +if(!$upload_ok) { $returnArray['data']='not_recognize'; echo $json->encode($returnArray); sugar_cleanup(); exit(); } -if(file_exists($file_name) && is_file($file_name)){ - $returnArray['path']=$file_name; +if(file_exists($file_name) && is_file($file_name)) { + $returnArray['path']=substr($file_name, 9); // strip upload prefix + $returnArray['url']= 'cache/images/'.$upload->get_stored_file_name(); if(!verify_uploaded_image($file_name, $returnArray['forQuotes'] == 'quotes')) { $returnArray['data']='other'; $returnArray['path'] = ''; @@ -88,6 +84,7 @@ if(file_exists($file_name) && is_file($file_name)){ } if (($test>20 || $test<3)&& $returnArray['forQuotes'] == 'quotes') $returnArray['data']='size'; + copy($file_name, sugar_cached('images/'.$upload->get_stored_file_name())); } if(!empty($returnArray['data'])){ echo $json->encode($returnArray); @@ -100,8 +97,5 @@ if(file_exists($file_name) && is_file($file_name)){ $returnArray['data']='file_error'; echo $json->encode($returnArray); } -if($rmdir) - rmdir_recursive($uploadTmpDir); sugar_cleanup(); exit(); -?> diff --git a/modules/Configurator/controller.php b/modules/Configurator/controller.php index d53091cd..6b128066 100644 --- a/modules/Configurator/controller.php +++ b/modules/Configurator/controller.php @@ -49,14 +49,14 @@ class ConfiguratorController extends SugarController } $this->view = 'fontmanager'; } - + /** * Delete a font and go back to the font manager */ function action_deleteFont(){ global $current_user; if(!is_admin($current_user)){ - sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); + sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); } $urlSTR = 'index.php?module=Configurator&action=FontManager'; if(!empty($_REQUEST['filename'])){ @@ -69,7 +69,7 @@ class ConfiguratorController extends SugarController } header("Location: $urlSTR"); } - + function action_listview(){ global $current_user; if(!is_admin($current_user)){ @@ -93,7 +93,7 @@ class ConfiguratorController extends SugarController function action_addFont(){ global $current_user, $mod_strings; if(!is_admin($current_user)){ - sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); + sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']); } if(empty($_FILES['pdf_metric_file']['name'])){ $this->errors[]=translate("ERR_MISSING_REQUIRED_FIELDS")." ".translate("LBL_PDF_METRIC_FILE", "Configurator"); @@ -107,13 +107,13 @@ class ConfiguratorController extends SugarController } $path_info = pathinfo($_FILES['pdf_font_file']['name']); $path_info_metric = pathinfo($_FILES['pdf_metric_file']['name']); - if(($path_info_metric['extension']!="afm" && $path_info_metric['extension']!="ufm") || + if(($path_info_metric['extension']!="afm" && $path_info_metric['extension']!="ufm") || ($path_info['extension']!="ttf" && $path_info['extension']!="otf" && $path_info['extension']!="pfb")){ $this->errors[]=translate("JS_ALERT_PDF_WRONG_EXTENSION", "Configurator"); $this->view = 'addFontView'; return; } - + if($_REQUEST['pdf_embedded'] == "false"){ if(empty($_REQUEST['pdf_cidinfo'])){ $this->errors[]=translate("ERR_MISSING_CIDINFO", "Configurator"); @@ -141,26 +141,26 @@ class ConfiguratorController extends SugarController $focus = new Administration(); $focus->retrieveSettings(); $focus->saveConfig(); - + $configurator = new Configurator(); $configurator->populateFromPost(); $configurator->handleOverride(); $configurator->parseLoggerSettings(); $configurator->saveConfig(); - + // Bug 37310 - Delete any existing currency that matches the one we've just set the default to during the admin wizard $currency = new Currency; $currency->retrieve($currency->retrieve_id_by_name($_REQUEST['default_currency_name'])); - if ( !empty($currency->id) + if ( !empty($currency->id) && $currency->symbol == $_REQUEST['default_currency_symbol'] && $currency->iso4217 == $_REQUEST['default_currency_iso4217'] ) { $currency->deleted = 1; $currency->save(); } - + SugarApplication::redirect('index.php?module=Users&action=Wizard&skipwelcome=1'); } - + function action_saveconfig() { global $current_user; @@ -169,17 +169,17 @@ class ConfiguratorController extends SugarController } $configurator = new Configurator(); $configurator->saveConfig(); - + $focus = new Administration(); $focus->saveConfig(); - + // Clear the Contacts file b/c portal flag affects rendering - if (file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/Contacts/EditView.tpl')) - unlink($GLOBALS['sugar_config']['cache_dir'].'modules/Contacts/EditView.tpl'); - + if (file_exists($cachedfile = sugar_cached('modules/Contacts/EditView.tpl'))) + unlink($cachedfile); + SugarApplication::redirect('index.php?module=Administration&action=index'); } - + function action_detail() { global $current_user; diff --git a/modules/Configurator/language/en_us.lang.php b/modules/Configurator/language/en_us.lang.php index bc3c676f..6e3e3a21 100644 --- a/modules/Configurator/language/en_us.lang.php +++ b/modules/Configurator/language/en_us.lang.php @@ -418,6 +418,14 @@ To configure additional system settings, click @@ -142,7 +142,7 @@ {$MOD.CURRENT_LOGO} {sugar_help text=$MOD.CURRENT_LOGO_HELP} @@ -224,21 +224,6 @@

get_user_date_format().")"; ?>
<?php echo $app_strings['LBL_ENTER_DATE']; ?> getImage('jscalendar', 'id="date_start_trigger" align="absmiddle"', null, null, ".gif", $app_strings['LBL_ENTER_DATE']); ?>

get_user_date_format().")"; ?>
<?php echo $app_strings['LBL_ENTER_DATE']; ?> getImage('jscalendar', 'id="date_end_trigger" align="absmiddle"', null, null, ".gif", $app_strings['LBL_ENTER_DATE']); ?>
- + $mod_strings.LBL_LOGO
- - - - - - - {if !empty($settings.system_mailmerge_on)} - {assign var='system_mailmerge_on_checked' value='CHECKED'} - {else} - {assign var='system_mailmerge_on_checked' value=''} - {/if} - - -

{$MOD.LBL_MAILMERGE}

{$MOD.LBL_ENABLE_MAILMERGE} {sugar_help text=$MOD.LBL_MAILMERGE_DESC WIDTH=400}
- @@ -368,7 +353,7 @@ addToValidateMoreThan('ConfigureSettings', 'list_max_entries_per_subpanel', 'int {literal} @@ -402,7 +387,7 @@ function toggleDisplay_2(div_string){ case 'size': alert(SUGAR.language.get('Configurator','LBL_ALERT_SIZE_RATIO')); document.getElementById(forQuotes + "_logo").value=file_type['path']; - document.getElementById(forQuotes + "_logo_image").src=file_type['path']; + document.getElementById(forQuotes + "_logo_image").src=file_type['url']; break; case 'file_error': alert(SUGAR.language.get('Configurator','ERR_ALERT_FILE_UPLOAD')); @@ -411,7 +396,7 @@ function toggleDisplay_2(div_string){ //File good case 'ok': document.getElementById(forQuotes + "_logo").value=file_type['path']; - document.getElementById(forQuotes + "_logo_image").src=file_type['path']; + document.getElementById(forQuotes + "_logo_image").src=file_type['url']; break; //error in getimagesize because unsupported type default: diff --git a/modules/Configurator/tpls/SugarpdfSettings.tpl b/modules/Configurator/tpls/SugarpdfSettings.tpl index 002184ba..f3a9f9d1 100644 --- a/modules/Configurator/tpls/SugarpdfSettings.tpl +++ b/modules/Configurator/tpls/SugarpdfSettings.tpl @@ -39,7 +39,7 @@ *} - +
@@ -50,19 +50,19 @@     - +
- +
{html_radios name="sugarpdf_pdf_class" options=$pdf_class selected=$selected_pdf_class separator=' ' onchange='processPDFClass()'}
- + @@ -86,8 +86,8 @@

{$MOD.SUGARPDF_BASIC_SETTINGS}

- - + + diff --git a/modules/Configurator/tpls/addFontView.tpl b/modules/Configurator/tpls/addFontView.tpl index d7ef745e..c264bd80 100644 --- a/modules/Configurator/tpls/addFontView.tpl +++ b/modules/Configurator/tpls/addFontView.tpl @@ -39,7 +39,7 @@ *} - +

{$MODULE_TITLE}

@@ -51,7 +51,7 @@ +

{$MOD.SUGARPDF_LOGO_SETTINGS}

  -

@@ -131,7 +131,7 @@ function checkFileExtension(metric){ if(element.value != ""){ var error=true; var filename = element.value; - var dot = filename.lastIndexOf("."); + var dot = filename.lastIndexOf("."); if( dot != -1 ){ var extension = filename.substr(dot,filename.length); if(!metric){ @@ -146,7 +146,7 @@ function checkFileExtension(metric){ alert("{$MOD.JS_ALERT_PDF_WRONG_EXTENSION}"); {literal} } - } + } } function showCidInfo(){ if(document.getElementById("pdf_embedded").checked == false){ diff --git a/modules/Configurator/tpls/adminwizard.tpl b/modules/Configurator/tpls/adminwizard.tpl index 79b22a28..a27cebd2 100644 --- a/modules/Configurator/tpls/adminwizard.tpl +++ b/modules/Configurator/tpls/adminwizard.tpl @@ -36,7 +36,7 @@ *} - + @@ -63,9 +63,9 @@ function disableReturnSubmission(e) { {$error.main} - + - +
@@ -84,7 +84,7 @@ function disableReturnSubmission(e) {

{$MOD.LBL_WIZARD_WELCOME}

-
+
{$MOD.LBL_WELCOME}
@@ -131,7 +131,7 @@ function disableReturnSubmission(e) { {$MOD.CURRENT_LOGO} {sugar_help text=$MOD.CURRENT_LOGO_HELP} - + {$MOD.LBL_LOGO} @@ -212,8 +212,9 @@ function disableReturnSubmission(e) {
+ {sugar_translate module='Administration' label='LBL_LOCALE_DEFAULT_NAME_FORMAT'}: - + {html_options id="default_locale_name_format" name="default_locale_name_format" selected=$config.default_locale_name_format options=$NAMEFORMATS} @@ -372,7 +373,7 @@ addToValidate('ConfigureSettings', 'system_name', 'varchar', true,'System Name' diff --git a/modules/Configurator/tpls/fontmanager.tpl b/modules/Configurator/tpls/fontmanager.tpl index 6cb82d08..c6cb8c5c 100644 --- a/modules/Configurator/tpls/fontmanager.tpl +++ b/modules/Configurator/tpls/fontmanager.tpl @@ -38,7 +38,7 @@ *} - + {literal} {JAVASCRIPT} - + {JSLANG} - - + + +
@@ -71,18 +71,18 @@ addUploadFiles('EditView'); addUploadDocs('EditView'); - return check_form('EditView');" - type="submit" name="button" value="{APP.LBL_SAVE_BUTTON_LABEL}"> - + return check_form('EditView');" + type="submit" name="button" value="{APP.LBL_SAVE_BUTTON_LABEL}" id="SAVE"> + - {APP.LBL_REQUIRED_SYMBOL} + {APP.LBL_REQUIRED_SYMBOL} - {APP.NTC_REQUIRED} + {APP.NTC_REQUIRED} - {ADMIN_EDIT} + {ADMIN_EDIT} @@ -93,13 +93,13 @@ @@ -108,48 +108,48 @@ @@ -159,45 +159,45 @@ {MOD.LBL_SUBJECT} diff --git a/modules/EmailTemplates/EditView.php b/modules/EmailTemplates/EditView.php index 075e199f..98cc8399 100644 --- a/modules/EmailTemplates/EditView.php +++ b/modules/EmailTemplates/EditView.php @@ -166,8 +166,8 @@ $xtpl->assign('encoded_assigned_users_popup_request_data', $json->encode($popup_ if(!empty($focus->assigned_user_name)) $xtpl->assign("ASSIGNED_USER_NAME", $focus->assigned_user_name); -$xtpl->assign("assign_user_select", SugarThemeRegistry::current()->getImage('id-ff-select')); -$xtpl->assign("assign_user_clear", SugarThemeRegistry::current()->getImage('id-ff-clear')); +$xtpl->assign("assign_user_select", SugarThemeRegistry::current()->getImage('id-ff-select','',null,null,'.png',$mod_strings['LBL_SELECT'])); +$xtpl->assign("assign_user_clear", SugarThemeRegistry::current()->getImage('id-ff-clear','',null,null,'.gif',$mod_strings['LBL_ID_FF_CLEAR'])); //Assign qsd script require_once('include/QuickSearchDefaults.php'); $qsd = new QuickSearchDefaults(); @@ -178,11 +178,11 @@ $xtpl->assign("CANCEL_SCRIPT", $cancel_script); $xtpl->assign("PRINT_URL", "index.php?".$GLOBALS['request_string']); $xtpl->assign("JAVASCRIPT", get_set_focus_js() . $quicksearch_js); -if(!is_file($GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $GLOBALS['current_language'] . '.js')) { +if(!is_file(sugar_cached('jsLanguage/') . $GLOBALS['current_language'] . '.js')) { require_once('include/language/jsLanguage.php'); jsLanguage::createAppStringsCache($GLOBALS['current_language']); } -$jsLang = ''; +$jsLang = getVersionedScript("cache/jsLanguage/{$GLOBALS['current_language']}.js", $GLOBALS['sugar_config']['js_lang_version']); $xtpl->assign("JSLANG", $jsLang); $xtpl->assign("ID", $focus->id); @@ -217,8 +217,9 @@ if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($ if(!empty($_REQUEST['record'])) { $record = $_REQUEST['record']; } - $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + + $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); + } if(isset($focus->parent_type) && $focus->parent_type != "") { $change_parent_button = "assign('ATTACHMENTS', $attachments); diff --git a/modules/EmailTemplates/EditViewMain.html b/modules/EmailTemplates/EditViewMain.html index b2514215..162727e5 100644 --- a/modules/EmailTemplates/EditViewMain.html +++ b/modules/EmailTemplates/EditViewMain.html @@ -43,12 +43,12 @@ #subjectfield { height: 1.6em; } {JAVASCRIPT} - - - + + + + {JSLANG} @@ -71,18 +71,18 @@ addUploadFiles('EditView'); addUploadDocs('EditView'); - return check_form('EditView');" - type="submit" name="button" value="{APP.LBL_SAVE_BUTTON_LABEL}"> - + return check_form('EditView');" + type="submit" name="button" value="{APP.LBL_SAVE_BUTTON_LABEL}" id="SAVE"> +
- {MOD.LBL_NAME} + {MOD.LBL_NAME} {APP.LBL_REQUIRED_SYMBOL} - +
- {MOD.LBL_DESCRIPTION} + {MOD.LBL_DESCRIPTION} - +
-   +  
- {MOD.LBL_INSERT_VARIABLE}  + {MOD.LBL_INSERT_VARIABLE}  - {DROPDOWN} - - {MOD.LBL_USE}: + {MOD.LBL_USE}: - + - +
- {MOD.LBL_INSERT_TRACKER_URL}  + {MOD.LBL_INSERT_TRACKER_URL}  - {TRACKER_KEY_OPTIONS} - +
- +
  - -  {MOD.LBL_SEND_AS_TEXT} + +  {MOD.LBL_SEND_AS_TEXT}
- {MOD.LBL_BODY} + {MOD.LBL_BODY}
- +

- +

+ +
- {MOD.LBL_ATTACHMENTS}: + {MOD.LBL_ATTACHMENTS}: - {ATTACHMENTS_JAVASCRIPT} {ATTACHMENTS} + {ATTACHMENTS_JAVASCRIPT} {ATTACHMENTS}
- {APP.LBL_REQUIRED_SYMBOL} + {APP.LBL_REQUIRED_SYMBOL} - {APP.NTC_REQUIRED} + {APP.NTC_REQUIRED} - {ADMIN_EDIT} + {ADMIN_EDIT}
@@ -92,72 +92,72 @@ @@ -167,26 +167,26 @@ {MOD.LBL_SUBJECT} diff --git a/modules/EmailTemplates/EmailTemplate.php b/modules/EmailTemplates/EmailTemplate.php index 08e7de8c..a67de984 100644 --- a/modules/EmailTemplates/EmailTemplate.php +++ b/modules/EmailTemplates/EmailTemplate.php @@ -59,6 +59,8 @@ class EmailTemplate extends SugarBean { var $created_by; var $created_by_name; var $modified_by_name; + var $assigned_user_id; + var $assigned_user_name; var $name; var $published; var $description; @@ -208,6 +210,7 @@ class EmailTemplate extends SugarBean { } $this->created_by_name = get_assigned_user_name($this->created_by); $this->modified_by_name = get_assigned_user_name($this->modified_user_id); + $this->assigned_user_name = get_assigned_user_name($this->assigned_user_id); $this->fill_in_additional_parent_fields(); } diff --git a/modules/EmailTemplates/EmailTemplateFormBase.php b/modules/EmailTemplates/EmailTemplateFormBase.php index 74638b33..54871031 100644 --- a/modules/EmailTemplates/EmailTemplateFormBase.php +++ b/modules/EmailTemplates/EmailTemplateFormBase.php @@ -47,8 +47,8 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); class EmailTemplateFormBase { function getFormBody($prefix, $mod='',$formname='', $size='30') { - - + + global $mod_strings; $temp_strings = $mod_strings; @@ -129,14 +129,11 @@ EOQ; } - function handleSave($prefix,$redirect=true, $useRequired=false) { - - - - + function handleSave($prefix,$redirect=true, $useRequired=false) + { require_once('include/formbase.php'); require_once('include/upload_file.php'); - global $upload_maxsize, $upload_dir; + global $upload_maxsize; global $mod_strings; global $sugar_config; @@ -159,30 +156,23 @@ EOQ; $preProcessedImages = array(); $emailTemplateBodyHtml = from_html($focus->body_html); - $fileBasePath = "{$sugar_config['cache_dir']}images/"; - $filePatternSearch = "{$sugar_config['cache_dir']}"; - $filePatternSearch = str_replace("/", "\/", $filePatternSearch); - $filePatternSearch = $filePatternSearch . "images\/"; - $fileBasePath1 = "\"" .$fileBasePath; - if(strpos($emailTemplateBodyHtml, "\"{$fileBasePath}")) { + if(strpos($emailTemplateBodyHtml, '"cache/images/')) { $matches = array(); - preg_match_all("/{$filePatternSearch}.+?\"/i", $emailTemplateBodyHtml, $matches); - foreach($matches[0] as $match) { - $filenameUndecoded = str_replace($fileBasePath, '', $match); - $filename = urldecode(substr($filenameUndecoded, 0, -1)); - $filenameUndecoded = str_replace("\"", '', $filenameUndecoded); - $cid = $filename; - $file_location = clean_path(getcwd()."/{$sugar_config['cache_dir']}images/{$filename}"); - $mime_type = strtolower(substr($filename, strrpos($filename, ".")+1, strlen($filename))); + preg_match_all('#]*[\s]+src[^=]*=[\s]*["\']cache/images/(.+?)["\']#si', $emailTemplateBodyHtml, $matches); + foreach($matches[1] as $match) { + $filename = urldecode($match); + + $file_location = sugar_cached("images/{$filename}"); + $mime_type = pathinfo($filename, PATHINFO_EXTENSION); if(file_exists($file_location)) { $id = create_guid(); - $newFileLocation = "{$sugar_config['upload_dir']}{$id}"; + $newFileLocation = "upload://$id"; if(!copy($file_location, $newFileLocation)) { - $GLOBALS['log']->debug("EMAIL Template could not copy attachment to {$sugar_config['upload_dir']} [ {$newFileLocation} ]"); + $GLOBALS['log']->debug("EMAIL Template could not copy attachment to $newFileLocation"); } else { - $secureLink = 'index.php?entryPoint=download&id='.$id.'&type=Notes'; - $emailTemplateBodyHtml = str_replace("{$sugar_config['cache_dir']}images/{$filenameUndecoded}", $secureLink, $emailTemplateBodyHtml); + $secureLink = "index.php?entryPoint=download&type=Notes&id={$id}"; + $emailTemplateBodyHtml = str_replace("cache/images/$match", $secureLink, $emailTemplateBodyHtml); unlink($file_location); $preProcessedImages[$filename] = $id; } @@ -204,7 +194,7 @@ EOQ; //// ADDING NEW ATTACHMENTS $max_files_upload = count($_FILES); - + if(!empty($focus->id)) { $note = new Note(); $where = "notes.parent_id='{$focus->id}'"; @@ -239,11 +229,10 @@ EOQ; $note->new_with_id = TRUE; $GLOBALS['log']->debug("Image {$file['name']} has already been processed."); } - + $i=preg_replace("/email_attachment(.+)/",'$1',$key); $upload_file = new UploadFile($key); - if(isset($_FILES[$key]) && $upload_file->confirm_upload() && preg_match("/^email_attachment/",$key)) { $note->filename = $upload_file->get_stored_file_name(); $note->file = $upload_file; @@ -262,13 +251,13 @@ EOQ; } $focus->saved_attachments = array(); - foreach($focus->attachments as $note) + foreach($focus->attachments as $note) { - if( !empty($note->id) && $note->new_with_id === FALSE) + if( !empty($note->id) && $note->new_with_id === FALSE) { - if(empty($_REQUEST['old_id'])) + if(empty($_REQUEST['old_id'])) array_push($focus->saved_attachments, $note); // to support duplication of email templates - else + else { // we're duplicating a template with attachments // dupe the file, create a new note, assign the note to the new template @@ -278,11 +267,10 @@ EOQ; $newNote->parent_id = $focus->id; $newNote->new_with_id = true; $newNote->date_modified = ''; - $newNote->date_entered = ''; + $newNote->date_entered = ''; $newNoteId = $newNote->save(); - $dupeFile = new UploadFile('duplicate'); - $dupeFile->duplicate_file($note->id, $newNoteId, $note->filename); + UploadFile::duplicate_file($note->id, $newNoteId, $note->filename); } continue; } @@ -292,10 +280,10 @@ EOQ; $note_id = $note->save(); array_push($focus->saved_attachments, $note); $note->id = $note_id; - + if($note->new_with_id === FALSE) $note->file->final_move($note->id); - else + else $GLOBALS['log']->debug("Not performing final move for note id {$note->id} as it has already been processed"); } @@ -319,7 +307,6 @@ EOQ; $doc = new Document(); $docRev = new DocumentRevision(); $docNote = new Note(); - $noteFile = new UploadFile('none'); $doc->retrieve($_REQUEST['documentId'.$i]); $docRev->retrieve($doc->document_revision_id); @@ -334,7 +321,7 @@ EOQ; $docNote->file_mime_type = $docRev->file_mime_type; $docId = $docNote = $docNote->save(); - $noteFile->duplicate_file($docRev->id, $docId, $docRev->filename); + UploadFile::duplicate_file($docRev->id, $docId, $docRev->filename); } } diff --git a/modules/EmailTemplates/PopupDocumentsCampaignTemplate.html b/modules/EmailTemplates/PopupDocumentsCampaignTemplate.html index 1b59c3c4..c4ec319a 100644 --- a/modules/EmailTemplates/PopupDocumentsCampaignTemplate.html +++ b/modules/EmailTemplates/PopupDocumentsCampaignTemplate.html @@ -37,8 +37,8 @@ --> - - + +
- {MOD.LBL_NAME} + {MOD.LBL_NAME} {APP.LBL_REQUIRED_SYMBOL} - +
{APP.LBL_ASSIGNED_TO}  - + - - +
- {MOD.LBL_DESCRIPTION} + {MOD.LBL_DESCRIPTION} - +
-   +  
- {MOD.LBL_INSERT_VARIABLE}  + {MOD.LBL_INSERT_VARIABLE}  - {DROPDOWN} - - {MOD.LBL_USE}: + {MOD.LBL_USE}: - + - +
- {MOD.LBL_INSERT_TRACKER_URL}  + {MOD.LBL_INSERT_TRACKER_URL}  - {TRACKER_KEY_OPTIONS} - +
- +
  - -  {MOD.LBL_SEND_AS_TEXT} + +  {MOD.LBL_SEND_AS_TEXT}
- {MOD.LBL_BODY} + {MOD.LBL_BODY}
- +

@@ -194,18 +194,18 @@

+ +
- {MOD.LBL_ATTACHMENTS}: + {MOD.LBL_ATTACHMENTS}: - {ATTACHMENTS_JAVASCRIPT} {ATTACHMENTS} + {ATTACHMENTS_JAVASCRIPT} {ATTACHMENTS}
diff --git a/modules/EmailTemplates/language/en_us.lang.php b/modules/EmailTemplates/language/en_us.lang.php index 4da1bf0a..c7dd3858 100644 --- a/modules/EmailTemplates/language/en_us.lang.php +++ b/modules/EmailTemplates/language/en_us.lang.php @@ -112,5 +112,8 @@ $mod_strings = array ( 'LBL_ACTIVITIES_REPORTS' => 'Activities Report', 'LNK_VIEW_MY_INBOX' => 'View My Email', 'LBL_ASSIGNED_TO_ID' => 'Assigned To', + 'LBL_EDIT_LAYOUT' => 'Edit Layout' /*for 508 compliance fix*/, + 'LBL_SELECT' => 'Select' /*for 508 compliance fix*/, + 'LBL_ID_FF_CLEAR' => 'Clear' /*for 508 compliance fix*/, ); ?> \ No newline at end of file diff --git a/modules/EmailText/EmailText.php b/modules/EmailText/EmailText.php new file mode 100644 index 00000000..b64114d1 --- /dev/null +++ b/modules/EmailText/EmailText.php @@ -0,0 +1,49 @@ +retrieve($data['parent_id']); + $bean = new $class(); + $bean->retrieve($data['parent_id']); + } if (isset($bean->full_name)) { $parentName = $bean->full_name; } elseif(isset($bean->name)) { @@ -130,7 +133,7 @@ function generateComposeDataPackage($data,$forFullCompose = TRUE) $email_id = ""; $attachments = array(); if ($bean->module_dir == 'Cases') { - $subject = str_replace('%1', $bean->case_number, $bean->getEmailSubjectMacro() . " ". from_html($bean->name)) ;//bug 41928 + $subject = str_replace('%1', $bean->case_number, $bean->getEmailSubjectMacro() . " ". from_html($bean->name)) ;//bug 41928 $bean->load_relationship("contacts"); $contact_ids = $bean->contacts->get(); $contact = new Contact(); @@ -145,7 +148,7 @@ function generateComposeDataPackage($data,$forFullCompose = TRUE) require_once("modules/Emails/EmailUI.php"); $subject = $bean->kbdocument_name; - $article_body = str_replace('/'.$GLOBALS['sugar_config']['cache_dir'].'images/',$GLOBALS['sugar_config']['site_url'].'/'.$GLOBALS['sugar_config']['cache_dir'].'images/',KBDocument::get_kbdoc_body_without_incrementing_count($bean->id)); + $article_body = str_replace('/cache/images/',$GLOBALS['sugar_config']['site_url'].'/cache/images/',KBDocument::get_kbdoc_body_without_incrementing_count($bean->id)); $body = from_html($article_body); $attachments = KBDocument::get_kbdoc_attachments_for_newemail($bean->id); $attachments = $attachments['attachments']; @@ -171,7 +174,7 @@ function generateComposeDataPackage($data,$forFullCompose = TRUE) ); } else if(isset($_REQUEST['ListView'])) { - + $email = new Email(); $namePlusEmail = $email->getNamePlusEmailAddressesForCompose($_REQUEST['action_module'], (explode(",", $_REQUEST['uid']))); $ret = array( @@ -240,7 +243,7 @@ function generateComposeDataPackage($data,$forFullCompose = TRUE) 'to_email_addrs' => '', ); } - + if($forFullCompose) initFullCompose($ret); else @@ -250,7 +253,7 @@ function generateComposeDataPackage($data,$forFullCompose = TRUE) function getQuotesRelatedData($bean,$data) { $return = array(); $emailId = $data['recordId']; - + require_once("modules/Emails/EmailUI.php"); $email = new Email(); $email->retrieve($emailId); diff --git a/modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.php b/modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.php index 87ab92d4..e52974b3 100644 --- a/modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.php +++ b/modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.php @@ -94,25 +94,31 @@ class MyEmailsDashlet extends DashletGeneric { diff --git a/modules/Emails/DetailView.html b/modules/Emails/DetailView.html index 0576d535..48608688 100644 --- a/modules/Emails/DetailView.html +++ b/modules/Emails/DetailView.html @@ -39,7 +39,7 @@ ********************************************************************************/ --> - + diff --git a/modules/Emails/DetailView.php b/modules/Emails/DetailView.php index d20caa86..70328f92 100644 --- a/modules/Emails/DetailView.php +++ b/modules/Emails/DetailView.php @@ -197,10 +197,8 @@ if(isset($start['assigned_user_id']) && !empty($start['assigned_user_id'])) { $html = trim(from_html($focus->description_html)); if(empty($html)) { $xtpl->assign('SHOW_PLAINTEXT', 'true'); - $description = nl2br($focus->description); } else { $xtpl->assign('SHOW_PLAINTEXT', 'false'); - $description = from_html($focus->description_html); } $show_subpanels=true; //if the email is of type campaign, process the macros...using the values stored in the relationship table. @@ -266,8 +264,6 @@ $xtpl->assign('CC', $cc_addr); $xtpl->assign('BCC', $bcc_addr); $xtpl->assign('CREATED_BY', $focus->created_by_name); $xtpl->assign('MODIFIED_BY', $focus->modified_by_name); -$xtpl->assign('DESCRIPTION', nl2br($focus->description)); -$xtpl->assign('DESCRIPTION_HTML', from_html($focus->description_html)); $xtpl->assign('DATE_SENT', $focus->date_entered); $xtpl->assign('EMAIL_NAME', 'RE: '.$focus->name); $xtpl->assign("TAG", $focus->listviewACLHelper()); @@ -296,7 +292,7 @@ $xtpl->assign("JS_VARS", $jsVars); // ADMIN EDIT if(is_admin($GLOBALS['current_user']) && $_REQUEST['module'] != 'DynamicLayout' && !empty($_SESSION['editinplace'])){ - $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); } if(isset($_REQUEST['offset']) && !empty($_REQUEST['offset'])) { $offset = $_REQUEST['offset']; } @@ -334,8 +330,11 @@ for($i=0; $ifilename)) $attachments .= "id."&type=Notes\">".$the_note->name."
"; + $focus->cid2Link($the_note->id, $the_note->file_mime_type); } +$xtpl->assign('DESCRIPTION', nl2br($focus->description)); +$xtpl->assign('DESCRIPTION_HTML', from_html($focus->description_html)); $xtpl->assign("ATTACHMENTS", $attachments); $xtpl->parse("main"); $xtpl->out("main"); diff --git a/modules/Emails/DetailViewSent.html b/modules/Emails/DetailViewSent.html index 45635b63..e7769586 100644 --- a/modules/Emails/DetailViewSent.html +++ b/modules/Emails/DetailViewSent.html @@ -39,7 +39,7 @@ ********************************************************************************/ --> - + diff --git a/modules/Emails/EditView.html b/modules/Emails/EditView.html deleted file mode 100644 index b675cce8..00000000 --- a/modules/Emails/EditView.html +++ /dev/null @@ -1,433 +0,0 @@ - - - - - - - - -{MESSAGE} - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - {ADMIN_EDIT} -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - -   - - - - - -  {CHANGE_PARENT_BUTTON} - -
- - {APP.LBL_ASSIGNED_TO}  - - - - - - - - - - - - - - - - -
-   -
-   - - {MOD.LBL_NOTE_SEMICOLON} - -   -
- - {MOD.LBL_TO} - - - - - - - - -
- - - - - - {CHANGE_TO_ADDRS_BUTTON} -
-
-
- - {MOD.LBL_CC} - - - - - - - - -
- - - - - - {CHANGE_CC_ADDRS_BUTTON} -
-
-
- - {MOD.LBL_BCC} - - - - - - - -
- - - - - - {CHANGE_BCC_ADDRS_BUTTON} -
-
- - {MOD.LBL_FROM} - - - - - - - -
- {FROM_ADDR_GROUP} - - -
-
-
-   -
- - {MOD.LBL_SUBJECT} - - - - - -
- {MOD.LBL_BODY} - - -
- - {MOD.LBL_EMAIL_EDITOR_OPTION} -
-
-
- - {MOD.LBL_USE_TEMPLATE}  - - - - - -
-   - - {TINY} - -
- -
-
- - {MOD.LBL_EDIT_ALT_TEXT} -
- -
-
- {MOD.LBL_ATTACHMENTS} - - {ATTACHMENTS_JAVASCRIPT} {ATTACHMENTS} -
-
-
- - - - - - - - - - - - - - - - - - - - -
- - -
-
-
-{JAVASCRIPT} - - \ No newline at end of file diff --git a/modules/Emails/EditView.php b/modules/Emails/EditView.php index 15e27839..12b674f9 100644 --- a/modules/Emails/EditView.php +++ b/modules/Emails/EditView.php @@ -498,7 +498,7 @@ if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($ if(!empty($_REQUEST['record'])){ $record = $_REQUEST['record']; } - $xtpl->assign('ADMIN_EDIT',"".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $xtpl->assign('ADMIN_EDIT',"".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); } //// END GENERAL TEMPLATE ASSIGNMENTS @@ -548,7 +548,7 @@ $change_parent_button = ''; - + $xtpl->assign("CHANGE_PARENT_BUTTON", $change_parent_button); $button_attr = ''; @@ -586,7 +586,7 @@ if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($ if(!empty($_REQUEST['record'])) { $record = $_REQUEST['record']; } - $xtpl->assign('ADMIN_EDIT',"".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $xtpl->assign('ADMIN_EDIT',"".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); } if(empty($focus->assigned_user_id) && empty($focus->id)) @@ -641,7 +641,7 @@ if(!empty($focus->id) || (!empty($_REQUEST['record']) && $_REQUEST['type'] == 'f $attachments .= "
-  "; + " . SugarThemeRegistry::current()->getImage('delete_inline', "onclick='deletePriorAttachment(\"{$the_note->id}\");' value='{$the_note->id}'", null, null, ".gif", $mod_strings['LBL_DELETE_INLINE']) . " "; $attachments .= "id."&type=Notes\">".$the_note->name."
"; //$attachments .= ''. $the_note->filename .'
'; @@ -655,7 +655,6 @@ if(!empty($focus->id) || (!empty($_REQUEST['record']) && $_REQUEST['type'] == 'f } $attJs = ''; $xtpl->assign('ATTACHMENTS', $attachments); diff --git a/modules/Emails/EditViewArchive.html b/modules/Emails/EditViewArchive.html index ba814f1d..eaa526c9 100644 --- a/modules/Emails/EditViewArchive.html +++ b/modules/Emails/EditViewArchive.html @@ -46,7 +46,7 @@ #from_addr_field { height: 1.6em; } - + {MESSAGE}
@@ -140,7 +140,7 @@ - + {MOD.LBL_USE_TEMPLATE}  diff --git a/modules/Emails/Email.php b/modules/Emails/Email.php index 67abab03..0809a5dd 100644 --- a/modules/Emails/Email.php +++ b/modules/Emails/Email.php @@ -42,8 +42,8 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * Reserved. Contributor(s): ______________________________________.. *********************************************************************************/ require_once('include/SugarPHPMailer.php'); - require_once('include/Pear/HTML_Safe/Safe.php'); +require_once 'include/upload_file.php'; class Email extends SugarBean { /* SugarBean schema */ @@ -145,19 +145,24 @@ class Email extends SugarBean { /* public */ var $et; // EmailUI object - - + // prefix to use when importing inlinge images in emails + public $imagePrefix; /** * sole constructor */ - function Email() { - $this->cachePath = $GLOBALS['sugar_config']['cache_dir'].'modules/Emails'; + function Email() + { + global $current_user; + $this->cachePath = sugar_cached('modules/Emails'); parent::SugarBean(); $this->safe = new HTML_Safe(); + $this->safe->whiteProtocols[] = "cid"; $this->safe->clear(); $this->emailAddress = new SugarEmailAddress(); + + $this->imagePrefix = rtrim($GLOBALS['sugar_config']['site_url'], "/")."/cache/images/"; } function email2init() { @@ -177,50 +182,32 @@ class Email extends SugarBean { * DOES NOT CREATE A NOTE * @return string ID of note associated with the attachment */ - function email2saveAttachment() { - global $sugar_config; - - $filesError = array( - 0 => 'UPLOAD_ERR_OK - There is no error, the file uploaded with success.', - 1 => 'UPLOAD_ERR_INI_SIZE - The uploaded file exceeds the upload_max_filesize directive in php.ini.', - 2 => 'UPLOAD_ERR_FORM_SIZE - The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', - 3 => 'UPLOAD_ERR_PARTIAL - The uploaded file was only partially uploaded.', - 4 => 'UPLOAD_ERR_NO_FILE - No file was uploaded.', - 5 => 'UNKNOWN ERROR', - 6 => 'UPLOAD_ERR_NO_TMP_DIR - Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.', - 7 => 'UPLOAD_ERR_CANT_WRITE - Failed to write file to disk. Introduced in PHP 5.1.0.', - ); - - // cn: Bug 5995 - rudimentary error checking - if($_FILES['email_attachment']['error'] != 0 && $_FILES['email_attachment']['error'] != 4) { - $GLOBALS['log']->debug('Email Attachment could not be attach due to error: '.$filesError[$_FILES['email_attachment']['error']]); - return array(); - } - - if(isset($_FILES['email_attachment']) && is_uploaded_file($_FILES['email_attachment']['tmp_name'])) { - $guid = create_guid(); - $cleanAttachmentFileName = from_html($_FILES['email_attachment']['name']); - $GLOBALS['log']->debug("Email Attachment [ {$cleanAttachmentFileName} ] "); - $cleanAttachmentFileName = str_replace("\\", "", $cleanAttachmentFileName); - $GLOBALS['log']->debug("Email Attachment [ {$cleanAttachmentFileName} ] "); - //$destination = clean_path("{$this->et->userCacheDir}/{$guid}{$cleanAttachmentFileName}"); - $destination = clean_path("{$this->et->userCacheDir}/{$guid}"); - $badExt = $this->safeAttachmentName($cleanAttachmentFileName); - if ($badExt) { - //$destination = $destination . ".txt"; - } // if - $fileName = $badExt ? $cleanAttachmentFileName . ".txt" : $cleanAttachmentFileName; - if(move_uploaded_file($_FILES['email_attachment']['tmp_name'], $destination)) { - return array( + public function email2saveAttachment() + { + $email_uploads = "modules/Emails/{$GLOBALS['current_user']->id}"; + $upload = new UploadFile('email_attachment'); + if(!$upload->confirm_upload()) { + $err = $upload->get_upload_error(); + if($err) { + $GLOBALS['log']->error("Email Attachment could not be attached due to error: $err"); + } + return array(); + } + + $guid = create_guid(); + $fileName = $upload->create_stored_filename(); + $GLOBALS['log']->debug("Email Attachment [$fileName]"); + if($upload->final_move($guid)) { + copy("upload://$guid", sugar_cached("$email_uploads/$guid")); + return array( 'guid' => $guid, - 'name' => $GLOBALS['db']->helper->escape_quote($fileName), + 'name' => $GLOBALS['db']->quote($fileName), 'nameForDisplay' => $fileName ); - } else { - $GLOBALS['log']->debug("Email Attachment [ {$cleanAttachmentFileName} ] could not be moved to cache dir"); - return array(); - } - } + } else { + $GLOBALS['log']->debug("Email Attachment [$fileName] could not be moved to upload dir"); + return array(); + } } function safeAttachmentName($filename) { @@ -699,11 +686,10 @@ class Email extends SugarBean { $note->parent_type = $this->module_dir; $note->name = $filename; $note->filename = $filename; - $noteFile = "{$sugar_config['upload_dir']}{$note->id}"; $note->file_mime_type = $this->email2GetMime($fileLocation); - - if(!copy($fileLocation, $noteFile)) { - $GLOBALS['log']->debug("EMAIL 2.0: could not copy attachment file to cache/upload [ {$fileLocation} ]"); + $dest = "upload://{$note->id}"; + if(!copy($fileLocation, $dest)) { + $GLOBALS['log']->debug("EMAIL 2.0: could not copy attachment file to $fileLocation => $dest"); } $note->save(); @@ -716,9 +702,6 @@ class Email extends SugarBean { if(!empty($request['documents'])) { $exDocs = explode("::", $request['documents']); - - - foreach($exDocs as $docId) { $docId = trim($docId); if(!empty($docId)) { @@ -728,7 +711,7 @@ class Email extends SugarBean { $docRev->retrieve($doc->document_revision_id); $filename = $docRev->filename; - $fileLocation = "{$sugar_config['upload_dir']}{$docRev->id}"; + $fileLocation = "upload://{$docRev->id}"; $mime_type = $docRev->file_mime_type; $mail->AddAttachment($fileLocation,$locale->translateCharsetMIME(trim($filename), 'UTF-8', $OBCharset), 'base64', $mime_type); @@ -742,10 +725,9 @@ class Email extends SugarBean { $note->name = $filename; $note->filename = $filename; $note->file_mime_type = $mime_type; - $noteFile = "{$sugar_config['upload_dir']}{$note->id}"; - - if(!copy($fileLocation, $noteFile)) { - $GLOBALS['log']->debug("EMAIL 2.0: could not copy SugarDocument revision file to {$sugar_config['upload_dir']} [ {$fileLocation} ]"); + $dest = "upload://{$note->id}"; + if(!copy($fileLocation, $dest)) { + $GLOBALS['log']->debug("EMAIL 2.0: could not copy SugarDocument revision file $fileLocation => $dest"); } $note->save(); @@ -765,7 +747,7 @@ class Email extends SugarBean { $note->retrieve($noteId); if (!empty($note->id)) { $filename = $note->filename; - $fileLocation = "{$sugar_config['upload_dir']}{$note->id}"; + $fileLocation = "upload://{$note->id}"; $mime_type = $note->file_mime_type; if (!$note->embed_flag) { $mail->AddAttachment($fileLocation,$filename, 'base64', $mime_type); @@ -1069,8 +1051,6 @@ class Email extends SugarBean { */ function saveTempNoteAttachments($filename,$fileLocation, $mimeType) { - global $sugar_config; - $tmpNote = new Note(); $tmpNote->id = create_guid(); $tmpNote->new_with_id = true; @@ -1079,9 +1059,10 @@ class Email extends SugarBean { $tmpNote->name = $filename; $tmpNote->filename = $filename; $tmpNote->file_mime_type = $mimeType; - $noteFile = "{$sugar_config['upload_dir']}{$tmpNote->id}"; - if(!copy($fileLocation, $noteFile)) - $GLOBALS['log']->fatal("EMAIL 2.0: could not copy SugarDocument revision file to {$sugar_config['upload_dir']} [ {$fileLocation} ]"); + $noteFile = "upload://{$tmpNote->id}"; + if(!copy($fileLocation, $noteFile)) { + $GLOBALS['log']->fatal("EMAIL 2.0: could not copy SugarDocument revision file $fileLocation => $noteFile"); + } $tmpNote->save(); } /** @@ -1154,8 +1135,21 @@ class Email extends SugarBean { return $guid; } + protected $email_to_text = array( + "email_id" => "id", + "description" => "description", + "description_html" => "description_html", + "raw_source" => "raw_source", + "from_addr" => "from_addr_name", + "reply_to_addr" => "reply_to_addr", + "to_addrs" => "to_addrs_names", + "cc_addrs" => "cc_addrs_names", + "bcc_addrs" => "bcc_addrs_names", + ); + function cleanEmails($emails) { + if(empty($emails)) return ''; $emails = str_replace(array(",",";"), "::", from_html($emails)); $addrs = explode("::", $emails); $res = array(); @@ -1170,33 +1164,23 @@ class Email extends SugarBean { $res[] .= $parts["email"]; } } - return join(", ", $res); + return join(", ", $res); } - function saveEmailText() { - $isOracle = ($this->db->dbType == "oci8") ? true : false; - if ($isOracle) { + protected function saveEmailText() + { + $text = SugarModule::get("EmailText")->loadBean(); + foreach($this->email_to_text as $textfield=>$mailfield) { + $text->$textfield = $this->$mailfield; + } + $text->email_id = $this->id; + if(!$this->new_with_id) { + $this->db->update($text); } else { - $description = $this->db->quote(trim($this->description)); - $description_html = $this->db->quoteForEmail(trim($this->description_html)); - $raw_source = $this->db->quote(trim($this->raw_source)); - $fromAddressName = $this->db->helper->escape_quote($this->from_addr_name); - $toAddressName = $this->db->helper->escape_quote($this->to_addrs_names); - $ccAddressName = $this->db->helper->escape_quote($this->cc_addrs_names); - $bccAddressName = $this->db->helper->escape_quote($this->bcc_addrs_names); - $replyToAddrName = $this->db->helper->escape_quote($this->reply_to_addr); - - if(!$this->new_with_id) { - $q = "UPDATE emails_text SET from_addr = '{$fromAddressName}', to_addrs = '{$toAddressName}', cc_addrs = '{$ccAddressName}', bcc_addrs = '{$bccAddressName}', reply_to_addr = '{$replyToAddrName}', description = '{$description}', description_html = '{$description_html}', raw_source = '{$raw_source}' WHERE email_id = '{$this->id}'"; - } else { - $q = "INSERT INTO emails_text (email_id, from_addr, to_addrs, cc_addrs, bcc_addrs, reply_to_addr, description, description_html, raw_source, deleted) VALUES('{$this->id}', '{$fromAddressName}', '{$toAddressName}', '{$ccAddressName}', '{$bccAddressName}', '{$replyToAddrName}', '{$description}', '{$description_html}', '{$raw_source}', 0)"; - } - $this->db->query($q); - - } // else + $this->db->insert($text); + } } - /////////////////////////////////////////////////////////////////////////// //// RETRIEVERS function retrieve($id, $encoded=true, $deleted=true) { @@ -1268,7 +1252,7 @@ class Email extends SugarBean { function retrieveEmailText() { $q = "SELECT from_addr, reply_to_addr, to_addrs, cc_addrs, bcc_addrs, description, description_html, raw_source FROM emails_text WHERE email_id = '{$this->id}'"; $r = $this->db->query($q); - $a = $this->db->fetchByAssoc($r, -1, false); + $a = $this->db->fetchByAssoc($r, false); $this->description = $a['description']; $this->description_html = $a['description_html']; @@ -1346,7 +1330,7 @@ class Email extends SugarBean { $noteDupe->parent_id = $this->id; $noteDupe->parent_type = $this->module_dir; - $noteFile = new UploadFile('none'); + $noteFile = new UploadFile(); $noteFile->duplicate_file($a['id'], $note->id, $note->filename); $note->save(); @@ -1748,7 +1732,7 @@ class Email extends SugarBean { $noteTemplate->date_entered = ''; $noteTemplate->save(); - $noteFile = new UploadFile('none'); + $noteFile = new UploadFile(); $noteFile->duplicate_file($noteId, $noteTemplate->id, $noteTemplate->filename); $noteArray[] = $noteTemplate; } @@ -1838,7 +1822,7 @@ class Email extends SugarBean { $doc = new Document(); $docRev = new DocumentRevision(); $docNote = new Note(); - $noteFile = new UploadFile('none'); + $noteFile = new UploadFile(); $doc->retrieve($_REQUEST['documentId'.$i]); $docRev->retrieve($doc->document_revision_id); @@ -1990,7 +1974,7 @@ class Email extends SugarBean { /** * preps SugarPHPMailer object for HTML or Plain text sends - * @param object SugarPHPMailer instance + * @param SugarPHPMailer $mail SugarPHPMailer instance */ function handleBody($mail) { global $current_user; @@ -2034,13 +2018,13 @@ class Email extends SugarBean { return $mail; } + /** * Retrieve function from handlebody() to unit test easily - * @param $mail + * @param SugarPHPMailer $mail SugarPHPMailer instance * @return formatted $mail body */ function handleBodyInHTMLformat($mail) { - global $current_user; global $sugar_config; // wp: if body is html, then insert new lines at 996 characters. no effect on client side // due to RFC 2822 which limits email lines to 998 @@ -2055,91 +2039,10 @@ class Email extends SugarBean { $mail->AltBody = $plainText; $this->description = $plainText; - $fileBasePath = "{$sugar_config['cache_dir']}images/"; - $filePatternSearch = "{$sugar_config['cache_dir']}"; - $filePatternSearch = str_replace("/", "\/", $filePatternSearch); - $filePatternSearch = $filePatternSearch . "images\/"; - if(strpos($mail->Body, "\"{$fileBasePath}") !== FALSE) - { //cache/images - $matches = array(); - preg_match_all("/{$filePatternSearch}.+?\"/i", $mail->Body, $matches); - foreach($matches[0] as $match) { - $filename = str_replace($fileBasePath, '', $match); - $filename = urldecode(substr($filename, 0, -1)); - $cid = $filename; - $file_location = clean_path(getcwd()."/{$sugar_config['cache_dir']}images/{$filename}"); - $mime_type = "image/".strtolower(substr($filename, strrpos($filename, ".")+1, strlen($filename))); - - if(file_exists($file_location)) { - $mail->AddEmbeddedImage($file_location, $cid, $filename, 'base64', $mime_type); - } - } - - //replace references to cache with cid tag - $mail->Body = str_replace("/" . $fileBasePath,'cid:',$mail->Body); - $mail->Body = str_replace($fileBasePath,'cid:',$mail->Body); - // remove bad img line from outbound email - $regex = '#]+src[^=]*=\"\/([^>]*?[^>]*)>#sim'; - $mail->Body = preg_replace($regex, '', $mail->Body); - } - $fileBasePath = "{$sugar_config['upload_dir']}"; - $filePatternSearch = "{$sugar_config['upload_dir']}"; - $filePatternSearch = str_replace("/", "\/", $filePatternSearch); - if(strpos($mail->Body, "\"{$fileBasePath}") !== FALSE) - { - $matches = array(); - preg_match_all("/{$filePatternSearch}.+?\"/i", $mail->Body, $matches); - foreach($matches[0] as $match) { - $filename = str_replace($fileBasePath, '', $match); - $filename = urldecode(substr($filename, 0, -1)); - $cid = $filename; - $file_location = clean_path(getcwd()."/{$sugar_config['upload_dir']}{$filename}"); - $mime_type = "image/".strtolower(substr($filename, strrpos($filename, ".")+1, strlen($filename))); - - if(file_exists($file_location)) { - $mail->AddEmbeddedImage($file_location, $cid, $filename, 'base64', $mime_type); - } - } - - //replace references to cache with cid tag - $mail->Body = str_replace("/" . $fileBasePath,'cid:',$mail->Body); - $mail->Body = str_replace($fileBasePath,'cid:',$mail->Body); - - // remove bad img line from outbound email - $regex = '#]+src[^=]*=\"\/([^>]*?[^>]*)>#sim'; - $mail->Body = preg_replace($regex, '', $mail->Body); - } + $mail->replaceImageByRegex("(?:{$sugar_config['site_url']})?/?cache/images/", sugar_cached("images/")); //Replace any embeded images using the secure entryPoint for src url. - $noteImgRegex = "/]*[\s]+src[^=]*=\"index.php\?entryPoint=download\&id=([^\&]*)[^>]*>/im"; - $embededImageMatches = array(); - preg_match_all($noteImgRegex, $mail->Body, $embededImageMatches,PREG_SET_ORDER); - - foreach ($embededImageMatches as $singleMatch ) - { - $fullMatch = $singleMatch[0]; - $noteId = $singleMatch[1]; - $cid = $noteId; - $filename = $noteId; - - //Retrieve note for mimetype - $tmpNote = new Note(); - $tmpNote->retrieve($noteId); - //Replace the src part of img tag with new cid tag - $cidRegex = "/src=\"([^\"]*)\"/im"; - $replaceMatch = preg_replace($cidRegex, "src=\"cid:$noteId\"", $fullMatch); - - //Replace the body, old tag for new tag - $mail->Body = str_replace($fullMatch, $replaceMatch, $mail->Body); - - //Attach the file - $file_location = clean_path(getcwd()."/{$sugar_config['upload_dir']}{$noteId}"); - - if(file_exists($file_location)) - $mail->AddEmbeddedImage($file_location, $cid, $filename, 'base64', $tmpNote->file_mime_type); - } - //End Replace - + $mail->replaceImageByRegex("(?:{$sugar_config['site_url']})?/?index.php[?]entryPoint=download&(?:amp;)?[^\"]+?id=", "upload://", true); $mail->Body = from_html($mail->Body); } @@ -2219,11 +2122,11 @@ class Email extends SugarBean { $mime_type = 'text/plain'; if($note->object_name == 'Note') { if(!empty($note->file->temp_file_location) && is_file($note->file->temp_file_location)) { // brandy-new file upload/attachment - $file_location = $sugar_config['upload_dir'].$note->id; + $file_location = "upload://$note->id"; $filename = $note->file->original_file_name; $mime_type = $note->file->mime_type; } else { // attachment coming from template/forward - $file_location = rawurldecode(UploadFile::get_file_path($note->filename,$note->id)); + $file_location = "upload://{$note->id}"; // cn: bug 9723 - documents from EmailTemplates sent with Doc Name, not file name. $filename = !empty($note->filename) ? $note->filename : $note->name; $mime_type = $note->file_mime_type; @@ -2232,21 +2135,14 @@ class Email extends SugarBean { $filePathName = $note->id; // cn: bug 9723 - Emails with documents send GUID instead of Doc name $filename = $note->getDocumentRevisionNameForDisplay(); - $file_location = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].$filePathName; + $file_location = "upload://$note->id"; $mime_type = $note->file_mime_type; } // strip out the "Email attachment label if exists $filename = str_replace($mod_strings['LBL_EMAIL_ATTACHMENT'].': ', '', $filename); - + $file_ext = pathinfo($filename, PATHINFO_EXTENSION); //is attachment in our list of bad files extensions? If so, append .txt to file location - //get position of last "." in file name - $file_ext_beg = strrpos($file_location,"."); - $file_ext = ""; - //get file extension - if($file_ext_beg >0){ - $file_ext = substr($file_location, $file_ext_beg+1 ); - } //check to see if this is a file with extension located in "badext" foreach($sugar_config['upload_badext'] as $badExt) { if(strtolower($file_ext) == strtolower($badExt)) { @@ -2392,7 +2288,7 @@ class Email extends SugarBean { function fill_in_additional_list_fields() { - global $timedate; + global $timedate, $mod_strings; $this->fill_in_additional_detail_fields(); $this->link_action = 'DetailView'; @@ -2404,6 +2300,10 @@ class Email extends SugarBean { $row = $this->db->fetchByAssoc($result); $this->attachment_image = ($row !=null) ? SugarThemeRegistry::current()->getImage('attachment',"","","") : ""; + if ($row !=null) { + $this->attachment_image = SugarThemeRegistry::current()->getImage('attachment',"","","",'.gif',translate('LBL_ATTACHMENT', 'Emails')); + } + /////////////////////////////////////////////////////////////////////// if(empty($this->contact_id) && !empty($this->parent_id) && !empty($this->parent_type) && $this->parent_type === 'Contacts' && !empty($this->parent_name) ){ $this->contact_id = $this->parent_id; @@ -2548,23 +2448,23 @@ class Email extends SugarBean { } else { switch($this->intent) { case 'support': - $email_fields['CREATE_RELATED'] = ''.$mod_strings['LBL_CREATE_CASE'].''; + $email_fields['CREATE_RELATED'] = '' . SugarThemeRegistry::current()->getImage('CreateCases', 'border="0"', null, null, ".gif", $mod_strings['LBL_CREATE_CASES']).$mod_strings['LBL_CREATE_CASE'].''; break; case 'sales': - $email_fields['CREATE_RELATED'] = ''.$mod_strings['LBL_CREATE_LEAD'].''; + $email_fields['CREATE_RELATED'] = ''.SugarThemeRegistry::current()->getImage('CreateLeads', 'border="0"', null, null, ".gif", $mod_strings['LBL_CREATE_LEADS']).$mod_strings['LBL_CREATE_LEAD'].''; break; case 'contact': - $email_fields['CREATE_RELATED'] = ''.$mod_strings['LBL_CREATE_CONTACT'].''; + $email_fields['CREATE_RELATED'] = ''.SugarThemeRegistry::current()->getImage('CreateContacts', 'border="0"', null, null, ".gif", $mod_strings['LBL_CREATE_CONTACTS']).$mod_strings['LBL_CREATE_CONTACT'].''; break; case 'bug': - $email_fields['CREATE_RELATED'] = ''.$mod_strings['LBL_CREATE_BUG'].''; + $email_fields['CREATE_RELATED'] = ''.SugarThemeRegistry::current()->getImage('CreateBugs', 'border="0"', null, null, ".gif", $mod_strings['LBL_CREATE_BUGS']).$mod_strings['LBL_CREATE_BUG'].''; break; case 'task': - $email_fields['CREATE_RELATED'] = ''.$mod_strings['LBL_CREATE_TASK'].''; + $email_fields['CREATE_RELATED'] = ''.SugarThemeRegistry::current()->getImage('CreateTasks', 'border="0"', null, null, ".gif", $mod_strings['LBL_CREATE_TASKS']).$mod_strings['LBL_CREATE_TASK'].''; break; case 'bounce': @@ -2601,7 +2501,7 @@ class Email extends SugarBean { // Coming from the home page via Dashlets if($currentModule != 'Email') $mod_strings = return_module_language($current_language, 'Emails'); - return $mod_strings['LBL_QUICK_CREATE']." ".SugarThemeRegistry::current()->getImage("advanced_search","alt='".$mod_strings['LBL_QUICK_CREATE']."' border='0' align='absmiddle'").""; + return $mod_strings['LBL_QUICK_CREATE']." ".SugarThemeRegistry::current()->getImage("advanced_search","border='0' align='absmiddle'", null,null,'.gif',$mod_strings['LBL_QUICK_CREATE']).""; } /** @@ -3065,9 +2965,9 @@ eoq; -   + '.SugarThemeRegistry::current()->getImage('Users', '', null, null, ".gif", $mod_strings['LBL_USERS']).'  - + @@ -3075,7 +2975,7 @@ eoq; @@ -3131,6 +3031,39 @@ eoq; } } + /** + * Convert reference to inline image (stored as Note) to URL link + * Enter description here ... + * @param string $note ID of the note + * @param string $ext type of the note + */ + public function cid2Link($noteId, $noteType) + { + if(empty($this->description_html)) return; + list($type, $subtype) = explode('/', $noteType); + if(strtolower($type) != 'image') { + return; + } + $upload = new UploadFile(); + $this->description_html = preg_replace("#class=\"image\" src=\"cid:$noteId\.(.+?)\"#", "class=\"image\" src=\"{$this->imagePrefix}{$noteId}.\\1\"", $this->description_html); + // ensure the image is in the cache + $imgfilename = sugar_cached("images/")."$noteId.".strtolower($subtype); + $src = "upload://$noteId"; + if(!file_exists($imgfilename) && file_exists($src)) { + copy($src, $imgfilename); + } + } - + /** + * Convert all cid: links in this email into URLs + */ + function cids2Links() + { + if(empty($this->description_html)) return; + $q = "SELECT id, file_mime_type FROM notes WHERE parent_id = '{$this->id}' AND deleted = 0"; + $r = $this->db->query($q); + while($a = $this->db->fetchByAssoc($r)) { + $this->cid2Link($a['id'], $a['file_mime_type']); + } + } } // end class def diff --git a/modules/Emails/EmailUI.php b/modules/Emails/EmailUI.php index c7e8688e..e3f0077e 100644 --- a/modules/Emails/EmailUI.php +++ b/modules/Emails/EmailUI.php @@ -81,7 +81,7 @@ class EmailUI { $this->smarty = new Sugar_Smarty(); $this->folder = new SugarFolder(); - $this->userCacheDir = "{$sugar_config['cache_dir']}modules/Emails/{$current_user->id}"; + $this->userCacheDir = sugar_cached("modules/Emails/{$current_user->id}"); $this->db = DBManagerFactory::getInstance(); } @@ -168,7 +168,7 @@ class EmailUI { $this->smarty->assign('dateFormatExample', str_replace(array("Y", "m", "d"), array("yyyy", "mm", "dd"), $cuDatePref['date'])); $this->smarty->assign('calFormat', $timedate->get_cal_date_format()); $this->smarty->assign('TIME_FORMAT', $timedate->get_user_time_format()); - + $ieAccounts = $ie->retrieveByGroupId($current_user->id); $ieAccountsOptions = "\n"; @@ -282,7 +282,7 @@ class EmailUI { loader.insert(); {$preloadFolder}; - + eoq; @@ -332,7 +332,7 @@ eoq; $QCAvailableModules[] = $module; } } - + return $QCAvailableModules; } @@ -365,15 +365,16 @@ eoq; * @param Array $composeData Associative array read and processed by generateComposeDataPackage. * @param String $fullLinkUrl A link that contains all pertinant information so the user can be * directed to the full compose screen if needed + * @param SugarBean $bean Optional - the parent object bean with data * @return JSON Object containg composePackage and fullLinkUrl */ - function generateComposePackageForQuickCreate($composeData,$fullLinkUrl, $lazyLoad=false) + function generateComposePackageForQuickCreate($composeData,$fullLinkUrl, $lazyLoad=false, $bean = null) { $_REQUEST['forQuickCreate'] = true; if(!$lazyLoad){ require_once('modules/Emails/Compose.php'); - $composePackage = generateComposeDataPackage($composeData,FALSE); + $composePackage = generateComposeDataPackage($composeData,FALSE, $bean); }else{ $composePackage = $composeData; } @@ -949,7 +950,7 @@ eoq; foreach($personals as $k => $personalAccount) { if(in_array($personalAccount->id, $showFolders)) { // check for cache value - $cacheRoot = "{$sugar_config['cache_dir']}modules/Emails/{$personalAccount->id}"; + $cacheRoot = sugar_cached("modules/Emails/{$personalAccount->id}"); $this->preflightEmailCache($cacheRoot); if($this->validCacheFileExists($personalAccount->id, 'folders', "folders.php")) { @@ -989,7 +990,7 @@ eoq; foreach($beans as $k => $groupAccount) { if(in_array($groupAccount->id, $showFolders)) { // check for cache value - $cacheRoot = "{$sugar_config['cache_dir']}modules/Emails/{$groupAccount->id}"; + $cacheRoot = sugar_cached("modules/Emails/{$groupAccount->id}"); $this->preflightEmailCache($cacheRoot); //$groupAccount->connectMailserver(); @@ -1150,9 +1151,9 @@ eoq; if ($ie->isPop3Protocol()) { // get the UIDL from database; $cachedUIDL = md5($uid); - $cache = "{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$cachedUIDL}.php"; + $cache = sugar_cached("modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$cachedUIDL}.php"); } else { - $cache = "{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$uid}.php"; + $cache = sugar_cached("modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$uid}.php"); } if(file_exists($cache)) { include($cache); // profides $cacheFile @@ -1164,19 +1165,14 @@ eoq; $this->parseAttachmentInfo($actualAttachmentInfo, $attachmentHtmlData); if (sizeof($actualAttachmentInfo) > 0) { foreach($actualAttachmentInfo as $key => $value) { - $attachmentid; - $fileName; - $datasplit = explode("&", $value); - $attachmentIdArray = explode("=", $datasplit[0]); - $attachmentid = $attachmentIdArray[1]; - - $fileNameArray = explode("=", $datasplit[4]); - $fileName = $fileNameArray[1]; + $info_vars = array(); + parse_str($value, $info_vars); + $fileName = $info_vars['tempName']; + $attachmentid = $info_vars['id']; $guid = create_guid(); - //$destination = clean_path("{$this->userCacheDir}/{$guid}{$fileName}"); $destination = clean_path("{$this->userCacheDir}/{$guid}"); - $attachmentFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/attachments/{$attachmentid}"; + $attachmentFilePath = sugar_cached("modules/Emails/{$ie->id}/attachments/{$attachmentid}"); copy($attachmentFilePath, $destination); $ret['attachments'][$guid] = array(); $ret['attachments'][$guid]['id'] = $guid . $fileName; @@ -1312,14 +1308,11 @@ eoq; } //Get the module language for javascript - if(!is_file($GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $_REQUEST['qc_module'] . '/' . $GLOBALS['current_language'] . '.js')) { + if(!is_file(sugar_cached('jsLanguage/') . $_REQUEST['qc_module'] . '/' . $GLOBALS['current_language'] . '.js')) { require_once('include/language/jsLanguage.php'); jsLanguage::createModuleStringsCache($_REQUEST['qc_module'], $GLOBALS['current_language']); } - $jsLanguage = ''; - + $jsLanguage = getVersionedScript("cache/jsLanguage/{$_REQUEST['qc_module']}/{$GLOBALS['current_language']}.js", $GLOBALS['sugar_config']['js_lang_version']); $EditView->view = 'EmailQCView'; @@ -1327,7 +1320,7 @@ eoq; $EditView->defs['templateMeta']['form']['footerTpl'] = 'include/EditView/footer.tpl'; $meta = array(); $meta['html'] = $jsLanguage . $EditView->display(false, true); - $meta['html'] = str_replace("src='include/SugarEmailAddress/SugarEmailAddress.js?s={$GLOBALS['js_version_key']}&c={$GLOBALS['sugar_config']['js_custom_version']}'", '', $meta['html']); + $meta['html'] = str_replace("src='".getVersionedPath('include/SugarEmailAddress/SugarEmailAddress.js')."'", '', $meta['html']); $meta['emailAddress'] = $emailAddress; $mod_strings = return_module_language($current_language, 'Emails'); @@ -1422,10 +1415,8 @@ eoq; $html = trim(from_html($focus->description_html)); if(empty($html)) { $smarty->assign('SHOW_PLAINTEXT', 'true'); - $description = nl2br($focus->description); } else { $smarty->assign('SHOW_PLAINTEXT', 'false'); - $description = from_html($focus->description_html); } //if not empty or set to test (from test campaigns) @@ -1455,8 +1446,6 @@ eoq; $smarty->assign('BCC', nl2br($focus->bcc_addrs)); $smarty->assign('CREATED_BY', $focus->created_by_name); $smarty->assign('MODIFIED_BY', $focus->modified_by_name); - $smarty->assign('DESCRIPTION', nl2br($focus->description)); - $smarty->assign('DESCRIPTION_HTML', from_html($focus->description_html)); $smarty->assign('DATE_SENT', $focus->date_entered); $smarty->assign('EMAIL_NAME', 'RE: '.$focus->name); $smarty->assign("TAG", $focus->listviewACLHelper()); @@ -1496,9 +1485,11 @@ eoq; $attachments = ''; for($i=0; $ifilename,$the_note->id)."\" target=\"_blank\">".$the_note->name.$the_note->description ."
"; - $attachments .= "id."&type=Notes\">".$the_note->name."
"; + $attachments .= "id}&type=Notes\">".$the_note->name."
"; + $focus->cid2Link($the_note->id, $the_note->file_mime_type); } + $smarty->assign('DESCRIPTION', nl2br($focus->description)); + $smarty->assign('DESCRIPTION_HTML', from_html($focus->description_html)); $smarty->assign("ATTACHMENTS", $attachments); /////////////////////////////////////////////////////////////////////////////// //// SUBPANELS @@ -1780,7 +1771,7 @@ function getLastRobin($ie) { function setLastRobin($ie, $lastRobin) { global $sugar_config; - $cacheFolderPath = clean_path("{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/folders"); + $cacheFolderPath = sugar_cached("modules/Emails/{$ie->id}/folders"); if (!file_exists($cacheFolderPath)) { mkdir_recursive($cacheFolderPath); } @@ -1903,6 +1894,7 @@ eoq; $ea = new SugarEmailAddress(); if(!empty($email)) { + $email->cids2Links(); $description = (empty($email->description_html)) ? $email->description : $email->description_html; } @@ -2057,7 +2049,7 @@ eoq; if(!empty($whereAdd)) { $whereAdd .= " AND "; } - $clause = $current_user->db->helper->escape_quote($clause); + $clause = $current_user->db->quote($clause); $whereAdd .= "{$column} LIKE '{$clause}%'"; } @@ -2195,7 +2187,7 @@ eoq; if(!empty($whereAdd)) { $whereAdd .= " OR "; } - $clause = $current_user->db->helper->escape_quote($clause); + $clause = $current_user->db->quote($clause); $whereAdd .= "{$column} LIKE '{$clause}%'"; } $table = $beanType; @@ -2367,7 +2359,7 @@ eoq; function clearInboundAccountCache($ieId) { global $sugar_config; - $cacheRoot = getcwd()."/{$sugar_config['cache_dir']}modules/Emails/{$ieId}"; + $cacheRoot = sugar_cached("modules/Emails/{$ieId}"); $files = findAllFiles($cacheRoot."/messages/", array()); foreach($files as $file) { unlink($file); @@ -2720,7 +2712,7 @@ eoq; $refreshOffset = $this->cacheTimeouts[$type]; // use defaults } - $cacheFilePath = getcwd()."/{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}"; + $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); if(file_exists($cacheFilePath)) { return true; } @@ -2739,7 +2731,7 @@ eoq; function getCacheValue($ieId, $type, $file, $key) { global $sugar_config; - $cacheFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}"; + $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); $cacheFile = array(); if(file_exists($cacheFilePath)) { @@ -2767,7 +2759,7 @@ eoq; function getCacheTimestamp($ieId, $type, $file) { global $sugar_config; - $cacheFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}"; + $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); $cacheFile = array(); if(file_exists($cacheFilePath)) { @@ -2792,7 +2784,7 @@ eoq; function setCacheTimestamp($ieId, $type, $file) { global $sugar_config; - $cacheFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}"; + $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); $cacheFile = array(); if(file_exists($cacheFilePath)) { @@ -2818,7 +2810,7 @@ eoq; function writeCacheFile($key, $var, $ieId, $type, $file) { global $sugar_config; - $the_file = clean_path("{$sugar_config['cache_dir']}/modules/Emails/{$ieId}/{$type}/{$file}"); + $the_file = sugar_cached("/modules/Emails/{$ieId}/{$type}/{$file}"); $timestamp = strtotime('now'); $array = array(); $array['timestamp'] = $timestamp; diff --git a/modules/Emails/EmailUIAjax.php b/modules/Emails/EmailUIAjax.php index 4d98d186..788370fa 100644 --- a/modules/Emails/EmailUIAjax.php +++ b/modules/Emails/EmailUIAjax.php @@ -689,9 +689,9 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); if(isset($_REQUEST['uid']) && !empty($_REQUEST['uid']) && isset($_REQUEST['ieId']) && !empty($_REQUEST['ieId'])) { $out = $email->et->getSingleMessage($ie); //Bug: - echo $json->encode($out); + //echo $json->encode($out); //header("Content-Type: application/json; charset=UTF-8"); - //echo $json->encode(utf8_recursive_encode($out)); + echo $json->encode(utf8_recursive_encode($out)); } else { echo "error: no UID"; } @@ -1614,17 +1614,3 @@ eoq; break; } // switch } // if - - - - - - - - - - - - - - diff --git a/modules/Emails/ListViewDrafts.html b/modules/Emails/ListViewDrafts.html index 5abcafec..2d23b953 100644 --- a/modules/Emails/ListViewDrafts.html +++ b/modules/Emails/ListViewDrafts.html @@ -39,7 +39,7 @@ ********************************************************************************/ --> - +
- + '.SugarThemeRegistry::current()->getImage('close', 'border="0"', null, null, ".gif", $mod_strings['LBL_CLOSE']).' '.$mod_strings['LBL_USER_SELECT'].'
diff --git a/modules/Emails/ListViewGroup.php b/modules/Emails/ListViewGroup.php index 7f3c91e7..600cda7e 100644 --- a/modules/Emails/ListViewGroup.php +++ b/modules/Emails/ListViewGroup.php @@ -144,8 +144,8 @@ if (!isset($_REQUEST['search_form']) || $_REQUEST['search_form'] != 'false') { $search_form = new XTemplate ('modules/Emails/SearchFormGroupInbox.html'); $search_form->assign('MOD', $mod_strings); $search_form->assign('APP', $app_strings); - $search_form->assign('ADVANCED_SEARCH_PNG', SugarThemeRegistry::current()->getImage('advanced_search','alt="'.$app_strings['LNK_ADVANCED_SEARCH'].'" border="0"')); - $search_form->assign('BASIC_SEARCH_PNG', SugarThemeRegistry::current()->getImage('basic_search','alt="'.$app_strings['LNK_BASIC_SEARCH'].'" border="0"')); + $search_form->assign('ADVANCED_SEARCH_PNG', SugarThemeRegistry::current()->getImage('advanced_search','border="0"', null,null,'.gif',$app_strings['LNK_ADVANCED_SEARCH'])); + $search_form->assign('BASIC_SEARCH_PNG', SugarThemeRegistry::current()->getImage('basic_search','border="0"', null,null,'.gif',$app_strings['LNK_BASIC_SEARCH'])); $search_form->assign('TYPE_OPTIONS', $types); $search_form->assign('ASSIGNED_TO_OPTIONS', $assigned_to); $search_form->assign('STATUS_OPTIONS', $email_status); @@ -212,7 +212,7 @@ $display_title = $mod_strings['LBL_LIST_TITLE_GROUP_INBOX']; echo getClassicModuleTitle("Emails", array($mod_strings['LBL_MODULE_TITLE'].$display_title), true); // admin-edit if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($_SESSION['editinplace'])){ - $header_text = " ".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""; + $header_text = " ".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""; } // search form echo get_form_header($mod_strings['LBL_SEARCH_FORM_TITLE']. $header_text, "", false); @@ -253,7 +253,7 @@ $ListView->shouldProcess = true; $ListView->show_mass_update = true; $ListView->show_mass_update_form = false; $ListView->initNewXTemplate( 'modules/Emails/ListViewGroupInbox.html',$mod_strings); -$ListView->xTemplateAssign('ATTACHMENT_HEADER', SugarThemeRegistry::current()->getImage('attachment',"","","")); +$ListView->xTemplateAssign('ATTACHMENT_HEADER', SugarThemeRegistry::current()->getImage('attachment',"","","",'.gif',$mod_strings['LBL_ATTACHMENT'])); $ListView->xTemplateAssign('ERROR', $error); $ListView->xTemplateAssign('CHECK_MAIL',$focus->checkInbox('group')); $ListView->setHeaderTitle($display_title . $header_text ); diff --git a/modules/Emails/ListViewGroupInbox.html b/modules/Emails/ListViewGroupInbox.html index 586b0e0f..3ffa5e9a 100644 --- a/modules/Emails/ListViewGroupInbox.html +++ b/modules/Emails/ListViewGroupInbox.html @@ -42,7 +42,7 @@ {CHECK_MAIL} - +{ERROR}
diff --git a/modules/Emails/ListViewHome.html b/modules/Emails/ListViewHome.html index 3fed5929..fa12e3eb 100644 --- a/modules/Emails/ListViewHome.html +++ b/modules/Emails/ListViewHome.html @@ -39,7 +39,7 @@ ********************************************************************************/ --> - +
diff --git a/modules/Emails/ListViewHome.php b/modules/Emails/ListViewHome.php index 21653dd3..4dc4b940 100644 --- a/modules/Emails/ListViewHome.php +++ b/modules/Emails/ListViewHome.php @@ -65,7 +65,7 @@ $limit = 10; /////////////////////////////////////////////////////////////////////////////// echo $focus->rolloverStyle; $ListView->initNewXTemplate('modules/Emails/ListViewHome.html',$current_mod_strings); -$ListView->xTemplateAssign('ATTACHMENT_HEADER', SugarThemeRegistry::current()->getImage('attachment',"","","")); +$ListView->xTemplateAssign('ATTACHMENT_HEADER', SugarThemeRegistry::current()->getImage('attachment',"","","",'.gif',$mod_strings['LBL_ATTACHMENT'])); $ListView->setHeaderTitle($display_title); $ListView->setQuery($where, '', 'date_sent, date_entered DESC', "EMAIL"); $ListView->setAdditionalDetails(); diff --git a/modules/Emails/ListViewMyInbox.html b/modules/Emails/ListViewMyInbox.html index f7d6b71f..6c205c71 100644 --- a/modules/Emails/ListViewMyInbox.html +++ b/modules/Emails/ListViewMyInbox.html @@ -39,7 +39,7 @@ ********************************************************************************/ --> - + {TAKE} {CHECK_MAIL} {TAKE_ERROR} diff --git a/modules/Emails/ListViewSent.html b/modules/Emails/ListViewSent.html index 1c73adce..8e89fcfa 100644 --- a/modules/Emails/ListViewSent.html +++ b/modules/Emails/ListViewSent.html @@ -39,7 +39,7 @@ ********************************************************************************/ --> - +
diff --git a/modules/Emails/PopupDocuments.html b/modules/Emails/PopupDocuments.html index 020c4d8b..30fecbb3 100644 --- a/modules/Emails/PopupDocuments.html +++ b/modules/Emails/PopupDocuments.html @@ -38,8 +38,8 @@ - - + +
diff --git a/modules/Emails/Popup_picker.html b/modules/Emails/Popup_picker.html index 71a46131..03a6220c 100644 --- a/modules/Emails/Popup_picker.html +++ b/modules/Emails/Popup_picker.html @@ -38,8 +38,8 @@ - - + +
@@ -74,7 +74,7 @@
- {PAGINATION} + {PAGINATION}
@@ -115,5 +115,5 @@
-{ASSOCIATED_JAVASCRIPT_DATA} +{ASSOCIATED_JAVASCRIPT_DATA} diff --git a/modules/Emails/Save.php b/modules/Emails/Save.php index 9fb5d873..267b5312 100644 --- a/modules/Emails/Save.php +++ b/modules/Emails/Save.php @@ -35,16 +35,6 @@ if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); * "Powered by SugarCRM". ********************************************************************************/ -/********************************************************************************* - - * Description: - * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights - * Reserved. Contributor(s): ______________________________________.. - *********************************************************************************/ - - - - /////////////////////////////////////////////////////////////////////////////// //// EMAIL SEND/SAVE SETUP @@ -208,6 +198,11 @@ $focus->db->query($query); // delete al the relationship of this email with all the beans //$query = "update emails_beans set deleted = 1, bean_id = '', bean_module = '' WHERE email_id = '{$focus->id}'"; //$focus->db->query($query); +if(!empty($_REQUEST['to_addrs_ids'])) { + $exContactIds = explode(';', $_REQUEST['to_addrs_ids']); +} else { + $exContactIds = array(); +} if(isset($_REQUEST['object_type']) && !empty($_REQUEST['object_type']) && isset($_REQUEST['object_id']) && !empty($_REQUEST['object_id'])) { //run linking code only if the object_id has not been linked as part of the contacts above and it is an OOB relationship @@ -252,9 +247,8 @@ $focus->save(false); $focus->load_relationship('users'); $focus->users->add($current_user->id); -if(!empty($_REQUEST['to_addrs_ids'])) { +if(!empty($exContactIds)) { $focus->load_relationship('contacts'); - $exContactIds = explode(';', $_REQUEST['to_addrs_ids']); foreach($exContactIds as $contactId) { $contactId = trim($contactId); $focus->contacts->add($contactId); diff --git a/modules/Emails/Status.php b/modules/Emails/Status.php index b7a75021..39b6c851 100644 --- a/modules/Emails/Status.php +++ b/modules/Emails/Status.php @@ -100,7 +100,7 @@ $xtpl->assign("STATUS", "".$mod_strings['LBL_ERROR_SENDING_EMAIL global $current_user; if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($_SESSION['editinplace'])){ - $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' alt='Edit Layout' align='bottom'").""); + $xtpl->assign("ADMIN_EDIT","".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif',$mod_strings['LBL_EDIT_LAYOUT']).""); } // adding custom fields: diff --git a/modules/Emails/SubPanelViewRecipients.php b/modules/Emails/SubPanelViewRecipients.php index 9139d6a2..0d85ebf1 100644 --- a/modules/Emails/SubPanelViewRecipients.php +++ b/modules/Emails/SubPanelViewRecipients.php @@ -78,8 +78,8 @@ $xtpl->assign("MOD", $mod_strings); $xtpl->assign("APP", $app_strings); $xtpl->assign("RETURN_URL", "&return_module=$currentModule&return_action=DetailView&return_id=$focus->id"); $xtpl->assign("EMAIL_ID", $focus->id); -$xtpl->assign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline','align="absmiddle" alt="'.$app_strings['LNK_REMOVE'].'" border="0"')); -$xtpl->assign("EDIT_INLINE_PNG", SugarThemeRegistry::current()->getImage('edit_inline','align="absmiddle" alt="'.$app_strings['LNK_EDIT'].'" border="0"')); +$xtpl->assign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline','align="absmiddle" border="0"',null,null,'.gif',$app_strings['LNK_REMOVE'])); +$xtpl->assign("EDIT_INLINE_PNG", SugarThemeRegistry::current()->getImage('edit_inline','align="absmiddle" border="0"', null,null,'.gif',$app_strings['LNK_EDIT'])); $oddRow = true; foreach($focus_users_list as $user) { diff --git a/modules/Emails/javascript/Email.js b/modules/Emails/javascript/Email.js index 16feb2a8..0ec12b29 100644 --- a/modules/Emails/javascript/Email.js +++ b/modules/Emails/javascript/Email.js @@ -336,7 +336,7 @@ function multiFiles( list_target){ // constants allowedTypes = ['gif', 'bmp', 'png', 'jpg', 'jpeg'], - imglocation = sugar_cache_dir + 'images/'; + imglocation = 'cache/images/'; //check if filetype is valid if (SUGAR.util.validateFileExt(fileName, allowedTypes)) { @@ -487,13 +487,9 @@ function docUpload() { this.parentNode.childNodes[2].checked='true'; var documentRevisionId = this.parentNode.childNodes[4].value; var mime_type = this.parentNode.childNodes[5].value; - if(mime_type == "image/gif" || mime_type == "image/bmp" || mime_type == "image/png" || mime_type == "image/x-png" || mime_type == "image/jpg") + if(mime_type == "image/gif" || mime_type == "image/bmp" || mime_type == "image/png" || mime_type == "image/x-png" || mime_type == "image/jpg" || mime_type == "image/jpeg") { - var imglocation = unescape(document.location.pathname.substr(1)); - imglocation = imglocation.substring(0,imglocation.lastIndexOf('/')+1); - imglocation='/'+imglocation+sugar_upload_dir; - embedImage=''; - embedImage1=''; + embedImage=''; insert_variable(embedImage); } else{ diff --git a/modules/Emails/javascript/EmailUICompose.js b/modules/Emails/javascript/EmailUICompose.js index add2d3c7..92c08bef 100644 --- a/modules/Emails/javascript/EmailUICompose.js +++ b/modules/Emails/javascript/EmailUICompose.js @@ -1379,21 +1379,25 @@ SE.composeLayout = { // query based on template, contact_id0,related_to //jchi 09/10/2008 refix #7743 - if(json_objects['email_template_object']['fields']['subject'] != '' ) { // cn: bug 7743, don't stomp populated Subject Line + if(json_objects['email_template_object']['fields']['subject'] != '' ) + { + // cn: bug 7743, don't stomp populated Subject Line document.getElementById('emailSubject' + idx).value = decodeURI(encodeURI(json_objects['email_template_object']['fields']['subject'])); } var text = ''; - if(json_objects['email_template_object']['fields']['text_only'] == 1){ + if(json_objects['email_template_object']['fields']['text_only'] == 1) + { text = "

" + decodeURI(encodeURI(json_objects['email_template_object']['fields']['body'])).replace(/
/ig, '

').replace(/
/gi, "

").replace(/&/gi,'&').replace(/</gi,'<').replace(/>/gi,'>').replace(/'/gi,'\'').replace(/"/gi,'"') + "

"; - document.getElementById("setEditor1").checked = true; - SUGAR.email2.composeLayout.renderTinyMCEToolBar('1', 1); + document.getElementById('setEditor' + idx).checked = true; + SUGAR.email2.composeLayout.renderTinyMCEToolBar(idx, 1); } - else{ + else + { text = decodeURI(encodeURI(json_objects['email_template_object']['fields']['body_html'])).replace(/
/ig, '\n').replace(/
/gi, "\n").replace(/&/gi,'&').replace(/</gi,'<').replace(/>/gi,'>').replace(/'/gi,'\'').replace(/"/gi,'"'); - document.getElementById("setEditor1").checked = false; - SUGAR.email2.composeLayout.renderTinyMCEToolBar('1', 0); + document.getElementById('setEditor' + idx).checked = false; + SUGAR.email2.composeLayout.renderTinyMCEToolBar(idx, 0); } - + var tiny = SE.util.getTiny('htmleditor' + idx); var tinyHTML = tiny.getContent(); @@ -2015,7 +2019,7 @@ SE.composeLayout = { } // if }, - setContentOnThisTiny : function() { + setContentOnThisTiny : function(recursive) { var tiny = SE.util.getTiny('htmleditor' + SE.composeLayout.currentInstanceId); var tinyHTML = tiny.getContent(); composePackage.body = decodeURI(encodeURI(composePackage.body)); @@ -2030,6 +2034,14 @@ SE.composeLayout = { } else { + + //check to see if tiny is defined, and this is not a recursive call if not, then call self function one more time + if(typeof tiny == 'undefined' && typeof recursive == 'undefined'){ + //call this same function again, this time setting the recursive flag to true + setTimeout("SE.composeLayout.setContentOnThisTiny(true);", 3000); + return; + } + //bug 48179 //check tinyHTML for closing tags var body = tinyHTML.lastIndexOf(''); diff --git a/modules/Emails/javascript/ajax.js b/modules/Emails/javascript/ajax.js index 1f7fd9cd..ffb931fd 100644 --- a/modules/Emails/javascript/ajax.js +++ b/modules/Emails/javascript/ajax.js @@ -189,7 +189,7 @@ var AjaxObject = { // apply attachment values SUGAR.email2.composeLayout.loadAttachments(a.attachments); - setTimeout("callbackReplyForward.finish(globalA);", 500); + setTimeout("callbackReplyForward.finish(globalA,0,1);", 500); }, /** @@ -1481,24 +1481,26 @@ var callbackRefreshSugarFolders = { }; var callbackReplyForward = { success : AjaxObject.handleReplyForward, - finish : function(a, retryCount) { + finish : function(a, retryCount,isReOrFwDraft) { if (typeof(retryCount) == 'undefined') { retryCount = 0; } else { retryCount++; } + if (typeof(isReOrFwDraft) == 'undefined') { + isReOrFwDraft = 0; + } var idx = SUGAR.email2.composeLayout.currentInstanceId; var t = tinyMCE.getInstanceById('htmleditor' + idx); try { var html = t.getContent(); - - if(typeof a.type != 'undefined' && a.type == 'draft'){ - html = a.description; - } - else{ - html = " 

" + a.description; - } - + + html = " "; + //add hr tag if this is not a reply draft or forward draft + if(!isReOrFwDraft){ + html += "

"; + } + html += a.description; t.setContent(html);// diff --git a/modules/Emails/javascript/composeEmailTemplate.js b/modules/Emails/javascript/composeEmailTemplate.js index a56f0512..1f450739 100644 --- a/modules/Emails/javascript/composeEmailTemplate.js +++ b/modules/Emails/javascript/composeEmailTemplate.js @@ -76,7 +76,7 @@ SUGAR.email2.templates['compose'] = '
' + ' ' + ' ' + -' {app_strings.LBL_EMAIL_FROM}:' + +' ' + ' ' + ' ' + '
' + @@ -92,7 +92,7 @@ SUGAR.email2.templates['compose'] = '
' + '
' + -'   ' + +'   ' + ' ' + '
' + '
' + @@ -109,7 +109,7 @@ SUGAR.email2.templates['compose'] = '
' + '
' + -'   ' + +'   ' + ' ' + '
' + '
' + @@ -123,7 +123,7 @@ SUGAR.email2.templates['compose'] = '
' + '
' + -'   ' + +'   ' + ' ' + '
' + '
' + @@ -131,7 +131,7 @@ SUGAR.email2.templates['compose'] = '
' + -' {app_strings.LBL_EMAIL_SUBJECT}:' + +' ' + ' ' + ' ' + '
' + diff --git a/modules/Emails/javascript/grid.js b/modules/Emails/javascript/grid.js index c67f5376..4c6f4a69 100644 --- a/modules/Emails/javascript/grid.js +++ b/modules/Emails/javascript/grid.js @@ -75,7 +75,7 @@ function gridInit() { var colModel = [ { - label: "", + label: "

", width: 10, sortable: false, fixed: true, diff --git a/modules/Emails/javascript/init.js b/modules/Emails/javascript/init.js index 0277cade..f7cfcf4e 100644 --- a/modules/Emails/javascript/init.js +++ b/modules/Emails/javascript/init.js @@ -348,6 +348,10 @@ function addChildNodes(parentNode, parentData) { // Default behavior is to wrap in span if no href property, and since this href // doesn't do anything, remove it so that it will be wrapped in spans. // nodes[i].href = "#"; + + // URL Decode the text, so it shows properly + nodes[i].text = unescape(nodes[i].text); + if (nodes[i].text) nodes[i].label = nodes[i].text; //Override YUI child node creation if (nodes[i].children) { diff --git a/modules/Emails/language/en_us.lang.php b/modules/Emails/language/en_us.lang.php index 740cab32..206ae658 100644 --- a/modules/Emails/language/en_us.lang.php +++ b/modules/Emails/language/en_us.lang.php @@ -369,9 +369,29 @@ $mod_strings = array ( 'LBL_EXCHANGE_SMTPPORT' => 'Exchange Server Port:', 'LBL_EXCHANGE_SMTPSERVER' => 'Exchange Server:', + 'LBL_EDIT_LAYOUT' => 'Edit Layout' /*for 508 compliance fix*/, + 'LBL_ATTACHMENT' => 'Attachment' /*for 508 compliance fix*/, + 'LBL_DELETE_INLINE' => 'Delete' /*for 508 compliance fix*/, + 'LBL_CREATE_CASES' => 'Create Cases' /*for 508 compliance fix*/, + 'LBL_CREATE_LEADS' => 'Create Leads' /*for 508 compliance fix*/, + 'LBL_CREATE_CONTACTS' => 'Create Contacts' /*for 508 compliance fix*/, + 'LBL_CREATE_BUGS' => 'Create Bugs' /*for 508 compliance fix*/, + 'LBL_CREATE_TASKS' => 'Create Tasks' /*for 508 compliance fix*/, + 'LBL_CHECK_INLINE' => 'Correct' /*for 508 compliance fix*/, + 'LBL_CLOSE' => 'Close' /*for 508 compliance fix*/, + 'LBL_HELP' => 'Help' /*for 508 compliance fix*/, + 'LBL_GMAIL_LOGO' => 'Gmail' /*for 508 compliance fix*/, + 'LBL_YAHOO_MAIL' => 'Yahoo' /*for 508 compliance fix*/, + 'LBL_EXCHANGE_LOGO' => 'Exchange' /*for 508 compliance fix*/, + 'LBL_WAIT' => 'Wait' /*for 508 compliance fix*/, + 'LBL_CHECKEMAIL' => 'Check Email' /*for 508 compliance fix*/, + 'LBL_COMPOSEEMAIL' => 'Compose Email' /*for 508 compliance fix*/, + 'LBL_EMAILSETTINGS' => 'Email Settings' /*for 508 compliance fix*/, + // SNIP 'LBL_CONTACTS_SUBPANEL_TITLE_SNIP' => 'Email Contacts', 'LBL_EMAILS_MEETINGS_REL' => 'Emails:Meetings', 'LBL_DATE_CREATED' => 'Date Created', 'LBL_DATE_MODIFIED' => 'Date Modified', -); \ No newline at end of file +); + diff --git a/modules/Emails/templates/_baseEmail.tpl b/modules/Emails/templates/_baseEmail.tpl index 9d8fd860..3d798c77 100644 --- a/modules/Emails/templates/_baseEmail.tpl +++ b/modules/Emails/templates/_baseEmail.tpl @@ -35,12 +35,11 @@ ********************************************************************************/ *} - - + {include file="modules/Emails/templates/_baseJsVars.tpl"} - - + + @@ -50,14 +49,14 @@ var calFormat = '{$calFormat}'; var theme = "{$theme}"; - + {$quickSearchForAssignedUser} - + SUGAR.email2.detailView.qcmodules = {$qcModules}; - + var isAdmin = {$is_admin}; - var loadingSprite = app_strings.LBL_EMAIL_LOADING + " "; + var loadingSprite = app_strings.LBL_EMAIL_LOADING + " $mod_strings.LBL_WAIT";