]> code.citadel.org Git - citadel.git/blob - citadel/modules/vandelay/serv_vandelay.c
Importing REALLY BIG messages can also cause the watchdog in sendcommand
[citadel.git] / citadel / modules / vandelay / serv_vandelay.c
1 /*
2  * $Id$
3  *
4  * This is the "Art Vandelay" module.  It is an importer/exporter.
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 <ctype.h>
32 #include <limits.h>
33 #include <libcitadel.h>
34 #include "citadel.h"
35 #include "server.h"
36 #include "citserver.h"
37 #include "support.h"
38 #include "config.h"
39 #include "database.h"
40 #include "msgbase.h"
41 #include "user_ops.h"
42 #include "room_ops.h"
43 #include "control.h"
44 #include "euidindex.h"
45
46
47 #include "ctdl_module.h"
48
49
50
51
52 #define END_OF_MESSAGE  "---eom---dbd---"
53
54 char artv_tempfilename1[PATH_MAX];
55 char artv_tempfilename2[PATH_MAX];
56 FILE *artv_global_message_list;
57
58 void artv_export_users_backend(struct ctdluser *buf, void *data) {
59         cprintf("user\n");
60 /*
61 #include "artv_serialize.h"
62 #include "dtds/user-defs.h"
63 #include "undef_data.h"
64 */
65         cprintf("%d\n", buf->version);
66         cprintf("%ld\n", (long)buf->uid);
67         cprintf("%s\n", buf->password);
68         cprintf("%u\n", buf->flags);
69         cprintf("%ld\n", buf->timescalled);
70         cprintf("%ld\n", buf->posted);
71         cprintf("%d\n", buf->axlevel);
72         cprintf("%ld\n", buf->usernum);
73         cprintf("%ld\n", (long)buf->lastcall);
74         cprintf("%d\n", buf->USuserpurge);
75         cprintf("%s\n", buf->fullname);
76         cprintf("%d\n", buf->USscreenwidth);
77         cprintf("%d\n", buf->USscreenheight);
78 }
79
80 void artv_dump_users_backend(struct ctdluser *buf, void *data) {
81         cprintf("user\n");
82
83 #include "artv_dump.h"
84 #include "dtds/user-defs.h"
85 #include "undef_data.h"
86         cprintf("\n");
87 }
88
89
90 void artv_export_users(void) {
91         ForEachUser(artv_export_users_backend, NULL);
92 }
93
94 void artv_dump_users(void) {
95         ForEachUser(artv_dump_users_backend, NULL);
96 }
97
98
99 void artv_export_room_msg(long msgnum, void *userdata) {
100         cprintf("%ld\n", msgnum);
101         fprintf(artv_global_message_list, "%ld\n", msgnum);
102 }
103
104 void artv_dump_room_msg(long msgnum, void *userdata) {
105         cprintf(" msgnum: %ld\n", msgnum);
106         fprintf(artv_global_message_list, "%ld\n", msgnum);
107         cprintf("\n");
108 }//// TODO
109
110
111 void artv_export_rooms_backend(struct ctdlroom *buf, void *data) {
112         cprintf("room\n");
113 /*
114 #include "artv_serialize.h"
115 #include "dtds/room-defs.h"
116 #include "undef_data.h"
117 */
118         cprintf("%s\n", buf->QRname);
119         cprintf("%s\n", buf->QRpasswd);
120         cprintf("%ld\n", buf->QRroomaide);
121         cprintf("%ld\n", buf->QRhighest);
122         cprintf("%ld\n", (long)buf->QRgen);
123         cprintf("%u\n", buf->QRflags);
124         cprintf("%s\n", buf->QRdirname);
125         cprintf("%ld\n", buf->QRinfo);
126         cprintf("%d\n", buf->QRfloor);
127         cprintf("%ld\n", (long)buf->QRmtime);
128         cprintf("%d\n", buf->QRep.expire_mode);
129         cprintf("%d\n", buf->QRep.expire_value);
130         cprintf("%ld\n", buf->QRnumber);
131         cprintf("%d\n", buf->QRorder);
132         cprintf("%u\n", buf->QRflags2);
133         cprintf("%d\n", buf->QRdefaultview);
134
135         getroom(&CC->room, buf->QRname);
136         /* format of message list export is all message numbers output
137          * one per line terminated by a 0.
138          */
139 //*/
140         getroom(&CC->room, buf->QRname);
141         /* format of message list export is all message numbers output
142          * one per line terminated by a 0.
143          */
144         CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL,
145                 artv_export_room_msg, NULL);
146         cprintf("0\n");
147
148 }
149
150 void artv_dump_rooms_backend(struct ctdlroom *buf, void *data) {
151         cprintf("room\n");
152
153 #include "artv_dump.h"
154 #include "dtds/room-defs.h"
155 #include "undef_data.h"
156
157         getroom(&CC->room, buf->QRname);
158         /* format of message list export is all message numbers output
159          * one per line terminated by a 0.
160          */
161 //*/
162         getroom(&CC->room, buf->QRname);
163         /* format of message list export is all message numbers output
164          * one per line terminated by a 0.
165          */
166         CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL,
167                 artv_dump_room_msg, NULL);
168         cprintf("\n\n");
169
170 }
171
172
173
174 void artv_export_rooms(void) {
175         char cmd[SIZ];
176         artv_global_message_list = fopen(artv_tempfilename1, "w");
177         if (artv_global_message_list != NULL) {
178                 ForEachRoom(artv_export_rooms_backend, NULL);
179                 fclose(artv_global_message_list);
180         }
181
182         /*
183          * Process the 'global' message list.  (Sort it and remove dups.
184          * Dups are ok because a message may be in more than one room, but
185          * this will be handled by exporting the reference count, not by
186          * exporting the message multiple times.)
187          */
188         snprintf(cmd, sizeof cmd, "sort <%s >%s", artv_tempfilename1, artv_tempfilename2);
189         system(cmd);
190         snprintf(cmd, sizeof cmd, "uniq <%s >%s", artv_tempfilename2, artv_tempfilename1);
191         system(cmd);
192 }
193
194 void artv_dump_rooms(void) {
195         char cmd[SIZ];
196         artv_global_message_list = fopen(artv_tempfilename1, "w");
197         if (artv_global_message_list != NULL) {
198                 ForEachRoom(artv_dump_rooms_backend, NULL);
199                 fclose(artv_global_message_list);
200         }
201
202         /*
203          * Process the 'global' message list.  (Sort it and remove dups.
204          * Dups are ok because a message may be in more than one room, but
205          * this will be handled by exporting the reference count, not by
206          * exporting the message multiple times.)
207          */
208         snprintf(cmd, sizeof cmd, "sort <%s >%s", artv_tempfilename1, artv_tempfilename2);
209         system(cmd);
210         snprintf(cmd, sizeof cmd, "uniq <%s >%s", artv_tempfilename2, artv_tempfilename1);
211         system(cmd);
212 }
213
214
215 void artv_export_floors(void) {
216         struct floor qfbuf, *buf;
217         int i;
218
219         for (i=0; i < MAXFLOORS; ++i) {
220                 cprintf("floor\n");
221                 cprintf("%d\n", i);
222                 getfloor(&qfbuf, i);
223                 buf = &qfbuf;
224 /*
225 #include "artv_serialize.h"
226 #include "dtds/floor-defs.h"
227 #include "undef_data.h"
228 /*/
229                 cprintf("%u\n", buf->f_flags);
230                 cprintf("%s\n", buf->f_name);
231                 cprintf("%d\n", buf->f_ref_count);
232                 cprintf("%d\n", buf->f_ep.expire_mode);
233                 cprintf("%d\n", buf->f_ep.expire_value);
234 //*/
235         }
236 }
237
238 void artv_dump_floors(void) {
239         struct floor qfbuf, *buf;
240         int i;
241
242         for (i=0; i < MAXFLOORS; ++i) {
243                 cprintf("floor\n");
244                 cprintf("%d\n", i);
245                 getfloor(&qfbuf, i);
246                 buf = &qfbuf;
247
248 #include "artv_serialize.h"
249 #include "dtds/floor-defs.h"
250 #include "undef_data.h"
251         }
252 }
253
254
255
256
257
258 /* 
259  *  Traverse the visits file...
260  */
261 void artv_export_visits(void) {
262         struct visit vbuf;
263         struct cdbdata *cdbv;
264
265         cdb_rewind(CDB_VISIT);
266
267         while (cdbv = cdb_next_item(CDB_VISIT), cdbv != NULL) {
268                 memset(&vbuf, 0, sizeof(struct visit));
269                 memcpy(&vbuf, cdbv->ptr,
270                        ((cdbv->len > sizeof(struct visit)) ?
271                         sizeof(struct visit) : cdbv->len));
272                 cdb_free(cdbv);
273
274                 cprintf("visit\n");
275                 cprintf("%ld\n", vbuf.v_roomnum);
276                 cprintf("%ld\n", vbuf.v_roomgen);
277                 cprintf("%ld\n", vbuf.v_usernum);
278
279                 if (!IsEmptyStr(vbuf.v_seen)) {
280                         cprintf("%s\n", vbuf.v_seen);
281                 }
282                 else {
283                         cprintf("%ld\n", vbuf.v_lastseen);
284                 }
285
286                 cprintf("%s\n", vbuf.v_answered);
287                 cprintf("%u\n", vbuf.v_flags);
288                 cprintf("%d\n", vbuf.v_view);
289         }
290 }
291
292 /* 
293  *  Traverse the visits file...
294  */
295 void artv_dump_visits(void) {
296         struct visit vbuf;
297         struct cdbdata *cdbv;
298
299         cdb_rewind(CDB_VISIT);
300
301         while (cdbv = cdb_next_item(CDB_VISIT), cdbv != NULL) {
302                 memset(&vbuf, 0, sizeof(struct visit));
303                 memcpy(&vbuf, cdbv->ptr,
304                        ((cdbv->len > sizeof(struct visit)) ?
305                         sizeof(struct visit) : cdbv->len));
306                 cdb_free(cdbv);
307
308                 cprintf("---visit---\n");
309                 cprintf(" Room-Num: %ld\n", vbuf.v_roomnum);
310                 cprintf(" Room-Gen%ld\n", vbuf.v_roomgen);
311                 cprintf(" User-Num%ld\n", vbuf.v_usernum);
312
313                 if (!IsEmptyStr(vbuf.v_seen)) {
314                         cprintf(" Seen: %s\n", vbuf.v_seen);
315                 }
316                 else {
317                         cprintf(" LastSeen: %ld\n", vbuf.v_lastseen);
318                 }
319
320                 cprintf(" Answered: %s\n", vbuf.v_answered);
321                 cprintf(" Flags: %u\n", vbuf.v_flags);
322                 cprintf(" View: %d\n", vbuf.v_view);
323         }
324 }
325
326
327 void artv_export_message(long msgnum) {
328         struct MetaData smi;
329         struct CtdlMessage *msg;
330         struct ser_ret smr;
331         FILE *fp;
332         char buf[SIZ];
333         char tempfile[PATH_MAX];
334
335         msg = CtdlFetchMessage(msgnum, 1);
336         if (msg == NULL) return;        /* fail silently */
337
338         cprintf("message\n");
339         GetMetaData(&smi, msgnum);
340         cprintf("%ld\n", msgnum);
341         cprintf("%d\n", smi.meta_refcount);
342         cprintf("%s\n", smi.meta_content_type);
343
344         serialize_message(&smr, msg);
345         CtdlFreeMessage(msg);
346
347         /* write it in base64 */
348         CtdlMakeTempFileName(tempfile, sizeof tempfile);
349         snprintf(buf, sizeof buf, "%s -e >%s", file_base64, tempfile);
350         fp = popen(buf, "w");
351         fwrite(smr.ser, smr.len, 1, fp);
352         pclose(fp);
353
354         free(smr.ser);
355
356         fp = fopen(tempfile, "r");
357         unlink(tempfile);
358         if (fp != NULL) {
359                 while (fgets(buf, sizeof(buf), fp) != NULL) {
360                         buf[strlen(buf)-1] = 0;
361                         cprintf("%s\n", buf);
362                 }
363                 fclose(fp);
364         }
365         cprintf("%s\n", END_OF_MESSAGE);
366 }
367
368 void artv_dump_message(long msgnum) {
369         struct MetaData smi;
370         struct CtdlMessage *msg;
371
372         msg = CtdlFetchMessage(msgnum, 1);
373         if (msg == NULL) return;        /* fail silently */
374
375         cprintf("message\n");
376         GetMetaData(&smi, msgnum);
377         cprintf(" MessageNum: %ld\n", msgnum);
378         cprintf(" MetaRefcount: %d\n", smi.meta_refcount);
379         cprintf(" MetaContentType: %s\n", smi.meta_content_type);
380
381         dump_message(msg, 80);
382         CtdlFreeMessage(msg);
383
384         cprintf("%s\n", END_OF_MESSAGE);
385 }
386
387
388
389 void artv_export_messages(void) {
390         char buf[SIZ];
391         long msgnum;
392         int count = 0;
393         t_context *Ctx;
394
395         Ctx = CC;
396         artv_global_message_list = fopen(artv_tempfilename1, "r");
397         if (artv_global_message_list != NULL) {
398                 CtdlLogPrintf(CTDL_INFO, "Opened %s\n", artv_tempfilename1);
399                 while ((Ctx->kill_me != 1) && 
400                        (fgets(buf, sizeof(buf), artv_global_message_list) != NULL)) {
401                         msgnum = atol(buf);
402                         if (msgnum > 0L) {
403                                 artv_export_message(msgnum);
404                                 ++count;
405                         }
406                 }
407                 fclose(artv_global_message_list);
408         }
409         if (Ctx->kill_me != 1)
410                 CtdlLogPrintf(CTDL_INFO, "Exported %d messages.\n", count);
411         else
412                 CtdlLogPrintf(CTDL_ERR, "Export aborted due to client disconnect! \n");
413 }
414
415 void artv_dump_messages(void) {
416         char buf[SIZ];
417         long msgnum;
418         int count = 0;
419         t_context *Ctx;
420
421         Ctx = CC;
422         artv_global_message_list = fopen(artv_tempfilename1, "r");
423         if (artv_global_message_list != NULL) {
424                 CtdlLogPrintf(CTDL_INFO, "Opened %s\n", artv_tempfilename1);
425                 while ((Ctx->kill_me != 1) && 
426                        (fgets(buf, sizeof(buf), artv_global_message_list) != NULL)) {
427                         msgnum = atol(buf);
428                         if (msgnum > 0L) {
429                                 artv_dump_message(msgnum);
430                                 ++count;
431                         }
432                 }
433                 fclose(artv_global_message_list);
434         }
435         if (Ctx->kill_me != 1)
436                 CtdlLogPrintf(CTDL_INFO, "Exported %d messages.\n", count);
437         else
438                 CtdlLogPrintf(CTDL_ERR, "Export aborted due to client disconnect! \n");
439 }
440
441
442
443
444 void artv_do_export(void) {
445         struct config *buf;
446         buf = &config;
447         t_context *Ctx;
448
449         Ctx = CC;
450         cprintf("%d Exporting all Citadel databases.\n", LISTING_FOLLOWS);
451
452         cprintf("version\n%d\n", REV_LEVEL);
453
454         /* export the config file (this is done using x-macros) */
455         cprintf("config\n");
456
457 #include "artv_serialize.h"
458 #include "dtds/config-defs.h"
459 #include "undef_data.h"
460         cprintf("\n");
461         
462         /* Export the control file */
463         get_control();
464         cprintf("control\n");
465         cprintf("%ld\n", CitControl.MMhighest);
466         cprintf("%u\n", CitControl.MMflags);
467         cprintf("%ld\n", CitControl.MMnextuser);
468         cprintf("%ld\n", CitControl.MMnextroom);
469         cprintf("%d\n", CitControl.version);
470         if (Ctx->kill_me != 1)
471                 artv_export_users();
472         if (Ctx->kill_me != 1)
473                 artv_export_rooms();
474         if (Ctx->kill_me != 1)
475                 artv_export_floors();
476         if (Ctx->kill_me != 1)
477                 artv_export_visits();
478         if (Ctx->kill_me != 1)
479                 artv_export_messages();
480
481         cprintf("000\n");
482 }
483
484 void artv_do_dump(void) {
485         struct config *buf;
486         buf = &config;
487         t_context *Ctx;
488
489         Ctx = CC;
490         cprintf("%d dumping Citadel structures.\n", LISTING_FOLLOWS);
491
492         cprintf("version\n%d\n", REV_LEVEL);
493
494         /* export the config file (this is done using x-macros) */
495         cprintf("config\n");
496
497 #include "artv_dump.h"
498 #include "dtds/config-defs.h"
499 #include "undef_data.h"
500
501         /* Export the control file */
502         get_control();
503         cprintf("control\n");
504         cprintf(" MMhighest: %ld\n", CitControl.MMhighest);
505         cprintf(" MMflags: %u\n", CitControl.MMflags);
506         cprintf(" MMnextuser: %ld\n", CitControl.MMnextuser);
507         cprintf(" MMnextroom: %ld\n", CitControl.MMnextroom);
508         cprintf(" version: %d\n\n", CitControl.version);
509         if (Ctx->kill_me != 1)
510                 artv_dump_users();
511         if (Ctx->kill_me != 1)
512                 artv_dump_rooms();
513         if (Ctx->kill_me != 1)
514                 artv_dump_floors();
515         if (Ctx->kill_me != 1)
516                 artv_dump_visits();
517         if (Ctx->kill_me != 1)
518                 artv_dump_messages();
519
520         cprintf("000\n");
521 }
522
523
524
525 void artv_import_config(void) {
526         char cbuf[SIZ];
527         struct config *buf;
528         buf = &config;
529
530         CtdlLogPrintf(CTDL_DEBUG, "Importing config file\n");
531
532 #include "artv_deserialize.h"
533 #include "dtds/config-defs.h"
534 #include "undef_data.h"
535
536         config.c_enable_fulltext = 0;   /* always disable */
537         put_config();
538         CtdlLogPrintf(CTDL_INFO, "Imported config file\n");
539 }
540
541
542 void artv_import_control(void) {
543         char buf[SIZ];
544
545         CtdlLogPrintf(CTDL_DEBUG, "Importing control file\n");
546         client_getln(buf, sizeof buf);  CitControl.MMhighest = atol(buf);
547         client_getln(buf, sizeof buf);  CitControl.MMflags = atoi(buf);
548         client_getln(buf, sizeof buf);  CitControl.MMnextuser = atol(buf);
549         client_getln(buf, sizeof buf);  CitControl.MMnextroom = atol(buf);
550         client_getln(buf, sizeof buf);  CitControl.version = atoi(buf);
551         CitControl.MMfulltext = (-1L);  /* always flush */
552         put_control();
553         CtdlLogPrintf(CTDL_INFO, "Imported control file\n");
554 }
555
556
557 void artv_import_user(void) {
558         char cbuf[SIZ];
559         struct ctdluser usbuf, *buf;
560         buf = &usbuf;
561 /*
562 #include "artv_deserialize.h"
563 #include "dtds/user-defs.h"
564 #include "undef_data.h"
565
566 /*/
567         client_getln(cbuf, sizeof cbuf);        buf->version = atoi(cbuf);
568         client_getln(cbuf, sizeof cbuf);        buf->uid = atoi(cbuf);
569         client_getln(buf->password, sizeof buf->password);
570         client_getln(cbuf, sizeof cbuf);        buf->flags = atoi(cbuf);
571         client_getln(cbuf, sizeof cbuf);        buf->timescalled = atol(cbuf);
572         client_getln(cbuf, sizeof cbuf);        buf->posted = atol(cbuf);
573         client_getln(cbuf, sizeof cbuf);        buf->axlevel = atoi(cbuf);
574         client_getln(cbuf, sizeof cbuf);        buf->usernum = atol(cbuf);
575         client_getln(cbuf, sizeof cbuf);        buf->lastcall = atol(cbuf);
576         client_getln(cbuf, sizeof cbuf);        buf->USuserpurge = atoi(cbuf);
577         client_getln(buf->fullname, sizeof buf->fullname);
578         client_getln(cbuf, sizeof cbuf);        buf->USscreenwidth = atoi(cbuf);
579         client_getln(cbuf, sizeof cbuf);        buf->USscreenheight = atoi(cbuf);
580 //*/
581         putuser(buf);
582 }
583
584
585 void artv_import_room(long *iterations) {
586         char cbuf[SIZ];
587         struct ctdlroom qrbuf, *buf;
588         long msgnum;
589         int msgcount = 0;
590
591         buf = &qrbuf;
592 /*
593 #include "artv_deserialize.h"
594 #include "dtds/room-defs.h"
595 #include "undef_data.h"
596
597 /*/
598         client_getln(buf->QRname, sizeof buf->QRname);
599         client_getln(buf->QRpasswd, sizeof buf->QRpasswd);
600         client_getln(cbuf, sizeof cbuf);        buf->QRroomaide = atol(cbuf);
601         client_getln(cbuf, sizeof cbuf);        buf->QRhighest = atol(cbuf);
602         client_getln(cbuf, sizeof cbuf);        buf->QRgen = atol(cbuf);
603         client_getln(cbuf, sizeof cbuf);        buf->QRflags = atoi(cbuf);
604         client_getln(buf->QRdirname, sizeof buf->QRdirname);
605         client_getln(cbuf, sizeof cbuf);        buf->QRinfo = atol(cbuf);
606         client_getln(cbuf, sizeof cbuf);        buf->QRfloor = atoi(cbuf);
607         client_getln(cbuf, sizeof cbuf);        buf->QRmtime = atol(cbuf);
608         client_getln(cbuf, sizeof cbuf);        buf->QRep.expire_mode = atoi(cbuf);
609         client_getln(cbuf, sizeof cbuf);        buf->QRep.expire_value = atoi(cbuf);
610         client_getln(cbuf, sizeof cbuf);        buf->QRnumber = atol(cbuf);
611         client_getln(cbuf, sizeof cbuf);        buf->QRorder = atoi(cbuf);
612         client_getln(cbuf, sizeof cbuf);        buf->QRflags2 = atoi(cbuf);
613         client_getln(cbuf, sizeof cbuf);        buf->QRdefaultview = atoi(cbuf);
614 //*/
615         putroom(buf);
616         CtdlLogPrintf(CTDL_INFO, "Imported room <%s>\n", qrbuf.QRname);
617         /* format of message list export is all message numbers output
618          * one per line terminated by a 0.
619          */
620         while (client_getln(cbuf, sizeof cbuf), msgnum = atol(cbuf), msgnum > 0) {
621                 CtdlLogPrintf(CTDL_DEBUG, "import room message link %d\n", msgnum);
622                 CtdlSaveMsgPointerInRoom(qrbuf.QRname, msgnum, 0, NULL);
623                 cprintf(".");
624                 ++(*iterations);
625                 if ((*iterations) % 64 == 0)
626                         cprintf("\n");
627                 ++msgcount;
628                 if (CtdlThreadCheckStop())
629                         break;
630         }
631         CtdlLogPrintf(CTDL_INFO, "(%d messages)\n", msgcount);
632 }
633
634
635 void artv_import_floor(void) {
636         struct floor flbuf, *buf;
637         int i;
638         char cbuf[SIZ];
639
640         buf = & flbuf;
641         memset(buf, 0, sizeof(buf));
642         client_getln(cbuf, sizeof cbuf);        i = atoi(cbuf);
643 /*
644 #include "artv_deserialize.h"
645 #include "dtds/floor-defs.h"
646 #include "undef_data.h"
647 /*/
648         client_getln(cbuf, sizeof cbuf);        buf->f_flags = atoi(cbuf);
649         client_getln(buf->f_name, sizeof buf->f_name);
650         client_getln(cbuf, sizeof cbuf);        buf->f_ref_count = atoi(cbuf);
651         client_getln(cbuf, sizeof cbuf);        buf->f_ep.expire_mode = atoi(cbuf);
652         client_getln(cbuf, sizeof cbuf);        buf->f_ep.expire_value = atoi(cbuf);
653 //*/
654         putfloor(buf, i);
655         CtdlLogPrintf(CTDL_INFO, "Imported floor #%d (%s)\n", i, flbuf.f_name);
656 }
657
658
659 /* 
660  */
661 void artv_import_visit(void) {
662         struct visit vbuf;
663         char buf[SIZ];
664         int i;
665         int is_textual_seen = 0;
666
667         client_getln(buf, sizeof buf);  vbuf.v_roomnum = atol(buf);
668         client_getln(buf, sizeof buf);  vbuf.v_roomgen = atol(buf);
669         client_getln(buf, sizeof buf);  vbuf.v_usernum = atol(buf);
670
671         client_getln(buf, sizeof buf);
672         vbuf.v_lastseen = atol(buf);
673         for (i=0; buf[i]; ++i) if (!isdigit(buf[i])) is_textual_seen = 1;
674         if (is_textual_seen)    strcpy(vbuf.v_seen, buf);
675
676         client_getln(vbuf.v_answered, sizeof vbuf.v_answered);
677         client_getln(buf, sizeof buf);  vbuf.v_flags = atoi(buf);
678         client_getln(buf, sizeof buf);  vbuf.v_view = atoi(buf);
679         put_visit(&vbuf);
680         CtdlLogPrintf(CTDL_INFO, "Imported visit %ld/%ld/%ld\n",
681                 vbuf.v_roomnum, vbuf.v_roomgen, vbuf.v_usernum);
682 }
683
684
685
686 void artv_import_message(long *iterations) {
687         struct MetaData smi;
688         long msgnum;
689         long msglen;
690         FILE *fp;
691         char buf[SIZ];
692         char tempfile[PATH_MAX];
693         char *mbuf;
694
695         memset(&smi, 0, sizeof(struct MetaData));
696         client_getln(buf, sizeof buf);  msgnum = atol(buf);
697                                 smi.meta_msgnum = msgnum;
698         client_getln(buf, sizeof buf);  smi.meta_refcount = atoi(buf);
699         client_getln(smi.meta_content_type, sizeof smi.meta_content_type);
700
701         CtdlLogPrintf(CTDL_INFO, "message #%ld\n", msgnum);
702
703         /* decode base64 message text */
704         CtdlMakeTempFileName(tempfile, sizeof tempfile);
705         snprintf(buf, sizeof buf, "%s -d >%s", file_base64, tempfile);
706         fp = popen(buf, "w");
707         while (client_getln(buf, sizeof buf), strcasecmp(buf, END_OF_MESSAGE)) {
708                 cprintf(".");
709                 ++(*iterations);
710                 if ((*iterations) % 64 == 0)
711                         cprintf("\n");
712                 fprintf(fp, "%s\n", buf);
713         }
714         pclose(fp);
715         fp = fopen(tempfile, "rb");
716         fseek(fp, 0L, SEEK_END);
717         msglen = ftell(fp);
718         fclose(fp);
719         CtdlLogPrintf(CTDL_DEBUG, "msglen = %ld\n", msglen);
720
721         mbuf = malloc(msglen);
722         fp = fopen(tempfile, "rb");
723         fread(mbuf, msglen, 1, fp);
724         fclose(fp);
725
726         cdb_store(CDB_MSGMAIN, &msgnum, sizeof(long), mbuf, msglen);
727
728         free(mbuf);
729         unlink(tempfile);
730
731         PutMetaData(&smi);
732         CtdlLogPrintf(CTDL_INFO, "Imported message %ld\n", msgnum);
733 }
734
735
736
737
738 void artv_do_import(void) {
739         char buf[SIZ];
740         char abuf[SIZ];
741         char s_version[SIZ];
742         int version;
743         long iterations;
744
745         unbuffer_output();
746
747         cprintf("%d sock it to me\n", SEND_LISTING);
748         abuf[0] = '\0';
749         unbuffer_output();
750         iterations = 0;
751         while (client_getln(buf, sizeof buf), strcmp(buf, "000")) {
752                 if (CtdlThreadCheckStop())
753                         break;  // Should we break or return?
754                 
755                 if (buf[0] == '\0')
756                         continue;
757                         
758                 CtdlLogPrintf(CTDL_DEBUG, "import keyword: <%s>\n", buf);
759                 if ((abuf[0] == '\0') || (strcasecmp(buf, abuf))) {
760                         cprintf ("\n\nImporting datatype %s\n", buf);
761                         strncpy (abuf, buf, SIZ);       
762                         iterations = 0;
763                 }
764                 else {
765                         cprintf(".");
766                         iterations ++;
767                         if (iterations % 64 == 0)
768                                 cprintf("\n");
769                 }
770                 
771                 if (!strcasecmp(buf, "version")) {
772                         client_getln(s_version, sizeof s_version);
773                         version = atoi(s_version);
774                         if ((version<EXPORT_REV_MIN) || (version>REV_LEVEL)) {
775                                 CtdlLogPrintf(CTDL_ERR, "Version mismatch in ARTV import; aborting\n");
776                                 break;
777                         }
778                 }
779                 else if (!strcasecmp(buf, "config")) artv_import_config();
780                 else if (!strcasecmp(buf, "control")) artv_import_control();
781                 else if (!strcasecmp(buf, "user")) artv_import_user();
782                 else if (!strcasecmp(buf, "room")) artv_import_room(&iterations);
783                 else if (!strcasecmp(buf, "floor")) artv_import_floor();
784                 else if (!strcasecmp(buf, "visit")) artv_import_visit();
785                 else if (!strcasecmp(buf, "message")) artv_import_message(&iterations);
786                 else break;
787         }
788         CtdlLogPrintf(CTDL_INFO, "Invalid keyword <%s>.  Flushing input.\n", buf);
789         while (client_getln(buf, sizeof buf), strcmp(buf, "000"))  ;;
790         rebuild_euid_index();
791 }
792
793
794
795 void cmd_artv(char *cmdbuf) {
796         char cmd[32];
797         static int is_running = 0;
798
799         if (CtdlAccessCheck(ac_internal)) return;
800         if (is_running) {
801                 cprintf("%d The importer/exporter is already running.\n",
802                         ERROR + RESOURCE_BUSY);
803                 return;
804         }
805         is_running = 1;
806
807         CtdlMakeTempFileName(artv_tempfilename1, sizeof artv_tempfilename1);
808         CtdlMakeTempFileName(artv_tempfilename2, sizeof artv_tempfilename2);
809
810         extract_token(cmd, cmdbuf, 0, '|', sizeof cmd);
811         if (!strcasecmp(cmd, "export")) artv_do_export();
812         else if (!strcasecmp(cmd, "import")) artv_do_import();
813         else if (!strcasecmp(cmd, "dump")) artv_do_dump();
814         else cprintf("%d illegal command\n", ERROR + ILLEGAL_VALUE);
815
816         unlink(artv_tempfilename1);
817         unlink(artv_tempfilename2);
818
819         is_running = 0;
820 }
821
822
823
824
825 CTDL_MODULE_INIT(vandelay)
826 {
827         if (!threading)
828         {
829                 CtdlRegisterProtoHook(cmd_artv, "ARTV", "import/export data store");
830         }
831         
832         /* return our Subversion id for the Log */
833         return "$Id$";
834 }