コード例 #1
0
ファイル: serv_roomchat.c プロジェクト: mingodad/citadel
/*
 * list users in chat in this room
 */
void roomchat_rwho(char *argbuf) {
	struct CitContext *nptr;
	int nContexts, i;

	if ((CC->cs_flags & CS_CHAT) == 0) {
		cprintf("%d Session is not in chat mode.\n", ERROR);
		return;
	}

	cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress() );
	
	nptr = CtdlGetContextArray(&nContexts) ;		// grab a copy of the wholist
	if (nptr) {
		for (i=0; i<nContexts; i++)  {			// list the users
		        if ( (nptr[i].room.QRnumber == CC->room.QRnumber) 
			   && (nptr[i].cs_flags & CS_CHAT)
			) {
				cprintf("%s\n", nptr[i].user.fullname);
			}
		}
		free(nptr);					// free our copy
	}

	cprintf("000\n");
}
コード例 #2
0
ファイル: xmpp_presence.c プロジェクト: henri14/citadel
/*
 * When a user logs in or out of the local Citadel system, notify all XMPP sessions about it.
 * THIS FUNCTION HAS A BUG IN IT THAT ENUMERATES THE SESSIONS WRONG.
 */
void xmpp_presence_notify(char *presence_jid, int event_type) {
	struct CitContext *cptr;
	static int unsolicited_id = 12345;
	int visible_sessions = 0;
	int nContexts, i;
	int which_cptr_is_relevant = (-1);

	if (IsEmptyStr(presence_jid)) return;
	if (CC->kill_me) return;

	cptr = CtdlGetContextArray(&nContexts);
	if (!cptr) {
		return;
	}

	/* Count the visible sessions for this user */
	for (i=0; i<nContexts; i++) {
		if ( (!strcasecmp(cptr[i].cs_inet_email, presence_jid))
		   && (xmpp_is_visible(&cptr[i], CC))
		)  {
			++visible_sessions;
			which_cptr_is_relevant = i;
		}
	}

	syslog(LOG_DEBUG, "%d sessions for <%s> are now visible to session %d\n", visible_sessions, presence_jid, CC->cs_pid);

	if ( (event_type == XMPP_EVT_LOGIN) && (visible_sessions == 1) ) {

		syslog(LOG_DEBUG, "Telling session %d that <%s> logged in\n", CC->cs_pid, presence_jid);

		/* Do an unsolicited roster update that adds a new contact. */
		assert(which_cptr_is_relevant >= 0);
		cprintf("<iq id=\"unsolicited_%x\" type=\"result\">", ++unsolicited_id);
		cprintf("<query xmlns=\"jabber:iq:roster\">");
		xmpp_roster_item(&cptr[which_cptr_is_relevant]);
		cprintf("</query></iq>");

		/* Transmit presence information */
		xmpp_indicate_presence(presence_jid);
	}

	if (visible_sessions == 0) {
		syslog(LOG_DEBUG, "Telling session %d that <%s> logged out\n",
			    CC->cs_pid, presence_jid);
		xmpp_destroy_buddy(presence_jid, 0);	/* non aggressive presence update */
	}

	free(cptr);
}
コード例 #3
0
ファイル: housekeeping.c プロジェクト: mingodad/citadel
void CtdlDisableHouseKeeping(void)
{
	int ActiveBackgroundJobs;
	int do_housekeeping_now = 0;
	struct CitContext *nptr;
	int nContexts, i;

retry_block_housekeeping:
	syslog(LOG_INFO, "trying to disable housekeeping services");
	begin_critical_section(S_HOUSEKEEPING);
	if (housekeeping_in_progress == 0) {
		do_housekeeping_now = 1;
		housekeeping_in_progress = 1;
	}
	end_critical_section(S_HOUSEKEEPING);
	if (do_housekeeping_now == 0) {
		usleep(1000000);
		goto retry_block_housekeeping;
	}
	
	syslog(LOG_INFO, "checking for running server Jobs");

retry_wait_for_contexts:
	/* So that we don't keep the context list locked for a long time
	 * we create a copy of it first
	 */
	ActiveBackgroundJobs = 0;
	nptr = CtdlGetContextArray(&nContexts) ;
	if (nptr)
	{
		for (i=0; i<nContexts; i++) 
		{
			if ((nptr[i].state != CON_SYS) || (nptr[i].IO == NULL) || (nptr[i].lastcmd == 0))
				continue;
			ActiveBackgroundJobs ++;
			syslog(LOG_INFO, "Job CC[%d] active; use TERM if you don't want to wait for it",nptr[i].cs_pid);
		
		}
	
		free(nptr);

	}
	if (ActiveBackgroundJobs != 0) {
		syslog(LOG_INFO, "found %d running jobs, need to wait", ActiveBackgroundJobs);
		usleep(5000000);
		goto retry_wait_for_contexts;
	}
	syslog(LOG_INFO, "Housekeeping disabled now.");
}
コード例 #4
0
ファイル: xmpp_presence.c プロジェクト: henri14/citadel
/* 
 * Initial dump of the entire wholist
 */
