2 * Transparently handle the upgrading of server data formats.
4 * Copyright (c) 1987-2015 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 cmd_bmbx
100 void cmd_bmbx_backend(struct ctdlroom *qrbuf, void *data) {
101 static struct RoomProcList *rplist = NULL;
102 struct RoomProcList *ptr;
105 /* Lazy programming here. Call this function as a CtdlForEachRoom backend
106 * in order to queue up the room names, or call it with a null room
107 * to make it do the processing.
110 ptr = (struct RoomProcList *) malloc(sizeof (struct RoomProcList));
111 if (ptr == NULL) return;
113 safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name);
119 while (rplist != NULL) {
121 if (CtdlGetRoomLock(&qr, rplist->name) == 0) {
122 syslog(LOG_DEBUG, "Processing <%s>...", rplist->name);
123 if ( (qr.QRflags & QR_MAILBOX) == 0) {
124 syslog(LOG_DEBUG, " -- not a mailbox");
128 qr.QRgen = time(NULL);
129 syslog(LOG_DEBUG, " -- fixed!");
131 CtdlPutRoomLock(&qr);
135 rplist = rplist->next;
141 * quick fix to bump mailbox generation numbers
143 void bump_mailbox_generation_numbers(void) {
144 syslog(LOG_WARNING, "Applying security fix to mailbox rooms");
145 CtdlForEachRoom(cmd_bmbx_backend, NULL);
146 cmd_bmbx_backend(NULL, NULL);
152 * Back end processing function for convert_ctdluid_to_minusone()
154 void cbtm_backend(struct ctdluser *usbuf, void *data) {
155 static struct UserProcList *uplist = NULL;
156 struct UserProcList *ptr;
159 /* Lazy programming here. Call this function as a ForEachUser backend
160 * in order to queue up the room names, or call it with a null user
161 * to make it do the processing.
164 ptr = (struct UserProcList *)
165 malloc(sizeof (struct UserProcList));
166 if (ptr == NULL) return;
168 safestrncpy(ptr->user, usbuf->fullname, sizeof ptr->user);
174 while (uplist != NULL) {
176 if (CtdlGetUserLock(&us, uplist->user) == 0) {
177 syslog(LOG_DEBUG, "Processing <%s>...", uplist->user);
178 if (us.uid == CTDLUID) {
181 CtdlPutUserLock(&us);
185 uplist = uplist->next;
191 * quick fix to change all CTDLUID users to (-1)
193 void convert_ctdluid_to_minusone(void) {
194 syslog(LOG_WARNING, "Applying uid changes");
195 ForEachUser(cbtm_backend, NULL);
196 cbtm_backend(NULL, NULL);
203 * These accounts may have been created by code that ran between mid 2008 and early 2011.
204 * If present they are no longer in use and may be deleted.
206 void remove_thread_users(void) {
207 char *deleteusers[] = {
216 "SYS_select_on_master",
221 struct ctdluser usbuf;
222 for (i=0; i<(sizeof(deleteusers)/sizeof(char *)); ++i) {
223 if (CtdlGetUser(&usbuf, deleteusers[i]) == 0) {
225 strcpy(usbuf.password, "deleteme");
228 "System user account <%s> is no longer in use and will be deleted.",
237 * Attempt to guess the name of the time zone currently in use
238 * on the underlying host system.
240 void guess_time_zone(void) {
244 fp = popen(file_guesstimezone, "r");
246 if (fgets(buf, sizeof buf, fp) && (strlen(buf) > 2)) {
247 buf[strlen(buf)-1] = 0;
248 CtdlSetConfigStr("c_default_cal_zone", buf);
249 syslog(LOG_INFO, "Configuring timezone: %s", buf);
257 * Perform any upgrades that can be done automatically based on our knowledge of the previous
258 * version of Citadel server that was running here.
260 * Note that if the previous version was 0 then this is a new installation running for the first time.
262 void update_config(void) {
264 int oldver = CtdlGetConfigInt("MM_hosted_upgrade_level");
267 CtdlSetConfigInt("c_rfc822_strict_from", 0);
271 CtdlSetConfigInt("c_purge_hour", 3);
275 CtdlSetConfigInt("c_ldap_port", 389);
279 CtdlSetConfigStr("c_ip_addr", "*");
283 CtdlSetConfigInt("c_enable_fulltext", 1);
287 CtdlSetConfigInt("c_auto_cull", 1);
291 CtdlSetConfigInt("c_xmpp_c2s_port", 5222);
292 CtdlSetConfigInt("c_xmpp_s2s_port", 5269);
296 CtdlSetConfigInt("c_nntp_port", 119);
297 CtdlSetConfigInt("c_nntps_port", 563);
300 if (IsEmptyStr(CtdlGetConfigStr("c_default_cal_zone"))) {
308 * Based on the server version number reported by the existing database,
309 * run in-place data format upgrades until everything is up to date.
311 void check_server_upgrades(void) {
313 syslog(LOG_INFO, "Existing database version on disk is %d.%02d",
314 (CtdlGetConfigInt("MM_hosted_upgrade_level") / 100),
315 (CtdlGetConfigInt("MM_hosted_upgrade_level") % 100)
318 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < REV_LEVEL) {
320 "Server hosted updates need to be processed at this time. Please wait..."
329 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 555)) {
330 syslog(LOG_EMERG, "This database is too old to be upgraded. Citadel server will exit.");
333 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 591)) {
334 bump_mailbox_generation_numbers();
336 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 608)) {
337 convert_ctdluid_to_minusone();
339 if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 659)) {
340 rebuild_euid_index();
342 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 735) {
345 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 736) {
346 rebuild_usersbynumber();
348 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 790) {
349 remove_thread_users();
351 if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 810) {
352 struct ctdlroom QRoom;
353 if (!CtdlGetRoom(&QRoom, SMTP_SPOOLOUT_ROOM)) {
354 QRoom.QRdefaultview = VIEW_QUEUE;
357 if (!CtdlGetRoom(&QRoom, FNBL_QUEUE_ROOM)) {
358 QRoom.QRdefaultview = VIEW_QUEUE;
363 CtdlSetConfigInt("MM_hosted_upgrade_level", REV_LEVEL);
366 * Negative values for maxsessions are not allowed.
368 if (CtdlGetConfigInt("c_maxsessions") < 0) {
369 CtdlSetConfigInt("c_maxsessions", 0);
372 /* We need a system default message expiry policy, because this is
373 * the top level and there's no 'higher' policy to fall back on.
374 * By default, do not expire messages at all.
376 if (CtdlGetConfigInt("c_ep_mode") == 0) {
377 CtdlSetConfigInt("c_ep_mode", EXPIRE_MANUAL);
378 CtdlSetConfigInt("c_ep_value", 0);
383 CTDL_MODULE_UPGRADE(upgrade)
385 check_server_upgrades();
387 /* return our module id for the Log */