<commit_before>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * 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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/* Arena and Honor Point Calculation System
 *    Copyright (c) 2007 Burlex
 */

#include "StdAfx.h"
#ifdef WIN32
static HANDLE m_abortEvent = INVALID_HANDLE_VALUE;
#else
static pthread_cond_t abortcond;
static pthread_mutex_t abortmutex;
#endif

DayWatcherThread::DayWatcherThread()
{
	m_running = true;
	m_dirty = false;
}

DayWatcherThread::~DayWatcherThread()
{

}

void DayWatcherThread::terminate()
{
	m_running = false;
#ifdef WIN32
	SetEvent(m_abortEvent);
#else
	pthread_cond_signal(&abortcond);
#endif
}

void DayWatcherThread::dupe_tm_pointer(tm * returnvalue, tm * mypointer)
{
	memcpy(mypointer, returnvalue, sizeof(tm));
}

void DayWatcherThread::update_settings()
{
	CharacterDatabase.Execute("REPLACE INTO server_settings VALUES(\"last_arena_update_time\", %u)", last_arena_time);
	CharacterDatabase.Execute("REPLACE INTO server_settings VALUES(\"last_daily_update_time\", %u)", last_daily_time);
}

void DayWatcherThread::load_settings()
{
	string arena_timeout = Config.MainConfig.GetStringDefault("Periods", "ArenaUpdate", "weekly");
	arena_period = get_timeout_from_string(arena_timeout.c_str(), WEEKLY);

	QueryResult * result = CharacterDatabase.Query("SELECT setting_value FROM server_settings WHERE setting_id = \"last_arena_update_time\"");
	if(result)
	{
		last_arena_time = result->Fetch()[0].GetUInt32();
		delete result;
	}
	else
	{
		Log.Notice("DayWatcherThread", "Initializing Arena Updates to zero.");
		last_arena_time = 0;
	}

	string daily_timeout = Config.MainConfig.GetStringDefault("Periods", "DailyUpdate", "daily");
	daily_period = get_timeout_from_string(daily_timeout.c_str(), DAILY);

	QueryResult * result2 = CharacterDatabase.Query("SELECT setting_value FROM server_settings WHERE setting_id = \"last_daily_update_time\"");
	if(result2)
	{
		last_daily_time = result2->Fetch()[0].GetUInt32();
		delete result2;
	}
	else
	{
		Log.Notice("DayWatcherThread", "Initializing Daily Updates to zero.");
		last_daily_time = 0;
	}
}

void DayWatcherThread::set_tm_pointers()
{
	dupe_tm_pointer(localtime(&last_arena_time), &local_last_arena_time);
	dupe_tm_pointer(localtime(&last_daily_time), &local_last_daily_time);
}

uint32 DayWatcherThread::get_timeout_from_string(const char * string, uint32 def)
{
	if(!stricmp(string, "weekly"))
		return WEEKLY;
	else if(!stricmp(string, "monthly"))
		return MONTHLY;
	else if(!stricmp(string, "daily"))
		return DAILY;
	else if(!stricmp(string, "hourly"))
		return HOURLY;
	else
		return def;
}

bool DayWatcherThread::has_timeout_expired(tm * now_time, tm * last_time, uint32 timeoutval)
{
	switch(timeoutval)
	{
	case WEEKLY:
		{
			if( (now_time->tm_mon != last_time->tm_mon) )
				return true;

			return ( (now_time->tm_mday / 7) != (last_time->tm_mday / 7) );
		}

	case MONTHLY:
		return (now_time->tm_mon != last_time->tm_mon);

	case HOURLY:
		return ((now_time->tm_hour != last_time->tm_hour) || (now_time->tm_mday != last_time->tm_mday) || (now_time->tm_mon != last_time->tm_mon));

	case DAILY:
		return (now_time->tm_mday != last_time->tm_mday);
	}
	return false;
}

bool DayWatcherThread::run()
{
	Log.Notice("DayWatcherThread", "Started.");
	currenttime = UNIXTIME;
	dupe_tm_pointer(localtime(&currenttime), &local_currenttime);
	load_settings();
	set_tm_pointers();
	m_busy = false;
#ifdef WIN32
	m_abortEvent = CreateEvent(NULL, NULL, FALSE, NULL);
#else
	struct timeval now;
	struct timespec tv;

	pthread_mutex_init(&abortmutex,NULL);
	pthread_cond_init(&abortcond,NULL);
#endif

	while(ThreadState != THREADSTATE_TERMINATE)
	{
		m_busy=true;
		currenttime = UNIXTIME;
		dupe_tm_pointer(localtime(&currenttime), &local_currenttime);

		if(has_timeout_expired(&local_currenttime, &local_last_arena_time, arena_period))
			update_arena();

		if(has_timeout_expired(&local_currenttime, &local_last_daily_time, daily_period))
			update_daily();

		if(m_dirty)
			update_settings();

		m_busy=false;
		if(ThreadState == THREADSTATE_TERMINATE)
			break;

#ifdef WIN32
		if (m_abortEvent)
			WaitForSingleObject(m_abortEvent, 120000);
#else
		gettimeofday(&now, NULL);
		tv.tv_sec = now.tv_sec + 120;
		tv.tv_nsec = now.tv_usec * 1000;
		pthread_mutex_lock(&abortmutex);
		pthread_cond_timedwait(&abortcond, &abortmutex, &tv);
		pthread_mutex_unlock(&abortmutex);
#endif
		if(!m_running)
			break;
	}
#ifdef WIN32
	if (m_abortEvent)
		CloseHandle(m_abortEvent);
#else
	pthread_mutex_destroy(&abortmutex);
	pthread_cond_destroy(&abortcond);
#endif
	return true;
}

void DayWatcherThread::update_daily()
{
	Log.Notice("DayWatcherThread", "Running Daily Quest Reset...");
	CharacterDatabase.WaitExecute("UPDATE characters SET finisheddailies = ''");
	objmgr.ResetDailies();
	last_daily_time = UNIXTIME;
	dupe_tm_pointer(localtime(&last_daily_time), &local_last_daily_time);
	m_dirty = true;
}

void DayWatcherThread::update_arena()
{
	Log.Notice("DayWatcherThread", "Running Weekly Arena Point Maintenance...");
	QueryResult * result = CharacterDatabase.Query("SELECT guid, arenaPoints FROM characters");		/* this one is a little more intensive. */
	Player * plr;
	uint32 guid, arenapoints, orig_arenapoints;
	ArenaTeam * team;
	uint32 arenapointsPerTeam[3] = {0};
	double X, Y;
	if(result)
	{
		do
		{
			Field * f = result->Fetch();
			guid = f[0].GetUInt32();
			arenapoints = f[1].GetUInt32();
			orig_arenapoints = arenapoints;

			for(uint32 i = 0; i < 3; ++i)
				arenapointsPerTeam[i] = 0;

			/* are we in any arena teams? */
			for(uint32 i = 0; i < 3; ++i)			// 3 arena team types
			{
				team = objmgr.GetArenaTeamByGuid(guid, i);
				if(team)
				{
					ArenaTeamMember *member = team->GetMemberByGuid(guid);
					if(member == NULL || team->m_stat_gamesplayedweek < 10 || ((member->Played_ThisWeek * 100) / team->m_stat_gamesplayedweek < 30))
 						continue;

					/* we're in an arena team of this type! */
					/* Source: http://www.wowwiki.com/Arena_point */
					X = (double)team->m_stat_rating;
					if(X <= 510.0)	// "if X<=510"
						continue;		// no change
					else if(X > 510.0 && X <= 1500.0)		// "if 510 < X <= 1500"
					{
						Y = (0.22 * X) + 14.0;
					}
					else			// "if X > 1500"
					{
						// http://eu.wowarmory.com/arena-calculator.xml
						//              1511.26
						//   ---------------------------
						//                   -0.00412*X
						//    1+1639.28*2.71828

						double power = ((-0.00412) * X);
						//if(power < 1.0)
						//	power = 1.0;

						double divisor = pow(((double)(2.71828)), power);
						divisor *= 1639.28;
						divisor += 1.0;
						//if(divisor < 1.0)
						//	divisor = 1.0;

						Y = 1511.26 / divisor;
					}

					// 2v2 teams only earn 70% (Was 60% until 13th March 07) of the arena points, 3v3 teams get 80%, while 5v5 teams get 100% of the arena points.
					// 2v2 - 76%, 3v3 - 88% as of patch 2.2
					if(team->m_type == ARENA_TEAM_TYPE_2V2)
					{
						Y *= 0.76;
						Y *= sWorld.getRate(RATE_ARENAPOINTMULTIPLIER2X);
					}
					else if(team->m_type == ARENA_TEAM_TYPE_3V3)
					{
						Y *= 0.88;
						Y *= sWorld.getRate(RATE_ARENAPOINTMULTIPLIER3X);
					}
					else
					{
						Y *= sWorld.getRate(RATE_ARENAPOINTMULTIPLIER5X);
					}

					if(Y > 1.0)
						arenapointsPerTeam[i] += long2int32(double(ceil(Y)));
				}
			}

			arenapointsPerTeam[0] = (uint32)max(arenapointsPerTeam[0],arenapointsPerTeam[1]);
			arenapoints += (uint32)max(arenapointsPerTeam[0],arenapointsPerTeam[2]);
			if (arenapoints > 5000) arenapoints = 5000;

			if(orig_arenapoints != arenapoints)
			{
				plr = objmgr.GetPlayer(guid);
				if(plr)
				{
					plr->m_arenaPoints = arenapoints;

					/* update visible fields (must be done through an event because of no uint lock */
					sEventMgr.AddEvent(plr, &Player::RecalculateHonor, EVENT_PLAYER_UPDATE, 100, 1, 0);

					/* send a little message :> */
					sChatHandler.SystemMessage(plr->GetSession(), "Your arena points have been updated! Check your PvP tab!");
				}

				/* update in sql */
				CharacterDatabase.Execute("UPDATE characters SET arenaPoints = %u WHERE guid = %u", arenapoints, guid);
			}
		}while(result->NextRow());
		delete result;
	}

	objmgr.UpdateArenaTeamWeekly();

	//===========================================================================
	last_arena_time = UNIXTIME;
	dupe_tm_pointer(localtime(&last_arena_time), &local_last_arena_time);
	m_dirty = true;
}

