From a80f9ae62e7c9a29d7dd768a73b145f8fce763a5 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 19 Apr 2016 10:38:59 -0400 Subject: [PATCH] Import roominfo and roompic files into the database. --- citadel/citadel.h | 3 +- citadel/modules/ctdlproto/serv_rooms.c | 1 - citadel/modules/migrate/serv_migrate.c | 9 +- citadel/modules/upgrade/serv_upgrade.c | 180 ++++++++++++++++++++++++- citadel/room_ops.c | 6 +- citadel/utillib/citadel_dirs.c | 40 ++---- citadel/utils/ctdlmigrate.c | 4 - 7 files changed, 203 insertions(+), 40 deletions(-) diff --git a/citadel/citadel.h b/citadel/citadel.h index 96422ac96..53606e3a3 100644 --- a/citadel/citadel.h +++ b/citadel/citadel.h @@ -134,7 +134,7 @@ struct ctdlroom { time_t QRgen; /* Generation number of room */ unsigned QRflags; /* See flag values below */ char QRdirname[15]; /* Directory name, if applicable */ - long QRinfo; /* Info file update relative to msgs*/ + long msgnum_info; /* msgnum of room banner (info file)*/ char QRfloor; /* Which floor this room is on */ time_t QRmtime; /* Date/time of last post */ struct ExpirePolicy QRep; /* Message expiration policy */ @@ -142,6 +142,7 @@ struct ctdlroom { char QRorder; /* Sort key for room listing order */ unsigned QRflags2; /* Additional flags */ int QRdefaultview; /* How to display the contents */ + long msgnum_pic; /* msgnum of room picture or icon */ }; /* Private rooms are always flagged with QR_PRIVATE. If neither QR_PASSWORDED diff --git a/citadel/modules/ctdlproto/serv_rooms.c b/citadel/modules/ctdlproto/serv_rooms.c index 9df142cd0..fa3d23ac4 100644 --- a/citadel/modules/ctdlproto/serv_rooms.c +++ b/citadel/modules/ctdlproto/serv_rooms.c @@ -931,7 +931,6 @@ void cmd_einf(char *ok) /* now update the room index so people will see our new info */ CtdlGetRoomLock(&CCC->room, CCC->room.QRname); /* lock so no one steps on us */ - CCC->room.QRinfo = CCC->room.QRhighest + 1L; CtdlPutRoomLock(&CCC->room); } diff --git a/citadel/modules/migrate/serv_migrate.c b/citadel/modules/migrate/serv_migrate.c index 645c8d249..4ae75836b 100644 --- a/citadel/modules/migrate/serv_migrate.c +++ b/citadel/modules/migrate/serv_migrate.c @@ -157,7 +157,6 @@ void migr_export_rooms_backend(struct ctdlroom *buf, void *data) { xml_strout(buf->QRdirname); client_write(HKEY("\n")); } - cprintf("%ld\n", buf->QRinfo); cprintf("%d\n", buf->QRfloor); cprintf("%ld\n", (long)buf->QRmtime); cprintf("%d\n", buf->QRep.expire_mode); @@ -166,6 +165,8 @@ void migr_export_rooms_backend(struct ctdlroom *buf, void *data) { cprintf("%d\n", buf->QRorder); cprintf("%u\n", buf->QRflags2); cprintf("%d\n", buf->QRdefaultview); + cprintf("%ld\n", buf->msgnum_info); + cprintf("%ld\n", buf->msgnum_pic); client_write(HKEY("\n")); /* message list goes inside this tag */ @@ -592,14 +593,13 @@ int migr_userrecord(void *data, const char *el) int migr_roomrecord(void *data, const char *el) { - if (!strcasecmp(el, "QRname")) safestrncpy(qrbuf.QRname, ChrPtr(migr_chardata), sizeof qrbuf.QRname); + if (!strcasecmp(el, "QRname")) safestrncpy(qrbuf.QRname, ChrPtr(migr_chardata), sizeof qrbuf.QRname); else if (!strcasecmp(el, "QRpasswd")) safestrncpy(qrbuf.QRpasswd, ChrPtr(migr_chardata), sizeof qrbuf.QRpasswd); else if (!strcasecmp(el, "QRroomaide")) qrbuf.QRroomaide = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRhighest")) qrbuf.QRhighest = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRgen")) qrbuf.QRgen = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRflags")) qrbuf.QRflags = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRdirname")) safestrncpy(qrbuf.QRdirname, ChrPtr(migr_chardata), sizeof qrbuf.QRdirname); - else if (!strcasecmp(el, "QRinfo")) qrbuf.QRinfo = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRfloor")) qrbuf.QRfloor = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRmtime")) qrbuf.QRmtime = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRexpire_mode")) qrbuf.QRep.expire_mode = atoi(ChrPtr(migr_chardata)); @@ -608,6 +608,8 @@ int migr_roomrecord(void *data, const char *el) else if (!strcasecmp(el, "QRorder")) qrbuf.QRorder = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRflags2")) qrbuf.QRflags2 = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "QRdefaultview")) qrbuf.QRdefaultview = atoi(ChrPtr(migr_chardata)); + else if (!strcasecmp(el, "msgnum_info")) qrbuf.msgnum_info = atol(ChrPtr(migr_chardata)); + else if (!strcasecmp(el, "msgnum_pic")) qrbuf.msgnum_pic = atol(ChrPtr(migr_chardata)); else return 0; return 1; } @@ -906,7 +908,6 @@ void migr_do_listdirs(void) { cprintf("messages|%s\n", ctdl_message_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"); } diff --git a/citadel/modules/upgrade/serv_upgrade.c b/citadel/modules/upgrade/serv_upgrade.c index 249c82505..652699927 100644 --- a/citadel/modules/upgrade/serv_upgrade.c +++ b/citadel/modules/upgrade/serv_upgrade.c @@ -1,5 +1,8 @@ /* - * Transparently handle the upgrading of server data formats. + * Transparently handle the upgrading of server data formats. If we see + * an existing version number of our database, we can make some intelligent + * guesses about what kind of data format changes need to be applied, and + * we apply them transparently. * * Copyright (c) 1987-2016 by the citadel.org team * @@ -199,6 +202,176 @@ void guess_time_zone(void) { } + +/* + * Per-room callback function for ingest_old_roominfo_and_roompic_files() + * + * This is the second pass, where we process the list of rooms with info or pic files. + */ +void iorarf_oneroom(char *roomname, char *infofile, char *picfile) +{ + FILE *fp; + long data_length; + char *unencoded_data; + char *encoded_data; + long info_msgnum = 0; + long pic_msgnum = 0; + char subject[SIZ]; + + syslog(LOG_DEBUG, "iorarf_oneroom( %s , %s , %s )", roomname, infofile, picfile); + + // Test for the presence of a legacy "room info file" + if (!IsEmptyStr(infofile)) { + fp = fopen(infofile, "r"); + } + else { + fp = NULL; + } + if (fp) { + fseek(fp, 0, SEEK_END); + data_length = ftell(fp); + + if (data_length >= 1) { + rewind(fp); + unencoded_data = malloc(data_length); + if (unencoded_data) { + fread(unencoded_data, data_length, 1, fp); + encoded_data = malloc((data_length * 2) + 100); + if (encoded_data) { + sprintf(encoded_data, "Content-type: text/plain\nContent-transfer-encoding: base64\n\n"); + CtdlEncodeBase64(&encoded_data[strlen(encoded_data)], unencoded_data, data_length, 1); + snprintf(subject, sizeof subject, "Imported room banner for %s", roomname); + info_msgnum = quickie_message("Citadel", NULL, NULL, SYSCONFIGROOM, encoded_data, FMT_RFC822, subject); + free(encoded_data); + } + free(unencoded_data); + } + } + fclose(fp); + // unlink(filename); + } + + // Test for the presence of a legacy "room picture file" and import it. + if (!IsEmptyStr(picfile)) { + fp = fopen(picfile, "r"); + } + else { + fp = NULL; + } + if (fp) { + fseek(fp, 0, SEEK_END); + data_length = ftell(fp); + + if (data_length >= 1) { + rewind(fp); + unencoded_data = malloc(data_length); + if (unencoded_data) { + fread(unencoded_data, data_length, 1, fp); + encoded_data = malloc((data_length * 2) + 100); + if (encoded_data) { + sprintf(encoded_data, "Content-type: image/gif\nContent-transfer-encoding: base64\n\n"); + CtdlEncodeBase64(&encoded_data[strlen(encoded_data)], unencoded_data, data_length, 1); + snprintf(subject, sizeof subject, "Imported room icon for %s", roomname); + pic_msgnum = quickie_message("Citadel", NULL, NULL, SYSCONFIGROOM, encoded_data, FMT_RFC822, subject); + free(encoded_data); + } + free(unencoded_data); + } + } + fclose(fp); + // unlink(filename); + } + + // Now we have the message numbers of our new banner and icon. Record them in the room record. + // NOTE: we are not deleting the old msgnum_info because that position in the record was previously + // a pointer to the highest message number which existed in the room when the info file was saved, + // and we don't want to delete messages that are not *actually* old banners. + struct ctdlroom qrbuf; + if (CtdlGetRoomLock(&qrbuf, roomname) == 0) { + qrbuf.msgnum_info = info_msgnum; + qrbuf.msgnum_pic = pic_msgnum; + CtdlPutRoomLock(&qrbuf); + } + +} + + + +struct iorarf_list { + struct iorarf_list *next; + char name[ROOMNAMELEN]; + char info[PATH_MAX]; + char pic[PATH_MAX]; +}; + + +/* + * Per-room callback function for ingest_old_roominfo_and_roompic_files() + * + * This is the first pass, where the list of qualifying rooms is gathered. + */ +void iorarf_backend(struct ctdlroom *qrbuf, void *data) +{ + FILE *fp; + struct iorarf_list **iorarf_list = (struct iorarf_list **)data; + + struct iorarf_list *i = malloc(sizeof(struct iorarf_list)); + i->next = *iorarf_list; + strcpy(i->name, qrbuf->QRname); + strcpy(i->info, ""); + strcpy(i->pic, ""); + + // Test for the presence of a legacy "room info file" + assoc_file_name(i->info, sizeof i->info, qrbuf, ctdl_info_dir); + fp = fopen(i->info, "r"); + if (fp) { + fclose(fp); + } + else { + i->info[0] = 0; + } + + // Test for the presence of a legacy "room picture file" + assoc_file_name(i->pic, sizeof i->pic, qrbuf, ctdl_image_dir); + fp = fopen(i->pic, "r"); + if (fp) { + fclose(fp); + } + else { + i->pic[0] = 0; + } + + if ( (!IsEmptyStr(i->info)) || (!IsEmptyStr(i->pic)) ) { + *iorarf_list = i; + } + else { + free(i); + } +} + + +/* + * Prior to Citadel Server version 902, room info and pictures (which comprise the + * displayed banner for each room) were stored in the filesystem. If we are upgrading + * from version >000 to version >=902, ingest those files into the database. + */ +void ingest_old_roominfo_and_roompic_files(void) +{ + struct iorarf_list *il = NULL; + + CtdlForEachRoom(iorarf_backend, &il); + + struct iorarf_list *p; + while (il) { + iorarf_oneroom(il->name, il->info, il->pic); + p = il->next; + free(il); + il = p; + } + +} + + /* * Perform any upgrades that can be done automatically based on our knowledge of the previous * version of Citadel server that was running here. @@ -300,6 +473,10 @@ void check_server_upgrades(void) { } } + if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 902)) { + ingest_old_roominfo_and_roompic_files(); + } + CtdlSetConfigInt("MM_hosted_upgrade_level", REV_LEVEL); /* @@ -323,6 +500,7 @@ void check_server_upgrades(void) { CTDL_MODULE_UPGRADE(upgrade) { check_server_upgrades(); + ingest_old_roominfo_and_roompic_files(); // FIXME remove this line, it's proper above!!!! /* return our module id for the Log */ return "upgrade"; diff --git a/citadel/room_ops.c b/citadel/room_ops.c index ef185650b..74adefb86 100644 --- a/citadel/room_ops.c +++ b/citadel/room_ops.c @@ -826,8 +826,10 @@ void CtdlUserGoto(char *where, int display_result, int transiently, /* Check for new mail */ newmailcount = NewMailCount(); - /* set info to 1 if the user needs to read the room's info file */ - if (CCC->room.QRinfo > vbuf.v_lastseen) { + /* Set info to 1 if the room banner is new since our last visit. + * Some clients only want to display it when it changes. + */ + if (CCC->room.msgnum_info > vbuf.v_lastseen) { info = 1; } diff --git a/citadel/utillib/citadel_dirs.c b/citadel/utillib/citadel_dirs.c index ab3701ac7..faf70e6fe 100644 --- a/citadel/utillib/citadel_dirs.c +++ b/citadel/utillib/citadel_dirs.c @@ -440,32 +440,18 @@ int create_dir(char *which, long ACCESS, long UID, long GID) int create_run_directories(long UID, long GID) { - int rv; - - rv = create_dir(ctdl_info_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_message_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_hlp_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_image_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_bb_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_file_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_spool_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_netout_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_netin_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_netdigest_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_nettmp_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_key_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); - if (rv != -1) - rv = create_dir(ctdl_run_dir , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, UID, GID); + int rv = 0; + rv += create_dir(ctdl_message_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_hlp_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_image_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_bb_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_file_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_spool_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_netout_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_netin_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_netdigest_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_nettmp_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_key_dir , S_IRUSR|S_IWUSR|S_IXUSR, UID, -1); + rv += create_dir(ctdl_run_dir , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, UID, GID); return rv; } diff --git a/citadel/utils/ctdlmigrate.c b/citadel/utils/ctdlmigrate.c index c3646c3e4..199772ecc 100644 --- a/citadel/utils/ctdlmigrate.c +++ b/citadel/utils/ctdlmigrate.c @@ -263,10 +263,6 @@ FAIL: if (sourcefp) pclose(sourcefp); snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/", socket_path, remote_user, remote_host, &buf[7], ctdl_image_dir); } - else if (!strncasecmp(buf, "info|", 5)) { - snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/", - socket_path, remote_user, remote_host, &buf[5], ctdl_info_dir); - } else { strcpy(cmd, "false"); /* cheap and sleazy way to throw an error */ } -- 2.30.2