예제 #1
0
	Ods::pag* CryptoManager::encrypt(ISC_STATUS* sv, Ods::pag* from, Ods::pag* to)
	{
		// Code calling us is not ready to process exceptions correctly
		// Therefore use old (status vector based) method
		try
		{
			if (crypt && cryptPlugin && Ods::pag_crypt_page[from->pag_type % (pag_max + 1)])
			{
				to[0] = from[0];

				LocalStatus status;
				cryptPlugin->encrypt(&status, dbb.dbb_page_size - sizeof(Ods::pag), &from[1], &to[1]);
				if (!status.isSuccess())
				{
					memcpy(sv, status.get(), sizeof(ISC_STATUS_ARRAY));
					return NULL;
				}

				to->pag_flags |= Ods::crypted_page;
				return to;
			}
			else
			{
				from->pag_flags &= ~Ods::crypted_page;
				return from;
			}
		}
		catch (const Exception& ex)
		{
			ex.stuff_exception(sv);
		}
		return NULL;
	}
예제 #2
0
	void setCharSet(thread_db* tdbb, EngineAttachmentInfo* attInfo, T* obj)
	{
		attachment->att_charset = attInfo->adminCharSet;

		if (!obj)
			return;

		Utf8 charSetName[MAX_SQL_IDENTIFIER_SIZE];

		{	// scope
			Attachment::Checkout attCout(attachment, FB_FUNCTION);

			LocalStatus status;
			obj->getCharSet(&status, attInfo->context, charSetName, MAX_SQL_IDENTIFIER_LEN);
			status.check();
			charSetName[MAX_SQL_IDENTIFIER_LEN] = '\0';
		}

		USHORT charSetId;

		if (!MET_get_char_coll_subtype(tdbb, &charSetId,
				reinterpret_cast<const UCHAR*>(charSetName), static_cast<USHORT>(strlen(charSetName))))
		{
			status_exception::raise(Arg::Gds(isc_charset_not_found) << Arg::Str(charSetName));
		}

		attachment->att_charset = charSetId;
	}
예제 #3
0
	bool CryptoManager::decrypt(ISC_STATUS* sv, Ods::pag* page)
	{
		// Code calling us is not ready to process exceptions correctly
		// Therefore use old (status vector based) method
		try
		{
			if (page->pag_flags & Ods::crypted_page)
			{
				if (!cryptPlugin)
				{
					// We are invoked from shared cache manager, i.e. no valid attachment in tdbb
					// Therefore create system temporary attachment like in crypt thread to be able to work with locks
					UserId user;
					user.usr_user_name = "(Crypt plugin loader)";

					Jrd::Attachment* const attachment = Jrd::Attachment::create(&dbb);
					RefPtr<SysAttachment> jAtt(new SysAttachment(attachment));
					attachment->att_interface = jAtt;
					attachment->att_filename = dbb.dbb_filename;
					attachment->att_user = &user;

					BackgroundContextHolder tdbb(&dbb, attachment, sv, FB_FUNCTION);

					// Lock crypt state
					takeStateLock(tdbb);

					Header hdr(tdbb, LCK_read);
					crypt = hdr->hdr_flags & Ods::hdr_encrypted;
					process = hdr->hdr_flags & Ods::hdr_crypt_process;

					if (crypt || process)
					{
						loadPlugin(hdr->hdr_crypt_plugin);
					}

					if (!cryptPlugin)
					{
						(Arg::Gds(isc_decrypt_error)).raise();
						return false;
					}
				}

				LocalStatus status;
				cryptPlugin->decrypt(&status, dbb.dbb_page_size - sizeof(Ods::pag), &page[1], &page[1]);
				if (!status.isSuccess())
				{
					memcpy(sv, status.get(), sizeof(ISC_STATUS_ARRAY));
					return false;
				}
			}

			return true;
		}
		catch (const Exception& ex)
		{
			ex.stuff_exception(sv);
		}
		return false;
	}