<commit_msg>* fixed bug where weekly scheduled tasks (such as Arena points recalculation) would also execute on 1st day of month<commit_after>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * 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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/* Arena and Honor Point Calculation System
 *    Copyright (c) 2007 Burlex
 */

#include "StdAfx.h"
#ifdef WIN32
static HANDLE m_abortEvent = INVALID_HANDLE_VALUE;
#else
static pthread_cond_t abortcond;
static pthread_mutex_t abortmutex;
#endif

DayWatcherThread::DayWatcherThread()
{
	m_running = true;
	m_dirty = false;
}

DayWatcherThread::~DayWatcherThread()
{

}

void DayWatcherThread::terminate()
{
	m_running = false;
#ifdef WIN32
	SetEvent(m_abortEvent);
#else
	pthread_cond_signal(&abortcond);
#endif
}

void DayWatcherThread::dupe_tm_pointer(tm * returnvalue, tm * mypointer)
{
	memcpy(mypointer, returnvalue, sizeof(tm));
}

void DayWatcherThread::update_settings()
{
	CharacterDatabase.Execute("REPLACE INTO server_settings VALUES(\"last_arena_update_time\", %u)", last_arena_time);
	CharacterDatabase.Execute("REPLACE INTO server_settings VALUES(\"last_daily_update_time\", %u)", last_daily_time);
}

void DayWatcherThread::load_settings()
{
	string arena_timeout = Config.MainConfig.GetStringDefault("Periods", "ArenaUpdate", "weekly");
	arena_period = get_timeout_from_string(arena_timeout.c_str(), WEEKLY);

	QueryResult * result = CharacterDatabase.Query("SELECT setting_value FROM server_settings WHERE setting_id = \"last_arena_update_time\"");
	if(result)
	{
		last_arena_time = result->Fetch()[0].GetUInt32();
		delete result;
	}
	else
	{
		Log.Notice("DayWatcherThread", "Initializing Arena Updates to zero.");
		last_arena_time = 0;
	}

	string daily_timeout = Config.MainConfig.GetStringDefault("Periods", "DailyUpdate", "daily");
	daily_period = get_timeout_from_string(daily_timeout.c_str(), DAILY);

	QueryResult * result2 = CharacterDatabase.Query("SELECT setting_value FROM server_settings WHERE setting_id = \"last_daily_update_time\"");
	if(result2)
	{
		last_daily_time = result2->Fetch()[0].GetUInt32();
		delete result2;
	}
	else
	{
		Log.Notice("DayWatcherThread", "Initializing Daily Updates to zero.");
		last_daily_time = 0;
	}
}

void DayWatcherThread::set_tm_pointers()
{
	dupe_tm_pointer(localtime(&last_arena_time), &local_last_arena_time);
	dupe_tm_pointer(localtime(&last_daily_time), &local_last_daily_time);
}

uint32 DayWatcherThread::get_timeout_from_string(const char * string, uint32 def)
{
	if(!stricmp(string, "weekly"))
		return WEEKLY;
	else if(!stricmp(string, "monthly"))
		return MONTHLY;
	else if(!stricmp(string, "daily"))
		return DAILY;
	else if(!stricmp(string, "hourly"))
		return HOURLY;
	else
		return def;
}

bool DayWatcherThread::has_timeout_expired(tm * now_time, tm * last_time, uint32 timeoutval)
{
	switch(timeoutval)
	{
	case WEEKLY:
		{
			return ( abs( now_time->tm_yday - last_time->tm_yday ) >= 7 );
		}

	case MONTHLY:
		return (now_time->tm_mon != last_time->tm_mon);

	case HOURLY:
		return ((now_time->tm_hour != last_time->tm_hour) || (now_time->tm_mday != last_time->tm_mday) || (now_time->tm_mon != last_time->tm_mon));

	case DAILY:
		return (now_time->tm_mday != last_time->tm_mday);
	}
	return false;
}

bool DayWatcherThread::run()
{
	Log.Notice("DayWatcherThread", "Started.");
	currenttime = UNIXTIME;
	dupe_tm_pointer(localtime(&currenttime), &local_currenttime);
	load_settings();
	set_tm_pointers();
	m_busy = false;
#ifdef WIN32
	m_abortEvent = CreateEvent(NULL, NULL, FALSE, NULL);
#else
	struct timeval now;
	struct timespec tv;

	pthread_mutex_init(&abortmutex,NULL);
	pthread_cond_init(&abortcond,NULL);
#endif

	while(ThreadState != THREADSTATE_TERMINATE)
	{
		m_busy=true;
		currenttime = UNIXTIME;
		dupe_tm_pointer(localtime(&currenttime), &local_currenttime);

		if(has_timeout_expired(&local_currenttime, &local_last_arena_time, arena_period))
			update_arena();

		if(has_timeout_expired(&local_currenttime, &local_last_daily_time, daily_period))
			update_daily();

		if(m_dirty)
			update_settings();

		m_busy=false;
		if(ThreadState == THREADSTATE_TERMINATE)
			break;

#ifdef WIN32
		if (m_abortEvent)
			WaitForSingleObject(m_abortEvent, 120000);
#else
		gettimeofday(&now, NULL);
		tv.tv_sec = now.tv_sec + 120;
		tv.tv_nsec = now.tv_usec * 1000;
		pthread_mutex_lock(&abortmutex);
		pthread_cond_timedwait(&abortcond, &abortmutex, &tv);
		pthread_mutex_unlock(&abortmutex);
#endif
		if(!m_running)
			break;
	}
#ifdef WIN32
	if (m_abortEvent)
		CloseHandle(m_abortEvent);
#else
	pthread_mutex_destroy(&abortmutex);
	pthread_cond_destroy(&abortcond);
#endif
	return true;
}

void DayWatcherThread::update_daily()
{
	Log.Notice("DayWatcherThread", "Running Daily Quest Reset...");
	CharacterDatabase.WaitExecute("UPDATE characters SET finisheddailies = ''");
	objmgr.ResetDailies();
	last_daily_time = UNIXTIME;
	dupe_tm_pointer(localtime(&last_daily_time), &local_last_daily_time);
	m_dirty = true;
}

void DayWatcherThread::update_arena()
{
	Log.Notice("DayWatcherThread", "Running Weekly Arena Point Maintenance...");
	QueryResult * result = CharacterDatabase.Query("SELECT guid, arenaPoints FROM characters");		/* this one is a little more intensive. */
	Player * plr;
	uint32 guid, arenapoints, orig_arenapoints;
	ArenaTeam * team;
	uint32 arenapointsPerTeam[3] = {0};
	double X, Y;
	if(result)
	{
		do
		{
			Field * f = result->Fetch();
			guid = f[0].GetUInt32();
			arenapoints = f[1].GetUInt32();
			orig_arenapoints = arenapoints;

			for(uint32 i = 0; i < 3; ++i)
				arenapointsPerTeam[i] = 0;

			/* are we in any arena teams? */
			for(uint32 i = 0; i < 3; ++i)			// 3 arena team types
			{
				team = objmgr.GetArenaTeamByGuid(guid, i);
				if(team)
				{
					ArenaTeamMember *member = team->GetMemberByGuid(guid);
					if(member == NULL || team->m_stat_gamesplayedweek < 10 || ((member->Played_ThisWeek * 100) / team->m_stat_gamesplayedweek < 30))
 						continue;

					/* we're in an arena team of this type! */
					/* Source: http://www.wowwiki.com/Arena_point */
					X = (double)team->m_stat_rating;
					if(X <= 510.0)	// "if X<=510"
						continue;		// no change
					else if(X > 510.0 && X <= 1500.0)		// "if 510 < X <= 1500"
					{
						Y = (0.22 * X) + 14.0;
					}
					else			// "if X > 1500"
					{
						// http://eu.wowarmory.com/arena-calculator.xml
						//              1511.26
						//   ---------------------------
						//                   -0.00412*X
						//    1+1639.28*2.71828

						double power = ((-0.00412) * X);
						//if(power < 1.0)
						//	power = 1.0;

						double divisor = pow(((double)(2.71828)), power);
						divisor *= 1639.28;
						divisor += 1.0;
						//if(divisor < 1.0)
						//	divisor = 1.0;

						Y = 1511.26 / divisor;
					}

					// 2v2 teams only earn 70% (Was 60% until 13th March 07) of the arena points, 3v3 teams get 80%, while 5v5 teams get 100% of the arena points.
					// 2v2 - 76%, 3v3 - 88% as of patch 2.2
					if(team->m_type == ARENA_TEAM_TYPE_2V2)
					{
						Y *= 0.76;
						Y *= sWorld.getRate(RATE_ARENAPOINTMULTIPLIER2X);
					}
					else if(team->m_type == ARENA_TEAM_TYPE_3V3)
					{
						Y *= 0.88;
						Y *= sWorld.getRate(RATE_ARENAPOINTMULTIPLIER3X);
					}
					else
					{
						Y *= sWorld.getRate(RATE_ARENAPOINTMULTIPLIER5X);
					}

					if(Y > 1.0)
						arenapointsPerTeam[i] += long2int32(double(ceil(Y)));
				}
			}

			arenapointsPerTeam[0] = (uint32)max(arenapointsPerTeam[0],arenapointsPerTeam[1]);
			arenapoints += (uint32)max(arenapointsPerTeam[0],arenapointsPerTeam[2]);
			if (arenapoints > 5000) arenapoints = 5000;

			if(orig_arenapoints != arenapoints)
			{
				plr = objmgr.GetPlayer(guid);
				if(plr)
				{
					plr->m_arenaPoints = arenapoints;

					/* update visible fields (must be done through an event because of no uint lock */
					sEventMgr.AddEvent(plr, &Player::RecalculateHonor, EVENT_PLAYER_UPDATE, 100, 1, 0);

					/* send a little message :> */
					sChatHandler.SystemMessage(plr->GetSession(), "Your arena points have been updated! Check your PvP tab!");
				}

				/* update in sql */
				CharacterDatabase.Execute("UPDATE characters SET arenaPoints = %u WHERE guid = %u", arenapoints, guid);
			}
		}while(result->NextRow());
		delete result;
	}

	objmgr.UpdateArenaTeamWeekly();

	//===========================================================================
	last_arena_time = UNIXTIME;
	dupe_tm_pointer(localtime(&last_arena_time), &local_last_arena_time);
	m_dirty = true;
}

