/*
- * This module imports an "unpacked" system. The unpacked data may come from
- * an older version of Citadel, or a different hardware architecture, or
- * whatever. You should only run an import when your installed system is
- * brand new and _empty_ !!
+ * $Id$
+ *
+ * Transparently handle the upgrading of server data formats.
+ *
*/
+#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/time.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
-#include <pthread.h>
#include "citadel.h"
#include "server.h"
-#include <syslog.h>
-#include "sysdep_decls.h"
#include "citserver.h"
#include "support.h"
#include "config.h"
-#include "dynloader.h"
+#include "control.h"
+#include "database.h"
#include "room_ops.h"
#include "user_ops.h"
-#include "database.h"
-#include "control.h"
-
-extern struct CitContext *ContextList;
-FILE *imfp, *exfp;
-
-#define MODULE_NAME "Import an unpacked system"
-#define MODULE_AUTHOR "Art Cancro"
-#define MODULE_EMAIL "ajc@uncnsrd.mt-kisco.ny.us"
-#define MAJOR_VERSION 0
-#define MINOR_VERSION 3
-
-static struct DLModule_Info info = {
- MODULE_NAME,
- MODULE_AUTHOR,
- MODULE_EMAIL,
- MAJOR_VERSION,
- MINOR_VERSION
- };
-
-
+#include "msgbase.h"
+#include "tools.h"
+#include "serv_upgrade.h"
+#include "euidindex.h"
-void fpgetfield(FILE *fp, char *string)
-{
- int a,b;
- strcpy(string,"");
- a=0;
- do {
- b=getc(fp);
- if (b<1) {
- string[a]=0;
- return;
- }
- string[a]=b;
- ++a;
- } while (b!=0);
- }
+#include "ctdl_module.h"
-void import_message(long msgnum, long msglen) {
- char *msgtext;
- msgtext = malloc(msglen);
- if (msgtext == NULL) {
- lprintf(3, "ERROR: cannot allocate memory\n");
- lprintf(3, "Your data files are now corrupt.\n");
- fclose(imfp);
- exit(1);
- }
-
- fread(msgtext, msglen, 1, imfp);
- cdb_store(CDB_MSGMAIN, &msgnum, sizeof(long), msgtext, msglen);
- free(msgtext);
+/*
+ * Back end processing function for cmd_bmbx
+ */
+void cmd_bmbx_backend(struct ctdlroom *qrbuf, void *data) {
+ static struct RoomProcList *rplist = NULL;
+ struct RoomProcList *ptr;
+ struct ctdlroom qr;
+
+ /* Lazy programming here. Call this function as a ForEachRoom backend
+ * in order to queue up the room names, or call it with a null room
+ * to make it do the processing.
+ */
+ if (qrbuf != NULL) {
+ ptr = (struct RoomProcList *)
+ malloc(sizeof (struct RoomProcList));
+ if (ptr == NULL) return;
+
+ safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name);
+ ptr->next = rplist;
+ rplist = ptr;
+ return;
}
-void imp_floors(void) {
- char key[256], tag[256], tval[256];
- struct floor fl;
- int floornum = 0;
-
-
- while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
-
- if (!strcasecmp(key, "floor")) {
- bzero(&fl, sizeof(struct floor));
-
- while(fpgetfield(imfp, tag),
- strcasecmp(tag, "endfloor")) {
- fpgetfield(imfp, tval);
+ while (rplist != NULL) {
- if (!strcasecmp(tag, "f_flags"))
- fl.f_flags = atoi(tval);
- if (!strcasecmp(tag, "f_name")) {
- lprintf(9, "Floor <%s>\n", tval);
- strcpy(fl.f_name, tval);
- }
- if (!strcasecmp(tag, "f_ref_count"))
- fl.f_ref_count = atoi(tval);
- }
-
- putfloor(&fl, floornum);
- ++floornum;
- }
- else {
- lprintf(3, "ERROR: invalid floor section.\n");
- lprintf(3, "Your data files are now corrupt.\n");
- fclose(imfp);
- return;
+ if (lgetroom(&qr, rplist->name) == 0) {
+ lprintf(CTDL_DEBUG, "Processing <%s>...\n", rplist->name);
+ if ( (qr.QRflags & QR_MAILBOX) == 0) {
+ lprintf(CTDL_DEBUG, " -- not a mailbox\n");
}
- }
- }
-
-
+ else {
-void imp_rooms(void) {
- char key[256];
- char tag[256], tval[256];
- int roomnum = 0;
- struct quickroom qr;
- long *msglist;
- int num_msgs = 0;
- long msgnum, msglen;
-
- while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
- if (!strcasecmp(key, "room")) {
- bzero(&qr, sizeof(struct quickroom));
- msglist = NULL;
- num_msgs = 0;
- lprintf(9, "Room ");
-
- while(fpgetfield(imfp, tag),
- strcasecmp(tag, "endroom")) {
- if (strcasecmp(tag, "message")) {
- fpgetfield(imfp, tval);
- }
- else {
- strcpy(tval, "");
- }
-
- if (!strcasecmp(tag, "qrname")) {
- strcpy(qr.QRname, tval);
- lprintf(9, "<%s> ", qr.QRname);
- }
- if (!strcasecmp(tag, "qrpasswd"))
- strcpy(qr.QRpasswd, tval);
- if (!strcasecmp(tag, "qrroomaide"))
- qr.QRroomaide = atol(tval);
- if (!strcasecmp(tag, "qrhighest"))
- qr.QRhighest = atol(tval);
- if (!strcasecmp(tag, "qrgen"))
- qr.QRgen = atol(tval);
- if (!strcasecmp(tag, "qrflags"))
- qr.QRflags = atoi(tval);
- if (!strcasecmp(tag, "qrdirname"))
- strcpy(qr.QRdirname, tval);
- if (!strcasecmp(tag, "qrinfo"))
- qr.QRinfo = atol(tval);
- if (!strcasecmp(tag, "qrfloor"))
- qr.QRfloor = atoi(tval);
- if (!strcasecmp(tag, "message")) {
- fpgetfield(imfp, tval);
- msgnum = atol(tval);
- fpgetfield(imfp, tval);
- msglen = atol(tval);
- import_message(msgnum, msglen);
- ++num_msgs;
- msglist = realloc(msglist,
- (sizeof(long)*num_msgs) );
- msglist[num_msgs - 1] = msgnum;
- }
-
- }
-
- lprintf(9, "(%d messages)\n", num_msgs);
- if ((roomnum!=1)&&(qr.QRflags&QR_INUSE)) {
- putroom(&qr, qr.QRname);
- }
-
- if (num_msgs > 0) {
- if ((roomnum!=1)&&(qr.QRflags&QR_INUSE)) {
- CC->msglist = msglist;
- CC->num_msgs = num_msgs;
- put_msglist(&qr);
- }
- free(msglist);
- }
-
- ++roomnum;
-
- }
- else {
- lprintf(3, "ERROR: invalid room section.\n");
- lprintf(3, "Your data files are now corrupt.\n");
- fclose(imfp);
- return;
+ qr.QRgen = time(NULL);
+ lprintf(CTDL_DEBUG, " -- fixed!\n");
}
+ lputroom(&qr);
}
- }
+ ptr = rplist;
+ rplist = rplist->next;
+ free(ptr);
+ }
+}
+/*
+ * quick fix to bump mailbox generation numbers
+ */
+void bump_mailbox_generation_numbers(void) {
+ lprintf(CTDL_WARNING, "Applying security fix to mailbox rooms\n");
+ ForEachRoom(cmd_bmbx_backend, NULL);
+ cmd_bmbx_backend(NULL, NULL);
+ return;
+}
-void import_a_user(void) {
- char key[256], value[256];
- char vkey[256], vvalue[256];
- struct usersupp us;
- struct quickroom qr;
- struct visit vbuf;
- int visits = 0;
- bzero(&us, sizeof(struct usersupp));
- while(fpgetfield(imfp, key), strcasecmp(key, "enduser")) {
- if ((strcasecmp(key, "mail"))
- &&(strcasecmp(key, "visit")) ) {
- fpgetfield(imfp, value);
- }
- else {
- strcpy(value, "");
- }
+/*
+ * Back end processing function for convert_ctdluid_to_minusone()
+ */
+void cbtm_backend(struct ctdluser *usbuf, void *data) {
+ static struct UserProcList *uplist = NULL;
+ struct UserProcList *ptr;
+ struct ctdluser us;
+
+ /* Lazy programming here. Call this function as a ForEachUser backend
+ * in order to queue up the room names, or call it with a null user
+ * to make it do the processing.
+ */
+ if (usbuf != NULL) {
+ ptr = (struct UserProcList *)
+ malloc(sizeof (struct UserProcList));
+ if (ptr == NULL) return;
+
+ safestrncpy(ptr->user, usbuf->fullname, sizeof ptr->user);
+ ptr->next = uplist;
+ uplist = ptr;
+ return;
+ }
- if (!strcasecmp(key, "usuid"))
- us.USuid = atoi(value);
- if (!strcasecmp(key, "password")) {
- strcpy(us.password, value);
- }
+ while (uplist != NULL) {
- if (!strcasecmp(key, "flags"))
- us.flags = atoi(value);
- if (!strcasecmp(key, "timescalled"))
- us.timescalled = atoi(value);
- if (!strcasecmp(key, "posted"))
- us.posted = atoi(value);
- if (!strcasecmp(key, "fullname")) {
- strcpy(us.fullname, value);
- lprintf(9, "User <%s> ", us.fullname);
- }
- if (!strcasecmp(key, "axlevel"))
- us.axlevel = atoi(value);
- if (!strcasecmp(key, "usscreenwidth"))
- us.USscreenwidth = atoi(value);
- if (!strcasecmp(key, "usscreenheight"))
- us.USscreenheight = atoi(value);
- if (!strcasecmp(key, "usernum")) {
- us.usernum = atol(value);
- lprintf(9, "<#%ld> ", us.usernum);
- }
- if (!strcasecmp(key, "lastcall"))
- us.lastcall = atol(value);
- if (!strcasecmp(key, "usname"))
- strcpy(us.USname, value);
- if (!strcasecmp(key, "usaddr"))
- strcpy(us.USaddr, value);
- if (!strcasecmp(key, "uscity"))
- strcpy(us.UScity, value);
- if (!strcasecmp(key, "usstate"))
- strcpy(us.USstate, value);
- if (!strcasecmp(key, "uszip"))
- strcpy(us.USzip, value);
- if (!strcasecmp(key, "usphone"))
- strcpy(us.USphone, value);
- if (!strcasecmp(key, "usemail"))
- strcpy(us.USemail, value);
- if (!strcasecmp(key, "visit")) {
- ++visits;
- bzero(&vbuf, sizeof(struct visit));
- bzero(&qr, sizeof(struct quickroom));
- while(fpgetfield(imfp, vkey),
- strcasecmp(vkey, "endvisit")) {
- fpgetfield(imfp, vvalue);
- if (!strcasecmp(vkey, "vname"))
- strcpy(qr.QRname, vvalue);
- if (!strcasecmp(vkey, "vgen")) {
- qr.QRgen = atol(vvalue);
- CtdlGetRelationship(&vbuf, &us, &qr);
- }
- if (!strcasecmp(vkey, "lastseen"))
- vbuf.v_lastseen = atol(vvalue);
- if (!strcasecmp(vkey, "flags"))
- vbuf.v_flags = atoi(vvalue);
- }
- CtdlSetRelationship(&vbuf, &us, &qr);
+ if (lgetuser(&us, uplist->user) == 0) {
+ lprintf(CTDL_DEBUG, "Processing <%s>...\n", uplist->user);
+ if (us.uid == CTDLUID) {
+ us.uid = (-1);
}
+ lputuser(&us);
}
-
- putuser(&us, us.fullname);
- lprintf(9, "(%d rooms)\n", visits);
+ ptr = uplist;
+ uplist = uplist->next;
+ free(ptr);
}
+}
+/*
+ * quick fix to change all CTDLUID users to (-1)
+ */
+void convert_ctdluid_to_minusone(void) {
+ lprintf(CTDL_WARNING, "Applying uid changes\n");
+ ForEachUser(cbtm_backend, NULL);
+ cbtm_backend(NULL, NULL);
+ return;
+}
-void imp_usersupp(void) {
- char key[256], value[256];
-
- while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
- if (strcasecmp(key, "user")) {
- fpgetfield(imfp, value);
- }
- else {
- strcpy(value, "");
- }
+/*
+ * Do various things to our configuration file
+ */
+void update_config(void) {
+ get_config();
- if (!strcasecmp(key, "user")) {
- import_a_user();
- }
- }
+ if (CitControl.version < 606) {
+ config.c_rfc822_strict_from = 0;
}
-
-void imp_globals(void) {
- char key[256], value[256];
-
- get_control();
- while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
- fpgetfield(imfp, value);
- lprintf(9, " %s = %s\n", key, value);
-
- if (!strcasecmp(key, "mmhighest"))
- CitControl.MMhighest = atol(value);
- if (!strcasecmp(key, "mmnextuser"))
- CitControl.MMnextuser = atol(value);
-
- }
- put_control();
+ if (CitControl.version < 609) {
+ config.c_purge_hour = 3;
}
-
-
-void imp_config(void) {
- char key[256], value[256];
- FILE *fp;
-
- while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
- fpgetfield(imfp, value);
- lprintf(9, " %s = %s\n", key, value);
-
- if (!strcasecmp(key, "c_nodename"))
- strcpy(config.c_nodename, value);
- if (!strcasecmp(key, "c_fqdn"))
- strcpy(config.c_fqdn, value);
- if (!strcasecmp(key, "c_humannode"))
- strcpy(config.c_humannode, value);
- if (!strcasecmp(key, "c_phonenum"))
- strcpy(config.c_phonenum, value);
- if (!strcasecmp(key, "c_phonenum"))
- strcpy(config.c_phonenum, value);
- if (!strcasecmp(key, "c_bbsuid"))
- config.c_bbsuid = atoi(value);
- if (!strcasecmp(key, "c_creataide"))
- config.c_creataide = atoi(value);
- if (!strcasecmp(key, "c_sleeping"))
- config.c_sleeping = atoi(value);
- if (!strcasecmp(key, "c_initax"))
- config.c_initax = atoi(value);
- if (!strcasecmp(key, "c_regiscall"))
- config.c_regiscall = atoi(value);
- if (!strcasecmp(key, "c_twitdetect"))
- config.c_twitdetect = atoi(value);
- if (!strcasecmp(key, "c_twitroom"))
- strcpy(config.c_twitroom, value);
- if (!strcasecmp(key, "c_defent"))
- config.c_defent = atoi(value);
- if (!strcasecmp(key, "c_moreprompt"))
- strcpy(config.c_moreprompt, value);
- if (!strcasecmp(key, "c_restrict"))
- config.c_restrict = atoi(value);
- if (!strcasecmp(key, "c_bbs_city"))
- strcpy(config.c_bbs_city, value);
- if (!strcasecmp(key, "c_sysadm"))
- strcpy(config.c_sysadm, value);
- if (!strcasecmp(key, "c_bucket_dir"))
- strcpy(config.c_bucket_dir, value);
- if (!strcasecmp(key, "c_setup_level"))
- config.c_setup_level = atoi(value);
- if (!strcasecmp(key, "c_maxsessions"))
- config.c_maxsessions = atoi(value);
- if (!strcasecmp(key, "c_net_password"))
- strcpy(config.c_net_password, value);
- if (!strcasecmp(key, "c_port_number"))
- config.c_port_number = atoi(value);
- }
-
- fp = fopen("citadel.config", "wb");
- fwrite(&config, sizeof(struct config), 1, fp);
- fclose(fp);
+ if (CitControl.version < 615) {
+ config.c_ldap_port = 389;
}
-
-
-
-
-
-void imp_ssv(void) {
- char key[256], value[256];
- int ssv_maxfloors = MAXFLOORS;
-
- while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
- fpgetfield(imfp, value);
- lprintf(9, " %s = %s\n", key, value);
-
- if (!strcasecmp(key, "maxfloors")) {
- ssv_maxfloors = atol(value);
- if (ssv_maxfloors > MAXFLOORS) {
- lprintf(3, "ERROR: maxfloors is %d, need %d\n",
- ssv_maxfloors, MAXFLOORS);
- fclose(imfp);
- return;
- }
- }
- }
- }
-
-
+ if (CitControl.version < 623) {
+ strcpy(config.c_ip_addr, "0.0.0.0");
+ }
+ if (CitControl.version < 650) {
+ config.c_enable_fulltext = 0;
+ }
+ if (CitControl.version < 652) {
+ config.c_auto_cull = 1;
+ }
+ put_config();
+}
-void import_databases(void) {
- char section[256];
- lprintf(9, " ** IMPORTING ** \n");
- while (fpgetfield(imfp, section), strcasecmp(section, "endfile")) {
- lprintf(9, "Section: <%s>\n", section);
- if (!strcasecmp(section, "ssv")) imp_ssv();
- else if (!strcasecmp(section, "config")) imp_config();
- else if (!strcasecmp(section, "globals")) imp_globals();
- else if (!strcasecmp(section, "usersupp")) imp_usersupp();
- else if (!strcasecmp(section, "rooms")) imp_rooms();
- else if (!strcasecmp(section, "floors")) imp_floors();
- else {
- lprintf(3, "ERROR: invalid import section.\n");
- lprintf(3, "Your data files are now corrupt.\n");
- fclose(imfp);
- return;
- }
- }
+void check_server_upgrades(void) {
+ get_control();
+ lprintf(CTDL_INFO, "Server-hosted upgrade level is %d.%02d\n",
+ (CitControl.version / 100),
+ (CitControl.version % 100) );
+
+ if (CitControl.version < REV_LEVEL) {
+ lprintf(CTDL_WARNING,
+ "Server hosted updates need to be processed at "
+ "this time. Please wait...\n");
}
-
-
-
-void do_import(char *argbuf) {
- char import_filename[PATH_MAX];
-
- extract(import_filename, argbuf, 0);
- imfp = fopen(import_filename, "rb");
- if (imfp == NULL) {
- lprintf(9, "Cannot open %s: %s\n",
- import_filename, strerror(errno));
- cprintf("%d Cannot open file\n", ERROR);
+ else {
return;
- }
-
- import_databases();
- lprintf(9, "Defragmenting databases (this may take a while)...\n");
- defrag_databases();
- lprintf(1, "Import is finished. Shutting down Citadel...\n");
- cprintf("%d Import finished. Shutting down Citadel...\n", OK);
- master_cleanup();
}
+ update_config();
-
-void do_export(char *argbuf) {
- char export_filename[PATH_MAX];
-
- extract(export_filename, argbuf, 0);
- exfp = fopen(export_filename, "wb");
- if (exfp == NULL) {
- lprintf(9, "Cannot open %s: %s\n",
- export_filename, strerror(errno));
- cprintf("%d Cannot open file\n", ERROR);
- return;
- }
-
- /* structure size variables */
- lprintf(9, "Structure size variables\n");
- fprintf(exfp, "ssv%c", 0);
- fprintf(exfp, "maxfloors%c%d%c", 0, MAXFLOORS, 0);
- fprintf(exfp, "endsection%c", 0);
-
- /* Write out the server config */
- lprintf(9,"Server config\n");
- fprintf(exfp, "config%c", 0);
- fprintf(exfp, "c_nodename%c%s%c", 0, config.c_nodename, 0);
- fprintf(exfp, "c_fqdn%c%s%c", 0, config.c_fqdn, 0);
- fprintf(exfp, "c_humannode%c%s%c", 0, config.c_humannode, 0);
- fprintf(exfp, "c_phonenum%c%s%c", 0, config.c_phonenum, 0);
- fprintf(exfp, "c_bbsuid%c%d%c", 0, config.c_bbsuid, 0);
- fprintf(exfp, "c_creataide%c%d%c", 0, config.c_creataide, 0);
- fprintf(exfp, "c_sleeping%c%d%c", 0, config.c_sleeping, 0);
- fprintf(exfp, "c_initax%c%d%c", 0, config.c_initax, 0);
- fprintf(exfp, "c_regiscall%c%d%c", 0, config.c_regiscall, 0);
- fprintf(exfp, "c_twitdetect%c%d%c", 0, config.c_twitdetect, 0);
- fprintf(exfp, "c_twitroom%c%s%c", 0, config.c_twitroom, 0);
- fprintf(exfp, "c_defent%c%d%c", 0, config.c_defent, 0);
- fprintf(exfp, "c_moreprompt%c%s%c", 0, config.c_moreprompt, 0);
- fprintf(exfp, "c_restrict%c%d%c", 0, config.c_restrict, 0);
- fprintf(exfp, "c_bbs_city%c%s%c", 0, config.c_bbs_city, 0);
- fprintf(exfp, "c_sysadm%c%s%c", 0, config.c_sysadm, 0);
- fprintf(exfp, "c_bucket_dir%c%s%c", 0, config.c_bucket_dir, 0);
- fprintf(exfp, "c_setup_level%c%d%c", 0, config.c_setup_level, 0);
- fprintf(exfp, "c_maxsessions%c%d%c", 0, config.c_maxsessions, 0);
- fprintf(exfp, "c_net_password%c%s%c", 0, config.c_net_password, 0);
- fprintf(exfp, "c_port_number%c%d%c", 0, config.c_port_number, 0);
- fprintf(exfp, "endsection%c", 0);
-
- /* Now some global stuff */
- lprintf(9, "Globals\n");
- get_control();
- fprintf(exfp, "globals%c", 0);
- fprintf(exfp, "mmhighest%c%ld%c", 0, CitControl.MMhighest, 0);
- fprintf(exfp, "mmnextuser%c%ld%c", 0, CitControl.MMnextuser, 0);
- fprintf(exfp, "mmflags%c%d%c", 0, CitControl.MMflags, 0);
- fprintf(exfp, "endsection%c", 0);
-
- /* export_rooms(exfp); */
- /* export_floors(exfp); */
- /* export_usersupp(exfp); */
- fprintf(exfp, "endfile%c", 0);
-
- fclose(exfp);
- lprintf(1, "Export is finished.\n");
- cprintf("%d Export is finished.\n", OK);
+ if ((CitControl.version > 000) && (CitControl.version < 555)) {
+ lprintf(CTDL_EMERG,
+ "Your data files are from a version of Citadel\n"
+ "that is too old to be upgraded. Sorry.\n");
+ exit(EXIT_FAILURE);
+ }
+ if ((CitControl.version > 000) && (CitControl.version < 591)) {
+ bump_mailbox_generation_numbers();
+ }
+ if ((CitControl.version > 000) && (CitControl.version < 608)) {
+ convert_ctdluid_to_minusone();
+ }
+ if ((CitControl.version > 000) && (CitControl.version < 659)) {
+ rebuild_euid_index();
}
+ CitControl.version = REV_LEVEL;
+ put_control();
+}
-struct DLModule_Info *Dynamic_Module_Init(void) {
- CtdlRegisterProtoHook(do_import,
- "IMPO",
- "Import an unpacked system");
- CtdlRegisterProtoHook(do_export,
- "EXPO",
- "Export the system");
- return &info;
- }
+CTDL_MODULE_INIT(upgrade)
+{
+ check_server_upgrades();
+
+ /* return our Subversion id for the Log */
+ return "$Id$";
+}