2 * Transparently handle the upgrading of server data formats.
4 * Copyright (c) 1987-2016 by the citadel.org team
6 * This program is open source software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
23 #include <sys/types.h>
25 #if TIME_WITH_SYS_TIME
26 # include <sys/time.h>
30 # include <sys/time.h>
39 #include <libcitadel.h>
42 #include "citserver.h"
49 #include "serv_upgrade.h"
50 #include "euidindex.h"
51 #include "ctdl_module.h"
55 * Fix up the name for Citadel user 0 and try to remove any extra users with number 0
57 void fix_sys_user_name(void)
59 struct ctdluser usbuf;
60 char usernamekey[USERNAME_SIZE];
62 /** If we have a user called Citadel rename them to SYS_Citadel */
63 if (CtdlGetUser(&usbuf, "Citadel") == 0)
65 rename_user("Citadel", "SYS_Citadel");
68 while (CtdlGetUserByNumber(&usbuf, 0) == 0)
70 /* delete user with number 0 and no name */
71 if (IsEmptyStr(usbuf.fullname)) {
72 cdb_delete(CDB_USERS, "", 0);
75 /* temporarily set this user to -1 */
81 /* Make sure user SYS_* is user 0 */
82 while (CtdlGetUserByNumber(&usbuf, -1) == 0)
84 if (strncmp(usbuf.fullname, "SYS_", 4))
85 { /* Delete any user 0 that doesn't start with SYS_ */
86 makeuserkey(usernamekey, usbuf.fullname, cutuserkey(usbuf.fullname));
87 cdb_delete(CDB_USERS, usernamekey, strlen(usernamekey));
98 * Back end processing function for convert_ctdluid_to_minusone()
100 void cbtm_backend(struct ctdluser *usbuf, void *data) {
101 static struct UserProcList *uplist = NULL;
102 struct UserProcList *ptr;
105 /* Lazy programming here. Call this function as a ForEachUser backend
106 * in order to queue up the room names, or call it with a null user
107 * to make it do the processing.
110 ptr = (struct UserProcList *)
111 malloc(sizeof (struct UserProcList));
112 if (ptr == NULL) return;
114 safestrncpy(ptr->user, usbuf->fullname, sizeof ptr->user);
120 while (uplist != NULL) {
122 if (CtdlGetUserLock(&us, uplist->user) == 0) {
123 syslog(LOG_DEBUG, "Processing <%s>...", uplist->user);
124 if (us.uid == CTDLUID) {
127 CtdlPutUserLock(&us);
131 uplist = uplist->next;
137 * quick fix to change all CTDLUID users to (-1)
139 void convert_ctdluid_to_minusone(void) {
140 syslog(LOG_WARNING, "Applying uid changes");
141 ForEachUser(cbtm_backend, NULL);
142 cbtm_backend(NULL, NULL);
149 * These accounts may have been created by code that ran between mid 2008 and early 2011.
150 * If present they are no longer in use and may be deleted.
152 void remove_thread_users(void) {
153 char *deleteusers[] = {
162 "SYS_select_on_master",
167 struct ctdluser usbuf;
168 for (i=0; i<(sizeof(deleteusers)/sizeof(char *)); ++i) {
169 if (CtdlGetUser(&usbuf, deleteusers[i]) == 0) {
171 strcpy(usbuf.password, "deleteme");
174 "System user account <%s> is no longer in use and will be deleted.",
183 * Attempt to guess the name of the time zone currently in use
184 * on the underlying host system.
186 void guess_time_zone(void) {
190 fp = popen(file_guesstimezone, "r");
192 if (fgets(buf, sizeof buf, fp) && (strlen(buf) > 2)) {
193 buf[strlen(buf)-1] = 0;
194 CtdlSetConfigStr("c_default_cal_zone", buf);
195 syslog(LOG_INFO, "Configuring timezone: %s", buf);
203 * Perform any upgrades that can be done automatically based on our knowledge of the previous
204 * version of Citadel server that was running here.
206 * Note that if the previous version was 0 then this is a new installation running for the first time.
208 void update_config(void) {
210 int oldver = CtdlGetConfigInt("MM_hosted_upgrade_level");
213 CtdlSetConfigInt("c_rfc822_strict_from", 0);
217 CtdlSetConfigInt("c_purge_hour", 3);
221 CtdlSetConfigInt("c_ldap_port", 389);
225 CtdlSetConfigStr("c_ip_addr", "*");
229 CtdlSetConfigInt("c_enable_fulltext", 1);
233 CtdlSetConfigInt("c_auto_cull", 1);
237 CtdlSetConfigInt("c_xmpp_c2s_port", 5222);
238 CtdlSetConfigInt("c_xmpp_s2s_port", 5269);
242 CtdlSetConfigInt("c_nntp_port", 119);
243 CtdlSetConfigInt("c_nntps_port", 563);
246 if (IsEmptyStr(CtdlGetConfigStr("c_default_cal_zone"))) {
254 * Based on the server version number reported by the existing database,
255 * run in-place data format upgrades until everything is up to date.
257 void check_server_upgrades(void) {
259 syslog(LOG_INFO, "Existing database version on disk is %d", CtdlGetConfigInt("MM_hosted_upgrade_level"));
261 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < REV_LEVEL) {
263 "Server hosted updates need to be processed at this time. Please wait..."
272 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 591)) {
273 syslog(LOG_EMERG, "This database is too old to be upgraded. Citadel server will exit.");
276 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 608)) {
277 convert_ctdluid_to_minusone();
279 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 659)) {
280 rebuild_euid_index();
282 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 735) {
285 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 736) {
286 rebuild_usersbynumber();
288 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 790) {
289 remove_thread_users();
291 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 810) {
292 struct ctdlroom QRoom;
293 if (!CtdlGetRoom(&QRoom, SMTP_SPOOLOUT_ROOM)) {
294 QRoom.QRdefaultview = VIEW_QUEUE;
297 if (!CtdlGetRoom(&QRoom, FNBL_QUEUE_ROOM)) {
298 QRoom.QRdefaultview = VIEW_QUEUE;
303 CtdlSetConfigInt("MM_hosted_upgrade_level", REV_LEVEL);
306 * Negative values for maxsessions are not allowed.
308 if (CtdlGetConfigInt("c_maxsessions") < 0) {
309 CtdlSetConfigInt("c_maxsessions", 0);
312 /* We need a system default message expiry policy, because this is
313 * the top level and there's no 'higher' policy to fall back on.
314 * By default, do not expire messages at all.
316 if (CtdlGetConfigInt("c_ep_mode") == 0) {
317 CtdlSetConfigInt("c_ep_mode", EXPIRE_MANUAL);
318 CtdlSetConfigInt("c_ep_value", 0);
323 CTDL_MODULE_UPGRADE(upgrade)
325 check_server_upgrades();
327 /* return our module id for the Log */