<|endoftext|>


<commit_before>//
//  IMAPIdleOperation.cc
//  mailcore2
//
//  Created by DINH Viêt Hoà on 1/12/13.
//  Copyright (c) 2013 MailCore. All rights reserved.
//

#include "MCIMAPIdleOperation.h"

#include "MCIMAPSession.h"
#include "MCIMAPAsyncConnection.h"

using namespace mailcore;

IMAPIdleOperation::IMAPIdleOperation()
{
    mLastKnownUid = 0;
    mSetupSuccess = false;
    pthread_mutex_init(&mLock, NULL);
}

IMAPIdleOperation::~IMAPIdleOperation()
{
    pthread_mutex_destroy(&mLock);
}

void IMAPIdleOperation::setLastKnownUID(uint32_t uid)
{
    mLastKnownUid = uid;
}

uint32_t IMAPIdleOperation::lastKnownUID()
{
    return mLastKnownUid;
}

void IMAPIdleOperation::prepare()
{
    mSetupSuccess = session()->session()->setupIdle();
}

void IMAPIdleOperation::unprepare()
{
    if (mSetupSuccess) {
        session()->session()->unsetupIdle();
    }
}

void IMAPIdleOperation::main()
{
    pthread_mutex_lock(&mLock);
    bool interrupted = mInterrupted;
    pthread_mutex_unlock(&mLock);
    if (interrupted) {
        return;
    }

    ErrorCode error;
    session()->session()->selectIfNeeded(folder(), &error);
    if (error != ErrorNone) {
        setError(error);
        return;
    }

    performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::prepare, NULL, true);

    if (!mSetupSuccess) {
        return;
    }

    session()->session()->idle(folder(), mLastKnownUid, &error);
    setError(error);

    performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::unprepare, NULL, true);
}

void IMAPIdleOperation::interruptIdle()
{
    pthread_mutex_lock(&mLock);
    mInterrupted = true;
    pthread_mutex_unlock(&mLock);
    if (mSetupSuccess) {
        session()->session()->interruptIdle();
    }
}

<commit_msg>Initial value for interrupted state of IDLE operation<commit_after>//
//  IMAPIdleOperation.cc
//  mailcore2
//
//  Created by DINH Viêt Hoà on 1/12/13.
//  Copyright (c) 2013 MailCore. All rights reserved.
//

#include "MCIMAPIdleOperation.h"

#include "MCIMAPSession.h"
#include "MCIMAPAsyncConnection.h"

using namespace mailcore;

IMAPIdleOperation::IMAPIdleOperation()
{
    mLastKnownUid = 0;
    mSetupSuccess = false;
    mInterrupted = false;
    pthread_mutex_init(&mLock, NULL);
}

IMAPIdleOperation::~IMAPIdleOperation()
{
    pthread_mutex_destroy(&mLock);
}

void IMAPIdleOperation::setLastKnownUID(uint32_t uid)
{
    mLastKnownUid = uid;
}

uint32_t IMAPIdleOperation::lastKnownUID()
{
    return mLastKnownUid;
}

void IMAPIdleOperation::prepare()
{
    mSetupSuccess = session()->session()->setupIdle();
}

void IMAPIdleOperation::unprepare()
{
    if (mSetupSuccess) {
        session()->session()->unsetupIdle();
    }
}

void IMAPIdleOperation::main()
{
    pthread_mutex_lock(&mLock);
    bool interrupted = mInterrupted;
    pthread_mutex_unlock(&mLock);
    if (interrupted) {
        return;
    }

    ErrorCode error;
    session()->session()->selectIfNeeded(folder(), &error);
    if (error != ErrorNone) {
        setError(error);
        return;
    }

    performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::prepare, NULL, true);

    if (!mSetupSuccess) {
        return;
    }

    session()->session()->idle(folder(), mLastKnownUid, &error);
    setError(error);

    performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::unprepare, NULL, true);
}

void IMAPIdleOperation::interruptIdle()
{
    pthread_mutex_lock(&mLock);
    mInterrupted = true;
    pthread_mutex_unlock(&mLock);
    if (mSetupSuccess) {
        session()->session()->interruptIdle();
    }
}

<|endoftext|>


<commit_before>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "src/rule.h"

#include <stdio.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <list>
#include <utility>

#include "operators/operator.h"
#include "actions/action.h"
#include "modsecurity/modsecurity.h"
#include "actions/transformations/none.h"
#include "variables/variations/exclusion.h"
#include "src/utils.h"

using ModSecurity::Variables::Variations::Exclusion;

namespace ModSecurity {

using operators::Operator;
using actions::Action;
using Variables::Variable;
using actions::transformations::None;

Rule::~Rule() {
    if (op != NULL) {
        delete op;
    }
    while (actions_conf.empty() == false) {
        auto *a = actions_conf.back();
        actions_conf.pop_back();
        delete a;
    }
    while (actions_runtime_pre.empty() == false) {
        auto *a = actions_runtime_pre.back();
        actions_runtime_pre.pop_back();
        delete a;
    }
    while (actions_runtime_pos.empty() == false) {
        auto *a = actions_runtime_pos.back();
        actions_runtime_pos.pop_back();
        delete a;
    }
    while (variables != NULL && variables->empty() == false) {
        auto *a = variables->back();
        variables->pop_back();
        delete a;
    }

    if (variables != NULL) {
        delete variables;
    }
}

Rule::Rule(std::string marker)
    : chained(false),
    chainedRule(NULL),
    variables(NULL),
    op(NULL),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(true),
    m_marker(marker),
    m_referenceCount(0) { };

Rule::Rule(Operator *_op,
        std::vector<Variable *> *_variables,
        std::vector<Action *> *actions)
    : chained(false),
    chainedRule(NULL),
    variables(_variables),
    op(_op),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(false),
    m_marker(""),
    m_referenceCount(0) {
    for (Action *a : *actions) {
        if (a->action_kind == Action::ConfigurationKind) {
            actions_conf.push_back(a);
            a->evaluate(this, NULL);
        } else if (a->action_kind == Action::RunTimeBeforeMatchAttemptKind) {
            actions_runtime_pre.push_back(a);
        } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) {
            actions_runtime_pos.push_back(a);
        } else {
            std::cout << "General failure, action: " << a->name;
            std::cout << " has an unknown type." << std::endl;
            delete a;
        }
    }
    /**
     * If phase is not entered, we assume phase 2. For historical reasons.
     *
     */
    if (phase == -1) {
        phase = ModSecurity::Phases::RequestHeadersPhase;
    }

    if (op == NULL) {
        m_unconditional = true;
    }

    delete actions;
}

bool Rule::evaluateActions(Assay *assay) {
    int none = 0;
    int transformations = 0;
    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        if (z != NULL) {
            none++;
        }
    }

    assay->debug(4, "Running unconditional rule.");

    if (none == 0) {
        /*
        for (Action *a : assay->m_rules->defaultActions[this->phase]) {
            if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                value = a->evaluate(value, assay);
                assay->debug(9, "(SecDefaultAction) T (" + \
                    std::to_string(transformations) + ") " + \
                    a->name + ": \"" + value +"\"");
                    transformations++;
            }
        }
        */
    }

    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        /*
        if (none == 0) {
            value = a->evaluate(value, assay);
            assay->debug(9, " T (" + \
                std::to_string(transformations) + ") " + \
                a->name + ": \"" + value +"\"");
                transformations++;
        }
        */
        if (z != NULL) {
            none--;
        }
    }

    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
            a->evaluate(this, assay);
        }
    }

    for (Action *a :
        this->actions_runtime_pos) {
        assay->debug(4, "Running action: " + a->action);
        a->evaluate(this, assay);
    }

    return true;
}

