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