void xmpp_wholist_presence_dump(void)
{
	struct CitContext *cptr = NULL;
	int nContexts, i;
	
	cptr = CtdlGetContextArray(&nContexts);
	if (!cptr) {
		return;
	}

	for (i=0; i<nContexts; i++) {
		if (xmpp_is_visible(&cptr[i], CC)) {
			xmpp_indicate_presence(cptr[i].cs_inet_email);
		}
	}
	free(cptr);
}
コード例 #5
0
/* 
 * Return the results for a "jabber:iq:roster:query"
 *
 * Since we are not yet managing a roster, we simply return the entire wholist
 * (minus any entries for this user -- don't tell me about myself)
 *
 */
void xmpp_iq_roster_query(void)
{
	struct CitContext *cptr;
	int nContexts, i;

	syslog(LOG_DEBUG, "Roster push!");
	cprintf("<query xmlns=\"jabber:iq:roster\">");
	cptr = CtdlGetContextArray(&nContexts);
	if (cptr) {
		for (i=0; i<nContexts; i++) {
			if (xmpp_is_visible(&cptr[i], CC)) {
				XMPP_syslog(LOG_DEBUG, "Rosterizing %s\n", cptr[i].user.fullname);
				xmpp_roster_item(&cptr[i]);
			}
		}
		free (cptr);
	}
	cprintf("</query>");
}
コード例 #6
0
ファイル: xmpp_presence.c プロジェクト: henri14/citadel
/*
 * Stupidly, XMPP does not specify a way to tell the client to flush its client-side roster
 * and prepare to receive a new one.  So instead we remember every buddy we've ever told the
 * client about, and push delete operations out at the beginning of a session.
 * 
 * We omit any users who happen to be online right now, but we still keep them in the mortuary,
 * which needs to be maintained as a list of every buddy the user has ever seen.  We don't know
 * when they're connecting from the same client and when they're connecting from a different client,
 * so we have no guarantee of what is in the client side roster at connect time.
 */
void xmpp_delete_old_buddies_who_no_longer_exist_from_the_client_roster(void)
{
	long len;
	void *Value;
	const char *Key;
	struct CitContext *cptr;
	int nContexts, i;
	int online_now = 0;
	HashList *mortuary = xmpp_fetch_mortuary();
	HashPos *HashPos = GetNewHashPos(mortuary, 0);

	/* we need to omit anyone who is currently online */
	cptr = CtdlGetContextArray(&nContexts);

	/* go through the list of users in the mortuary... */
	while (GetNextHashPos(mortuary, HashPos, &len, &Key, &Value) != 0)
	{

		online_now = 0;
		if (cptr) for (i=0; i<nContexts; i++) {
			if (xmpp_is_visible(&cptr[i], CC)) {
				if (!strcasecmp(cptr[i].cs_inet_email, (char *)Value)) {
					online_now = 1;
				}
			}
		}

		if (!online_now) {
			xmpp_destroy_buddy((char *)Value, 1);	/* aggressive presence update */
		}

	}
	DeleteHashPos(&HashPos);
	DeleteHash(&mortuary);
	free(cptr);
}
コード例 #7
0
ファイル: xmpp_presence.c プロジェクト: henri14/citadel
/*
 * Upon logout we make an attempt to delete the whole roster, in order to
 * try to keep "ghost" buddies from remaining in the client-side roster.
 *
 * Since the client is probably not still alive, also remember the current
 * roster for next time so we can delete dead buddies then.
 */
void xmpp_massacre_roster(void)
{
	struct CitContext *cptr;
	int nContexts, i;
	HashList *mortuary = xmpp_fetch_mortuary();

	cptr = CtdlGetContextArray(&nContexts);
	if (cptr) {
		for (i=0; i<nContexts; i++) {
			if (xmpp_is_visible(&cptr[i], CC)) {
				if (mortuary) {
					char *buddy = strdup(cptr[i].cs_inet_email);
					Put(mortuary, buddy, strlen(buddy), buddy, NULL);
				}
			}
		}
		free (cptr);
	}

	if (mortuary) {
		xmpp_store_mortuary(mortuary);
		DeleteHash(&mortuary);
	}
}
コード例 #8
0
ファイル: serv_rwho.c プロジェクト: henri14/citadel
/*
 * display who's online
 */
