示例#1
0
void check_ref_counts(void) {
	struct floor flbuf;
	int a;

	int new_refcounts[MAXFLOORS];

	syslog(LOG_DEBUG, "Checking floor reference counts\n");
	for (a=0; a<MAXFLOORS; ++a) {
		new_refcounts[a] = 0;
	}

	cdb_begin_transaction();
	CtdlForEachRoom(check_ref_counts_backend, (void *)new_refcounts );
	cdb_end_transaction();

	for (a=0; a<MAXFLOORS; ++a) {
		lgetfloor(&flbuf, a);
		flbuf.f_ref_count = new_refcounts[a];
		if (new_refcounts[a] > 0) {
			flbuf.f_flags = flbuf.f_flags | QR_INUSE;
		}
		else {
			flbuf.f_flags = flbuf.f_flags & ~QR_INUSE;
		}
		lputfloor(&flbuf, a);
		syslog(LOG_DEBUG, "Floor %d: %d rooms\n", a, new_refcounts[a]);
	}
}	
示例#2
0
文件: control.c 项目: henri14/citadel
/*
 * check_control   -  check the control record has sensible values for message, user and room numbers
 */
void check_control(void)
{
	syslog(LOG_INFO, "Checking/re-building control record\n");
	get_control();
	// Find highest room number and message number.
	CtdlForEachRoom(control_find_highest, NULL);
	ForEachUser(control_find_user, NULL);
	put_control();
}
示例#3
0
void cmd_lprm(char *argbuf)
{
	int FloorBeingSearched = (-1);
	if (!IsEmptyStr(argbuf))
		FloorBeingSearched = extract_int(argbuf, 0);

	cprintf("%d Public rooms:\n", LISTING_FOLLOWS);

	CtdlForEachRoom(cmd_lprm_backend, &FloorBeingSearched);
	cprintf("000\n");
}
示例#4
0
//
// Implements the LIST commands
//
void nntp_list(const char *cmd) {
	if (CtdlAccessCheck(ac_logged_in_or_guest)) return;

	char list_format[64];
	char wildmat_pattern[1024];
	struct nntp_list_data nld;

	extract_token(list_format, cmd, 1, ' ', sizeof list_format);
	extract_token(wildmat_pattern, cmd, 2, ' ', sizeof wildmat_pattern);

	if (strlen(wildmat_pattern) > 0) {
		nld.wildmat_pattern = wildmat_pattern;
	}
	else {
		nld.wildmat_pattern = NULL;
	}

	if ( (strlen(cmd) < 6) || (!strcasecmp(list_format, "ACTIVE")) ) {
		nld.list_format = NNTP_LIST_ACTIVE;
	}
	else if (!strcasecmp(list_format, "NEWSGROUPS")) {
		nld.list_format = NNTP_LIST_NEWSGROUPS;
	}
	else if (!strcasecmp(list_format, "OVERVIEW.FMT")) {
		nld.list_format = NNTP_LIST_OVERVIEW_FMT;
	}
	else {
		cprintf("501 syntax error , unsupported list format\r\n");
		return;
	}

	// OVERVIEW.FMT delivers a completely different type of data than all of the
	// other LIST commands.  It's a stupid place to put it.  But that's how it's
	// written into RFC3977, so we have to handle it here.
	if (nld.list_format == NNTP_LIST_OVERVIEW_FMT) {
		cprintf("215 Order of fields in overview database.\r\n");
		cprintf("Subject:\r\n");
		cprintf("From:\r\n");
		cprintf("Date:\r\n");
		cprintf("Message-ID:\r\n");
		cprintf("References:\r\n");
		cprintf("Bytes:\r\n");
		cprintf("Lines:\r\n");
		cprintf(".\r\n");
		return;
	}

	cprintf("215 list of newsgroups follows\r\n");
	CtdlGetUser(&CC->user, CC->curr_user);
	CtdlForEachRoom(nntp_list_backend, &nld);
	cprintf(".\r\n");
}
示例#5
0
void cmd_lrms(char *argbuf)
{
	int FloorBeingSearched = (-1);
	if (!IsEmptyStr(argbuf))
		FloorBeingSearched = extract_int(argbuf, 0);

	if (CtdlAccessCheck(ac_logged_in_or_guest)) return;

	CtdlGetUser(&CC->user, CC->curr_user);
	cprintf("%d Accessible rooms:\n", LISTING_FOLLOWS);

	CtdlForEachRoom(cmd_lrms_backend, &FloorBeingSearched);
	cprintf("000\n");
}
示例#6
0
void PurgeMessages(void) {
	FILE *purgelist;

	syslog(LOG_DEBUG, "PurgeMessages() called");
	messages_purged = 0;

	purgelist = tmpfile();
	if (purgelist == NULL) {
		syslog(LOG_CRIT, "Can't create purgelist temp file: %s", strerror(errno));
		return;
	}

	CtdlForEachRoom(GatherPurgeMessages, (void *)purgelist );
	DoPurgeMessages(purgelist);
	fclose(purgelist);
}
示例#7
0
int PurgeRooms(void) {
	struct PurgeList *pptr;
	int num_rooms_purged = 0;
	struct ctdlroom qrbuf;
	struct ValidUser *vuptr;
	char *transcript = NULL;

	syslog(LOG_DEBUG, "PurgeRooms() called");


	/* Load up a table full of valid user numbers so we can delete
	 * user-owned rooms for users who no longer exist */
	ForEachUser(AddValidUser, NULL);

	/* Then cycle through the room file */
	CtdlForEachRoom(DoPurgeRooms, NULL);

	/* Free the valid user list */
	while (ValidUserList != NULL) {
		vuptr = ValidUserList->next;
		free(ValidUserList);
		ValidUserList = vuptr;
	}


	transcript = malloc(SIZ);
	strcpy(transcript, "The following rooms have been auto-purged:\n");

	while (RoomPurgeList != NULL) {
		if (CtdlGetRoom(&qrbuf, RoomPurgeList->name) == 0) {
			transcript=realloc(transcript, strlen(transcript)+SIZ);
			snprintf(&transcript[strlen(transcript)], SIZ, " %s\n",
				qrbuf.QRname);
			CtdlDeleteRoom(&qrbuf);
		}
		pptr = RoomPurgeList->next;
		free(RoomPurgeList);
		RoomPurgeList = pptr;
		++num_rooms_purged;
	}

	if (num_rooms_purged > 0) CtdlAideMessage(transcript, "Room Autopurger Message");
	free(transcript);

	syslog(LOG_DEBUG, "Purged %d rooms.", num_rooms_purged);
	return(num_rooms_purged);
}
示例#8
0
//
// Implements the NEWGROUPS command
//
void nntp_newgroups(const char *cmd) {
	if (CtdlAccessCheck(ac_logged_in_or_guest)) return;

	char stringy_date[16];
	char stringy_time[16];
	char stringy_gmt[16];
	struct tm tm;
	time_t thetime;

	extract_token(stringy_date, cmd, 1, ' ', sizeof stringy_date);
	extract_token(stringy_time, cmd, 2, ' ', sizeof stringy_time);
	extract_token(stringy_gmt, cmd, 3, ' ', sizeof stringy_gmt);

	memset(&tm, 0, sizeof tm);
	if (strlen(stringy_date) == 6) {
		sscanf(stringy_date, "%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday);
		tm.tm_year += 100;
	}
	else {
		sscanf(stringy_date, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday);
		tm.tm_year -= 1900;
	}
	tm.tm_mon -= 1;		// tm_mon is zero based (0=January)
	tm.tm_isdst = (-1);	// let the C library figure out whether DST is in effect
	sscanf(stringy_time, "%2d%2d%2d", &tm.tm_hour, &tm.tm_min ,&tm.tm_sec);
	thetime = mktime(&tm);
	if (!strcasecmp(stringy_gmt, "GMT")) {
		tzset();
		thetime += timezone;
	}


	cprintf("231 list of new newsgroups follows\r\n");
	CtdlGetUser(&CC->user, CC->curr_user);
	CtdlForEachRoom(nntp_newgroups_backend, &thetime);
	cprintf(".\r\n");
}
示例#9
0
/*
 * Purge visits
 *
 * This is a really cumbersome "garbage collection" function.  We have to
 * delete visits which refer to rooms and/or users which no longer exist.  In
 * order to prevent endless traversals of the room and user files, we first
 * build linked lists of rooms and users which _do_ exist on the system, then
 * traverse the visit file, checking each record against those two lists and
 * purging the ones that do not have a match on _both_ lists.  (Remember, if
 * either the room or user being referred to is no longer on the system, the
 * record is completely useless.)
 */
int PurgeVisits(void) {
	struct cdbdata *cdbvisit;
	visit vbuf;
	struct VPurgeList *VisitPurgeList = NULL;
	struct VPurgeList *vptr;
	int purged = 0;
	char IndexBuf[32];
	int IndexLen;
	struct ValidRoom *vrptr;
	struct ValidUser *vuptr;
	int RoomIsValid, UserIsValid;

	/* First, load up a table full of valid room/gen combinations */
	CtdlForEachRoom(AddValidRoom, NULL);

	/* Then load up a table full of valid user numbers */
	ForEachUser(AddValidUser, NULL);

	/* Now traverse through the visits, purging irrelevant records... */
	cdb_rewind(CDB_VISIT);
	while(cdbvisit = cdb_next_item(CDB_VISIT), cdbvisit != NULL) {
		memset(&vbuf, 0, sizeof(visit));
		memcpy(&vbuf, cdbvisit->ptr,
			( (cdbvisit->len > sizeof(visit)) ?
			  sizeof(visit) : cdbvisit->len) );
		cdb_free(cdbvisit);

		RoomIsValid = 0;
		UserIsValid = 0;

		/* Check to see if the room exists */
		for (vrptr=ValidRoomList; vrptr!=NULL; vrptr=vrptr->next) {
			if ( (vrptr->vr_roomnum==vbuf.v_roomnum)
			     && (vrptr->vr_roomgen==vbuf.v_roomgen))
				RoomIsValid = 1;
		}

		/* Check to see if the user exists */
		for (vuptr=ValidUserList; vuptr!=NULL; vuptr=vuptr->next) {
			if (vuptr->vu_usernum == vbuf.v_usernum)
				UserIsValid = 1;
		}

		/* Put the record on the purge list if it's dead */
		if ((RoomIsValid==0) || (UserIsValid==0)) {
			vptr = (struct VPurgeList *)
				malloc(sizeof(struct VPurgeList));
			vptr->next = VisitPurgeList;
			vptr->vp_roomnum = vbuf.v_roomnum;
			vptr->vp_roomgen = vbuf.v_roomgen;
			vptr->vp_usernum = vbuf.v_usernum;
			VisitPurgeList = vptr;
		}

	}

	/* Free the valid room/gen combination list */
	while (ValidRoomList != NULL) {
		vrptr = ValidRoomList->next;
		free(ValidRoomList);
		ValidRoomList = vrptr;
	}

	/* Free the valid user list */
	while (ValidUserList != NULL) {
		vuptr = ValidUserList->next;
		free(ValidUserList);
		ValidUserList = vuptr;
	}

	/* Now delete every visit on the purged list */
	while (VisitPurgeList != NULL) {
		IndexLen = GenerateRelationshipIndex(IndexBuf,
				VisitPurgeList->vp_roomnum,
				VisitPurgeList->vp_roomgen,
				VisitPurgeList->vp_usernum);
		cdb_delete(CDB_VISIT, IndexBuf, IndexLen);
		vptr = VisitPurgeList->next;
		free(VisitPurgeList);
		VisitPurgeList = vptr;
		++purged;
	}

	return(purged);
}
示例#10
0
/*
 * Begin the fulltext indexing process.
 */
void do_fulltext_indexing(void) {
	int i;
	static time_t last_index = 0L;
	static time_t last_progress = 0L;
	time_t run_time = 0L;
	time_t end_time = 0L;
	static int is_running = 0;
	if (is_running) return;         /* Concurrency check - only one can run */
	is_running = 1;
	
	/*
	 * Don't do this if the site doesn't have it enabled.
	 */
	if (!CtdlGetConfigInt("c_enable_fulltext")) {
		return;
	}

	/*
	 * Make sure we don't run the indexer too frequently.
	 * FIXME move the setting into config
	 */
 
	if ( (time(NULL) - last_index) < 300L) {
		return;
	}

	/*
	 * Check to see whether the fulltext index is up to date; if there
	 * are no messages to index, don't waste any more time trying.
	 */
	if (
		(CtdlGetConfigLong("MMfulltext") >= CtdlGetConfigLong("MMhighest"))
		&& (CtdlGetConfigInt("MM_fulltext_wordbreaker") == FT_WORDBREAKER_ID)
	) {
		return;		/* nothing to do! */
	}
	
	run_time = time(NULL);
	syslog(LOG_DEBUG, "do_fulltext_indexing() started (%ld)", run_time);
	
	/*
	 * If we've switched wordbreaker modules, burn the index and start
	 * over.
	 */
	begin_critical_section(S_CONTROL);
	if (CtdlGetConfigInt("MM_fulltext_wordbreaker") != FT_WORDBREAKER_ID) {
		syslog(LOG_DEBUG, "wb ver on disk = %d, code ver = %d",
			CtdlGetConfigInt("MM_fulltext_wordbreaker"), FT_WORDBREAKER_ID
		);
		syslog(LOG_INFO, "(re)initializing full text index");
		cdb_trunc(CDB_FULLTEXT);
		CtdlSetConfigLong("MMfulltext", 0);
	}
	end_critical_section(S_CONTROL);

	/*
	 * Now go through each room and find messages to index.
	 */
	ft_newhighest = CtdlGetConfigLong("MMhighest");
	CtdlForEachRoom(ft_index_room, NULL);	/* load all msg pointers */

	if (ft_num_msgs > 0) {
		qsort(ft_newmsgs, ft_num_msgs, sizeof(long), longcmp);
		for (i=0; i<(ft_num_msgs-1); ++i) { /* purge dups */
			if (ft_newmsgs[i] == ft_newmsgs[i+1]) {
				memmove(&ft_newmsgs[i], &ft_newmsgs[i+1],
					((ft_num_msgs - i - 1)*sizeof(long)));
				--ft_num_msgs;
				--i;
			}
		}

		/* Here it is ... do each message! */
		for (i=0; i<ft_num_msgs; ++i) {
			if (time(NULL) != last_progress) {
				syslog(LOG_DEBUG,
					"Indexed %d of %d messages (%d%%)",
						i, ft_num_msgs,
						((i*100) / ft_num_msgs)
				);
				last_progress = time(NULL);
			}
			ft_index_message(ft_newmsgs[i], 1);

			/* Check to see if we need to quit early */
			if (server_shutting_down) {
				syslog(LOG_DEBUG, "Indexer quitting early");
				ft_newhighest = ft_newmsgs[i];
				break;
			}

			/* Check to see if we have to maybe flush to disk */
			if (i >= FT_MAX_CACHE) {
				syslog(LOG_DEBUG, "Time to flush.");
				ft_newhighest = ft_newmsgs[i];
				break;
			}

		}

		free(ft_newmsgs);
		ft_num_msgs = 0;
		ft_num_alloc = 0;
		ft_newmsgs = NULL;
	}
	end_time = time(NULL);

	if (server_shutting_down) {
		is_running = 0;
		return;
	}
	
	syslog(LOG_DEBUG, "do_fulltext_indexing() duration (%ld)", end_time - run_time);
		
	/* Save our place so we don't have to do this again */
	ft_flush_cache();
	begin_critical_section(S_CONTROL);
	CtdlSetConfigLong("MMfulltext", ft_newhighest);
	CtdlSetConfigInt("MM_fulltext_wordbreaker", FT_WORDBREAKER_ID);
	end_critical_section(S_CONTROL);
	last_index = time(NULL);

	syslog(LOG_DEBUG, "do_fulltext_indexing() finished");
	is_running = 0;
	return;
}