bool Rule::evaluate(Assay *assay) {
    bool ret = false;
    std::vector<Variable *> *variables = this->variables;

    if (m_secmarker == true) {
        return true;
    }
    if (m_unconditional == true) {
        return evaluateActions(assay);
    }

    assay->debug(4, "Executing operator \"" + this->op->op \
        + "\" with param \"" + this->op->param +  "\" against " \
        + Variable::to_s(variables) + ".");

    clock_t begin = clock();

    std::list<std::string> exclusions;
    for (int i = 0; i < variables->size(); i++) {
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);

        if (exl != NULL) {
            std::list<std::pair<std::string, std::string>> z =
                variable->evaluate(assay);
            for (auto &y : z) {
                exclusions.push_back(y.first);
            }
            exclusions.push_back(variable->name);
        }
    }

    for (int i = 0; i < variables->size(); i++) {
        int transformations = 0;
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);
        if (exl != NULL) {
            continue;
        }

        std::list<std::pair<std::string, std::string>> e =
            variable->evaluate(assay);

        for (auto &v : e) {
            if (std::find(exclusions.begin(), exclusions.end(),
                v.first) != exclusions.end()) {
                assay->debug(9, "Variable: " + v.first + " is part of the" +
                    " exclusion list, skipping...");
                continue;
            }
            std::string value = v.second;
            int none = 0;
            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (z != NULL) {
                    none++;
                }
            }

            // Check for transformations on the SecDefaultAction
            // Notice that first we make sure that won't be a t:none
            // on the target rule.
            if (none == 0) {
                for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                    if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                        value = a->evaluate(value, assay);
                        assay->debug(9, "(SecDefaultAction) T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                        transformations++;
                    }
                }
            }

            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (none == 0) {
                    value = a->evaluate(value, assay);
                    assay->debug(9, " T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                    transformations++;
                }
                if (z != NULL) {
                    none--;
                }
            }

            assay->debug(9, "Target value: \"" + limitTo(80, toHexIfNeeded(value)) + \
                "\" (Variable: " + v.first + ")");

            ret = this->op->evaluate(assay, value);

            clock_t end = clock();
            double elapsed_secs = static_cast<double>(end - begin) \
                / CLOCKS_PER_SEC;

            assay->debug(4, "Operator completed in " + \
                std::to_string(elapsed_secs) + " seconds");

            if (ret) {
                bool chainResult = false;
                assay->debug(4, "Rule returned 1.");

                if (this->chained && this->chainedRule == NULL) {
                    assay->debug(4, "Rule is marked as chained but there " \
                        "isn't a subsequent rule.");
                }
                if (this->chained && this->chainedRule != NULL) {
                    assay->debug(4, "Executing chained rule.");
                    if (assay->update_variable_first("MATCHED_VAR",
                        value) == false) {
                        assay->store_variable("MATCHED_VAR", value);
                    }
                    if (assay->update_variable_first("MATCHED_VAR_NAME",
                        v.first) == false) {
                        assay->store_variable("MATCHED_VAR_NAME", v.first);
                    }
                    assay->store_variable("MATCHED_VARS:" + v.first, value);
                    assay->store_variable("MATCHED_VARS_NAMES:" + v.first,
                        v.first);
                    chainResult = this->chainedRule->evaluate(assay);
                    assay->update_variable_first("MATCHED_VAR", "");
                    assay->delete_variable("MATCHED_VARS:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                }
                if (this->chained && chainResult == true || !this->chained) {
                    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
                            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
                            a->evaluate(this, assay);
                        }
                    }
                    for (Action *a :
                        this->actions_runtime_pos) {
                        assay->debug(4, "Running action: " + a->action);
                        a->evaluate(this, assay);
                    }
                }

            } else {
                assay->debug(4, "Rule returned 0.");
            }
        }
    }
    return ret;
}

}  // namespace ModSecurity
<commit_msg>Adds rule number to the debug logs and printing expaded variables<commit_after>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "src/rule.h"

#include <stdio.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <list>
#include <utility>

#include "operators/operator.h"
#include "actions/action.h"
#include "modsecurity/modsecurity.h"
#include "actions/transformations/none.h"
#include "variables/variations/exclusion.h"
#include "src/utils.h"
#include "src/macro_expansion.h"

using ModSecurity::Variables::Variations::Exclusion;

namespace ModSecurity {

using operators::Operator;
using actions::Action;
using Variables::Variable;
using actions::transformations::None;

Rule::~Rule() {
    if (op != NULL) {
        delete op;
    }
    while (actions_conf.empty() == false) {
        auto *a = actions_conf.back();
        actions_conf.pop_back();
        delete a;
    }
    while (actions_runtime_pre.empty() == false) {
        auto *a = actions_runtime_pre.back();
        actions_runtime_pre.pop_back();
        delete a;
    }
    while (actions_runtime_pos.empty() == false) {
        auto *a = actions_runtime_pos.back();
        actions_runtime_pos.pop_back();
        delete a;
    }
    while (variables != NULL && variables->empty() == false) {
        auto *a = variables->back();
        variables->pop_back();
        delete a;
    }

    if (variables != NULL) {
        delete variables;
    }
}

Rule::Rule(std::string marker)
    : chained(false),
    chainedRule(NULL),
    variables(NULL),
    op(NULL),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(true),
    m_marker(marker),
    m_referenceCount(0) { };

Rule::Rule(Operator *_op,
        std::vector<Variable *> *_variables,
        std::vector<Action *> *actions)
    : chained(false),
    chainedRule(NULL),
    variables(_variables),
    op(_op),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(false),
    m_marker(""),
    m_referenceCount(0) {
    for (Action *a : *actions) {
        if (a->action_kind == Action::ConfigurationKind) {
            actions_conf.push_back(a);
            a->evaluate(this, NULL);
        } else if (a->action_kind == Action::RunTimeBeforeMatchAttemptKind) {
            actions_runtime_pre.push_back(a);
        } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) {
            actions_runtime_pos.push_back(a);
        } else {
            std::cout << "General failure, action: " << a->name;
            std::cout << " has an unknown type." << std::endl;
            delete a;
        }
    }
    /**
     * If phase is not entered, we assume phase 2. For historical reasons.
     *
     */
    if (phase == -1) {
        phase = ModSecurity::Phases::RequestHeadersPhase;
    }

    if (op == NULL) {
        m_unconditional = true;
    }

    delete actions;
}

bool Rule::evaluateActions(Assay *assay) {
    int none = 0;
    int transformations = 0;
    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        if (z != NULL) {
            none++;
        }
    }

    assay->debug(4, "Running unconditional rule.");

    if (none == 0) {
        /*
        for (Action *a : assay->m_rules->defaultActions[this->phase]) {
            if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                value = a->evaluate(value, assay);
                assay->debug(9, "(SecDefaultAction) T (" + \
                    std::to_string(transformations) + ") " + \
                    a->name + ": \"" + value +"\"");
                    transformations++;
            }
        }
        */
    }

    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        /*
        if (none == 0) {
            value = a->evaluate(value, assay);
            assay->debug(9, " T (" + \
                std::to_string(transformations) + ") " + \
                a->name + ": \"" + value +"\"");
                transformations++;
        }
        */
        if (z != NULL) {
            none--;
        }
    }

    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
            a->evaluate(this, assay);
        }
    }

    for (Action *a :
        this->actions_runtime_pos) {
        assay->debug(4, "Running action: " + a->action);
        a->evaluate(this, assay);
    }

    return true;
}

bool Rule::evaluate(Assay *assay) {
    bool ret = false;
    std::vector<Variable *> *variables = this->variables;

    if (m_secmarker == true) {
        return true;
    }
    if (m_unconditional == true) {
        return evaluateActions(assay);
    }

    assay->debug(4, "(Rule: " + std::to_string(rule_id) \
        + ") Executing operator \"" + this->op->op \
        + "\" with param: " \
        + MacroExpansion::expandKeepOriginal(this->op->param, assay) \
        + ", against " \
        + Variable::to_s(variables) + ".");

    clock_t begin = clock();

    std::list<std::string> exclusions;
    for (int i = 0; i < variables->size(); i++) {
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);

        if (exl != NULL) {
            std::list<std::pair<std::string, std::string>> z =
                variable->evaluate(assay);
            for (auto &y : z) {
                exclusions.push_back(y.first);
            }
            exclusions.push_back(variable->name);
        }
    }

    for (int i = 0; i < variables->size(); i++) {
        int transformations = 0;
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);
        if (exl != NULL) {
            continue;
        }

        std::list<std::pair<std::string, std::string>> e =
            variable->evaluate(assay);

        for (auto &v : e) {
            if (std::find(exclusions.begin(), exclusions.end(),
                v.first) != exclusions.end()) {
                assay->debug(9, "Variable: " + v.first + " is part of the" +
                    " exclusion list, skipping...");
                continue;
            }
            std::string value = v.second;
            int none = 0;
            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (z != NULL) {
                    none++;
                }
            }

            // Check for transformations on the SecDefaultAction
            // Notice that first we make sure that won't be a t:none
            // on the target rule.
            if (none == 0) {
                for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                    if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                        value = a->evaluate(value, assay);
                        assay->debug(9, "(SecDefaultAction) T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                        transformations++;
                    }
                }
            }

            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (none == 0) {
                    value = a->evaluate(value, assay);
                    assay->debug(9, " T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                    transformations++;
                }
                if (z != NULL) {
                    none--;
                }
            }

            assay->debug(9, "Target value: \"" + limitTo(80, toHexIfNeeded(value)) + \
                "\" (Variable: " + v.first + ")");

            ret = this->op->evaluate(assay, value);

            clock_t end = clock();
            double elapsed_secs = static_cast<double>(end - begin) \
                / CLOCKS_PER_SEC;

            assay->debug(4, "Operator completed in " + \
                std::to_string(elapsed_secs) + " seconds");

            if (ret) {
                bool chainResult = false;
                assay->debug(4, "Rule returned 1.");

                if (this->chained && this->chainedRule == NULL) {
                    assay->debug(4, "Rule is marked as chained but there " \
                        "isn't a subsequent rule.");
                }
                if (this->chained && this->chainedRule != NULL) {
                    assay->debug(4, "Executing chained rule.");
                    if (assay->update_variable_first("MATCHED_VAR",
                        value) == false) {
                        assay->store_variable("MATCHED_VAR", value);
                    }
                    if (assay->update_variable_first("MATCHED_VAR_NAME",
                        v.first) == false) {
                        assay->store_variable("MATCHED_VAR_NAME", v.first);
                    }
                    assay->store_variable("MATCHED_VARS:" + v.first, value);
                    assay->store_variable("MATCHED_VARS_NAMES:" + v.first,
                        v.first);
                    chainResult = this->chainedRule->evaluate(assay);
                    assay->update_variable_first("MATCHED_VAR", "");
                    assay->delete_variable("MATCHED_VARS:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                }
                if (this->chained && chainResult == true || !this->chained) {
                    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
                            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
                            a->evaluate(this, assay);
                        }
                    }
                    for (Action *a :
                        this->actions_runtime_pos) {
                        assay->debug(4, "Running action: " + a->action);
                        a->evaluate(this, assay);
                    }
                }

            } else {
                assay->debug(4, "Rule returned 0.");
            }
        }
    }
    return ret;
}

}  // namespace ModSecurity
<|endoftext|>