void cmd_rwho(char *argbuf) {
	struct CitContext *nptr;
	int nContexts, i;
	int spoofed = 0;
	int user_spoofed = 0;
	int room_spoofed = 0;
	int host_spoofed = 0;
	int aide;
	char un[40];
	char real_room[ROOMNAMELEN], room[ROOMNAMELEN];
	char host[64], flags[5];
	
	/* So that we don't keep the context list locked for a long time
	 * we create a copy of it first
	 */
	nptr = CtdlGetContextArray(&nContexts) ;
	if (!nptr)
	{
		/* Couldn't malloc so we have to bail but stick to the protocol */
		cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress() );
		cprintf("000\n");
		return;
	}
	
	aide = ( (CC->user.axlevel >= AxAideU) || (CC->internal_pgm) ) ;
	cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress() );
	
	for (i=0; i<nContexts; i++) 
	{
		flags[0] = '\0';
		spoofed = 0;
		user_spoofed = 0;
		room_spoofed = 0;
		host_spoofed = 0;
		
		if (!aide && nptr[i].state == CON_SYS)
			continue;

		if (!aide && nptr[i].kill_me != 0)
			continue;

		if (nptr[i].cs_flags & CS_POSTING)
		   strcat(flags, "*");
		else
		   strcat(flags, ".");
		   
		if (nptr[i].fake_username[0])
		{
		   strcpy(un, nptr[i].fake_username);
		   spoofed = 1;
		   user_spoofed = 1;
		}
		else
		   strcpy(un, nptr[i].curr_user);
		   
		if (nptr[i].fake_hostname[0])
		{
		   strcpy(host, nptr[i].fake_hostname);
		   spoofed = 1;
		   host_spoofed = 1;
		}
		else
		   strcpy(host, nptr[i].cs_host);

		GenerateRoomDisplay(real_room, &nptr[i], CC);

		if (nptr[i].fake_roomname[0]) {
			strcpy(room, nptr[i].fake_roomname);
			spoofed = 1;
			room_spoofed = 1;
		}
		else {
			strcpy(room, real_room);
		}
		
                if ((aide) && (spoofed)) {
                	strcat(flags, "+");
		}
		
		if ((nptr[i].cs_flags & CS_STEALTH) && (aide)) {
			strcat(flags, "-");
		}
		
		if (((nptr[i].cs_flags&CS_STEALTH)==0) || (aide))
		{
			cprintf("%d|%s|%s|%s|%s|%ld|%s|%s|",
				nptr[i].cs_pid, un, room,
				host, nptr[i].cs_clientname,
				(long)(nptr[i].lastidle),
				nptr[i].lastcmdname, flags
			);

			if ((user_spoofed) && (aide)) {
				cprintf("%s|", nptr[i].curr_user);
			}
			else {
				cprintf("|");
			}
	
			if ((room_spoofed) && (aide)) {
				cprintf("%s|", real_room);
			}
			else {
				cprintf("|");
			}
	
			if ((host_spoofed) && (aide)) {
				cprintf("%s|", nptr[i].cs_host);
			}
			else {
				cprintf("|");
			}
	
			cprintf("%d\n", nptr[i].logged_in);
		}
	}
	
	/* release out copy of the context list */
	free(nptr);

	/* Now it's magic time.  Before we finish, call any EVT_RWHO hooks
	 * so that external paging modules such as serv_icq can add more
	 * content to the Wholist.
	 */
	PerformSessionHooks(EVT_RWHO);
	cprintf("000\n");
}
コード例 #9
0
ファイル: serv_instmsg.c プロジェクト: henri14/citadel
/*
 * Locate instant message conversations which have gone idle
 * (or, if the server is shutting down, locate *all* conversations)
 * and flush them to disk (in the participants' log rooms, etc.)
 */
void flush_conversations_to_disk(time_t if_older_than) {

	struct imlog *flush_these = NULL;
	struct imlog *dont_flush_these = NULL;
	struct imlog *imptr = NULL;
	struct CitContext *nptr;
	int nContexts, i;

	nptr = CtdlGetContextArray(&nContexts) ;	/* Make a copy of the current wholist */

	begin_critical_section(S_IM_LOGS);
	while (imlist)
	{
		imptr = imlist;
		imlist = imlist->next;

		/* For a two party conversation, if one party has logged out, force flush. */
		if (nptr) {
			int user0_is_still_online = 0;
			int user1_is_still_online = 0;
			for (i=0; i<nContexts; i++)  {
				if (nptr[i].user.usernum == imptr->usernums[0]) ++user0_is_still_online;
				if (nptr[i].user.usernum == imptr->usernums[1]) ++user1_is_still_online;
			}
			if (imptr->usernums[0] != imptr->usernums[1]) {		/* two party conversation */
				if ((!user0_is_still_online) || (!user1_is_still_online)) {
					imptr->lastmsg = 0L;	/* force flush */
				}
			}
			else {		/* one party conversation (yes, people do IM themselves) */
				if (!user0_is_still_online) {
					imptr->lastmsg = 0L;	/* force flush */
				}
			}
		}

		/* Now test this conversation to see if it qualifies for flushing. */
		if ((time(NULL) - imptr->lastmsg) > if_older_than)
		{
			/* This conversation qualifies.  Move it to the list of ones to flush. */
			imptr->next = flush_these;
			flush_these = imptr;
		}
		else  {
			/* Move it to the list of ones not to flush. */
			imptr->next = dont_flush_these;
			dont_flush_these = imptr;
		}
	}
	imlist = dont_flush_these;
	end_critical_section(S_IM_LOGS);
	free(nptr);

	/* We are now outside of the critical section, and we are the only thread holding a
	 * pointer to a linked list of conversations to be flushed to disk.
	 */
	while (flush_these) {

		flush_individual_conversation(flush_these);	/* This will free the string buffer */
		imptr = flush_these;
		flush_these = flush_these->next;
		free(imptr);
	}
}