예제 #4
0
void ExtEngineManager::Trigger::execute(thread_db* tdbb, ExternalTrigger::Action action,
	record_param* oldRpb, record_param* newRpb) const
{
	EngineAttachmentInfo* attInfo = extManager->getEngineAttachment(tdbb, engine);
	ContextManager<ExternalTrigger> ctxManager(tdbb, attInfo, trigger,
		CallerName(obj_trigger, trg->name));

	// ASF: Using Array instead of HalfStaticArray to not need to do alignment hacks here.
	Array<UCHAR> oldMsg;
	Array<UCHAR> newMsg;

	if (oldRpb)
		setValues(tdbb, oldMsg, oldRpb);

	if (newRpb)
		setValues(tdbb, newMsg, newRpb);

	{	// scope
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);

		LocalStatus status;
		trigger->execute(&status, attInfo->context, action,
			(oldMsg.hasData() ? oldMsg.begin() : NULL), (newMsg.hasData() ? newMsg.begin() : NULL));
		status.check();
	}

	if (newRpb)
	{
		// Move data back from the message to the record.

		Record* record = newRpb->rpb_record;
		UCHAR* p = newMsg.begin();

		for (unsigned i = 0; i < format->fmt_count / 2u; ++i)
		{
			USHORT fieldPos = fieldsPos[i];

			dsc target;
			bool readonly = !EVL_field(newRpb->rpb_relation, record, fieldPos, &target) &&
				target.dsc_address && !(target.dsc_flags & DSC_null);

			if (!readonly)
			{
				SSHORT* nullSource = (SSHORT*) (p + (IPTR) format->fmt_desc[i * 2 + 1].dsc_address);

				if (*nullSource == 0)
				{
					dsc source = format->fmt_desc[i * 2];
					source.dsc_address += (IPTR) p;
					MOV_move(tdbb, &source, &target);
					record->clearNull(fieldPos);
				}
				else
					record->setNull(fieldPos);
			}
		}
	}
}
예제 #5
0
void TraceManager::update_session(const TraceSession& session)
{
	// if this session is already known, nothing to do
	FB_SIZE_T pos;
	if (trace_sessions.find(session.ses_id, pos)) {
		return;
	}

	// if this session is not from administrator, it may trace connections
	// only created by the same user
	if (!(session.ses_flags & trs_admin))
	{
		if (attachment)
		{
			if (!attachment->att_user || attachment->att_user->usr_user_name != session.ses_user)
				return;
		}
		else if (service)
		{
			if (session.ses_user != service->getUserName())
				return;
		}
		else
		{
			// failed attachment attempts traced by admin trace only
			return;
		}
	}

	MasterInterfacePtr master;

	for (FactoryInfo* info = factories->begin(); info != factories->end(); ++info)
	{
		TraceInitInfoImpl attachInfo(session, attachment, filename);
		LocalStatus status;
		ITracePlugin* plugin = info->factory->trace_create(&status, &attachInfo);

		if (plugin)
		{
			plugin->addRef();
			SessionInfo sesInfo;
			sesInfo.plugin = plugin;
			sesInfo.factory_info = info;
			sesInfo.ses_id = session.ses_id;
			trace_sessions.add(sesInfo);

			trace_needs |= info->factory->trace_needs();
		}
		else if (status.getStatus() & IStatus::FB_HAS_ERRORS)
		{
			string header;
			header.printf("Trace plugin %s returned error on call trace_create.", info->name);
			iscLogStatus(header.c_str(), &status);
		}
	}
}
예제 #6
0
void ExtEngineManager::Function::execute(thread_db* tdbb, UCHAR* inMsg, UCHAR* outMsg) const
{
	EngineAttachmentInfo* attInfo = extManager->getEngineAttachment(tdbb, engine);
	ContextManager<ExternalFunction> ctxManager(tdbb, attInfo, function,
		(udf->getName().package.isEmpty() ?
			CallerName(obj_udf, udf->getName().identifier) :
			CallerName(obj_package_header, udf->getName().package)));

	Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);

	LocalStatus status;
	function->execute(&status, attInfo->context, inMsg, outMsg);
	status.check();
}
예제 #7
0
ExtEngineManager::Trigger::Trigger(thread_db* tdbb, MemoryPool& pool, ExtEngineManager* aExtManager,
			ExternalEngine* aEngine, RoutineMetadata* aMetadata,
			ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg)
	: extManager(aExtManager),
	  engine(aEngine),
	  metadata(aMetadata),
	  trigger(aTrigger),
	  trg(aTrg),
	  fieldsPos(pool),
	  database(tdbb->getDatabase())
{
	dsc shortDesc;
	shortDesc.makeShort(0);

	jrd_rel* relation = trg->relation;

	if (relation)
	{
		GenericMap<Left<MetaName, USHORT> > fieldsMap;

		for (FB_SIZE_T i = 0; i < relation->rel_fields->count(); ++i)
		{
			jrd_fld* field = (*relation->rel_fields)[i];
			if (field)
				fieldsMap.put(field->fld_name, (USHORT) i);
		}

		format = Routine::createFormat(pool, metadata->triggerFields, false);

		LocalStatus status;

		for (unsigned i = 0; i < format->fmt_count / 2u; ++i)
		{
			const char* fieldName = metadata->triggerFields->getField(&status, i);
			status.check();

			USHORT pos;

			if (!fieldsMap.get(fieldName, pos))
				fb_assert(false);
			else
				fieldsPos.add(pos);
		}
	}
}
예제 #8
0
	void CryptoManager::KeyHolderPlugins::init(IDbCryptPlugin* crypt)
	{
		MutexLockGuard g(holdersMutex, FB_FUNCTION);

		Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 64> holdersVector;
		unsigned int length = knownHolders.getCount();
		IKeyHolderPlugin** vector = holdersVector.getBuffer(length);
		for (unsigned i = 0; i < length; ++i)
		{
			vector[i] = knownHolders[i].getPlugin();
		}

		LocalStatus st;
		crypt->setKey(&st, length, vector);
		if (!st.isSuccess())
		{
			status_exception::raise(st.get());
		}
	}