<commit_before>#include "PosixFileSystem.hpp"
#include "../File.hpp"
#include "../InputStream.hpp"
#include "../OutputStream.hpp"
#include "../EmptyFile.hpp"
#include "../PartFile.hpp"
#include "../Exception.hpp"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>

BEGIN_INANITY_PLATFORM

class PosixFile : public File
{
private:
	void* data;
	size_t size;

public:
	PosixFile(void* data, size_t size)
	: data(data), size(size) {}

	~PosixFile()
	{
		munmap(data, size);
	}

	void* GetData() const
	{
		return data;
	}

	size_t GetSize() const
	{
		return size;
	}
};

class PosixInputStream : public InputStream
{
private:
	int fd;

public:
	PosixInputStream(int fd) : fd(fd) {}

	~PosixInputStream()
	{
		close(fd);
	}

	size_t Read(void* data, size_t size)
	{
		char* dataPtr = (char*)data;
		size_t resultSize = 0;
		while(size > 0)
		{
			ssize_t readSize = size;
			if(readSize > SSIZE_MAX)
				readSize = SSIZE_MAX;
			readSize = read(fd, dataPtr, readSize);
			if(readSize < 0)
				THROW("Disk read error");
			if(readSize == 0)
				break;
			resultSize += readSize;
			size -= readSize;
			dataPtr += readSize;
		}
		return resultSize;
	}

	size_t GetSize() const
	{
		struct stat st;
		if(fstat(fd, &st) != 0)
			THROW("Error getting size");
		return st.st_size;
	}
};

class PosixOutputStream : public OutputStream
{
private:
	int fd;

public:
	PosixOutputStream(int fd) : fd(fd) {}

	~PosixOutputStream()
	{
		close(fd);
	}

	void Write(const void* data, size_t size)
	{
		const char* dataPtr = (const char*)data;
		while(size > 0)
		{
			ssize_t written = write(fd, dataPtr, size);
			if(written < 0)
				THROW("Disk write error");
			size -= written;
			dataPtr += written;
		}
	}
};

PosixFileSystem::PosixFileSystem(const String& userFolderName)
{
	//если имя абсолютное
	if(userFolderName.length() >= 1 && userFolderName[0] == '/')
		folderName = userFolderName;
	//иначе относительное
	else
	{
		//получить полное имя текущего каталога
		char* currentDirectory = getcwd(0, 0);
		if(!currentDirectory)
			THROW("Can't get current directory");
		folderName = currentDirectory;
		free(currentDirectory);

		//прибавить к нему заданное имя каталога, и получить таким образом полный каталог
		if(userFolderName.length())
		{
			folderName += '/';
			folderName += userFolderName;
		}
	}
}

PosixFileSystem::PosixFileSystem()
{
	//создать абсолютную файловую систему, то есть ничего не делать;
	//folderName - пустая строка
}

String PosixFileSystem::GetFullName(String fileName) const
{
	if(folderName.length() && fileName.length() && fileName[0] == '/')
		fileName = fileName.substr(1);
	return folderName.length() ? (folderName + "/" + fileName) : fileName;
}

size_t PosixFileSystem::GetFileSize(const String& fileName)
{
	struct stat st;
	if(stat(fileName.c_str(), &st) != 0)
		THROW("Can't determine file size");

	return st.st_size;
}

ptr<File> PosixFileSystem::LoadPartOfFile(const String& fileName, long long mappingStart, size_t mappingSize)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(name.c_str(), O_RDONLY, 0);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());
		size_t size;
		if(mappingSize)
			size = mappingSize;
		else
		{
			struct stat st;
			if(fstat(fd, &st) < 0)
				THROW_SECONDARY("Can't get file size", Exception::SystemError());
			size = st.st_size;
		}
		if(!size)
			return NEW(EmptyFile());

		//получить размер страницы
		static size_t pageSize = 0;
		if(!pageSize)
			pageSize = getpagesize();

		//округлить начало проекции вниз на размер страницы
		size_t realMappingStart = mappingStart & ~(pageSize - 1);
		//вычислить реальный размер
		size_t realMappingSize = size + (size_t)(mappingStart - realMappingStart);
		//спроецировать файл с учетом этого сдвига
		void* data = mmap(0, realMappingSize, PROT_READ, MAP_PRIVATE, fd, realMappingStart);
		if(data == (caddr_t)-1)
			THROW_SECONDARY("Can't map file", Exception::SystemError());

		//если сдвиг был
		if(realMappingStart < (unsigned long long)mappingStart)
			//вернуть указатель на частичный файл, с учетом сдвига
			return NEW(PartFile(NEW(PosixFile(data, realMappingSize)), (char*)data + (size_t)(mappingStart - realMappingStart), size));
		//иначе сдвига не было, просто вернуть файл
		return NEW(PosixFile(data, size));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY("Can't load file \"" + fileName + "\" as \"" + name + "\"", exception);
	}
}

void PosixFileSystem::SaveFile(ptr<File> file, const String& fileName)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(fileName.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());

		const char* data = (const char*)file->GetData();
		size_t size = file->GetSize();

		while(size > 0)
		{
			ssize_t written = write(fd, data, size);
			if(written < 0)
			{
				ptr<Exception> exception = Exception::SystemError();
				close(fd);
				THROW_SECONDARY("Can't write file", exception);
			}
			size -= written;
			data += written;
		}
		close(fd);
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY(String("Can't save file \"") + fileName + "\" as \"" + name + "\"", exception);
	}
}

ptr<InputStream> PosixFileSystem::LoadStream(const String& fileName)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(name.c_str(), O_RDONLY, 0);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());
		return NEW(PosixInputStream(fd));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY(String("Can't load file \"") + fileName + "\" as \"" + name + "\" as stream", exception);
	}
}

ptr<OutputStream> PosixFileSystem::SaveStream(const String& fileName)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(fileName.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());
		return NEW(PosixOutputStream(fd));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY(String("Can't save file \"") + fileName + "\" as \"" + name + "\" as stream", exception);
	}
}

void PosixFileSystem::GetDirectoryEntries(const String& directoryName, std::vector<String>& entries) const
{
	String fullDirectoryName = GetFullName(directoryName);
	DIR* dir = opendir(fullDirectoryName.c_str());

	while(struct dirent* ent = readdir(dir))
	{
		if(errno)
		{
			ptr<Exception> exception = Exception::SystemError();
			closedir(dir);
			THROW_SECONDARY("Can't read dir", exception);
		}

		String fileTitle = ent->d_name;
		String fullFileName = fullDirectoryName + fileTitle;
		struct stat st;
		if(stat(fullFileName.c_str(), &st) < 0)
		{
			ptr<Exception> exception = Exception::SystemError();
			closedir(dir);
			THROW_SECONDARY("Can't stat file " + fullFileName, exception);
		}

		// если файл скрыт (или ненужен: . или ..)
		if(!fileTitle.length() || fileTitle[0] == '.')
			// пропустить его
			continue;

		// если это каталог
		if((st.st_mode & S_IFMT) == S_IFDIR)
			// добавить слеш в конец
			fileTitle += '/';
		// добавить файл/каталог в результат
		entries.push_back(directoryName + fileTitle);
	}

	closedir(dir);
}

ptr<File> PosixFileSystem::LoadFile(const String& fileName)
{
	return LoadPartOfFile(fileName, 0, 0);
}

ptr<PosixFileSystem> PosixFileSystem::GetNativeFileSystem()
{
	//этот метод сделан просто для лучшей понятности
	return NEW(PosixFileSystem());
}

void PosixFileSystem::GetFileNames(std::vector<String>& fileNames) const
{
	//только если файловая система не абсолютная
	if(folderName.length())
		GetAllDirectoryEntries("/", fileNames);
}

END_INANITY_PLATFORM
<commit_msg>fix PosixFileSystem.cpp build<commit_after>#include "PosixFileSystem.hpp"
#include "../File.hpp"
#include "../InputStream.hpp"
#include "../OutputStream.hpp"
#include "../EmptyFile.hpp"
#include "../PartFile.hpp"
#include "../Exception.hpp"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <climits>

BEGIN_INANITY_PLATFORM

class PosixFile : public File
{
private:
	void* data;
	size_t size;

public:
	PosixFile(void* data, size_t size)
	: data(data), size(size) {}

	~PosixFile()
	{
		munmap(data, size);
	}

	void* GetData() const
	{
		return data;
	}

	size_t GetSize() const
	{
		return size;
	}
};

