diff --git a/Dockerfile b/Dockerfile index 361bc55492fa0c43e69e1cb09046518bf2f1d5b1..29df3ba6efe4c07d5b328803e6c53384d1c56a29 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,22 @@ -FROM nextcloud:29.0.12-fpm AS nextcloud +FROM nextcloud:30.0.14-fpm AS nextcloud ARG BASE_DIR="/usr/src/nextcloud" ARG TMP_PATCH_DIR="/tmp/build_patches" -ARG THEME_HELPER_JOB_ID="1168069" +ARG THEME_HELPER_JOB_ID="1313213" ARG NOTES_VERSION="4.11.0" -ARG CONTACTS_JOB_ID="881946" -ARG CALENDAR_JOB_ID="991372" -ARG EMAIL_RECOVERY_JOB_ID="1168177" -ARG EA_JOB_ID="1168157" -ARG LAUNCHER_JOB_ID="1168135" +ARG CONTACTS_JOB_ID="1313223" +ARG CALENDAR_JOB_ID="1313255" +ARG EMAIL_RECOVERY_JOB_ID="1313239" +ARG EA_JOB_ID="1289726" +ARG LAUNCHER_JOB_ID="1313268" ARG GOOGLE_INTEGRATION_VERSION="3.2.0" -ARG DASHBOARD_JOB_ID="1168115" +ARG DASHBOARD_JOB_ID="1313279" ARG SNAPPY_VERSION="2.37.2" -ARG SNAPPY_THEME_VERSION="4.0.1" -ARG USER_MIGRATION_JOB_ID="1168093" +ARG SNAPPY_THEME_VERSION="4.0.4" +ARG USER_MIGRATION_JOB_ID="1313296" ARG MEMORIES_VERSION="7.5.2" ARG DROP_ACCOUNT_VERSION="2.7.1" -RUN sed -i 's/29,0,12,2/29,0,12,5/' ${BASE_DIR}/version.php +RUN sed -i 's/30,0,14,1/30,0,14,8/' ${BASE_DIR}/version.php COPY custom_entrypoint.sh / RUN chmod +x /custom_entrypoint.sh RUN mkdir -p /var/www/skeleton/Documents && mkdir -p /var/www/skeleton/Images @@ -78,10 +78,10 @@ RUN curl -fsSL -o ecloud-dashboard.zip \ mv dist/murena-dashboard ${BASE_DIR}/custom_apps/ && \ rm ecloud-dashboard.zip; -RUN curl -fsSL -o snappymail.tar.gz \ - "https://snappymail.eu/repository/nextcloud/snappymail-${SNAPPY_VERSION}-nextcloud.tar.gz" && \ - tar -xf snappymail.tar.gz -C ${BASE_DIR}/custom_apps/ && \ - rm snappymail.tar.gz; +#RUN curl -fsSL -o snappymail.tar.gz \ +# "https://snappymail.eu/repository/nextcloud/snappymail-${SNAPPY_VERSION}-nextcloud.tar.gz" && \ +# tar -xf snappymail.tar.gz -C ${BASE_DIR}/custom_apps/ && \ +# rm snappymail.tar.gz; RUN curl -fsSL -o user_migration.zip \ "https://gitlab.e.foundation/e/infra/ecloud/nextcloud-apps/user_migration/-/jobs/${USER_MIGRATION_JOB_ID}/artifacts/download" && \ @@ -90,19 +90,19 @@ RUN curl -fsSL -o user_migration.zip \ rm user_migration.zip; # Fix snappymail icon -RUN sed -i 's/logo-white-64x64.png/app.svg/' ${BASE_DIR}/custom_apps/snappymail/appinfo/info.xml +#RUN sed -i 's/logo-white-64x64.png/app.svg/' ${BASE_DIR}/custom_apps/snappymail/appinfo/info.xml # Hide personal settings of snappymail -RUN sed -i "s/'additional'/null/" ${BASE_DIR}/custom_apps/snappymail/lib/Settings/PersonalSettings.php +#RUN sed -i "s/'additional'/null/" ${BASE_DIR}/custom_apps/snappymail/lib/Settings/PersonalSettings.php # Snappy theme -RUN curl -fsSL -o Murena-snappymail-theme.tar.gz \ - "https://gitlab.e.foundation/e/infra/ecloud/nextcloud-apps/snappymail-theme/-/archive/${SNAPPY_THEME_VERSION}/snappymail-theme-${SNAPPY_THEME_VERSION}.tar.gz" && \ - tar -xf Murena-snappymail-theme.tar.gz -C /tmp/ && \ - mkdir -p ${BASE_DIR}/themes/Murena && \ - mv /tmp/snappymail-theme-${SNAPPY_THEME_VERSION}/ ${BASE_DIR}/themes/Murena/snappymail && \ - chown -R www-data:www-data ${BASE_DIR}/themes/Murena/ && \ - rm -rf Murena-snappymail-theme.tar.gz +#RUN curl -fsSL -o Murena-snappymail-theme.tar.gz \ +# "https://gitlab.e.foundation/e/infra/ecloud/nextcloud-apps/snappymail-theme/-/archive/${SNAPPY_THEME_VERSION}/snappymail-theme-${SNAPPY_THEME_VERSION}.tar.gz" && \ +# tar -xf Murena-snappymail-theme.tar.gz -C /tmp/ && \ +# mkdir -p ${BASE_DIR}/themes/Murena && \ +# mv /tmp/snappymail-theme-${SNAPPY_THEME_VERSION}/ ${BASE_DIR}/themes/Murena/snappymail && \ +# chown -R www-data:www-data ${BASE_DIR}/themes/Murena/ && \ +# rm -rf Murena-snappymail-theme.tar.gz RUN curl -fsSL -o memories.tar.gz \ "https://github.com/pulsejet/memories/releases/download/v${MEMORIES_VERSION}/memories.tar.gz" && \ @@ -123,7 +123,7 @@ RUN apt-get -y remove unzip RUN sed -i "s/\$systemConfig->setValue('theme', '');/\$systemConfig->setValue('theme', 'eCloud');/g" ${BASE_DIR}/lib/base.php # Disable editor feature of media viewer -RUN sed -i 's/canEdit(){return!this.isMobile&&L()/canEdit(){return!this.isMobile&&false&&L()/' ${BASE_DIR}/apps/viewer/js/viewer-main.mjs +RUN sed -i 's/canEdit(){return!this.isMobile\&\&L()/canEdit(){return!this.isMobile\&\&false\&\&L()/' ${BASE_DIR}/apps/viewer/js/viewer-main.mjs ENTRYPOINT ["/custom_entrypoint.sh"] @@ -133,7 +133,7 @@ From nextcloud as selfhost ARG BASE_DIR="/usr/src/nextcloud" ARG TMP_PATCH_DIR="/tmp/build_patches" ARG THEME_VERSION="26.0.2" -ARG USER_BACKEND_RAW_SQL_VERSION="2.0.1" +#ARG USER_BACKEND_RAW_SQL_VERSION="2.0.1" ARG SELFHOST_THEME_VERSION="2.0.0" ARG IS_SELFHOST=true @@ -168,10 +168,10 @@ RUN curl -fsSL -o eCloud-theme.tar.gz \ rm -rf eCloud-theme.tar.gz ${BASE_DIR}/themes/example/ # User Backend -RUN curl -fsSL -o user_backend_sql_raw.tar.gz \ - "https://github.com/PanCakeConnaisseur/user_backend_sql_raw/releases/download/v${USER_BACKEND_RAW_SQL_VERSION}/user_backend_sql_raw.tar.gz" && \ - tar -xf user_backend_sql_raw.tar.gz -C ${BASE_DIR}/custom_apps/ && \ - rm user_backend_sql_raw.tar.gz; +#RUN curl -fsSL -o user_backend_sql_raw.tar.gz \ +# "https://github.com/PanCakeConnaisseur/user_backend_sql_raw/releases/download/v${USER_BACKEND_RAW_SQL_VERSION}/user_backend_sql_raw.tar.gz" && \ +# tar -xf user_backend_sql_raw.tar.gz -C ${BASE_DIR}/custom_apps/ && \ +# rm user_backend_sql_raw.tar.gz; # Selfhost theme RUN if [ "$IS_SELFHOST" = true ]; then \ @@ -203,17 +203,11 @@ RUN sed -i "s/\['total'\]/\['quota'\]/" ${BASE_DIR}/apps/provisioning_api/lib/Co # Fix API call in files script RUN sed -i "s/ajax\/getstoragestats/api\/v1\/stats/g" ${BASE_DIR}/apps/files/js/files.js -#fix for who can access data- its needed with 011-privacy-settings.patch -RUN sed -i 's|Your home storage is encrypted using {linkopen}server-side-encryption ↗{linkclose} with a master key\. It means that administrators can access your files, but not read their content\.|Like in most cloud services, a reduced number of administrators can see your files and all the information in the database as they need to make backups, perform upgrades, reset passwords, etc.
{linkopen1}Learn more about this topic here. ↗{linkclose1}|g' ${BASE_DIR}/apps/privacy/js/privacy-main.js -RUN sed -i 's/t((0,n\.Iu)("privacy","Your files on external storages may be encrypted using {linkopen}server-side-encryption ↗{linkclose} with a master key based on their configuration\."))/t("{linkopen}"+(0,n\.Iu)("privacy","To protect your data, we have implemented server-side-encryption on our servers which hides by default the content of your files and notes even to these administrators")+"↗{linkclose}")/g' ${BASE_DIR}/apps/privacy/js/privacy-main.js -RUN sed -i 's|t=t=>e.push(t.replace("{linkopen}",'"'"''"'"').replace("{linkclose}",""))|t=t=>e.push(t.replace("{linkopen}",'"'"''"'"').replace("{linkclose}",""))|g' ${BASE_DIR}/apps/privacy/js/privacy-main.js -RUN sed -i 's|.replace("{linkclose}","")|.replace("{linkclose}","").replace("{linkopen1}",'"'"''"'"').replace("{linkclose1}","")|g' ${BASE_DIR}/apps/privacy/js/privacy-main.js - From selfhost as ecloud ARG BASE_DIR="/usr/src/nextcloud" ARG TMP_PATCH_DIR="/tmp/build_patches" -ARG THEME_VERSION="28.0.2" -ARG LDAP_WRITE_SUPPORT_VERSION="1.11.0" +ARG THEME_VERSION="30.0.0" +ARG LDAP_WRITE_SUPPORT_VERSION="1.12.1" ARG IS_SELFHOST=false RUN curl -fsSL -o ldap_write_support.tar.gz \ @@ -242,11 +236,14 @@ RUN rm -rf ${TMP_PATCH_DIR} # Remove user avatar generation for system addressbook card RUN sed -i 's/$this->getAvatarImage($user)/null/' ${BASE_DIR}/apps/dav/lib/CardDAV/Converter.php +# redirect user to sso login on successful resetting password +#RUN cd ${BASE_DIR}/dist && sed -i "s|window\.location\.href=(0,g\.Jv)(\"login\")|window.location.href = '/'|g" core-login.js + # show reset pwd page with a query param # RUN cd ${BASE_DIR}/dist && sed -i 's/resetPassword:!1/resetPassword:!1||Z.showResetPassword==="1"/' core-login.js # add attr about how many notifications to notif icon -RUN sed -i 's/attrs:{id:"notifications",/attrs:{id:"notifications","data-has-notifications":0!==t.notifications.length,/' ${BASE_DIR}/apps/notifications/js/notifications-src_NotificationsApp_vue.js +RUN sed -i 's/attrs:{id:"notifications",/attrs:{id:"notifications","data-has-notifications":0!==u.notifications.length,/' ${BASE_DIR}/apps/notifications/js/NotificationsApp-DS2Cdf60.chunk.mjs # Rename Memories to Gallery RUN sed -i 's/Memories<\/name>/Gallery<\/name>/g' ${BASE_DIR}/custom_apps/memories/appinfo/info.xml @@ -255,14 +252,14 @@ RUN cd ${BASE_DIR}/custom_apps/memories/js && sed -i 's/Memories Settings/Galler # autocomplete leak tweak apps frontend with sed, disable group suggestion -RUN cd ${BASE_DIR}/custom_apps/contacts && sed -i ' s/"GROUP","INDIVIDUAL"/"INDIVIDUAL"/g' js/contacts-main.js +RUN cd ${BASE_DIR}/custom_apps/contacts && sed -i 's/\["INDIVIDUAL"\]/\[\]/g' js/contacts-main.mjs RUN cd ${BASE_DIR}/custom_apps/calendar && sed -i 's/"GROUP","INDIVIDUAL"/"INDIVIDUAL"/g' js/calendar-main.js RUN cd ${BASE_DIR}/custom_apps/calendar && sed -i 's/{name:\[a,"displayname"\]},//' js/calendar-main.js RUN cd ${BASE_DIR}/custom_apps/notes && sed -i 's/OCA\\Notes\\Migration\\EditorHint<\/step>//g' appinfo/info.xml RUN cd ${BASE_DIR}/apps/theming && sed -i 's/OCA\\Theming\\Migration\\MigrateUserConfig<\/step>//g' appinfo/info.xml # sharing search by email -RUN cd ${BASE_DIR}/custom_apps/contacts && sed -i 's/kM.principalPropertySearchByDisplayname(t);/kM.principalPropertySearch(\[{name:\["http:\/\/sabredav.org\/ns","email-address"\]\}],t,"anyof");/g' js/contacts-main.js +#RUN cd ${BASE_DIR}/custom_apps/contacts && sed -i 's/kM.principalPropertySearchByDisplayname(t);/kM.principalPropertySearch(\[{name:\["http:\/\/sabredav.org\/ns","email-address"\]\}],t,"anyof");/g' js/contacts-main.js # Remove colored background from email template logo RUN sed -i 's/$this->header, \[$this->themingDefaults->getDefaultColorPrimary()/$this->header, \["none"/' ${BASE_DIR}/lib/private/Mail/EMailTemplate.php @@ -275,7 +272,7 @@ RUN sed -i 's/$this->changeAvatar/\/\/ $this->changeAvatar/' ${BASE_DIR}/custom_ RUN sed -i '/OCA\\DAV\\Migration\\CalDAVRemoveEmptyValue<\/step>/d' ${BASE_DIR}/apps/dav/appinfo/info.xml # Hide `Play sound when a call started (requires Nextcloud Talk)` checkbox from notification setting -RUN sed -i 's/attrs:{checked:e\.config\.sound_talk}/staticClass:"notification_talk",attrs:{checked:e\.config\.sound_talk}/g' ${BASE_DIR}/apps/notifications/js/notifications-settings.js +RUN sed -i 's/attrs:{checked:r\.config\.sound_talk}/staticClass:"notification_talk",attrs:{checked:r\.config\.sound_talk}/g' ${BASE_DIR}/apps/notifications/js/notifications-settings.mjs # Hide `Navigation bar settings` from theming RUN sed -i 's/{attrs:{name:t.t("theming","Navigation bar settings")}}/{staticClass:"navigation-bar-settings",attrs:{name:t.t("theming","Navigation bar settings")}}/g' ${BASE_DIR}/dist/theming-personal-theming.js @@ -308,5 +305,6 @@ RUN sed -i ':a;N;$!ba;s/t("NcActionButton",{on:{click:e.onToggleSharing},scopedS # Add id to delete account settings section and hide it by default RUN sed -i 's/"NcSettingsSection",{attrs:{/"NcSettingsSection",{attrs:{id:"delete-account-settings-section",style:"visibility:hidden;",/' ${BASE_DIR}/custom_apps/drop_account/js/drop_account-personal-settings.mjs -# Fix of https://github.com/nextcloud/server/commit/e727a3b00bd9b574279d25c006a0bc6b8fa4eec3 for availability setting -RUN sed -i 's/n.data/await n.text()/' ${BASE_DIR}/dist/dav-settings-personal-availability.js \ No newline at end of file +# Hide personal settings of files_external +RUN sed -i "s/'externalstorages'/null/" ${BASE_DIR}/apps/files_external/lib/Settings/Personal.php + diff --git a/custom_entrypoint-slim.sh b/custom_entrypoint-slim.sh new file mode 100755 index 0000000000000000000000000000000000000000..726009409ec5d4e148ba4ce41f1d182749616c8a --- /dev/null +++ b/custom_entrypoint-slim.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +echo "Murena entrypoint" + +# syslog-ng +if [ -n ${SYSLOG_HOST} ]; then + sed -i "s|\${SYSLOG_HOST}|${SYSLOG_HOST:-127.0.0.1}|g" /etc/syslog-ng/syslog-ng.conf + syslog-ng --no-caps + echo "syslog-ng started." +fi + +/entrypoint.sh "$@" diff --git a/custom_entrypoint.sh b/custom_entrypoint.sh index 726009409ec5d4e148ba4ce41f1d182749616c8a..76a1b266ac1174200a83e5a307129152dc2c5bd7 100755 --- a/custom_entrypoint.sh +++ b/custom_entrypoint.sh @@ -2,11 +2,46 @@ echo "Murena entrypoint" -# syslog-ng -if [ -n ${SYSLOG_HOST} ]; then - sed -i "s|\${SYSLOG_HOST}|${SYSLOG_HOST:-127.0.0.1}|g" /etc/syslog-ng/syslog-ng.conf - syslog-ng --no-caps - echo "syslog-ng started." +echo "Custom eCloud entrypoint" +rsync_options="-rlDog --chown www-data:www-data --delete" + +SRC_DIR="/usr/src/nextcloud" +DST_DIR="/var/www/html" + +installed_version="0.0.0.0" + +if [ -f /var/www/html/version.php ]; then + installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')" +fi +image_version="$(php -r 'require "/usr/src/nextcloud/version.php"; echo implode(".", $OC_Version);')" + +if version_greater "$image_version" "$installed_version"; then + rsync $rsync_options --include "/notes/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/calendar/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/contacts/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/user_backend_sql_raw/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/email-recovery/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/ecloud-accounts/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/ecloud-theme-helper/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/murena_launcher/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/integration_google/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/ldap_write_support/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/murena-dashboard/" --exclude '/*' $SRC_DIR/custom_apps/ /$DST_DIR/custom_apps/ + #rsync $rsync_options --include "/snappymail/" --exclude '/*' $SRC_DIR/custom_apps/ /$DST_DIR/custom_apps/ + rsync $rsync_options --include "/eCloud/" --exclude '/*' $SRC_DIR/themes/ $DST_DIR/themes/ + rsync $rsync_options --include "/Murena/" --exclude '/*' $SRC_DIR/themes/ $DST_DIR/themes/ + rsync $rsync_options --include "/memories/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/drop_account/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/user_migration/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ + rsync $rsync_options --include "/selfhost-theme-helper/" --exclude '/*' $SRC_DIR/custom_apps/ $DST_DIR/custom_apps/ +else + echo "Skipping rsync step as version not updated!" +fi + +if [ "$(id -u)" = 0 ]; then + su -p www-data -s /bin/sh -c "php $DST_DIR/occ config:system:set profile.enabled --value=false --type=boolean" +else + sh -c "php $DST_DIR/occ config:system:set profile.enabled --value=false --type=boolean" fi /entrypoint.sh "$@" diff --git a/patches/002-login-without-domain.patch b/patches/002-login-without-domain.patch index aa1f15e6448343196a60c1c278071c1f0d25df73..5021b6d20bb8965735ca6a1abdefbfc6b05fee20 100644 --- a/patches/002-login-without-domain.patch +++ b/patches/002-login-without-domain.patch @@ -9,11 +9,10 @@ only the admin user (also configured in env var) will not have his login appende diff --git ./core/Controller/LoginController.php ./core/Controller/LoginController-new.php --- ./core/Controller/LoginController.php 2024-04-26 15:08:54.979407062 +0530 +++ ./core/Controller/LoginController-new.php 2024-04-26 15:16:48.582366408 +0530 -@@ -315,7 +315,28 @@ - self::LOGIN_MSG_CSRFCHECKFAILED +@@ -315,6 +315,27 @@ ); } -+ $user = trim($user); + + $user = mb_strtolower($user, 'UTF-8'); + $actualUser = $user; + $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); @@ -22,7 +21,7 @@ diff --git ./core/Controller/LoginController.php ./core/Controller/LoginControll + $mainDomainSuffix = !empty($mainDomain) ? '@' . $mainDomain : ''; + $admin_username = $_ENV["NEXTCLOUD_ADMIN_USER"]; + $is_admin = strcmp($user, $admin_username) === 0; - ++ + if (!$is_admin && str_ends_with($user, $legacyDomainSuffix)) { + $user = str_replace($legacyDomainSuffix, '', $user); + } @@ -37,8 +36,8 @@ diff --git ./core/Controller/LoginController.php ./core/Controller/LoginControll + $data = new LoginData( $this->request, - trim($user), -@@ -328,7 +349,7 @@ + $user, +@@ -327,7 +348,7 @@ if (!$result->isSuccess()) { return $this->createLoginFailedResponse( $data->getUsername(), @@ -47,14 +46,14 @@ diff --git ./core/Controller/LoginController.php ./core/Controller/LoginControll $redirect_url, $result->getErrorMessage() ); + --- ./core/Controller/WebAuthnController.php 2023-04-21 15:18:58.813220092 +0530 +++ ./core/Controller/WebAuthnController-new.php 2023-04-21 15:24:40.036538414 +0530 -@@ -66,6 +66,27 @@ +@@ -48,6 +48,27 @@ $this->logger->debug('Converting login name to UID'); $uid = $loginName; -+ -+ $uid = trim($uid); ++ $uid = trim($uid); + $uid = mb_strtolower($uid, 'UTF-8'); + $legacyDomain = \OC::$server->getConfig()->getSystemValue('legacy_domain', ''); + $legacyDomainSuffix = !empty($legacyDomain) ? '@' . $legacyDomain : ''; @@ -74,15 +73,16 @@ diff --git ./core/Controller/LoginController.php ./core/Controller/LoginControll + if (!\OC::$server->get(\OCP\IUserManager::class)->userExists($uid)) { + $uid = $uid . $legacyDomainSuffix; + } ++ Util::emitHook( '\OCA\Files_Sharing\API\Server2Server', 'preLoginNameUsedAsUserName', --- ./lib/private/User/Session.php 2023-04-21 15:27:00.417034490 +0530 +++ ./lib/private/User/Session-new.php 2023-04-21 15:28:18.309111435 +0530 -@@ -430,6 +430,10 @@ +@@ -383,6 +383,10 @@ $remoteAddress = $request->getRemoteAddress(); - $currentDelay = $throttler->sleepDelay($remoteAddress, 'login'); + $currentDelay = $throttler->sleepDelayOrThrowOnMax($remoteAddress, 'login'); + $mainDomain = $this->config->getSystemValue('main_domain', ''); + $mainDomainSuffix = !empty($mainDomain) ? '@' . $mainDomain : ''; @@ -90,4 +90,4 @@ diff --git ./core/Controller/LoginController.php ./core/Controller/LoginControll + if ($this->manager instanceof PublicEmitter) { $this->manager->emit('\OC\User', 'preLogin', [$user, $password]); - } + } \ No newline at end of file diff --git a/patches/004-contact-search-controller-removal.patch b/patches/004-contact-search-controller-removal.patch index e9b8a360943ecf1a6f997aebb2aaba2af67636dd..f8e49e4b80ddbe716ab296595773b9d21d29a162 100644 --- a/patches/004-contact-search-controller-removal.patch +++ b/patches/004-contact-search-controller-removal.patch @@ -7,11 +7,12 @@ This patch removes some results from the contact menu controller, not to leak us diff --git ContactsMenuController.php ContactsMenuController-new.php --- ./core/Controller/ContactsMenuController.php 2023-02-01 21:40:07.515628276 +0530 +++ ./core/Controller/ContactsMenuController-new.php 2023-02-01 21:39:07.398140201 +0530 -@@ -49,7 +49,7 @@ - * @throws Exception - */ +@@ -32,7 +32,7 @@ + #[NoAdminRequired] + #[FrontpageRoute(verb: 'POST', url: '/contactsmenu/contacts')] public function index(?string $filter = null): array { - return $this->manager->getEntries($this->userSession->getUser(), $filter); + return []; } + /** diff --git a/patches/005-autocomplete-user-leak-core.patch b/patches/005-autocomplete-user-leak-core.patch index bf69e89e0705548aebf3463367f4bcb42982e086..b8d92820bb441e51dacd3bcf101bf1461b36a845 100644 --- a/patches/005-autocomplete-user-leak-core.patch +++ b/patches/005-autocomplete-user-leak-core.patch @@ -14,7 +14,7 @@ this filtering works in conjunction with the autocomplete feature disabled in ne diff --git lib/private/Collaboration/Collaborators/UserPlugin.php lib/private/Collaboration/Collaborators/UserPlugin-new.php --- lib/private/Collaboration/Collaborators/UserPlugin.php 2025-02-13 19:30:40 +++ lib/private/Collaboration/Collaborators/UserPlugin-new.php 2025-03-07 12:48:50 -@@ -175,8 +175,8 @@ +@@ -150,8 +150,8 @@ if ( $this->shareeEnumerationFullMatch && $lowerSearch !== '' && (strtolower($uid) === $lowerSearch || @@ -29,7 +29,7 @@ diff --git lib/private/Collaboration/Collaborators/UserPlugin.php lib/private/Co diff --git lib/private/Collaboration/Collaborators/MailPlugin.php lib/private/Collaboration/Collaborators/MailPlugin-new.php --- lib/private/Collaboration/Collaborators/MailPlugin.php 2025-02-13 19:30:40 +++ lib/private/Collaboration/Collaborators/MailPlugin-new.php 2025-03-07 12:55:25 -@@ -39,6 +39,7 @@ +@@ -19,6 +19,7 @@ use OCP\IUserSession; use OCP\Mail\IMailer; use OCP\Share\IShare; @@ -37,7 +37,7 @@ diff --git lib/private/Collaboration/Collaborators/MailPlugin.php lib/private/Co class MailPlugin implements ISearchPlugin { protected bool $shareWithGroupOnly; -@@ -61,8 +62,10 @@ +@@ -42,8 +43,10 @@ private KnownUserService $knownUserService, private IUserSession $userSession, private IMailer $mailer, @@ -48,7 +48,7 @@ diff --git lib/private/Collaboration/Collaborators/MailPlugin.php lib/private/Co $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; $this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes'; -@@ -216,27 +219,61 @@ +@@ -204,27 +207,61 @@ if ($exactEmailMatch) { $searchResult->markExactIdMatch($emailType); } diff --git a/patches/006-recovery-email-changes.patch b/patches/006-recovery-email-changes.patch index a424dd06e44ac80480b897266e971b9b3567f60a..80d37255f6b4b552baddd1026d4ea1fb11a5cda7 100644 --- a/patches/006-recovery-email-changes.patch +++ b/patches/006-recovery-email-changes.patch @@ -1,9 +1,10 @@ --- ./core/Controller/LostController.php 2023-05-05 18:38:07.080445742 +0530 +++ ./core/Controller/LostController-new.php 2023-05-05 18:48:27.385043088 +0530 -@@ -172,8 +172,23 @@ - */ +@@ -126,7 +126,24 @@ protected function checkPasswordResetToken(string $token, string $userId): void { try { + $user = $this->userManager->get($userId); +- $this->verificationToken->check($token, $user, 'lostpassword', $user ? $user->getEMailAddress() : '', true); + $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); + $legacyDomainSuffix = !empty($legacyDomain) ? '@' . $legacyDomain : ''; + $mainDomain = $this->config->getSystemValue('main_domain', ''); @@ -18,14 +19,14 @@ + if(!$this->userManager->userExists($userId)) { + $userId = $userId . $legacyDomainSuffix; + } - $user = $this->userManager->get($userId); -- $this->verificationToken->check($token, $user, 'lostpassword', $user ? $user->getEMailAddress() : '', true); ++ $user = $this->userManager->get($userId); + $recoveryEmail = $this->config->getUserValue($userId, 'email-recovery', 'recovery-email', ''); + $this->verificationToken->check($token, $user, 'lostpassword', $user ? $recoveryEmail : '', true); ++ } catch (InvalidTokenException $e) { $error = $e->getCode() === InvalidTokenException::TOKEN_EXPIRED ? $this->l10n->t('Could not reset password because the token is expired') -@@ -273,9 +288,22 @@ +@@ -236,9 +253,22 @@ * @throws \OCP\PreConditionNotMetException */ protected function sendEmail(string $input): void { @@ -49,3 +50,4 @@ if (empty($email)) { throw new ResetPasswordException('Could not send reset e-mail since there is no email for username ' . $input); } + diff --git a/patches/007-remove-dev-notice.patch b/patches/007-remove-dev-notice.patch index 92e776485b7a568bafc84b2b768d6463c148d51f..a1ef8a3e8f84e11e3fdc1359cc6e2c00a1e98975 100644 --- a/patches/007-remove-dev-notice.patch +++ b/patches/007-remove-dev-notice.patch @@ -7,7 +7,7 @@ This patch removes the development notice portion in personal info settings diff --git ./apps/settings/lib/Settings/Personal/ServerDevNotice.php ./apps/settings/lib/Settings/Personal/ServerDevNotice-new.php --- ./apps/settings/lib/Settings/Personal/ServerDevNotice.php 2022-03-23 12:22:57.000000000 +0100 +++ ./apps/settings/lib/Settings/Personal/ServerDevNotice.php-new 2022-03-23 12:23:25.000000000 +0100 -@@ -100,11 +100,7 @@ +@@ -81,11 +81,7 @@ * @return string|null the section ID, e.g. 'sharing' */ public function getSection(): ?string { @@ -18,5 +18,5 @@ diff --git ./apps/settings/lib/Settings/Personal/ServerDevNotice.php ./apps/sett - return 'personal-info'; + return null; } - + /** diff --git a/patches/009-help-links.patch b/patches/009-help-links.patch index ce58874f4607da112b248deadaabc85981e34f2e..874325a09137a49100f3978b1029cf91a7b6839a 100644 --- a/patches/009-help-links.patch +++ b/patches/009-help-links.patch @@ -7,7 +7,7 @@ help links are shown --- ./apps/settings/lib/Controller/HelpController.php 2025-03-07 11:04:18 +++ ./apps/settings/lib/Controller/HelpController-new.php 2025-03-07 11:04:21 -@@ -123,6 +123,7 @@ +@@ -103,6 +103,7 @@ 'urlAdminDocs' => $urlAdminDocs, 'mode' => $mode, 'pageTitle' => $pageTitle, @@ -15,10 +15,10 @@ help links are shown 'knowledgebaseEmbedded' => $knowledgebaseEmbedded, 'legalNoticeUrl' => $legalNoticeUrl, 'privacyUrl' => $privacyUrl, -\ No newline at end of file + --- ./apps/settings/templates/help.php 2025-03-13 21:19:20 +++ ./apps/settings/templates/help-new.php 2025-03-26 13:04:36 -@@ -5,85 +5,48 @@ +@@ -9,84 +9,47 @@ -- -+ -\ No newline at end of file + --- ./apps/settings/css/help.css 2021-08-20 14:16:57.951439620 +0530 +++ ./apps/settings/css/help-new.css 2021-08-20 17:02:43.549016337 +0530 -@@ -50,4 +50,12 @@ - - .help-content__body > .button { +.help-content__body > .button { margin: 20px; +} +#content #app-navigation { @@ -132,5 +128,4 @@ help links are shown + +#app-navigation:not(.vue) > ul > li > a { + padding: 0 12px 0 44px; - } - + } \ No newline at end of file diff --git a/patches/010-disable-app-store-upgrade.patch b/patches/010-disable-app-store-upgrade.patch index 569905c90f84a0e8536745c41f2d5f89b94d0fec..07ab975af8b837c0761e9a716286e4d20c05d26d 100644 --- a/patches/010-disable-app-store-upgrade.patch +++ b/patches/010-disable-app-store-upgrade.patch @@ -6,17 +6,18 @@ This patch disables checking the app store for app updates during "occ upgrade" --- ./lib/private/Updater.php 2021-11-16 12:12:35.631823438 +0530 +++ ./lib/private/Updater-new.php 2021-11-16 12:14:28.445155684 +0530 -@@ -268,11 +268,11 @@ +@@ -240,11 +240,11 @@ $appManager = \OC::$server->getAppManager(); // upgrade appstore apps - $this->upgradeAppStoreApps($appManager->getInstalledApps()); -+ /*$this->upgradeAppStoreApps($appManager->getInstalledApps()); ++ /* $this->upgradeAppStoreApps($appManager->getInstalledApps()); $autoDisabledApps = $appManager->getAutoDisabledApps(); if (!empty($autoDisabledApps)) { $this->upgradeAppStoreApps(array_keys($autoDisabledApps), $autoDisabledApps); - } -+ }*/ ++ } */ // install new shipped apps on upgrade $errors = Installer::installShippedApps(true); + diff --git a/patches/011-privacy-settings.patch b/patches/011-privacy-settings.patch index fbf44d2f7b6e335a4c91ae8f8c755bad1a6df81c..940d8eacc6a84e09b7fdcbda6a8cbc5162350bf0 100644 --- a/patches/011-privacy-settings.patch +++ b/patches/011-privacy-settings.patch @@ -6,7 +6,7 @@ This patch removes certain unnecessary sections from the "privacy" section in pe --- ./apps/privacy/lib/Settings/MissionSettings.php 2021-09-07 17:38:08.650902445 +0530 +++ ./apps/privacy/lib/Settings/MissionSettings-new.php 2021-09-07 17:40:30.078256502 +0530 -@@ -52,7 +52,7 @@ +@@ -36,7 +36,7 @@ return null; } @@ -18,7 +18,7 @@ This patch removes certain unnecessary sections from the "privacy" section in pe --- ./apps/privacy/lib/Settings/UserDataManifestoSettings.php 2021-09-07 17:38:06.284224253 +0530 +++ ./apps/privacy/lib/Settings/UserDataManifestoSettings-new.php 2021-09-07 17:40:42.288315736 +0530 -@@ -45,7 +45,7 @@ +@@ -29,7 +29,7 @@ return null; } @@ -30,7 +30,7 @@ This patch removes certain unnecessary sections from the "privacy" section in pe --- ./apps/privacy/lib/Controller/PersonalController.php 2024-08-01 12:57:29 +0530 +++ ./apps/privacy/lib/Controller/PersonalController-new.php 2024-08-01 12:57:03 +0530 -@@ -103,7 +103,7 @@ +@@ -87,7 +87,7 @@ 'internal' => false, ]; } @@ -40,4 +40,3 @@ This patch removes certain unnecessary sections from the "privacy" section in pe } } \ No newline at end of file - diff --git a/patches/013-revert-token-password-update.patch b/patches/013-revert-token-password-update.patch index e63ccfc6e24013c4c15f412569025d62c1df9340..32af56388fbda6560d537d8be6c45c665241a78a 100644 --- a/patches/013-revert-token-password-update.patch +++ b/patches/013-revert-token-password-update.patch @@ -7,11 +7,11 @@ This patch reverts to only update when there are expired tokens. --- ./lib/private/Authentication/Token/PublicKeyTokenProvider.php 2024-07-25 17:51:37 +0530 +++ ./lib/private/Authentication/Token/PublicKeyTokenProvider-new.php 2024-07-25 17:53:16 +0530 -@@ -517,6 +517,11 @@ +@@ -504,6 +504,11 @@ } public function updatePasswords(string $uid, string $password) { -+ if (!$this->mapper->hasExpiredTokens($uid)) { ++ if (!$this->mapper->hasExpiredTokens($uid)) { + //Nothing to do here + return; + } @@ -19,3 +19,4 @@ This patch reverts to only update when there are expired tokens. // prevent setting an empty pw as result of pw-less-login if ($password === '' || !$this->config->getSystemValueBool('auth.storeCryptedPassword', true)) { return; + diff --git a/patches/014-add-mail-usage.patch b/patches/014-add-mail-usage.patch index 2ccfa97cd64e79dfc031374e73132f23f7d02c34..4418b3e15bc2307765220dfab542671e00c3ccc0 100644 --- a/patches/014-add-mail-usage.patch +++ b/patches/014-add-mail-usage.patch @@ -1,24 +1,22 @@ ---- lib/private/legacy/OC_Helper.php 2022-11-23 19:35:50.880495300 +0530 -+++ lib/private/legacy/OC_Helper-new.php 2022-11-23 19:40:09.970495300 +0530 -@@ -542,6 +542,12 @@ +--- lib/private/legacy/OC_Helper.php 2025-05-25 16:00:00.880495300 +0530 ++++ lib/private/legacy/OC_Helper-new.php 2025-05-25 16:02:00.970495300 +0530 +@@ -512,6 +512,12 @@ } try { $free = $sourceStorage->free_space($rootInfo->getInternalPath()); + $ownerId = $storage->getOwner($path); + $mailQuotaUsage = (int) \OC::$server->getConfig()->getUserValue($ownerId, 'ecloud-accounts', 'mailQuotaUsage', 0); -+ $free = max(0,$free - $mailQuotaUsage); ++ $free = max(0, $free - $mailQuotaUsage); + if($path === '/') { + $used = $used + $mailQuotaUsage; -+ } ++ } if (is_bool($free)) { $free = 0.0; } -@@ -571,8 +577,6 @@ - $relative = 0; - } +@@ -547,7 +553,6 @@ + */ + $isRemoteShare = $storage->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class); -- /** @var string $ownerId */ - $ownerId = $storage->getOwner($path); - $ownerDisplayName = ''; - if ($ownerId) { - $ownerDisplayName = \OC::$server->getUserManager()->getDisplayName($ownerId) ?? ''; \ No newline at end of file + $hasOwnerId = $ownerId !== false && $ownerId !== null; + $ownerDisplayName = ''; \ No newline at end of file diff --git a/patches/015-email-mail-template.patch b/patches/015-email-mail-template.patch index 039ee020c004d8de472a6960a660d4c862e16316..3b0a77b862d6ea16f5cb230265d87bb38b5b1c66 100644 --- a/patches/015-email-mail-template.patch +++ b/patches/015-email-mail-template.patch @@ -7,26 +7,25 @@ This patch helps in indentifying that For a recurring event, the invitee knows w --- ./apps/dav/lib/CalDAV/Schedule/IMipPlugin.php 2024-03-18 11:18:20 +++ ./apps/dav/lib/CalDAV/Schedule/IMipPlugin-new.php 2024-03-11 11:18:22 -@@ -174,7 +174,29 @@ +@@ -149,7 +149,30 @@ /** @var VEvent $oldVevent */ $oldVevent = !empty($modified['old']) && is_array($modified['old']) ? array_pop($modified['old']) : null; $isModified = isset($oldVevent); -- + $recurrenceId = $vEvent->{'RECURRENCE-ID'}; + if (isset($recurrenceId) && $modified['sentOld'] === 1 && !empty($oldVevent)) { + $dateTime = $recurrenceId->getValue(); + $recurrenceArray = explode('T', $dateTime); -+ + + $oldVEventStart = $oldVevent->DTSTART; + $oldStartDateTime = $oldVEventStart->getValue(); + $startDateTimeArray = explode('T', $oldStartDateTime); + $finalStartTime = $recurrenceArray[0] . 'T' . $startDateTimeArray[1]; -+ ++ + $timeZoneId = (string) $recurrenceId['TZID']; + $oldVevent->DTSTART->setDateTime( + new \DateTime($finalStartTime, new \DateTimeZone($timeZoneId)) + ); -+ ++ + $oldVEventEnd = $oldVevent->DTEND; + $oldEndDateTime = $oldVEventEnd->getValue(); + $endDateTimeArray = explode('T', $oldEndDateTime); @@ -35,64 +34,64 @@ This patch helps in indentifying that For a recurring event, the invitee knows w + new \DateTime($finalEndTime, new \DateTimeZone($timeZoneId)) + ); + } ++ // No changed events after all - this shouldn't happen if there is significant change yet here we are // The scheduling status is debatable - if(empty($vEvent)) { -@@ -242,6 +266,13 @@ + if (empty($vEvent)) { +@@ -217,12 +240,35 @@ $data['invitee_name'] = ($senderName ?: $sender); $fromEMail = Util::getDefaultEmailAddress('invitations-noreply'); -+ //if sender name is empty sometimes in case of email client ++ // if sender name is empty sometimes in case of email client + if ($senderName === null || empty(trim($senderName))) { + $users = $this->userManager->getByEmail($sender); + if (count($users) === 1) { + $senderName = $users[0]->getDisplayName(); + } + } ++ $fromName = $this->imipService->getFrom($senderName, $this->defaults->getName()); - $message = $this->mailer->createMessage() -@@ -262,7 +293,22 @@ $template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data); $template->addHeader(); - $this->imipService->addSubjectAndHeading($template, $method, $data['invitee_name'], $data['meeting_title'], $isModified, $replyingAttendee); + $l10n = \OC::$server->getL10N('dav'); -+ if ( count($vEvent)>1) { ++ if (count($vEvent) > 1) { + $this->imipService->addSubjectAndHeadingUpdated($template, $method, $data['invitee_name'], $data['meeting_title'], $isModified, $replyingAttendee); + } else { + $this->imipService->addSubjectAndHeading($template, $method, $data['invitee_name'], $data['meeting_title'], $isModified, $replyingAttendee); + } + if ($method === self::METHOD_CANCEL) { -+ $template->addHeadingBanner('#FFC2B9','#7D1000',$l10n->t('The invitation has been cancelled')); ++ $template->addHeadingBanner('#FFC2B9', '#7D1000', $l10n->t('The invitation has been cancelled')); + } -+ if ($method !== self::METHOD_CANCEL && $method !== self::METHOD_REPLY && count($vEvent)>1) { -+ $template->addHeadingBanner('#EFFFDB','#293618',$l10n->t('This recurring event has been updated, please review the information below:')); ++ if ($method !== self::METHOD_CANCEL && $method !== self::METHOD_REPLY && count($vEvent) > 1) { ++ $template->addHeadingBanner('#EFFFDB', '#293618', $l10n->t('This recurring event has been updated, please review the information below:')); + } + $sequence = $vEvent->SEQUENCE ? $vEvent->SEQUENCE->getValue() : NULL; -+ if (($sequence && $method !== self::METHOD_CANCEL && $method !== self::METHOD_REPLY && ($sequence > 2)) || isset($vEvent->{'RECURRENCE-ID'})) { -+ $template->addHeadingBanner('#EFFFDB','#293618',$l10n->t('This event has been updated, please review the information below:')); ++ if (($sequence && $method !== self::METHOD_CANCEL && $method !== self::METHOD_REPLY && ($sequence > 2)) || isset($vEvent->{'RECURRENCE-ID'})) { ++ $template->addHeadingBanner('#EFFFDB', '#293618', $l10n->t('This event has been updated, please review the information below:')); + } $this->imipService->addBulletList($template, $vEvent, $data); // Only add response buttons to invitation requests: Fix Issue #11230 -@@ -295,7 +341,6 @@ +@@ -255,7 +301,6 @@ || in_array(strtolower($recipientDomain), $invitationLinkRecipients)) { $token = $this->imipService->createInvitationToken($iTipMessage, $vEvent, $lastOccurrence); $this->imipService->addResponseButtons($template, $token); - $this->imipService->addMoreOptionsButton($template, $token); } - } - + } + --- ./apps/dav/lib/CalDAV/Schedule/IMipService.php 2024-03-18 11:40:39 +++ ./apps/dav/lib/CalDAV/Schedule/IMipService-new.php 2024-03-18 13:47:17 -@@ -169,10 +169,30 @@ +@@ -163,7 +163,31 @@ $oldUrl = self::readPropertyWithDefault($oldVEvent, 'URL', $defaultVal); $data['meeting_url_html'] = !empty($oldUrl) && $oldUrl !== $data['meeting_url'] ? sprintf('%1$s', $oldUrl) : $data['meeting_url']; -- $data['meeting_when_html'] = -+ if(isset($vEvent->RRULE)){ -+ $RRule= (string) $vEvent->RRULE->getValue(); +- $data['meeting_when_html'] = $oldMeetingWhen !== $data['meeting_when'] ? sprintf("%s
%s", $oldMeetingWhen, $data['meeting_when']) : $data['meeting_when']; ++ if (isset($vEvent->RRULE)) { ++ $RRule = (string) $vEvent->RRULE->getValue(); + if (strpos($RRule, 'FREQ=DAILY') !== false) { + $timeTitle = $this->l10n->t('Repeats daily:'); + } @@ -100,29 +99,30 @@ This patch helps in indentifying that For a recurring event, the invitee knows w + $timeTitle = $this->l10n->t('Repeats weekly:'); + } + if (strpos($RRule, 'FREQ=MONTHLY') !== false) { -+ $timeTitle = $this->l10n->t('Repeats monthly:'); ++ $timeTitle = $this->l10n->t('Repeats monthly:'); + } + if (strpos($RRule, 'FREQ=YEARLY') !== false) { + $timeTitle = $this->l10n->t('Repeats yearly:'); + } + $data['meeting_when_html'] = - ($oldMeetingWhen !== $data['meeting_when'] && $oldMeetingWhen !== null) -- ? sprintf("%s
%s", $oldMeetingWhen, $data['meeting_when']) -+ ? sprintf("%s
%s %s", $oldMeetingWhen,$timeTitle, $data['meeting_when']) -+ : $data['meeting_when']; ++ ($oldMeetingWhen !== $data['meeting_when'] && $oldMeetingWhen !== null) ++ ? sprintf("%s
%s %s", $oldMeetingWhen, $timeTitle, $data['meeting_when']) ++ : $data['meeting_when']; + } else { + $data['meeting_when_html'] = -+ ($oldMeetingWhen !== $data['meeting_when'] && $oldMeetingWhen !== null) -+ ? sprintf("%s
%s %s", $oldMeetingWhen, $this->l10n->t('Time:'),$data['meeting_when']) - : $data['meeting_when']; ++ ($oldMeetingWhen !== $data['meeting_when'] && $oldMeetingWhen !== null) ++ ? sprintf("%s
%s %s", $oldMeetingWhen, $this->l10n->t('Time:'), $data['meeting_when']) ++ : $data['meeting_when']; + } ++ + } + // generate occurring next string + if ($eventReaderCurrent->recurs()) { +@@ -967,6 +991,51 @@ } - return $data; - } -@@ -444,6 +464,51 @@ } - /** ++ /** + * @param IEMailTemplate $template + * @param string $method + * @param string $sender @@ -130,7 +130,7 @@ This patch helps in indentifying that For a recurring event, the invitee knows w + * @param string|null $partstat + */ + public function addSubjectAndHeadingUpdated(IEMailTemplate $template, -+ string $method, string $sender, string $summary, bool $isModified, ?Property $replyingAttendee = null): void { ++ string $method, string $sender, string $summary, bool $isModified, ?Property $replyingAttendee = null): void { + if ($method === IMipPlugin::METHOD_CANCEL) { + // TRANSLATORS Subject for email, when an invitation is cancelled. Ex: "Cancelled: {{Event Name}}" + $template->setSubject($this->l10n->t('Cancelled: %1$s', [$summary])); @@ -167,51 +167,26 @@ This patch helps in indentifying that For a recurring event, the invitee knows w + } + } + -+ /** + /** * @param string $path * @return string - */ -@@ -537,12 +602,36 @@ - $data['meeting_title_html'] ?? $data['meeting_title'], $this->l10n->t('Title:'), - $this->getAbsoluteImagePath('caldav/title.png'), $data['meeting_title'], '', IMipPlugin::IMIP_INDENT); - if ($data['meeting_when'] !== '') { -- $template->addBodyListItem($data['meeting_when_html'] ?? $data['meeting_when'], $this->l10n->t('Time:'), -+ if(isset($vevent->RRULE)){ -+ $RRule=(string) $vevent->RRULE->getValue(); -+ if (strpos($RRule, 'FREQ=DAILY') !== false) { -+ $timeTitle = $this->l10n->t('Repeats daily:'); -+ } -+ if (strpos($RRule, 'FREQ=WEEKLY') !== false) { -+ $timeTitle = $this->l10n->t('Repeats weekly:'); -+ } -+ if (strpos($RRule, 'FREQ=MONTHLY') !== false) { -+ $timeTitle = $this->l10n->t('Repeats monthly:'); -+ } -+ if (strpos($RRule, 'FREQ=YEARLY') !== false) { -+ $timeTitle = $this->l10n->t('Repeats yearly:'); -+ } -+ $template->addBodyListItem($data['meeting_when_html'] ?? $data['meeting_when'], $timeTitle, +@@ -1065,8 +1134,13 @@ $this->getAbsoluteImagePath('caldav/time.png'), $data['meeting_when'], '', IMipPlugin::IMIP_INDENT); -+ } else { -+ $template->addBodyListItem($data['meeting_when_html'] ?? $data['meeting_when'], $this->l10n->t('Time:'), -+ $this->getAbsoluteImagePath('caldav/time.png'), $data['meeting_when'], '', IMipPlugin::IMIP_INDENT); -+ } } if ($data['meeting_location'] !== '') { - $template->addBodyListItem($data['meeting_location_html'] ?? $data['meeting_location'], $this->l10n->t('Location:'), - $this->getAbsoluteImagePath('caldav/location.png'), $data['meeting_location'], '', IMipPlugin::IMIP_INDENT); -+ if(filter_var(trim($data['meeting_location']), FILTER_VALIDATE_URL)) { ++ if(filter_var(trim($data['meeting_location']), FILTER_VALIDATE_URL)) { + $template->addBodyListItem($data['meeting_location_html'] ?? $data['meeting_location'], $this->l10n->t('Location:'), + $this->getAbsoluteImagePath('caldav/videocall.png'), $data['meeting_location'], '', IMipPlugin::IMIP_INDENT); -+ + } else { + $template->addBodyListItem($data['meeting_location_html'] ?? $data['meeting_location'], $this->l10n->t('Location:'), + $this->getAbsoluteImagePath('caldav/location.png'), $data['meeting_location'], '', IMipPlugin::IMIP_INDENT); -+ } ++ } } if ($data['meeting_url'] !== '') { $template->addBodyListItem($data['meeting_url_html'] ?? $data['meeting_url'], $this->l10n->t('Link:'), -@@ -637,7 +726,7 @@ +@@ -1143,7 +1217,7 @@ * @param $token */ public function addResponseButtons(IEMailTemplate $template, $token) { @@ -220,7 +195,7 @@ This patch helps in indentifying that For a recurring event, the invitee knows w $this->l10n->t('Accept'), $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.accept', [ 'token' => $token, -@@ -645,20 +734,10 @@ +@@ -1151,20 +1225,10 @@ $this->l10n->t('Decline'), $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.decline', [ 'token' => $token, @@ -247,30 +222,28 @@ This patch helps in indentifying that For a recurring event, the invitee knows w --- ./apps/dav/lib/CalDAV/EventComparisonService.php 2024-05-06 12:46:29 +++ ./apps/dav/lib/CalDAV/EventComparisonService-new.php 2024-05-06 12:47:11 -@@ -100,11 +100,10 @@ - unset($newEventComponents[$k]); +@@ -78,8 +78,9 @@ } } -- + + $sentOld = 0; - if(empty($old)) { + if (empty($old)) { - return ['old' => null, 'new' => $newEventComponents]; + return ['old' => null, 'new' => $newEventComponents, 'sentOld' => $sentOld]; } -- + $oldEventComponents = $old->getComponents(); - if(is_array($oldEventComponents) && !empty($oldEventComponents)) { - foreach ($oldEventComponents as $k => $event) { -@@ -113,11 +112,15 @@ +@@ -90,11 +91,16 @@ continue; } - if($this->removeIfUnchanged($event, $newEventComponents)) { + if ($this->removeIfUnchanged($event, $newEventComponents)) { - unset($oldEventComponents[$k]); -+ if($k!=1){ -+ unset($oldEventComponents[$k]); -+ } else { ++ if($k!=1){ ++ unset($oldEventComponents[$k]); ++ } else { + $sentOld = 1; + } ++ } } } diff --git a/patches/016-login-screen.patch b/patches/016-login-screen.patch index 939529202b36db9198cdda77bfdbbc63758e5cdb..d7d7b98af69044bcd7a358fdd9ef4d765aa7e3ab 100644 --- a/patches/016-login-screen.patch +++ b/patches/016-login-screen.patch @@ -1,8 +1,6 @@ ---- ./core/templates/layout.guest.php 2024-03-15 19:20:21 -+++ ./core/templates/layout.guest-new.php 2024-03-15 19:24:49 ---- layout.guest.php 2024-07-25 19:23:57 -+++ layout.guest-new.php 2024-07-25 19:34:27 -@@ -22,6 +22,7 @@ +--- layout.guest.php 2025-07-24 10:37:50 ++++ layout.guest-new.php 2025-07-24 10:58:20 +@@ -32,6 +32,7 @@ @@ -10,67 +8,66 @@ -@@ -30,12 +31,37 @@ - $initialState) { ?> - - --
--
-+
" > -+ +@@ -42,10 +43,38 @@ + +
+
++
" > ++ +