Did away with lprintf all together now its called CtdlLogPrintf()
[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(void) {
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                 CtdlSaveMsgPointerInRoom(qrbuf.QRname, msgnum, 0, NULL);
622                 ++msgcount;
623         }
624         CtdlLogPrintf(CTDL_INFO, "(%d messages)\n", msgcount);
625 }
626
627
628 void artv_import_floor(void) {
629         struct floor flbuf, *buf;
630         int i;
631         char cbuf[SIZ];
632
633         buf = & flbuf;
634         memset(buf, 0, sizeof(buf));
635         client_getln(cbuf, sizeof cbuf);        i = atoi(cbuf);
636 /*
637 #include "artv_deserialize.h"
638 #include "dtds/floor-defs.h"
639 #include "undef_data.h"
640 /*/
641         client_getln(cbuf, sizeof cbuf);        buf->f_flags = atoi(cbuf);
642         client_getln(buf->f_name, sizeof buf->f_name);
643         client_getln(cbuf, sizeof cbuf);        buf->f_ref_count = atoi(cbuf);
644         client_getln(cbuf, sizeof cbuf);        buf->f_ep.expire_mode = atoi(cbuf);
645         client_getln(cbuf, sizeof cbuf);        buf->f_ep.expire_value = atoi(cbuf);
646 //*/
647         putfloor(buf, i);
648         CtdlLogPrintf(CTDL_INFO, "Imported floor #%d (%s)\n", i, flbuf.f_name);
649 }
650
651
652 /* 
653  */
654 void artv_import_visit(void) {
655         struct visit vbuf;
656         char buf[SIZ];
657         int i;
658         int is_textual_seen = 0;
659
660         client_getln(buf, sizeof buf);  vbuf.v_roomnum = atol(buf);
661         client_getln(buf, sizeof buf);  vbuf.v_roomgen = atol(buf);
662         client_getln(buf, sizeof buf);  vbuf.v_usernum = atol(buf);
663
664         client_getln(buf, sizeof buf);
665         vbuf.v_lastseen = atol(buf);
666         for (i=0; buf[i]; ++i) if (!isdigit(buf[i])) is_textual_seen = 1;
667         if (is_textual_seen)    strcpy(vbuf.v_seen, buf);
668
669         client_getln(vbuf.v_answered, sizeof vbuf.v_answered);
670         client_getln(buf, sizeof buf);  vbuf.v_flags = atoi(buf);
671         client_getln(buf, sizeof buf);  vbuf.v_view = atoi(buf);
672         put_visit(&vbuf);
673         CtdlLogPrintf(CTDL_INFO, "Imported visit %ld/%ld/%ld\n",
674                 vbuf.v_roomnum, vbuf.v_roomgen, vbuf.v_usernum);
675 }
676
677
678
679 void artv_import_message(void) {
680         struct MetaData smi;
681         long msgnum;
682         long msglen;
683         FILE *fp;
684         char buf[SIZ];
685         char tempfile[PATH_MAX];
686         char *mbuf;
687
688         memset(&smi, 0, sizeof(struct MetaData));
689         client_getln(buf, sizeof buf);  msgnum = atol(buf);
690                                 smi.meta_msgnum = msgnum;
691         client_getln(buf, sizeof buf);  smi.meta_refcount = atoi(buf);
692         client_getln(smi.meta_content_type, sizeof smi.meta_content_type);
693
694         CtdlLogPrintf(CTDL_INFO, "message #%ld\n", msgnum);
695
696         /* decode base64 message text */
697         CtdlMakeTempFileName(tempfile, sizeof tempfile);
698         snprintf(buf, sizeof buf, "%s -d >%s", file_base64, tempfile);
699         fp = popen(buf, "w");
700         while (client_getln(buf, sizeof buf), strcasecmp(buf, END_OF_MESSAGE)) {
701                 fprintf(fp, "%s\n", buf);
702         }
703         pclose(fp);
704         fp = fopen(tempfile, "rb");
705         fseek(fp, 0L, SEEK_END);
706         msglen = ftell(fp);
707         fclose(fp);
708         CtdlLogPrintf(CTDL_DEBUG, "msglen = %ld\n", msglen);
709
710         mbuf = malloc(msglen);
711         fp = fopen(tempfile, "rb");
712         fread(mbuf, msglen, 1, fp);
713         fclose(fp);
714
715         cdb_store(CDB_MSGMAIN, &msgnum, sizeof(long), mbuf, msglen);
716
717         free(mbuf);
718         unlink(tempfile);
719
720         PutMetaData(&smi);
721         CtdlLogPrintf(CTDL_INFO, "Imported message %ld\n", msgnum);
722 }
723
724
725
726
727 void artv_do_import(void) {
728         char buf[SIZ];
729         char abuf[SIZ];
730         char s_version[SIZ];
731         int version;
732         long iterations;
733
734         unbuffer_output();
735
736         cprintf("%d sock it to me\n", SEND_LISTING);
737         abuf[0] = '\0';
738         unbuffer_output();
739         iterations = 0;
740         while (client_getln(buf, sizeof buf), strcmp(buf, "000")) {
741
742                 CtdlLogPrintf(CTDL_DEBUG, "import keyword: <%s>\n", buf);
743                 if ((abuf[0] == '\0') || (strcasecmp(buf, abuf))) {
744                         cprintf ("\n\nImporting datatype %s\n", buf);
745                         strncpy (abuf, buf, SIZ);       
746                         iterations = 0;
747                 }
748                 else {
749                         cprintf(".");
750                         if (iterations % 64 == 0)
751                                 cprintf("\n");
752                         
753                 }
754                 
755                 if (!strcasecmp(buf, "version")) {
756                         client_getln(s_version, sizeof s_version);
757                         version = atoi(s_version);
758                         if ((version<EXPORT_REV_MIN) || (version>REV_LEVEL)) {
759                                 CtdlLogPrintf(CTDL_ERR, "Version mismatch in ARTV import; aborting\n");
760                                 break;
761                         }
762                 }
763                 else if (!strcasecmp(buf, "config")) artv_import_config();
764                 else if (!strcasecmp(buf, "control")) artv_import_control();
765                 else if (!strcasecmp(buf, "user")) artv_import_user();
766                 else if (!strcasecmp(buf, "room")) artv_import_room();
767                 else if (!strcasecmp(buf, "floor")) artv_import_floor();
768                 else if (!strcasecmp(buf, "visit")) artv_import_visit();
769                 else if (!strcasecmp(buf, "message")) artv_import_message();
770                 else break;
771                 iterations ++;
772         }
773         CtdlLogPrintf(CTDL_INFO, "Invalid keyword <%s>.  Flushing input.\n", buf);
774         while (client_getln(buf, sizeof buf), strcmp(buf, "000"))  ;;
775         rebuild_euid_index();
776 }
777
778
779
780 void cmd_artv(char *cmdbuf) {
781         char cmd[32];
782         static int is_running = 0;
783
784         if (CtdlAccessCheck(ac_internal)) return;
785         if (is_running) {
786                 cprintf("%d The importer/exporter is already running.\n",
787                         ERROR + RESOURCE_BUSY);
788                 return;
789         }
790         is_running = 1;
791
792         CtdlMakeTempFileName(artv_tempfilename1, sizeof artv_tempfilename1);
793         CtdlMakeTempFileName(artv_tempfilename2, sizeof artv_tempfilename2);
794
795         extract_token(cmd, cmdbuf, 0, '|', sizeof cmd);
796         if (!strcasecmp(cmd, "export")) artv_do_export();
797         else if (!strcasecmp(cmd, "import")) artv_do_import();
798         else if (!strcasecmp(cmd, "dump")) artv_do_dump();
799         else cprintf("%d illegal command\n", ERROR + ILLEGAL_VALUE);
800
801         unlink(artv_tempfilename1);
802         unlink(artv_tempfilename2);
803
804         is_running = 0;
805 }
806
807
808
809
810 CTDL_MODULE_INIT(vandelay)
811 {
812         if (!threading)
813         {
814                 CtdlRegisterProtoHook(cmd_artv, "ARTV", "import/export data store");
815         }
816         
817         /* return our Subversion id for the Log */
818         return "$Id$";
819 }