class PosixInputStream : public InputStream
{
private:
	int fd;

public:
	PosixInputStream(int fd) : fd(fd) {}

	~PosixInputStream()
	{
		close(fd);
	}

	size_t Read(void* data, size_t size)
	{
		char* dataPtr = (char*)data;
		size_t resultSize = 0;
		while(size > 0)
		{
			ssize_t readSize = size;
			if(readSize > SSIZE_MAX)
				readSize = SSIZE_MAX;
			readSize = read(fd, dataPtr, readSize);
			if(readSize < 0)
				THROW("Disk read error");
			if(readSize == 0)
				break;
			resultSize += readSize;
			size -= readSize;
			dataPtr += readSize;
		}
		return resultSize;
	}

	size_t GetSize() const
	{
		struct stat st;
		if(fstat(fd, &st) != 0)
			THROW("Error getting size");
		return st.st_size;
	}
};

class PosixOutputStream : public OutputStream
{
private:
	int fd;

public:
	PosixOutputStream(int fd) : fd(fd) {}

	~PosixOutputStream()
	{
		close(fd);
	}

	void Write(const void* data, size_t size)
	{
		const char* dataPtr = (const char*)data;
		while(size > 0)
		{
			ssize_t written = write(fd, dataPtr, size);
			if(written < 0)
				THROW("Disk write error");
			size -= written;
			dataPtr += written;
		}
	}
};

PosixFileSystem::PosixFileSystem(const String& userFolderName)
{
	//если имя абсолютное
	if(userFolderName.length() >= 1 && userFolderName[0] == '/')
		folderName = userFolderName;
	//иначе относительное
	else
	{
		//получить полное имя текущего каталога
		char* currentDirectory = getcwd(0, 0);
		if(!currentDirectory)
			THROW("Can't get current directory");
		folderName = currentDirectory;
		free(currentDirectory);

		//прибавить к нему заданное имя каталога, и получить таким образом полный каталог
		if(userFolderName.length())
		{
			folderName += '/';
			folderName += userFolderName;
		}
	}
}

PosixFileSystem::PosixFileSystem()
{
	//создать абсолютную файловую систему, то есть ничего не делать;
	//folderName - пустая строка
}

String PosixFileSystem::GetFullName(String fileName) const
{
	if(folderName.length() && fileName.length() && fileName[0] == '/')
		fileName = fileName.substr(1);
	return folderName.length() ? (folderName + "/" + fileName) : fileName;
}

size_t PosixFileSystem::GetFileSize(const String& fileName)
{
	struct stat st;
	if(stat(fileName.c_str(), &st) != 0)
		THROW("Can't determine file size");

	return st.st_size;
}

ptr<File> PosixFileSystem::LoadPartOfFile(const String& fileName, long long mappingStart, size_t mappingSize)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(name.c_str(), O_RDONLY, 0);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());
		size_t size;
		if(mappingSize)
			size = mappingSize;
		else
		{
			struct stat st;
			if(fstat(fd, &st) < 0)
				THROW_SECONDARY("Can't get file size", Exception::SystemError());
			size = st.st_size;
		}
		if(!size)
			return NEW(EmptyFile());

		//получить размер страницы
		static size_t pageSize = 0;
		if(!pageSize)
			pageSize = getpagesize();

		//округлить начало проекции вниз на размер страницы
		size_t realMappingStart = mappingStart & ~(pageSize - 1);
		//вычислить реальный размер
		size_t realMappingSize = size + (size_t)(mappingStart - realMappingStart);
		//спроецировать файл с учетом этого сдвига
		void* data = mmap(0, realMappingSize, PROT_READ, MAP_PRIVATE, fd, realMappingStart);
		if(data == (caddr_t)-1)
			THROW_SECONDARY("Can't map file", Exception::SystemError());

		//если сдвиг был
		if(realMappingStart < (unsigned long long)mappingStart)
			//вернуть указатель на частичный файл, с учетом сдвига
			return NEW(PartFile(NEW(PosixFile(data, realMappingSize)), (char*)data + (size_t)(mappingStart - realMappingStart), size));
		//иначе сдвига не было, просто вернуть файл
		return NEW(PosixFile(data, size));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY("Can't load file \"" + fileName + "\" as \"" + name + "\"", exception);
	}
}

void PosixFileSystem::SaveFile(ptr<File> file, const String& fileName)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(fileName.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());

		const char* data = (const char*)file->GetData();
		size_t size = file->GetSize();

		while(size > 0)
		{
			ssize_t written = write(fd, data, size);
			if(written < 0)
			{
				ptr<Exception> exception = Exception::SystemError();
				close(fd);
				THROW_SECONDARY("Can't write file", exception);
			}
			size -= written;
			data += written;
		}
		close(fd);
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY(String("Can't save file \"") + fileName + "\" as \"" + name + "\"", exception);
	}
}

ptr<InputStream> PosixFileSystem::LoadStream(const String& fileName)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(name.c_str(), O_RDONLY, 0);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());
		return NEW(PosixInputStream(fd));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY(String("Can't load file \"") + fileName + "\" as \"" + name + "\" as stream", exception);
	}
}

ptr<OutputStream> PosixFileSystem::SaveStream(const String& fileName)
{
	String name = GetFullName(fileName);
	try
	{
		int fd = open(fileName.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
		if(fd < 0)
			THROW_SECONDARY("Can't open file", Exception::SystemError());
		return NEW(PosixOutputStream(fd));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY(String("Can't save file \"") + fileName + "\" as \"" + name + "\" as stream", exception);
	}
}

void PosixFileSystem::GetDirectoryEntries(const String& directoryName, std::vector<String>& entries) const
{
	String fullDirectoryName = GetFullName(directoryName);
	DIR* dir = opendir(fullDirectoryName.c_str());

	while(struct dirent* ent = readdir(dir))
	{
		if(errno)
		{
			ptr<Exception> exception = Exception::SystemError();
			closedir(dir);
			THROW_SECONDARY("Can't read dir", exception);
		}

		String fileTitle = ent->d_name;
		String fullFileName = fullDirectoryName + fileTitle;
		struct stat st;
		if(stat(fullFileName.c_str(), &st) < 0)
		{
			ptr<Exception> exception = Exception::SystemError();
			closedir(dir);
			THROW_SECONDARY("Can't stat file " + fullFileName, exception);
		}

		// если файл скрыт (или ненужен: . или ..)
		if(!fileTitle.length() || fileTitle[0] == '.')
			// пропустить его
			continue;

		// если это каталог
		if((st.st_mode & S_IFMT) == S_IFDIR)
			// добавить слеш в конец
			fileTitle += '/';
		// добавить файл/каталог в результат
		entries.push_back(directoryName + fileTitle);
	}

	closedir(dir);
}

ptr<File> PosixFileSystem::LoadFile(const String& fileName)
{
	return LoadPartOfFile(fileName, 0, 0);
}

ptr<PosixFileSystem> PosixFileSystem::GetNativeFileSystem()
{
	//этот метод сделан просто для лучшей понятности
	return NEW(PosixFileSystem());
}

void PosixFileSystem::GetFileNames(std::vector<String>& fileNames) const
{
	//только если файловая система не абсолютная
	if(folderName.length())
		GetAllDirectoryEntries("/", fileNames);
}

END_INANITY_PLATFORM
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commericial and non commericial applications,
 * as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osg/Switch>
#include <osgText/Text>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <iostream>

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
    arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");

    osgViewer::Viewer viewer(arguments);

    unsigned int helpType = 0;
    if ((helpType = arguments.readHelpType()))
    {
        arguments.getApplicationUsage()->write(std::cout, helpType);
        return 1;
    }

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

        std::string pathfile;
        char keyForAnimationPath = '5';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid())
            {
                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
                ++keyForAnimationPath;
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the thread model handler
    viewer.addEventHandler(new osgViewer::ThreadingHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));

    // add the record camera path handler
    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    // add the LOD Scale handler
    viewer.addEventHandler(new osgViewer::LODScaleHandler);

    // load the data
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
    if (!loadedModel)
    {
        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // optimize the scene graph, remove redundant nodes and state etc.
    osgUtil::Optimizer optimizer;
    optimizer.optimize(loadedModel.get());

    viewer.setSceneData( loadedModel.get() );

    viewer.realize();

    return viewer.run();

}
<commit_msg>Added camera final callback attachment code.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commericial and non commericial applications,
 * as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osg/Switch>
#include <osgText/Text>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <iostream>

class WindowCaptureCallback : public osg::Camera::DrawCallback
{
    public:

        WindowCaptureCallback()
        {
        }

        virtual void operator () (osg::RenderInfo& renderInfo) const
        {
            osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
            osg::notify(osg::NOTICE)<<"Capture screen image "<<gc<<std::endl;

        }
};

