* Renamed "struct user" to "struct ctdluser"
[citadel.git] / citadel / serv_upgrade.c
1 /*
2  * $Id$
3  *
4  * Transparently handle the upgrading of server data formats.
5  *
6  */
7
8 #include "sysdep.h"
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <signal.h>
14 #include <pwd.h>
15 #include <errno.h>
16 #include <sys/types.h>
17
18 #if TIME_WITH_SYS_TIME
19 # include <sys/time.h>
20 # include <time.h>
21 #else
22 # if HAVE_SYS_TIME_H
23 #  include <sys/time.h>
24 # else
25 #  include <time.h>
26 # endif
27 #endif
28
29 #include <sys/wait.h>
30 #include <string.h>
31 #include <limits.h>
32 #include "citadel.h"
33 #include "server.h"
34 #include "sysdep_decls.h"
35 #include "citserver.h"
36 #include "support.h"
37 #include "config.h"
38 #include "control.h"
39 #include "serv_extensions.h"
40 #include "database.h"
41 #include "room_ops.h"
42 #include "user_ops.h"
43 #include "msgbase.h"
44 #include "tools.h"
45 #include "serv_upgrade.h"
46
47 void do_pre555_user_upgrade(void) {
48         struct pre555user usbuf;
49         struct ctdluser newus;
50         struct cdbdata *cdbus;
51         char tempfilename[PATH_MAX];
52         FILE *fp, *tp;
53         static char vcard[1024];
54
55         lprintf(5, "Upgrading user file\n");
56         fp = tmpfile();
57         if (fp == NULL) {
58                 lprintf(1, "%s\n", strerror(errno));
59                 exit(errno);
60         }
61         strcpy(tempfilename, tmpnam(NULL));
62
63         /* First, back out all old version records to a flat file */
64         cdb_rewind(CDB_USERS);
65         while(cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
66                 memset(&usbuf, 0, sizeof(struct pre555user));
67                 memcpy(&usbuf, cdbus->ptr,
68                         ( (cdbus->len > sizeof(struct pre555user)) ?
69                         sizeof(struct pre555user) : cdbus->len) );
70                 cdb_free(cdbus);
71                 fwrite(&usbuf, sizeof(struct pre555user), 1, fp);
72         }
73
74         /* ...and overwrite the records with new format records */
75         rewind(fp);
76         while (fread(&usbuf, sizeof(struct pre555user), 1, fp) > 0) {
77             if (strlen(usbuf.fullname) > 0) {
78                 lprintf(9, "Upgrading <%s>\n", usbuf.fullname);
79                 memset(&newus, 0, sizeof(struct ctdluser));
80
81                 newus.uid = usbuf.USuid;
82                 strcpy(newus.password, usbuf.password);
83                 newus.flags = usbuf.flags;
84                 newus.timescalled = (long) usbuf.timescalled;
85                 newus.posted = (long) usbuf.posted;
86                 newus.axlevel = (cit_uint8_t) usbuf.axlevel;
87                 newus.usernum = (long) usbuf.usernum;
88                 newus.lastcall = (long) usbuf.lastcall;
89                 newus.USuserpurge = (int) usbuf.USuserpurge;
90                 strcpy(newus.fullname, usbuf.fullname);
91                 newus.USscreenwidth = (cit_uint8_t) usbuf.USscreenwidth;
92                 newus.USscreenheight = (cit_uint8_t) usbuf.USscreenheight;
93
94                 putuser(&newus);
95
96                 /* write the vcard */
97                 snprintf(vcard, sizeof vcard,
98                         "Content-type: text/x-vcard\n\n"
99                         "begin:vcard\n"
100                         "n:%s\n"
101                         "tel;home:%s\n"
102                         "email;internet:%s\n"
103                         "adr:;;%s;%s;%s;%s;USA\n"
104                         "end:vcard\n",
105                         usbuf.USname,
106                         usbuf.USphone,
107                         usbuf.USemail,
108                         usbuf.USaddr,
109                         usbuf.UScity,
110                         usbuf.USstate,
111                         usbuf.USzip);
112
113                 tp = fopen(tempfilename, "w");
114                 fwrite(vcard, strlen(vcard)+1, 1, tp);
115                 fclose(tp);
116
117                 CtdlWriteObject(USERCONFIGROOM, "text/x-vcard",
118                         tempfilename, &newus, 0, 1, CM_SKIP_HOOKS);
119                 unlink(tempfilename);
120             }
121         }
122
123         fclose(fp);     /* this file deletes automatically */
124 }
125
126
127
128
129
130
131
132
133 /* 
134  * Back end processing function for cmd_bmbx
135  */
136 void cmd_bmbx_backend(struct ctdlroom *qrbuf, void *data) {
137         static struct RoomProcList *rplist = NULL;
138         struct RoomProcList *ptr;
139         struct ctdlroom qr;
140
141         /* Lazy programming here.  Call this function as a ForEachRoom backend
142          * in order to queue up the room names, or call it with a null room
143          * to make it do the processing.
144          */
145         if (qrbuf != NULL) {
146                 ptr = (struct RoomProcList *)
147                         mallok(sizeof (struct RoomProcList));
148                 if (ptr == NULL) return;
149
150                 safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name);
151                 ptr->next = rplist;
152                 rplist = ptr;
153                 return;
154         }
155
156         while (rplist != NULL) {
157
158                 if (lgetroom(&qr, rplist->name) == 0) {
159                         lprintf(9, "Processing <%s>...\n", rplist->name);
160                         if ( (qr.QRflags & QR_MAILBOX) == 0) {
161                                 lprintf(9, "  -- not a mailbox\n");
162                         }
163                         else {
164
165                                 qr.QRgen = time(NULL);
166                                 lprintf(9, "  -- fixed!\n");
167                         }
168                         lputroom(&qr);
169                 }
170
171                 ptr = rplist;
172                 rplist = rplist->next;
173                 phree(ptr);
174         }
175 }
176
177 /*
178  * quick fix to bump mailbox generation numbers
179  */
180 void bump_mailbox_generation_numbers(void) {
181         lprintf(5, "Applying security fix to mailbox rooms\n");
182         ForEachRoom(cmd_bmbx_backend, NULL);
183         cmd_bmbx_backend(NULL, NULL);
184         return;
185 }
186
187
188 /* 
189  * Back end processing function for convert_bbsuid_to_minusone()
190  */
191 void cbtm_backend(struct ctdluser *usbuf, void *data) {
192         static struct UserProcList *uplist = NULL;
193         struct UserProcList *ptr;
194         struct ctdluser us;
195
196         /* Lazy programming here.  Call this function as a ForEachUser backend
197          * in order to queue up the room names, or call it with a null user
198          * to make it do the processing.
199          */
200         if (usbuf != NULL) {
201                 ptr = (struct UserProcList *)
202                         mallok(sizeof (struct UserProcList));
203                 if (ptr == NULL) return;
204
205                 safestrncpy(ptr->user, usbuf->fullname, sizeof ptr->user);
206                 ptr->next = uplist;
207                 uplist = ptr;
208                 return;
209         }
210
211         while (uplist != NULL) {
212
213                 if (lgetuser(&us, uplist->user) == 0) {
214                         lprintf(9, "Processing <%s>...\n", uplist->user);
215                         if (us.uid == BBSUID) {
216                                 us.uid = (-1);
217                         }
218                         lputuser(&us);
219                 }
220
221                 ptr = uplist;
222                 uplist = uplist->next;
223                 phree(ptr);
224         }
225 }
226
227 /*
228  * quick fix to change all BBSUID users to (-1)
229  */
230 void convert_bbsuid_to_minusone(void) {
231         lprintf(5, "Applying uid changes\n");
232         ForEachUser(cbtm_backend, NULL);
233         cbtm_backend(NULL, NULL);
234         return;
235 }
236
237
238 /*
239  * This field was originally used for something else, so when we upgrade
240  * we have to initialize it to 0 in case there was trash in that space.
241  */
242 void initialize_c_rfc822_strict_from(void) {
243         get_config();
244         config.c_rfc822_strict_from = 0;
245         put_config();
246 }
247
248
249
250
251 void check_server_upgrades(void) {
252
253         get_control();
254         lprintf(5, "Server-hosted upgrade level is %d.%02d\n",
255                 (CitControl.version / 100),
256                 (CitControl.version % 100) );
257
258         if (CitControl.version < REV_LEVEL) {
259                 lprintf(5, "Server hosted updates need to be processed at "
260                                 "this time.  Please wait...\n");
261         }
262         else {
263                 return;
264         }
265
266         if (CitControl.version < 555) do_pre555_user_upgrade();
267         if (CitControl.version < 591) bump_mailbox_generation_numbers();
268         if (CitControl.version < 606) initialize_c_rfc822_strict_from();
269         if (CitControl.version < 608) convert_bbsuid_to_minusone();
270
271         CitControl.version = REV_LEVEL;
272         put_control();
273 }
274
275
276
277
278
279
280
281
282
283
284
285 char *serv_upgrade_init(void)
286 {
287         check_server_upgrades();
288         return "$Id$";
289 }