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