void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback)
{
    osgViewer::ViewerBase::Windows windows;
    viewer.getWindows(windows);
    for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
        itr != windows.end();
        ++itr)
    {
        osgViewer::GraphicsWindow* window = *itr;
        osg::GraphicsContext::Cameras& cameras = window->getCameras();
        osg::Camera* lastCamera = 0;
        for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
            cam_itr != cameras.end();
            ++cam_itr)
        {
            if (lastCamera)
            {
                if ((*cam_itr)->getRenderOrder() > (*cam_itr)->getRenderOrder())
                {
                    lastCamera = (*cam_itr);
                }
                if ((*cam_itr)->getRenderOrder() == lastCamera->getRenderOrder() &&
                    (*cam_itr)->getRenderOrderNum() >= lastCamera->getRenderOrderNum())
                {
                    lastCamera = (*cam_itr);
                }
            }
            else
            {
                lastCamera = *cam_itr;
            }
        }

        if (lastCamera)
        {
            osg::notify(osg::NOTICE)<<"Last camera "<<lastCamera<<std::endl;

            lastCamera->setFinalDrawCallback(callback);
        }
        else
        {
            osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
        }
    }
}

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
    arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");

    osgViewer::Viewer viewer(arguments);

    unsigned int helpType = 0;
    if ((helpType = arguments.readHelpType()))
    {
        arguments.getApplicationUsage()->write(std::cout, helpType);
        return 1;
    }

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

        std::string pathfile;
        char keyForAnimationPath = '5';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid())
            {
                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
                ++keyForAnimationPath;
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the thread model handler
    viewer.addEventHandler(new osgViewer::ThreadingHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));

    // add the record camera path handler
    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    // add the LOD Scale handler
    viewer.addEventHandler(new osgViewer::LODScaleHandler);

    // load the data
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
    if (!loadedModel)
    {
        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // optimize the scene graph, remove redundant nodes and state etc.
    osgUtil::Optimizer optimizer;
    optimizer.optimize(loadedModel.get());

    viewer.setSceneData( loadedModel.get() );

    viewer.realize();

    addCallbackToViewer(viewer, new WindowCaptureCallback);

    return viewer.run();

}
<|endoftext|>


<commit_before>#include <iostream>

#include <vw/Image/ImageMath.h>
#include <vw/Image/UtilityViews.h>
#include <vw/Plate/PlateFile.h>

#include <mvp/MVPWorkspace.h>
#include <mvp/MVPJob.h>

#include <boost/program_options.hpp>

using namespace vw;
using namespace vw::cartography;
using namespace vw::platefile;
using namespace std;
using namespace mvp;

namespace po = boost::program_options;

int main(int argc, char* argv[])
{
  po::options_description cmd_opts("Command line options");
  cmd_opts.add_options()
    ("help,h", "Print this message")
    ("silent", "Run without outputting status")
    ("config-file,f", po::value<string>()->default_value("mvp.conf"), "Specify a pipeline configuration file")
    ;

  po::options_description mvp_opts;
  mvp_opts.add(MVPWorkspace::program_options());

  po::options_description all_opts;
  all_opts.add(cmd_opts).add(mvp_opts);

  po::variables_map vm;
  store(po::command_line_parser(argc, argv).options(all_opts).run(), vm);

  if (vm.count("help")) {
    cout << all_opts << endl;
    return 0;
  }

  ifstream ifs(vm["config-file"].as<string>().c_str());
  if (ifs) {
    store(parse_config_file(ifs, mvp_opts), vm);
  }

  notify(vm);

  MVPWorkspace work(MVPWorkspace::construct_from_program_options(vm));

  /*
  const int MAX_OVERLAP = 4;

  work.add_image_pattern("synth.%d.pinhole", "synth.%d.tif", Vector2i(0, 3));

  int render_level = work.equal_resolution_level();
  BBox2i tile_bbox(work.tile_work_area(render_level));

  cout << tile_bbox << endl;
  cout << work.pixel_work_area(render_level) << endl;

  boost::shared_ptr<PlateFile> pf(new PlateFile("output.plate", "equi", "desc", plate_georef.tile_size(), "tif", VW_PIXEL_RGBA, VW_CHANNEL_UINT8));
  Transaction tid = pf->transaction_request("tdesc", -1);

  for (int col = tile_bbox.min().x(); col < tile_bbox.max().x(); col++) {
    for (int row = tile_bbox.min().y(); row < tile_bbox.max().y(); row++) {
      MVPJobRequest job = work.assemble_job(col, row, render_level);
      MVPTileProcessor proc(job);
      MVPTileResult result = proc.process();

      ImageView<PixelRGBA<uint8> > rendered_tile = pixel_cast_rescale<PixelRGB<uint8> >(result.post_height / MAX_OVERLAP);

      pf->write_request();
      pf->write_update(rendered_tile, col, row, render_level, tid);
      pf->sync();
      pf->write_complete();

      cout << "Wrote tile: " << col << " " << row << " " << render_level << endl;
    }
  }

  for (int level = 2; level < render_level; level++) {
    int divisor = render_level - level;
    for (int col = tile_bbox.min().x() >> divisor; col <= tile_bbox.max().x() >> divisor; col++) {
      for (int row = tile_bbox.min().y() >> divisor; row <= tile_bbox.max().y() >> divisor; row++) {
        ImageView<PixelRGBA<uint8> > rendered_tile(constant_view(PixelRGBA<uint8>(255, 0, 0, 255), plate_georef.tile_size(), plate_georef.tile_size()));
        pf->write_request();
        pf->write_update(rendered_tile, col, row, level, tid);
        pf->sync();
        pf->write_complete();
      }
    }
  }
  */
  return 0;
}
<commit_msg>updated mvp_solo to to MVPJob api and also take command args<commit_after>#include <iostream>

#include <vw/Image/ImageMath.h>
#include <vw/Image/UtilityViews.h>
#include <vw/Plate/PlateFile.h>

#include <mvp/MVPWorkspace.h>
#include <mvp/MVPJob.h>

#include <boost/program_options.hpp>

using namespace vw;
using namespace vw::cartography;
using namespace vw::platefile;
using namespace std;
using namespace mvp;

namespace po = boost::program_options;

