* do typedef the visit struct, remove all those 'struct' statements from all over...
[citadel.git] / citadel / modules / migrate / serv_migrate.c
index 7885a10a220eb80b872acdd33c4cc757ca4edb98..8b431c8afbfdf021b9f290da5c5746ad85688e08 100644 (file)
@@ -1,13 +1,14 @@
 /*
- * $Id: serv_migrate.c 7274 2009-03-27 15:11:14Z ajc $
- * Copyright (c) 2000-2009 by the citadel.org development team
+ * $Id$
  *
  * This module dumps and/or loads the Citadel database in XML format.
  *
+ * Copyright (c) 1987-2010 by the citadel.org team
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +17,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- * 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include "sysdep.h"
@@ -56,7 +55,6 @@
 #include "database.h"
 #include "msgbase.h"
 #include "user_ops.h"
-#include "room_ops.h"
 #include "control.h"
 #include "euidindex.h"
 
@@ -158,7 +156,7 @@ void migr_export_rooms_backend(struct ctdlroom *buf, void *data) {
 
        /* message list goes inside this tag */
 
-       getroom(&CC->room, buf->QRname);
+       CtdlGetRoom(&CC->room, buf->QRname);
        client_write("<room_messages>", 15);
        client_write("<FRname>", 8);    xml_strout(CC->room.QRname);    client_write("</FRname>\n", 10);
        client_write("<FRmsglist>", 11);