예제 #9
0
void UserManagement::commit()
{
	for (unsigned i = 0; i < managers.getCount(); ++i)
	{
		IManagement* manager = managers[i].second;
		if (manager)
		{
			LocalStatus status;
			CheckStatusWrapper statusWrapper(&status);

			manager->commit(&statusWrapper);
			if (status.getState() & IStatus::STATE_ERRORS)
				status_exception::raise(&statusWrapper);

			PluginManagerInterfacePtr()->releasePlugin(manager);
			managers[i].second = NULL;
		}
	}
}
예제 #10
0
ExtEngineManager::ResultSet::ResultSet(thread_db* tdbb, UCHAR* inMsg, UCHAR* outMsg,
		const ExtEngineManager::Procedure* aProcedure)
	: procedure(aProcedure),
	  attachment(tdbb->getAttachment()),
	  firstFetch(true)
{
	attInfo = procedure->extManager->getEngineAttachment(tdbb, procedure->engine);
	ContextManager<ExternalProcedure> ctxManager(tdbb, attInfo, procedure->procedure,
		(procedure->prc->getName().package.isEmpty() ?
			CallerName(obj_procedure, procedure->prc->getName().identifier) :
			CallerName(obj_package_header, procedure->prc->getName().package)));

	charSet = attachment->att_charset;

	Attachment::Checkout attCout(attachment, FB_FUNCTION);

	LocalStatus status;
	resultSet = procedure->procedure->open(&status, attInfo->context, inMsg, outMsg);
	status.check();
}
예제 #11
0
void ExtEngineManager::setupAdminCharSet(thread_db* tdbb, ExternalEngine* engine,
	EngineAttachmentInfo* attInfo)
{
	ContextManager<ExternalFunction> ctxManager(tdbb, attInfo, CS_UTF8);

	Utf8 charSetName[MAX_SQL_IDENTIFIER_SIZE] = "NONE";

	LocalStatus status;
	engine->open(&status, attInfo->context, charSetName, MAX_SQL_IDENTIFIER_LEN);
	status.check();

	charSetName[MAX_SQL_IDENTIFIER_LEN] = '\0';

	if (!MET_get_char_coll_subtype(tdbb, &attInfo->adminCharSet,
			reinterpret_cast<const UCHAR*>(charSetName),
			static_cast<USHORT>(strlen(charSetName))))
	{
		status_exception::raise(
			Arg::Gds(isc_charset_not_found) <<
			Arg::Str(charSetName));
	}
}
예제 #12
0
bool ExtEngineManager::ResultSet::fetch(thread_db* tdbb)
{
	bool wasFirstFetch = firstFetch;
	firstFetch = false;

	if (!resultSet)
		return wasFirstFetch;

	ContextManager<ExternalProcedure> ctxManager(tdbb, attInfo, charSet,
		(procedure->prc->getName().package.isEmpty() ?
			CallerName(obj_procedure, procedure->prc->getName().identifier) :
			CallerName(obj_package_header, procedure->prc->getName().package)));

	fb_assert(attachment == tdbb->getAttachment());
	Attachment::Checkout attCout(attachment, FB_FUNCTION);

	LocalStatus status;
	bool ret = resultSet->fetch(&status);
	status.check();

	return ret;
}
예제 #13
0
	void CryptoManager::KeyHolderPlugins::attach(Attachment* att, Config* config)
	{
		MutexLockGuard g(holdersMutex, FB_FUNCTION);

		for (GetPlugins<IKeyHolderPlugin> keyControl(PluginType::KeyHolder,
			FB_KEYHOLDER_PLUGIN_VERSION, upInfo, config); keyControl.hasData(); keyControl.next())
		{
			IKeyHolderPlugin* keyPlugin = keyControl.plugin();
			LocalStatus st;
			if (keyPlugin->keyCallback(&st, att->att_crypt_callback) == 1)
			{
				// holder accepted attachment's key
				HolderAttachments* ha = NULL;

				for (unsigned i = 0; i < knownHolders.getCount(); ++i)
				{
					if (knownHolders[i] == keyPlugin)
					{
						ha = &knownHolders[i];
						break;
					}
				}

				if (!ha)
				{
					ha = &(knownHolders.add());
					ha->setPlugin(keyPlugin);
				}

				ha->registerAttachment(att);
				break;		// Do not need >1 key from attachment to single DB
			}
			else if (!st.isSuccess())
			{
				status_exception::raise(st.get());
			}
		}
	}