int main(int argc, char* argv[])
{
  po::options_description cmd_opts("Command line options");
  cmd_opts.add_options()
    ("help,h", "Print this message")
    ("silent", "Run without outputting status")
    ("config-file,f", po::value<string>()->default_value("mvp.conf"), "Specify a pipeline configuration file")
    ;

  po::options_description mvp_opts;
  mvp_opts.add(MVPWorkspace::program_options());

  po::options_description all_opts;
  all_opts.add(cmd_opts).add(mvp_opts);

  po::variables_map vm;
  store(po::command_line_parser(argc, argv).options(all_opts).run(), vm);

  if (vm.count("help")) {
    cout << all_opts << endl;
    return 0;
  }

  ifstream ifs(vm["config-file"].as<string>().c_str());
  if (ifs) {
    store(parse_config_file(ifs, mvp_opts), vm);
  }

  notify(vm);

  MVPWorkspace work(MVPWorkspace::construct_from_program_options(vm));

  int render_level = work.equal_resolution_level();

  BBox2i tile_bbox(work.tile_work_area(render_level));

  boost::shared_ptr<PlateFile> pf(new PlateFile(work.result_platefile(),
                                                work.plate_georef().map_proj(),
                                                "desc",
                                                work.plate_georef().tile_size(),
                                                "tif", VW_PIXEL_RGBA, VW_CHANNEL_UINT8));

  Transaction tid = pf->transaction_request("tdesc", -1);

  const int MAX_OVERLAP = 4;

  int curr_tile = 0;
  int num_tiles = tile_bbox.width() * tile_bbox.height();
  for (int col = tile_bbox.min().x(); col < tile_bbox.max().x(); col++) {
    for (int row = tile_bbox.min().y(); row < tile_bbox.max().y(); row++) {
      ostringstream status;
      status << "Tile: " << ++curr_tile << "/" << num_tiles << " Location: [" << col << ", " << row << "] @" << render_level << " ";

      MVPTileResult result = mvpjob_process_tile(work.assemble_job(col, row, render_level), TerminalProgressCallback("mvp", status.str()));

      ImageView<PixelRGBA<uint8> > rendered_tile = pixel_cast_rescale<PixelRGB<uint8> >(result.post_height / MAX_OVERLAP);

      pf->write_request();
      pf->write_update(rendered_tile, col, row, render_level, tid);
      pf->sync();
      pf->write_complete();
    }
  }

  // This way that tile is easy to find...

  for (int level = 2; level < render_level; level++) {
    int divisor = render_level - level;
    for (int col = tile_bbox.min().x() >> divisor; col <= tile_bbox.max().x() >> divisor; col++) {
      for (int row = tile_bbox.min().y() >> divisor; row <= tile_bbox.max().y() >> divisor; row++) {
        ImageView<PixelRGBA<uint8> > rendered_tile(constant_view(PixelRGBA<uint8>(255, 0, 0, 255),
                                                                 work.plate_georef().tile_size(), work.plate_georef().tile_size()));
        pf->write_request();
        pf->write_update(rendered_tile, col, row, level, tid);
        pf->sync();
        pf->write_complete();
      }
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sys/sysctl.h>
#include <sys/socket.h>

#define PF_LIST_INET	1

#ifdef INET6
	#define PF_LIST_INET6	2
#endif

int main()
{
	get_sockets("net.inet6.tcp6.pcblist");
	get_sockets("net.inet6.udp6.pcblist");
	return 0;
}

void sysctl_sucker(int *name, u_int namelen, void **vp, size_t *szp)
{
	int rc;
	void *v;
	size_t sz;

	/* printf("name %p, namelen %u\n", name, namelen); */

	v = NULL;
	sz = 0;
	do {
		rc = prog_sysctl(&name[0], namelen, v, &sz, NULL, 0);
		if (rc == -1 && errno != ENOMEM)
			err(1, "sysctl");
		if (rc == -1 && v != NULL) {
			free(v);
			v = NULL;
		}
		if (v == NULL) {
			v = malloc(sz);
			rc = -1;
		}
		if (v == NULL)
			err(1, "malloc");
	} while (rc == -1);

	*vp = v;
	*szp = sz;
	/* printf("got %zu at %p\n", sz, v); */
}

void get_sockets(const char *mib)
{
	void *v;
	size_t sz;
	int rc, n, name[CTL_MAXNAME];
	u_int namelen;

	sz = CTL_MAXNAME;
	rc = sysctlnametomib(mib, &name[0], &sz);
	if (rc == -1) {
		if (errno == ENOENT)
			return;
		err(1, "sysctlnametomib: %s", mib);
	}
	namelen = sz;

	name[namelen++] = PCB_ALL;
	name[namelen++] = 0;		/* XXX all pids */
	name[namelen++] = sizeof(struct kinfo_pcb);
	name[namelen++] = INT_MAX;	/* all of them */

	sysctl_sucker(&name[0], namelen, &v, &sz);
	n = sz / sizeof(struct kinfo_pcb);
	socket_add_hash(v, n);
}<commit_msg>BSD dev...<commit_after>#include <iostream>
#include <sys/sysctl.h>
#include <sys/socket.h>

#define PF_LIST_INET	1

#ifdef INET6
	#define PF_LIST_INET6	2
#endif

void sysctl_sucker(int *name, u_int namelen, void **vp, size_t *szp);
void get_sockets(const char *mib);

int main()
{
	get_sockets("net.inet6.tcp6.pcblist");
	get_sockets("net.inet6.udp6.pcblist");
	return 0;
}

void sysctl_sucker(int *name, u_int namelen, void **vp, size_t *szp)
{
	int rc;
	void *v;
	size_t sz;

	/* printf("name %p, namelen %u\n", name, namelen); */

	v = NULL;
	sz = 0;
	do {
		rc = prog_sysctl(&name[0], namelen, v, &sz, NULL, 0);
		if (rc == -1 && errno != ENOMEM)
			err(1, "sysctl");
		if (rc == -1 && v != NULL) {
			free(v);
			v = NULL;
		}
		if (v == NULL) {
			v = malloc(sz);
			rc = -1;
		}
		if (v == NULL)
			err(1, "malloc");
	} while (rc == -1);

	*vp = v;
	*szp = sz;
	/* printf("got %zu at %p\n", sz, v); */
}

void get_sockets(const char *mib)
{
	void *v;
	size_t sz;
	int rc, n, name[CTL_MAXNAME];
	u_int namelen;

	sz = CTL_MAXNAME;
	rc = sysctlnametomib(mib, &name[0], &sz);
	if (rc == -1) {
		if (errno == ENOENT)
			return;
		err(1, "sysctlnametomib: %s", mib);
	}
	namelen = sz;

	name[namelen++] = PCB_ALL;
	name[namelen++] = 0;		/* XXX all pids */
	name[namelen++] = sizeof(struct kinfo_pcb);
	name[namelen++] = INT_MAX;	/* all of them */

	sysctl_sucker(&name[0], namelen, &v, &sz);
	n = sz / sizeof(struct kinfo_pcb);
	socket_add_hash(v, n);
}<|endoftext|>


<commit_before>#include <Share.h>

#include <bps/event.h>
#include <bps/navigator.h>
//#include <bps/navigator_invoke.h>
#include <screen/screen.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <vector>

using namespace std;

namespace openflShareExtension {

	void log(const char *msg) {
		/*
		FILE *logFile = fopen("logs/log.txt", "a");
		fprintf(logFile, "%s\n", msg);
		fclose(logFile);
		*/
	}

	void doShare(const char *method, const char *text) {

		navigator_invoke_invocation_t *invoke = NULL;
		navigator_invoke_invocation_create(&invoke);

		navigator_invoke_invocation_set_action(invoke, "bb.action.SHARE");
		navigator_invoke_invocation_set_data(invoke, text, strlen(text));
		navigator_invoke_invocation_set_target(invoke, method);
		navigator_invoke_invocation_set_type(invoke, "text/plain");

		navigator_invoke_invocation_send(invoke);
		navigator_invoke_invocation_destroy(invoke);

	}

	vector<ShareQueryResult> query() {

		/*
		FILE *logFile = fopen("logs/log.txt", "w");
		fclose(logFile);
		char msg[64];
		*/

		/*
		snprintf(msg, 64, "pid %d\n", getpid());
		log(msg);
		*/

		vector<ShareQueryResult> results;

		navigator_invoke_query_t *query = NULL;
		navigator_invoke_query_create(&query);

		navigator_invoke_query_set_id(query, "12345");
		navigator_invoke_query_set_action(query, "bb.action.SHARE");
		navigator_invoke_query_set_type(query, "text/plain");

		if (navigator_invoke_query_send(query)!=BPS_SUCCESS) {
			log("navigator_invoke_query_send Failed");
		}

		bps_event_t *event = NULL;

		do {

			bps_get_event(&event, -1);
			/*
			snprintf(msg, 64, "query result %#04x\n", bps_event_get_code(event));
			log(msg);
			*/
		} while (

			navigator_get_domain()!=bps_event_get_domain(event) ||
			bps_event_get_code(event)!=NAVIGATOR_INVOKE_QUERY_RESULT

		);

		// create integer holding the number of actions returned by the query
		int action_count =
			navigator_invoke_event_get_query_result_action_count(event);

		// loop listing all actions returned by the query
		for (int i=0; i<action_count; i++) {

			const navigator_invoke_query_result_action_t *action =
				navigator_invoke_event_get_query_result_action(event, i);

			// retrieve action attributes
			const char *name =
				navigator_invoke_query_result_action_get_name(action);
			const char *icon =
				navigator_invoke_query_result_action_get_icon(action);
			const char *label =
				navigator_invoke_query_result_action_get_label(action);

			// create integer holding the number of targets in the action
			int target_count =
				navigator_invoke_query_result_action_get_target_count(action);

			// loop listing all targets in the action
			for (int j=0; j < target_count; j++) {

				const navigator_invoke_query_result_target_t *target =
					navigator_invoke_query_result_action_get_target(action, j);

				if (target==NULL) {
					log("target is null!");
				}

				// retrieve target attributes
				ShareQueryResult result;

				const char *key =
					navigator_invoke_query_result_target_get_key(target);
				const char *icon =
					navigator_invoke_query_result_target_get_icon(target);
				const char *label =
					navigator_invoke_query_result_target_get_label(target);

				strcpy(result.key, key);
				strcpy(result.icon, icon);
				strcpy(result.label, label);

				results.push_back(result);

			}

		}

		navigator_invoke_query_destroy(query);

		return results;

	}

}
<commit_msg>Update Share.cpp<commit_after>#include <Share.h>

#include <bps/event.h>
#include <bps/navigator.h>
#include <bps/navigator_invoke.h>
#include <screen/screen.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <vector>

using namespace std;

namespace openflShareExtension {

	void log(const char *msg) {
		/*
		FILE *logFile = fopen("logs/log.txt", "a");
		fprintf(logFile, "%s\n", msg);
		fclose(logFile);
		*/
	}

	void doShare(const char *method, const char *text) {

		navigator_invoke_invocation_t *invoke = NULL;
		navigator_invoke_invocation_create(&invoke);

		navigator_invoke_invocation_set_action(invoke, "bb.action.SHARE");
		navigator_invoke_invocation_set_data(invoke, text, strlen(text));
		navigator_invoke_invocation_set_target(invoke, method);
		navigator_invoke_invocation_set_type(invoke, "text/plain");

		navigator_invoke_invocation_send(invoke);
		navigator_invoke_invocation_destroy(invoke);

	}

	vector<ShareQueryResult> query() {

		/*
		FILE *logFile = fopen("logs/log.txt", "w");
		fclose(logFile);
		char msg[64];
		*/

		/*
		snprintf(msg, 64, "pid %d\n", getpid());
		log(msg);
		*/

		vector<ShareQueryResult> results;

		navigator_invoke_query_t *query = NULL;
		navigator_invoke_query_create(&query);

		navigator_invoke_query_set_id(query, "12345");
		navigator_invoke_query_set_action(query, "bb.action.SHARE");
		navigator_invoke_query_set_type(query, "text/plain");

		if (navigator_invoke_query_send(query)!=BPS_SUCCESS) {
			log("navigator_invoke_query_send Failed");
		}

		bps_event_t *event = NULL;

		do {

			bps_get_event(&event, -1);
			/*
			snprintf(msg, 64, "query result %#04x\n", bps_event_get_code(event));
			log(msg);
			*/
		} while (

			navigator_get_domain()!=bps_event_get_domain(event) ||
			bps_event_get_code(event)!=NAVIGATOR_INVOKE_QUERY_RESULT

		);

		// create integer holding the number of actions returned by the query
		int action_count =
			navigator_invoke_event_get_query_result_action_count(event);

		// loop listing all actions returned by the query
		for (int i=0; i<action_count; i++) {

			const navigator_invoke_query_result_action_t *action =
				navigator_invoke_event_get_query_result_action(event, i);

			// retrieve action attributes
			const char *name =
				navigator_invoke_query_result_action_get_name(action);
			const char *icon =
				navigator_invoke_query_result_action_get_icon(action);
			const char *label =
				navigator_invoke_query_result_action_get_label(action);

			// create integer holding the number of targets in the action
			int target_count =
				navigator_invoke_query_result_action_get_target_count(action);

			// loop listing all targets in the action
			for (int j=0; j < target_count; j++) {

				const navigator_invoke_query_result_target_t *target =
					navigator_invoke_query_result_action_get_target(action, j);

				if (target==NULL) {
					log("target is null!");
				}

				// retrieve target attributes
				ShareQueryResult result;

				const char *key =
					navigator_invoke_query_result_target_get_key(target);
				const char *icon =
					navigator_invoke_query_result_target_get_icon(target);
				const char *label =
					navigator_invoke_query_result_target_get_label(target);

				strcpy(result.key, key);
				strcpy(result.icon, icon);
				strcpy(result.label, label);

				results.push_back(result);

			}

		}

		navigator_invoke_query_destroy(query);

		return results;

	}

}
<|endoftext|>