}
+
+struct listgroup_range {
+ long lo;
+ long hi;
+};
+
+
+
/*
- * Implements the GROUP command
+ * back end for the LISTGROUP command , called for each message number
+ */
+void nntp_listgroup_backend(long msgnum, void *userdata) {
+
+ struct listgroup_range *lr = (struct listgroup_range *)userdata;
+
+ // check range if supplied
+ if (msgnum < lr->lo) return;
+ if ((lr->hi != 0) && (msgnum > lr->hi)) return;
+
+ cprintf("%ld\r\n", msgnum);
+}
+
+
+/*
+ * Implements the GROUP and LISTGROUP commands
*/
void nntp_group(const char *cmd) {
/*
*/
if (CtdlAccessCheck(ac_logged_in_or_guest)) return;
+ char verb[16];
char requested_group[1024];
+ char message_range[256];
+ char range_lo[256];
+ char range_hi[256];
char requested_room[ROOMNAMELEN];
+ char augmented_roomname[ROOMNAMELEN];
+ int c = 0;
+ int ok = 0;
+ int ra = 0;
+ struct ctdlroom QRscratch;
+ int msgs, new;
+ long oldest,newest;
+ struct listgroup_range lr;
+
+ extract_token(verb, cmd, 0, ' ', sizeof verb);
extract_token(requested_group, cmd, 1, ' ', sizeof requested_group);
+ extract_token(message_range, cmd, 2, ' ', sizeof message_range);
+ extract_token(range_lo, message_range, 0, '-', sizeof range_lo);
+ extract_token(range_hi, message_range, 1, '-', sizeof range_hi);
+ lr.lo = atoi(range_lo);
+ lr.hi = atoi(range_hi);
+
+ /* In LISTGROUP mode we can specify an empty name for 'currently selected' */
+ if ((!strcasecmp(verb, "LISTGROUP")) && (IsEmptyStr(requested_group))) {
+ room_to_newsgroup(requested_group, CC->room.QRname, sizeof requested_group);
+ }
+
+ /* First try a regular match */
newsgroup_to_room(requested_room, requested_group, sizeof requested_room);
+ c = CtdlGetRoom(&QRscratch, requested_room);
+
+ /* Then try a mailbox name match */
+ if (c != 0) {
+ CtdlMailboxName(augmented_roomname, sizeof augmented_roomname, &CC->user, requested_room);
+ c = CtdlGetRoom(&QRscratch, augmented_roomname);
+ if (c == 0) {
+ safestrncpy(requested_room, augmented_roomname, sizeof(requested_room));
+ }
+ }
+
+ /* If the room exists, check security/access */
+ if (c == 0) {
+ /* See if there is an existing user/room relationship */
+ CtdlRoomAccess(&QRscratch, &CC->user, &ra, NULL);
- cprintf("599 FIXME screw you and your %s\r\n", requested_room);
+ /* normal clients have to pass through security */
+ if (ra & UA_KNOWN) {
+ ok = 1;
+ }
+ }
+
+ /* Fail here if no such room */
+ if (!ok) {
+ cprintf("411 no such newsgroup\r\n");
+ return;
+ }
+
+
+ /*
+ * CtdlUserGoto() formally takes us to the desired room, happily returning
+ * the number of messages and number of new messages.
+ */
+ memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom));
+ CtdlUserGoto(NULL, 0, 0, &msgs, &new, &oldest, &newest);
+ cprintf("211 %d %ld %ld %s\r\n", msgs, oldest, newest, requested_group);
+
+ // If this is a GROUP command, we can stop here.
+ if (!strcasecmp(verb, "GROUP")) {
+ return;
+ }
+
+ // If we get to this point we are running a LISTGROUP command. Fetch those message numbers.
+ CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, nntp_listgroup_backend, &lr);
+ cprintf(".\r\n");
}
nntp_group(ChrPtr(Cmd));
}
+ else if (!strcasecmp(cmdname, "listgroup")) {
+ nntp_group(ChrPtr(Cmd));
+ }
+
else {
cprintf("500 I'm afraid I can't do that.\r\n");
}
return "nntp";
}
+
+
+
+
+