예제 #14
0
IManagement* UserManagement::registerManager(Auth::Get& getPlugin, const char* plugName)
{
	IManagement* manager = getPlugin.plugin();
	fb_assert(manager);

	// Start new management plugin ...
	LocalStatus status;
	CheckStatusWrapper statusWrapper(&status);

	UserIdInfo idInfo(att);
	manager->start(&statusWrapper, &idInfo);
	if (status.getState() & IStatus::STATE_ERRORS)
	{
		status_exception::raise(&statusWrapper);
	}

	// ... and store it in cache
	Manager& m(managers.add());
	m.first = plugName;
	m.second = manager;
	manager->addRef();

	return manager;
}
예제 #15
0
void ExtEngineManager::makeProcedure(thread_db* tdbb, jrd_prc* prc,
	const MetaName& engine, const string& entryPoint, const string& body)
{
	string entryPointTrimmed = entryPoint;
	entryPointTrimmed.trim();

	EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine);
	ContextManager<ExternalProcedure> ctxManager(tdbb, attInfo, attInfo->adminCharSet,
		(prc->getName().package.isEmpty() ?
			CallerName(obj_procedure, prc->getName().identifier) :
			CallerName(obj_package_header, prc->getName().package)));

	///MemoryPool& pool = *tdbb->getDefaultPool();
	MemoryPool& pool = *getDefaultMemoryPool();

	AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
	metadata->package = prc->getName().package;
	metadata->name = prc->getName().identifier;
	metadata->entryPoint = entryPointTrimmed;
	metadata->body = body;
	metadata->inputParameters = Routine::createMetadata(prc->getInputFields());
	metadata->outputParameters = Routine::createMetadata(prc->getOutputFields());

	LocalStatus status;

	RefPtr<IMetadataBuilder> inBuilder(metadata->inputParameters->getBuilder(&status));
	status.check();
	inBuilder->release();

	RefPtr<IMetadataBuilder> outBuilder(metadata->outputParameters->getBuilder(&status));
	status.check();
	outBuilder->release();

	ExternalProcedure* externalProcedure;

	{	// scope
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);

		externalProcedure = attInfo->engine->makeProcedure(&status, attInfo->context, metadata,
			inBuilder, outBuilder);
		status.check();

		if (!externalProcedure)
		{
			status_exception::raise(
				Arg::Gds(isc_eem_proc_not_returned) <<
					prc->getName().toString() << engine);
		}

		metadata->inputParameters = inBuilder->getMetadata(&status);
		status.check();

		metadata->outputParameters = outBuilder->getMetadata(&status);
		status.check();
	}

	try
	{
		prc->setInputFormat(Routine::createFormat(pool, metadata->inputParameters, false));
		prc->setOutputFormat(Routine::createFormat(pool, metadata->outputParameters, false));

		prc->setExternal(FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine,
			metadata.release(), externalProcedure, prc));
	}
	catch (...)
	{
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
		externalProcedure->dispose();
		throw;
	}
}
예제 #16
0
void ExtEngineManager::makeProcedure(thread_db* tdbb, CompilerScratch* csb, jrd_prc* prc,
	const MetaName& engine, const string& entryPoint, const string& body)
{
	string entryPointTrimmed = entryPoint;
	entryPointTrimmed.trim();

	EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine);
	ContextManager<ExternalProcedure> ctxManager(tdbb, attInfo, attInfo->adminCharSet,
		(prc->getName().package.isEmpty() ?
			CallerName(obj_procedure, prc->getName().identifier) :
			CallerName(obj_package_header, prc->getName().package)));

	///MemoryPool& pool = *tdbb->getDefaultPool();
	MemoryPool& pool = *getDefaultMemoryPool();

	AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
	metadata->package = prc->getName().package;
	metadata->name = prc->getName().identifier;
	metadata->entryPoint = entryPointTrimmed;
	metadata->body = body;
	metadata->inputParameters = Routine::createMetadata(prc->getInputFields());
	metadata->outputParameters = Routine::createMetadata(prc->getOutputFields());

	LocalStatus status;

	RefPtr<IMetadataBuilder> inBuilder(REF_NO_INCR, metadata->inputParameters->getBuilder(&status));
	status.check();

	RefPtr<IMetadataBuilder> outBuilder(REF_NO_INCR, metadata->outputParameters->getBuilder(&status));
	status.check();

	ExternalProcedure* externalProcedure;

	{	// scope
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);

		externalProcedure = attInfo->engine->makeProcedure(&status, attInfo->context, metadata,
			inBuilder, outBuilder);
		status.check();

		if (!externalProcedure)
		{
			status_exception::raise(
				Arg::Gds(isc_eem_proc_not_returned) <<
					prc->getName().toString() << engine);
		}

		metadata->inputParameters = inBuilder->getMetadata(&status);
		status.check();

		metadata->outputParameters = outBuilder->getMetadata(&status);
		status.check();
	}

	prc->setInputFormat(Routine::createFormat(pool, metadata->inputParameters, false));
	prc->setOutputFormat(Routine::createFormat(pool, metadata->outputParameters, true));

	try
	{
		prc->setExternal(FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine,
			metadata.release(), externalProcedure, prc));

		CompoundStmtNode* mainNode = FB_NEW(getPool()) CompoundStmtNode(getPool());

		ExtMessageNode* inMessageNode = prc->getInputFields().hasData() ?
			FB_NEW(getPool()) ExtMessageNode(tdbb, getPool(), csb, 0,
				prc->getInputFields(), prc->getInputFormat()) :
			NULL;
		if (inMessageNode)
			mainNode->statements.add(inMessageNode);

		ExtMessageNode* outMessageNode = FB_NEW(getPool()) ExtMessageNode(tdbb, getPool(), csb, 1,
			prc->getOutputFields(), prc->getOutputFormat());
		mainNode->statements.add(outMessageNode);

		ExtInitOutputNode* initOutputNode = FB_NEW(getPool()) ExtInitOutputNode(
			tdbb, getPool(), csb, outMessageNode);
		mainNode->statements.add(initOutputNode);

		ReceiveNode* receiveNode = inMessageNode ?
			FB_NEW(getPool()) ReceiveNode(getPool()) : NULL;

		if (inMessageNode)
		{
			receiveNode->message = inMessageNode;
			receiveNode->statement = FB_NEW(getPool()) ExtValidationNode(
				getPool(), inMessageNode, true, true);
			mainNode->statements.add(receiveNode);
		}

		ExtProcedureNode* extProcedureNode = FB_NEW(getPool()) ExtProcedureNode(getPool(),
			receiveNode, prc->getExternal());
		mainNode->statements.add(extProcedureNode);
		extProcedureNode->message = outMessageNode;
		extProcedureNode->statement = FB_NEW(getPool()) ExtValidationNode(
			getPool(), outMessageNode, true, false);

		JrdStatement* statement = prc->getStatement();
		PAR_preparsed_node(tdbb, NULL, mainNode, NULL, &csb, &statement, false, 0);
		prc->setStatement(statement);
	}
	catch (...)
	{
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
		externalProcedure->dispose();
		throw;
	}
}
예제 #17
0
void ExtEngineManager::makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::Trigger* trg,
	const MetaName& engine, const string& entryPoint, const string& body,
	ExternalTrigger::Type type)
{
	string entryPointTrimmed = entryPoint;
	entryPointTrimmed.trim();

	EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine);
	ContextManager<ExternalTrigger> ctxManager(tdbb, attInfo, attInfo->adminCharSet,
		CallerName(obj_trigger, trg->name));

	///MemoryPool& pool = *tdbb->getDefaultPool();
	MemoryPool& pool = *getDefaultMemoryPool();

	AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
	metadata->name = trg->name;
	metadata->entryPoint = entryPointTrimmed;
	metadata->body = body;
	metadata->triggerType = type;

	jrd_rel* relation = trg->relation;

	if (relation)
	{
		metadata->triggerTable = relation->rel_name;

		MsgMetadata* fieldsMsg = new MsgMetadata;
		metadata->triggerFields = fieldsMsg;

		Format* relFormat = relation->rel_current_format;

		for (FB_SIZE_T i = 0; i < relation->rel_fields->count(); ++i)
		{
			jrd_fld* field = (*relation->rel_fields)[i];
			if (field)
				fieldsMsg->addItem(field->fld_name, !field->fld_not_null, relFormat->fmt_desc[i]);
		}
	}

	LocalStatus status;

	RefPtr<IMetadataBuilder> fieldsBuilder(REF_NO_INCR, relation ?
		metadata->triggerFields->getBuilder(&status) : NULL);
	if (relation)
	{
		status.check();
	}

	ExternalTrigger* externalTrigger;

	{	// scope
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);

		LocalStatus status;
		externalTrigger = attInfo->engine->makeTrigger(&status, attInfo->context, metadata,
			fieldsBuilder);
		status.check();

		if (!externalTrigger)
		{
			status_exception::raise(
				Arg::Gds(isc_eem_trig_not_returned) << trg->name << engine);
		}

		if (relation)
		{
			metadata->triggerFields = fieldsBuilder->getMetadata(&status);
			status.check();
		}
	}

	try
	{
		trg->extTrigger = FB_NEW(getPool()) Trigger(tdbb, pool, this, attInfo->engine,
			metadata.release(), externalTrigger, trg);

		CompoundStmtNode* mainNode = FB_NEW(getPool()) CompoundStmtNode(getPool());

		ExtTriggerNode* extTriggerNode = FB_NEW(getPool()) ExtTriggerNode(getPool(),
			trg->extTrigger);
		mainNode->statements.add(extTriggerNode);

		PAR_preparsed_node(tdbb, trg->relation, mainNode, NULL, &csb, &trg->statement, true, 0);
	}
	catch (...)
	{
		Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
		externalTrigger->dispose();
		throw;
	}
}
예제 #18
0
void UserManagement::execute(USHORT id)
{
	if (id >= commands.getCount())
	{
		status_exception::raise(Arg::Gds(isc_random) << "Wrong job id passed to UserManagement::execute()");
	}

	if (!commands[id])
		return;	// Already executed

	Auth::UserData* command = commands[id];
	IManagement* manager = getManager(command->plugin.c_str());

	if (!manager)
		return;	// Already commited

	LocalStatus status;
	CheckStatusWrapper statusWrapper(&status);

	if (command->attr.entered() || command->op == Auth::ADDMOD_OPER)
	{
		Auth::StackUserData cmd;
		cmd.op = Auth::DIS_OPER;
		cmd.user.set(&statusWrapper, command->userName()->get());
		check(&statusWrapper);
		cmd.user.setEntered(&statusWrapper, 1);
		check(&statusWrapper);

		OldAttributes oldAttributes;
		int ret = manager->execute(&statusWrapper, &cmd, &oldAttributes);
		if (ret == 0 || status.getErrors()[1] != isc_missing_data_structures)
			checkSecurityResult(ret, &status, command->userName()->get(), command->operation());
		else
			statusWrapper.init();

		if (command->op == Auth::ADDMOD_OPER)
			command->op = oldAttributes.present ? Auth::MOD_OPER : Auth::ADD_OPER;

		if (command->attr.entered())
		{
			ConfigFile ocf(ConfigFile::USE_TEXT, oldAttributes.value.c_str(), ConfigFile::NO_COMMENTS);
			ConfigFile::Parameters::const_iterator old(ocf.getParameters().begin());
			ConfigFile::Parameters::const_iterator oldEnd(ocf.getParameters().end());

			ConfigFile ccf(ConfigFile::USE_TEXT, command->attr.get(), ConfigFile::NO_COMMENTS);
			ConfigFile::Parameters::const_iterator cur(ccf.getParameters().begin());
			ConfigFile::Parameters::const_iterator curEnd(ccf.getParameters().end());

			// Dup check
			ConfigFile::KeyType prev;
			while (cur != curEnd)
			{
				if (cur->name == prev)
					(Arg::Gds(isc_dup_attribute) << cur->name).raise();

				prev = cur->name;
				++cur;
			}
			cur = ccf.getParameters().begin();

			string merged;
			while (old != oldEnd && cur != curEnd)
			{
				if (old->name == cur->name)
				{
					merge(merged, cur);
					++old;
					++cur;
				}
				else if (old->name < cur->name)
				{
					merge(merged, old);
					++old;
				}
				else
				{
					merge(merged, cur);
					++cur;
				}
			}

			while (cur != curEnd)
			{
				merge(merged, cur);
				++cur;
			}

			while (old != oldEnd)
			{
				merge(merged, old);
				++old;
			}

			if (merged.hasData())
			{
				command->attr.set(&statusWrapper, merged.c_str());
				check(&statusWrapper);
			}
			else
			{
				command->attr.setEntered(&statusWrapper, 0);
				check(&statusWrapper);
				command->attr.setSpecified(1);
				command->attr.set(&statusWrapper, "");
				check(&statusWrapper);
			}
		}
	}

	if (command->op == Auth::ADD_OPER)
	{
		if (!command->pass.entered())
			Arg::PrivateDyn(291).raise();

		if (!command->act.entered())
		{
			command->act.set(&statusWrapper, 1);
			check(&statusWrapper);
			command->act.setEntered(&statusWrapper, 1);
			check(&statusWrapper);
		}
	}

	int errcode = manager->execute(&statusWrapper, command, NULL);
	checkSecurityResult(errcode, &status, command->userName()->get(), command->operation());

	delete commands[id];
	commands[id] = NULL;
}