@@ -174,7 +172,7 @@ void migr_export_rooms(void) {
        char cmd[SIZ];
        migr_global_message_list = fopen(migr_tempfilename1, "w");
        if (migr_global_message_list != NULL) {
-               ForEachRoom(migr_export_rooms_backend, NULL);
+               CtdlForEachRoom(migr_export_rooms_backend, NULL);
                fclose(migr_global_message_list);
        }
 
@@ -198,7 +196,7 @@ void migr_export_floors(void) {
         for (i=0; i < MAXFLOORS; ++i) {
                client_write("<floor>\n", 8);
                cprintf("<f_num>%d</f_num>\n", i);
-                getfloor(&qfbuf, i);
+                CtdlGetFloor(&qfbuf, i);
                buf = &qfbuf;
                cprintf("<f_flags>%u</f_flags>\n", buf->f_flags);
                client_write("<f_name>", 8); xml_strout(buf->f_name); client_write("</f_name>\n", 10);
@@ -215,16 +213,16 @@ void migr_export_floors(void) {
  *  Traverse the visits file...
  */
 void migr_export_visits(void) {
-       struct visit vbuf;
+       visit vbuf;
        struct cdbdata *cdbv;
 
        cdb_rewind(CDB_VISIT);
 
        while (cdbv = cdb_next_item(CDB_VISIT), cdbv != NULL) {
-               memset(&vbuf, 0, sizeof(struct visit));
+               memset(&vbuf, 0, sizeof(visit));
                memcpy(&vbuf, cdbv->ptr,
-                      ((cdbv->len > sizeof(struct visit)) ?
-                       sizeof(struct visit) : cdbv->len));
+                      ((cdbv->len > sizeof(visit)) ?
+                       sizeof(visit) : cdbv->len));
                cdb_free(cdbv);
 
                client_write("<visit>\n", 8);
@@ -254,6 +252,25 @@ void migr_export_message(long msgnum) {
        struct CtdlMessage *msg;
        struct ser_ret smr;
 
+       /* We can use a static buffer here because there will never be more than
+        * one of this operation happening at any given time, and it's really best
+        * to just keep it allocated once instead of torturing malloc/free.
+        * Call this function with msgnum "-1" to free the buffer when finished.
+        */
+       static int encoded_alloc = 0;
+       static char *encoded_msg = NULL;
+
+       if (msgnum < 0) {
+               if ((encoded_alloc == 0) && (encoded_msg != NULL)) {
+                       free(encoded_msg);
+                       encoded_alloc = 0;
+                       encoded_msg = NULL;
+               }
+               return;
+       }
+
+       /* Ok, here we go ... */
+
        msg = CtdlFetchMessage(msgnum, 1);
        if (msg == NULL) return;        /* fail silently */
 
@@ -267,14 +284,21 @@ void migr_export_message(long msgnum) {
        serialize_message(&smr, msg);
        CtdlFreeMessage(msg);
 
-       int encoded_len = 0;
-       int encoded_alloc = smr.len * 139 / 100;        /* well-tested formula for predicting encoded size */
-       char *encoded_msg = malloc(encoded_alloc);
+       /* Predict the buffer size we need.  Expand the buffer if necessary. */
+       int encoded_len = smr.len * 15 / 10 ;
+       if (encoded_len > encoded_alloc) {
+               encoded_alloc = encoded_len;
+               encoded_msg = realloc(encoded_msg, encoded_alloc);
+       }
 
-       if (encoded_msg != NULL) {
+       if (encoded_msg == NULL) {
+               /* Questionable hack that hopes it'll work next time and we only lose one message */
+               encoded_alloc = 0;
+       }
+       else {
+               /* Once we do the encoding we know the exact size */
                encoded_len = CtdlEncodeBase64(encoded_msg, (char *)smr.ser, smr.len, 1);
                client_write(encoded_msg, encoded_len);
-               free(encoded_msg);
        }
 
        free(smr.ser);
@@ -313,7 +337,7 @@ void migr_export_messages(void) {
        char buf[SIZ];
        long msgnum;
        int count = 0;
-       t_context *Ctx;
+       CitContext *Ctx;
 
        Ctx = CC;
        migr_global_message_list = fopen(migr_tempfilename1, "r");
@@ -333,6 +357,8 @@ void migr_export_messages(void) {
                CtdlLogPrintf(CTDL_INFO, "Exported %d messages.\n", count);
        else
                CtdlLogPrintf(CTDL_ERR, "Export aborted due to client disconnect! \n");
+
+       migr_export_message(-1L);       /* This frees the encoding buffer */
 }
 
 
@@ -340,7 +366,7 @@ void migr_export_messages(void) {
 void migr_do_export(void) {
        struct config *buf;
        buf = &config;
-       t_context *Ctx;
+       CitContext *Ctx;
 
        Ctx = CC;
        cprintf("%d Exporting all Citadel databases.\n", LISTING_FOLLOWS);
@@ -471,7 +497,7 @@ long openid_usernum = 0;
 char FRname[ROOMNAMELEN];
 struct floor flbuf;
 int floornum = 0;
-struct visit vbuf;
+visit vbuf;
 struct MetaData smi;
 long import_msgnum = 0;
 char *decoded_msg = NULL;
@@ -535,7 +561,7 @@ void migr_xml_start(void *data, const char *el, const char **attr) {
        else if (!strcasecmp(el, "room"))               memset(&qrbuf, 0, sizeof (struct ctdlroom));
        else if (!strcasecmp(el, "room_messages"))      memset(FRname, 0, sizeof FRname);
        else if (!strcasecmp(el, "floor"))              memset(&flbuf, 0, sizeof (struct floor));
-       else if (!strcasecmp(el, "visit"))              memset(&vbuf, 0, sizeof (struct visit));
+       else if (!strcasecmp(el, "visit"))              memset(&vbuf, 0, sizeof (visit));
 
        else if (!strcasecmp(el, "message")) {
                memset(&smi, 0, sizeof (struct MetaData));
@@ -549,7 +575,7 @@ void migr_xml_start(void *data, const char *el, const char **attr) {
 }
 
 
-void migr_xml_end(void *data, const char *el, const char **attr) {
+void migr_xml_end(void *data, const char *el) {
        char *ptr;
        int msgcount = 0;
        long msgnum = 0L;
@@ -691,7 +717,7 @@ void migr_xml_end(void *data, const char *el, const char **attr) {
        else if (!strcasecmp(el, "u_fullname"))                 safestrncpy(usbuf.fullname, migr_chardata, sizeof usbuf.fullname);
 
        else if (!strcasecmp(el, "user")) {
-               putuser(&usbuf);
+               CtdlPutUser(&usbuf);
                CtdlLogPrintf(CTDL_INFO, "Imported user: %s\n", usbuf.fullname);
        }
 
@@ -732,7 +758,7 @@ void migr_xml_end(void *data, const char *el, const char **attr) {
        else if (!strcasecmp(el, "QRdefaultview"))              qrbuf.QRdefaultview = atoi(migr_chardata);
 
        else if (!strcasecmp(el, "room")) {
-               putroom(&qrbuf);
+               CtdlPutRoom(&qrbuf);
                CtdlLogPrintf(CTDL_INFO, "Imported room: %s\n", qrbuf.QRname);
        }
 
@@ -769,7 +795,7 @@ void migr_xml_end(void *data, const char *el, const char **attr) {
                                }
                        }
                        if (msgcount > 0) {
-                               CtdlSaveMsgPointersInRoom(FRname, msglist, msgcount, 0, NULL);
+                               CtdlSaveMsgPointersInRoom(FRname, msglist, msgcount, 0, NULL, 1);
                        }
                        free(msglist);
                        msglist = NULL;
@@ -790,7 +816,7 @@ void migr_xml_end(void *data, const char *el, const char **attr) {
        else if (!strcasecmp(el, "f_ep_expire_value"))          flbuf.f_ep.expire_value = atoi(migr_chardata);
 
        else if (!strcasecmp(el, "floor")) {
-               putfloor(&flbuf, floornum);
+               CtdlPutFloor(&flbuf, floornum);
                CtdlLogPrintf(CTDL_INFO, "Imported floor #%d (%s)\n", floornum, flbuf.f_name);
        }
 
@@ -895,6 +921,23 @@ void migr_do_import(void) {
 
 
 
+/*
+ * Dump out the pathnames of directories which can be copied "as is"
+ */
+void migr_do_listdirs(void) {
+       cprintf("%d Don't forget these:\n", LISTING_FOLLOWS);
+       cprintf("bio|%s\n",             ctdl_bio_dir);
+       cprintf("files|%s\n",           ctdl_file_dir);
+       cprintf("userpics|%s\n",        ctdl_usrpic_dir);
+       cprintf("messages|%s\n",        ctdl_message_dir);
+       cprintf("netconfigs|%s\n",      ctdl_netcfg_dir);
+       cprintf("keys|%s\n",            ctdl_key_dir);
+       cprintf("images|%s\n",          ctdl_image_dir);
+       cprintf("info|%s\n",            ctdl_info_dir);
+       cprintf("000\n");
+}
+
+
 /*
  * Common code appears in this section
  */
@@ -917,6 +960,9 @@ void cmd_migr(char *cmdbuf) {
                else if (!strcasecmp(cmd, "import")) {
                        migr_do_import();
                }
+               else if (!strcasecmp(cmd, "listdirs")) {
+                       migr_do_listdirs();
+               }
                else {
                        cprintf("%d illegal command\n", ERROR + ILLEGAL_VALUE);
                }
@@ -938,9 +984,9 @@ CTDL_MODULE_INIT(migrate)
        if (!threading)
        {
                CtdlRegisterProtoHook(cmd_migr, "MIGR", "Across-the-wire migration");
-               CtdlRegisterProtoHook(cmd_migr, "ARTV", "Across-the-wire migration (legacy calling syntax)"
+               CtdlRegisterProtoHook(cmd_migr, "ARTV", "Across-the-wire migration (legacy syntax)");
        }
        
        /* return our Subversion id for the Log */
-       return "$Id: serv_migrate.c 7274 2009-03-27 15:11:14Z ajc $";
+       return "$Id$";
 }