<commit_before>#include <qlayout.h>
#include <qlineedit.h>
#include <qlabel.h>
#include "ktimewidget.h"
#include <qvalidator.h>
#include <kdebug.h>

enum ValidatorType { HOUR, MINUTE };

class TimeValidator :public QValidator
{
public:
	TimeValidator(ValidatorType tp, QWidget *parent=0, const char *name=0) :QValidator(parent, name)
	{
		_tp = tp;
	}
	State validate(QString &str, int &) const
	{
		if (str.isEmpty())
			return Acceptable;

		bool ok;
		int val = str.toInt( &ok );
		if ( ! ok )
			return Invalid;

		if ( str.contains('-') != 0 )
			return Invalid;

		if ( _tp==MINUTE && val >= 60  )
			return Invalid;
		else
			return Acceptable;
	}

public:
	ValidatorType _tp;
};

class KarmLineEdit :public QLineEdit
{

public:
	KarmLineEdit( QWidget* parent, const char* name = 0 ) :QLineEdit( parent, name )
	{
	}

protected:

	virtual void keyPressEvent( QKeyEvent *event ) {
		QLineEdit::keyPressEvent( event );
		if ( text().length() == 2 && !event->text().isNull() )
			focusNextPrevChild(true);
	}
};

KTimeWidget::KTimeWidget(  QWidget* parent, const char* name ) : QWidget(parent, name)
{
	QHBoxLayout *layout = new QHBoxLayout(this);

	_hourLE = new QLineEdit( this);

	_hourLE->setFixedWidth(fontMetrics().maxWidth()*5);
	layout->addWidget(_hourLE);
	TimeValidator *validator = new TimeValidator( HOUR, _hourLE, "Validator for _hourLE");
	_hourLE->setValidator( validator );
	_hourLE->setAlignment( Qt::AlignRight );

	QLabel *dot = new QLabel(QString::fromLatin1( " : " ), this);
	layout->addWidget(dot);

	_minuteLE = new KarmLineEdit(this);

	_minuteLE->setFixedWidth(fontMetrics().maxWidth()*2);
	layout->addWidget(_minuteLE);
	validator = new TimeValidator( MINUTE, _minuteLE, "Validator for _minuteLE");
	_minuteLE->setValidator( validator );
	_minuteLE->setMaxLength(2);
	_minuteLE->setAlignment( Qt::AlignRight );

	layout->addStretch(1);
	setFocusProxy( _hourLE );
}

void KTimeWidget::setTime( int hour, int minute )
{
	QString dummy;

	dummy.setNum( hour );
	_hourLE->setText( dummy );

	dummy.setNum( minute );
	if (minute < 10 ) {
		dummy = QString::fromLatin1( "0" ) + dummy;
	}
	_minuteLE->setText( dummy );
}

long KTimeWidget::time() const
{
	bool ok;
	return _hourLE->text().toInt( &ok ) * 60 + _minuteLE->text().toInt( &ok );
}
<commit_msg>negative numbers should be handled correctly now - the unresolved question is - do they make any sense?<commit_after>#include <qlayout.h>
#include <qlineedit.h>
#include <qlabel.h>
#include "ktimewidget.h"
#include <qvalidator.h>
#include <kdebug.h>

enum ValidatorType { HOUR, MINUTE };

class TimeValidator :public QValidator
{
public:
	TimeValidator(ValidatorType tp, QWidget *parent=0, const char *name=0) :QValidator(parent, name)
	{
		_tp = tp;
	}
	State validate(QString &str, int &) const
	{
		if (str.isEmpty())
			return Acceptable;

		bool ok;
		int val = str.toInt( &ok );
		if ( ! ok )
			return Invalid;

		if ( str.contains('-') != 0 )
			return Invalid;

		if ( _tp==MINUTE && val >= 60  )
			return Invalid;
		else
			return Acceptable;
	}

public:
	ValidatorType _tp;
};

class KarmLineEdit :public QLineEdit
{

public:
	KarmLineEdit( QWidget* parent, const char* name = 0 ) :QLineEdit( parent, name )
	{
	}

protected:

	virtual void keyPressEvent( QKeyEvent *event ) {
		QLineEdit::keyPressEvent( event );
		if ( text().length() == 2 && !event->text().isNull() )
			focusNextPrevChild(true);
	}
};

KTimeWidget::KTimeWidget(  QWidget* parent, const char* name ) : QWidget(parent, name)
{
	QHBoxLayout *layout = new QHBoxLayout(this);

	_hourLE = new QLineEdit( this);

	_hourLE->setFixedWidth(fontMetrics().maxWidth()*5);
	layout->addWidget(_hourLE);
	TimeValidator *validator = new TimeValidator( HOUR, _hourLE, "Validator for _hourLE");
	_hourLE->setValidator( validator );
	_hourLE->setAlignment( Qt::AlignRight );

	QLabel *dot = new QLabel(QString::fromLatin1( " : " ), this);
	layout->addWidget(dot);

	_minuteLE = new KarmLineEdit(this);

	_minuteLE->setFixedWidth(fontMetrics().maxWidth()*2);
	layout->addWidget(_minuteLE);
	validator = new TimeValidator( MINUTE, _minuteLE, "Validator for _minuteLE");
	_minuteLE->setValidator( validator );
	_minuteLE->setMaxLength(2);
	_minuteLE->setAlignment( Qt::AlignRight );

	layout->addStretch(1);
	setFocusProxy( _hourLE );
}

void KTimeWidget::setTime( int hour, int minute )
{
	QString dummy;

	dummy.setNum( hour );
	_hourLE->setText( dummy );

	dummy.setNum( abs(minute) );
	if (abs(minute) < 10 ) {
		dummy = QString::fromLatin1( "0" ) + dummy;
	}
	_minuteLE->setText( dummy );
}

long KTimeWidget::time() const
{
	bool ok;
	int h, m;

	h = _hourLE->text().toInt( &ok );
	m = _minuteLE->text().toInt( &ok );

	// if h is negative, we have to *subtract* m
	return h * 60 + ( ( h < 0) ? -1 : 1 ) * m;
}
<|endoftext|>


<commit_before>#include "NOD/DiscBase.hpp"
#include "NOD/IFileIO.hpp"
#include "NOD/NOD.hpp"

#include <errno.h>
#ifndef _WIN32
#include <unistd.h>
#endif

namespace NOD
{

void DiscBase::IPartition::parseFST(IPartReadStream& s)
{
    std::unique_ptr<uint8_t[]> fst(new uint8_t[m_fstSz]);
    s.seek(m_fstOff);
    s.read(fst.get(), m_fstSz);

    const FSTNode* nodes = (FSTNode*)fst.get();

    /* Root node indicates the count of all contained nodes */
    uint32_t nodeCount = nodes[0].getLength();
    const char* names = (char*)fst.get() + 12 * nodeCount;
    m_nodes.clear();
    m_nodes.reserve(nodeCount);

    /* Construct nodes */
    for (uint32_t n=0 ; n<nodeCount ; ++n)
    {
        const FSTNode& node = nodes[n];
        m_nodes.emplace_back(*this, node, n ? names + node.getNameOffset() : "");
    }

    /* Setup dir-child iterators */
    for (std::vector<Node>::iterator it=m_nodes.begin();
         it != m_nodes.end();
         ++it)
    {
        Node& node = *it;
        if (node.m_kind == Node::NODE_DIRECTORY)
        {
            node.m_childrenBegin = it + 1;
            node.m_childrenEnd = m_nodes.begin() + node.m_discLength;
        }
    }
}

void DiscBase::IPartition::parseDOL(IPartReadStream& s)
{
    /* Read Dol header */
    DOLHeader dolHeader;
    s.read(&dolHeader, sizeof(DOLHeader));

    /* Calculate Dol size */
    uint32_t dolSize = SBig(dolHeader.textOff[0]);
    for (uint32_t i = 0 ; i < 7 ; i++)
        dolSize += SBig(dolHeader.textSizes[i]);
    for (uint32_t i = 0 ; i < 11 ; i++)
        dolSize += SBig(dolHeader.dataSizes[i]);

    m_dolSz = dolSize;
}

bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath, const ExtractionContext& ctx) const
{
    SystemStringView nameView(getName());
    SystemString path = basePath + _S("/") + nameView.sys_str();

    if (m_kind == NODE_DIRECTORY)
    {
        if (ctx.verbose && ctx.progressCB && !getName().empty())
            ctx.progressCB(getName());
        if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
        {
            LogModule.report(LogVisor::Error, _S("unable to mkdir '%s'"), path.c_str());
            return false;
        }
        for (Node& subnode : *this)
            if (!subnode.extractToDirectory(path, ctx))
                return false;
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB(getName());
    }
    else if (m_kind == NODE_FILE)
    {
        Sstat theStat;
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB(getName());

        if (ctx.force || Stat(path.c_str(), &theStat))
        {
            std::unique_ptr<IPartReadStream> rs = beginReadStream();
            std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(path)->beginWriteStream();
            ws->copyFromDisc(*rs, m_discLength);
        }
    }
    return true;
}

bool DiscBase::IPartition::extractToDirectory(const SystemString& path, const ExtractionContext& ctx)
{
    Sstat theStat;
    if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
    {
        LogModule.report(LogVisor::Error, _S("unable to mkdir '%s'"), path.c_str());
        return false;
    }

    /* Extract Apploader */
    SystemString apploaderPath = path + _S("/apploader.bin");
    if (ctx.force || Stat(apploaderPath.c_str(), &theStat))
    {
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB("apploader.bin");
        std::unique_ptr<uint8_t[]> buf = getApploaderBuf();
        NewFileIO(apploaderPath)->beginWriteStream()->write(buf.get(), m_apploaderSz);
    }

    /* Extract Dol */
    SystemString dolPath = path + _S("/main.dol");
    if (ctx.force || Stat(dolPath.c_str(), &theStat))
    {
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB("main.dol");
        std::unique_ptr<uint8_t[]> buf = getDOLBuf();
        NewFileIO(dolPath)->beginWriteStream()->write(buf.get(), m_dolSz);
    }

    /* Extract Filesystem */
    return m_nodes[0].extractToDirectory(path, ctx);
}

}
<commit_msg>Fix goof<commit_after>#include "NOD/DiscBase.hpp"
#include "NOD/IFileIO.hpp"
#include "NOD/NOD.hpp"

#include <errno.h>
#ifndef _WIN32
#include <unistd.h>
#endif

namespace NOD
{

void DiscBase::IPartition::parseFST(IPartReadStream& s)
{
    std::unique_ptr<uint8_t[]> fst(new uint8_t[m_fstSz]);
    s.seek(m_fstOff);
    s.read(fst.get(), m_fstSz);

    const FSTNode* nodes = (FSTNode*)fst.get();

    /* Root node indicates the count of all contained nodes */
    uint32_t nodeCount = nodes[0].getLength();
    const char* names = (char*)fst.get() + 12 * nodeCount;
    m_nodes.clear();
    m_nodes.reserve(nodeCount);

    /* Construct nodes */
    for (uint32_t n=0 ; n<nodeCount ; ++n)
    {
        const FSTNode& node = nodes[n];
        m_nodes.emplace_back(*this, node, n ? names + node.getNameOffset() : "");
    }

    /* Setup dir-child iterators */
    for (std::vector<Node>::iterator it=m_nodes.begin();
         it != m_nodes.end();
         ++it)
    {
        Node& node = *it;
        if (node.m_kind == Node::NODE_DIRECTORY)
        {
            node.m_childrenBegin = it + 1;
            node.m_childrenEnd = m_nodes.begin() + node.m_discLength;
        }
    }
}

void DiscBase::IPartition::parseDOL(IPartReadStream& s)
{
    /* Read Dol header */
    DOLHeader dolHeader;
    s.read(&dolHeader, sizeof(DOLHeader));

    /* Calculate Dol size */
    uint32_t dolSize = SBig(dolHeader.textOff[0]);
    for (uint32_t i = 0 ; i < 7 ; i++)
        dolSize += SBig(dolHeader.textSizes[i]);
    for (uint32_t i = 0 ; i < 11 ; i++)
        dolSize += SBig(dolHeader.dataSizes[i]);

    m_dolSz = dolSize;
}

bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath, const ExtractionContext& ctx) const
{
    SystemStringView nameView(getName());
    SystemString path = basePath + _S("/") + nameView.sys_str();

    if (m_kind == NODE_DIRECTORY)
    {
        if (ctx.verbose && ctx.progressCB && !getName().empty())
            ctx.progressCB(getName());
        if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
        {
            LogModule.report(LogVisor::Error, _S("unable to mkdir '%s'"), path.c_str());
            return false;
        }
        for (Node& subnode : *this)
            if (!subnode.extractToDirectory(path, ctx))
                return false;
    }
    else if (m_kind == NODE_FILE)
    {
        Sstat theStat;
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB(getName());

        if (ctx.force || Stat(path.c_str(), &theStat))
        {
            std::unique_ptr<IPartReadStream> rs = beginReadStream();
            std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(path)->beginWriteStream();
            ws->copyFromDisc(*rs, m_discLength);
        }
    }
    return true;
}

bool DiscBase::IPartition::extractToDirectory(const SystemString& path, const ExtractionContext& ctx)
{
    Sstat theStat;
    if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
    {
        LogModule.report(LogVisor::Error, _S("unable to mkdir '%s'"), path.c_str());
        return false;
    }

    /* Extract Apploader */
    SystemString apploaderPath = path + _S("/apploader.bin");
    if (ctx.force || Stat(apploaderPath.c_str(), &theStat))
    {
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB("apploader.bin");
        std::unique_ptr<uint8_t[]> buf = getApploaderBuf();
        NewFileIO(apploaderPath)->beginWriteStream()->write(buf.get(), m_apploaderSz);
    }

    /* Extract Dol */
    SystemString dolPath = path + _S("/main.dol");
    if (ctx.force || Stat(dolPath.c_str(), &theStat))
    {
        if (ctx.verbose && ctx.progressCB)
            ctx.progressCB("main.dol");
        std::unique_ptr<uint8_t[]> buf = getDOLBuf();
        NewFileIO(dolPath)->beginWriteStream()->write(buf.get(), m_dolSz);
    }

    /* Extract Filesystem */
    return m_nodes[0].extractToDirectory(path, ctx);
}

}
<|endoftext|>


<commit_before>/*
This file is part of WME Lite.
http://dead-code.org/redir.php?target=wmelite

Copyright (c) 2011 Jan Nedoma

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "dcgf.h"
#include "SXArray.h"

IMPLEMENT_PERSISTENT(CSXArray, false);

//////////////////////////////////////////////////////////////////////////
CSXArray::CSXArray(CBGame* inGame, CScStack* Stack):CBScriptable(inGame)
{
	m_Length = 0;
	m_Values = new CScValue(Game);

	int NumParams = Stack->Pop()->GetInt(0);

	// Originally there was 1 and >1
	// This made a serious problem when called a = new Array("X"); as the
	// item got swallowed and game would break.
	// NEED to ask if there are any issues I've just caused with this fix...

//	if(NumParams==0) m_Length = Stack->Pop()->GetInt(0);

	if(NumParams>=1){
		m_Length = NumParams;
		char ParamName[20];
		for(int i=0; i<NumParams; i++){
			sprintf(ParamName, "%d", i);
			m_Values->SetProp(ParamName, Stack->Pop());
		}
	}
}

//////////////////////////////////////////////////////////////////////////
CSXArray::CSXArray(CBGame* inGame):CBScriptable(inGame)
{
	m_Length = 0;
	m_Values = new CScValue(Game);
}

//////////////////////////////////////////////////////////////////////////
CSXArray::~CSXArray()
{
	SAFE_DELETE(m_Values);
}

//////////////////////////////////////////////////////////////////////////
char* CSXArray::ScToString()
{
	static char Dummy[32768];
	strcpy(Dummy, "");
	char PropName[20];
	for(int i=0; i<m_Length; i++){
		sprintf(PropName, "%d", i);
		CScValue* val = m_Values->GetProp(PropName);
		if(val){
			if(strlen(Dummy) + strlen(val->GetString()) < 32768){
				strcat(Dummy, val->GetString());
			}
		}

		if(i<m_Length-1 && strlen(Dummy)+1 < 32768) strcat(Dummy, ",");
	}
	return Dummy;
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
	//////////////////////////////////////////////////////////////////////////
	// Push
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Push")==0){
		int NumParams = Stack->Pop()->GetInt(0);
		char ParamName[20];

		for(int i=0; i<NumParams; i++){
			m_Length++;
			sprintf(ParamName, "%d", m_Length-1);
			m_Values->SetProp(ParamName, Stack->Pop(), true);
		}
		Stack->PushInt(m_Length);

		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Pop
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Pop")==0){

		Stack->CorrectParams(0);

		if(m_Length>0){
			char ParamName[20];
			sprintf(ParamName, "%d", m_Length-1);
			Stack->Push(m_Values->GetProp(ParamName));
			m_Values->DeleteProp(ParamName);
			m_Length--;
		}
		else Stack->PushNULL();

		return S_OK;
	}

	else return E_FAIL;
}

//////////////////////////////////////////////////////////////////////////
CScValue* CSXArray::ScGetProperty(char *Name)
{
	m_ScValue->SetNULL();

	//////////////////////////////////////////////////////////////////////////
	// Type
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Type")==0){
		m_ScValue->SetString("array");
		return m_ScValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// Length
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "Length")==0){
		m_ScValue->SetInt(m_Length);
		return m_ScValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// [number]
	//////////////////////////////////////////////////////////////////////////
	else{
		char ParamName[20];
		if(ValidNumber(Name, ParamName)){
			return m_Values->GetProp(ParamName);
		}
		else return m_ScValue;
	}
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::ScSetProperty(char *Name, CScValue *Value)
{
	//////////////////////////////////////////////////////////////////////////
	// Length
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Length")==0){
		int OrigLength = m_Length;
		m_Length = max(Value->GetInt(0), 0);

		char PropName[20];
		if(m_Length < OrigLength){
			for(int i=m_Length; i<OrigLength; i++){
				sprintf(PropName, "%d", i);
				m_Values->DeleteProp(PropName);
			}
		}
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// [number]
	//////////////////////////////////////////////////////////////////////////
	else{
		char ParamName[20];
		if(ValidNumber(Name, ParamName)){
			int Index = atoi(ParamName);
			if(Index>=m_Length) m_Length = Index + 1;
			return m_Values->SetProp(ParamName, Value);
		}
		else return E_FAIL;
	}
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::Persist(CBPersistMgr* PersistMgr)
{
	CBScriptable::Persist(PersistMgr);

	PersistMgr->Transfer(TMEMBER(m_Length));
	PersistMgr->Transfer(TMEMBER(m_Values));

	return S_OK;
}

//////////////////////////////////////////////////////////////////////////
bool CSXArray::ValidNumber(const char *OrigStr, char *OutStr)
{
	bool IsNumber = true;
	for(int i=0; i<strlen(OrigStr); i++){
		if(!isdigit(OrigStr[i])){
			IsNumber = false;
			break;
		}
	}

	if(IsNumber){
		int Index = atoi(OrigStr);
		sprintf(OutStr, "%d", Index);
		return true;
	}
	else return false;
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::Push(CScValue* Val)
{
	char ParamName[20];
	m_Length++;
	sprintf(ParamName, "%d", m_Length-1);
	m_Values->SetProp(ParamName, Val, true);
	return S_OK;
}<commit_msg>Final fix<commit_after>/*
This file is part of WME Lite.
http://dead-code.org/redir.php?target=wmelite

Copyright (c) 2011 Jan Nedoma

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "dcgf.h"
#include "SXArray.h"

IMPLEMENT_PERSISTENT(CSXArray, false);

//////////////////////////////////////////////////////////////////////////
CSXArray::CSXArray(CBGame* inGame, CScStack* Stack):CBScriptable(inGame)
{
	m_Length = 0;
	m_Values = new CScValue(Game);

	int NumParams = Stack->Pop()->GetInt(0);

	if(NumParams>=1){
		if(NumParams==1 && Stack->GetTop()->IsInt())
			m_Length = Stack->Pop()->GetInt(0);
		else
		{
			m_Length = NumParams;
			char ParamName[20];
			for(int i=0; i<NumParams; i++){
				sprintf(ParamName, "%d", i);
				m_Values->SetProp(ParamName, Stack->Pop());
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////
CSXArray::CSXArray(CBGame* inGame):CBScriptable(inGame)
{
	m_Length = 0;
	m_Values = new CScValue(Game);
}

//////////////////////////////////////////////////////////////////////////
CSXArray::~CSXArray()
{
	SAFE_DELETE(m_Values);
}

//////////////////////////////////////////////////////////////////////////
char* CSXArray::ScToString()
{
	static char Dummy[32768];
	strcpy(Dummy, "");
	char PropName[20];
	for(int i=0; i<m_Length; i++){
		sprintf(PropName, "%d", i);
		CScValue* val = m_Values->GetProp(PropName);
		if(val){
			if(strlen(Dummy) + strlen(val->GetString()) < 32768){
				strcat(Dummy, val->GetString());
			}
		}

		if(i<m_Length-1 && strlen(Dummy)+1 < 32768) strcat(Dummy, ",");
	}
	return Dummy;
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
	//////////////////////////////////////////////////////////////////////////
	// Push
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Push")==0){
		int NumParams = Stack->Pop()->GetInt(0);
		char ParamName[20];

		for(int i=0; i<NumParams; i++){
			m_Length++;
			sprintf(ParamName, "%d", m_Length-1);
			m_Values->SetProp(ParamName, Stack->Pop(), true);
		}
		Stack->PushInt(m_Length);

		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Pop
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Pop")==0){

		Stack->CorrectParams(0);

		if(m_Length>0){
			char ParamName[20];
			sprintf(ParamName, "%d", m_Length-1);
			Stack->Push(m_Values->GetProp(ParamName));
			m_Values->DeleteProp(ParamName);
			m_Length--;
		}
		else Stack->PushNULL();

		return S_OK;
	}

	else return E_FAIL;
}

//////////////////////////////////////////////////////////////////////////
CScValue* CSXArray::ScGetProperty(char *Name)
{
	m_ScValue->SetNULL();

	//////////////////////////////////////////////////////////////////////////
	// Type
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Type")==0){
		m_ScValue->SetString("array");
		return m_ScValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// Length
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "Length")==0){
		m_ScValue->SetInt(m_Length);
		return m_ScValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// [number]
	//////////////////////////////////////////////////////////////////////////
	else{
		char ParamName[20];
		if(ValidNumber(Name, ParamName)){
			return m_Values->GetProp(ParamName);
		}
		else return m_ScValue;
	}
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::ScSetProperty(char *Name, CScValue *Value)
{
	//////////////////////////////////////////////////////////////////////////
	// Length
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "Length")==0){
		int OrigLength = m_Length;
		m_Length = max(Value->GetInt(0), 0);

		char PropName[20];
		if(m_Length < OrigLength){
			for(int i=m_Length; i<OrigLength; i++){
				sprintf(PropName, "%d", i);
				m_Values->DeleteProp(PropName);
			}
		}
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// [number]
	//////////////////////////////////////////////////////////////////////////
	else{
		char ParamName[20];
		if(ValidNumber(Name, ParamName)){
			int Index = atoi(ParamName);
			if(Index>=m_Length) m_Length = Index + 1;
			return m_Values->SetProp(ParamName, Value);
		}
		else return E_FAIL;
	}
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::Persist(CBPersistMgr* PersistMgr)
{
	CBScriptable::Persist(PersistMgr);

	PersistMgr->Transfer(TMEMBER(m_Length));
	PersistMgr->Transfer(TMEMBER(m_Values));

	return S_OK;
}

//////////////////////////////////////////////////////////////////////////
bool CSXArray::ValidNumber(const char *OrigStr, char *OutStr)
{
	bool IsNumber = true;
	for(int i=0; i<strlen(OrigStr); i++){
		if(!isdigit(OrigStr[i])){
			IsNumber = false;
			break;
		}
	}

	if(IsNumber){
		int Index = atoi(OrigStr);
		sprintf(OutStr, "%d", Index);
		return true;
	}
	else return false;
}

//////////////////////////////////////////////////////////////////////////
HRESULT CSXArray::Push(CScValue* Val)
{
	char ParamName[20];
	m_Length++;
	sprintf(ParamName, "%d", m_Length-1);
	m_Values->SetProp(ParamName, Val, true);
	return S_OK;
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: seinitializer_nssimpl.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 18:13:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

/*
 * Turn off DEBUG Assertions
 */
#ifdef _DEBUG
    #define _DEBUG_WAS_DEFINED _DEBUG
    #undef _DEBUG
#else
    #undef _DEBUG_WAS_DEFINED
#endif

/*
 * and turn off the additional virtual methods which are part of some interfaces when compiled
 * with debug
 */
#ifdef DEBUG
    #define DEBUG_WAS_DEFINED DEBUG
    #undef DEBUG
#else
    #undef DEBUG_WAS_DEFINED
#endif

#include <sal/types.h>

#include <tools/debug.hxx>

#include "seinitializer_nssimpl.hxx"

#include "securityenvironment_nssimpl.hxx"

#ifndef _COM_SUN_STAR_MOZILLA_XMOZILLABOOTSTRAP_HPP_
#include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
#endif

#include "nspr.h"
#include "prtypes.h"
#include "pk11func.h"
#include "cert.h"
#include "cryptohi.h"
#include "certdb.h"
#include "nss.h"

namespace cssu = com::sun::star::uno;
namespace cssl = com::sun::star::lang;
namespace cssxc = com::sun::star::xml::crypto;

using namespace com::sun::star;

#define SERVICE_NAME "com.sun.star.xml.crypto.SEInitializer"
#define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.SEInitializer_NssImpl"
#define SECURITY_ENVIRONMENT "com.sun.star.xml.crypto.SecurityEnvironment"
#define SECURITY_CONTEXT "com.sun.star.xml.crypto.XMLSecurityContext"

bool nsscrypto_initialize( const char* token ) {
    static char initialized = 0 ;

    //PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
    if( !initialized ) {
        PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;

        if( NSS_Init( token ) != SECSuccess )
            return false ;

        initialized = 1 ;
    }

    return true ;
}

void nsscrypto_finalize() {
    PK11_LogoutAll();
    NSS_Shutdown();
}

//bool getMozillaCurrentProfile(rtl::OUString& profilePath);
bool getMozillaCurrentProfile(
    const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF,
    rtl::OUString& profilePath);

SEInitializer_NssImpl::SEInitializer_NssImpl(
    const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF)
    :mxMSF( rxMSF )
{
}

SEInitializer_NssImpl::~SEInitializer_NssImpl()
{
}

/* XSEInitializer */
cssu::Reference< cssxc::XXMLSecurityContext > SAL_CALL
    SEInitializer_NssImpl::createSecurityContext(
    const rtl::OUString& sCertDB )
    throw (cssu::RuntimeException)
{
    CERTCertDBHandle    *pCertHandle = NULL ;
    PK11SlotInfo        *pSlot = NULL , *pInternalSlot = NULL ;
    PK11SymKey          *pSymKey = NULL ;
    PRBool              found;

    rtl::OString sCertDir;
    if( sCertDB.getLength() )
    {
        sCertDir = rtl::OString(sCertDB, sCertDB.getLength(), RTL_TEXTENCODING_ASCII_US);
    }
    else
    {
        static rtl::OString* pDefaultCertDir = NULL;
        if ( !pDefaultCertDir )
        {
            pDefaultCertDir = new rtl::OString;
            rtl::OUString ouCertDir;

#if 0
            /*
             * a dialog should be displayed to let user select a product, from
             * 1) Mozilla (mozilla::MozillaProductType_Mozilla),
             * 2) Thunderbird (mozilla::MozillaProductType_Thunderbird),
             * 3) Firefox(mozilla::MozillaProductType_Firefox),
             *
             * At this moment, I just use Mozilla
             */
            mozilla::MozillaProductType profileType = mozilla::MozillaProductType_Firefox;

            char* productNames[4] = {
                "Mozilla","Thunderbird","Firefox","Default"
            };

            mozilla::MozillaProductType productTypes[4] = {
                mozilla::MozillaProductType_Mozilla,
                mozilla::MozillaProductType_Thunderbird,
                mozilla::MozillaProductType_Firefox,
                mozilla::MozillaProductType_Default };

            int nProduct = 4;

            fprintf( stdout, "\nSelect a product from the following list\n" ) ;
            fprintf( stdout, "================================================================================" ) ;
            for( int i = 0; i < nProduct; ++i )
            {
                fprintf( stdout, "%d : [%s]\n", i+1, productNames[i]);
            }

            fprintf( stdout, "================================================================================\n" ) ;
            bool bInvalid = false;
            int sel = 0;

            do
            {
                if (bInvalid)
                {
                    fprintf( stdout, "Invalid value! " );
                }

                fprintf( stdout, "Select <1-%d>:", nProduct ) ;
                fscanf( stdin, "%d", &sel ) ;
                bInvalid = true;
            }while(sel<1 || sel>nProduct);

            profileType = productTypes[sel-1];
#endif

            if ( getMozillaCurrentProfile(mxMSF, ouCertDir) )
                *pDefaultCertDir = rtl::OString(ouCertDir, ouCertDir.getLength(), RTL_TEXTENCODING_ASCII_US);
        }
        sCertDir = *pDefaultCertDir;

    }

    if( !sCertDir.getLength() )
        return NULL;

    /* Initialize NSPR and NSS */
    /* Replaced with new methods by AF. ----
    //PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
    PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;

    if (NSS_Init(sCertDir.getStr()) != SECSuccess )
    {
        PK11_LogoutAll();
        return NULL;
    }
    ----*/
    if( !nsscrypto_initialize( sCertDir.getStr() ) )
        return NULL ;
    else
        atexit( nsscrypto_finalize ) ;

    pCertHandle = CERT_GetDefaultCertDB() ;

    /*- i39448 - we will get all slots defined in the profile
    * ---------- and alloc them in each SecurityEnviroment .
    * ---------- By CP/20050105
    --------------------------*/
    pInternalSlot = PK11_GetInternalKeySlot() ;
    if (pInternalSlot == NULL)
    {
    //  PK11_LogoutAll();
    //  NSS_Shutdown();
        return NULL;
    }
    try
    {
        PK11SlotList* soltList ;
        PK11SlotListElement* soltEle ;

        /* Build XML Security Context */
        const rtl::OUString sSecyrutyContext ( RTL_CONSTASCII_USTRINGPARAM( SECURITY_CONTEXT ) );
        cssu::Reference< cssxc::XXMLSecurityContext > xSecCtx( mxMSF->createInstance ( sSecyrutyContext ), cssu::UNO_QUERY );
        if( !xSecCtx.is() )
        {
        //  PK11_LogoutAll();
        //  NSS_Shutdown();
            return NULL;
        }

        soltList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL ) ;
        if( soltList != NULL ) {
            for( soltEle = soltList->head ; soltEle != NULL; soltEle = soltEle->next ) {

                found = PR_FALSE;

                pSlot = soltEle->slot ;

                if(pSlot != NULL){

                    pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC, NULL, 128, NULL ) ;
                    if( pSymKey == NULL )
                    {
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    /* Build Security Environment */
                    const rtl::OUString sSecyrutyEnvironment ( RTL_CONSTASCII_USTRINGPARAM( SECURITY_ENVIRONMENT ) );
                    cssu::Reference< cssxc::XSecurityEnvironment > xSecEnv( mxMSF->createInstance ( sSecyrutyEnvironment ), cssu::UNO_QUERY );
                    if( !xSecEnv.is() )
                    {
                        PK11_FreeSymKey( pSymKey ) ;
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    /* Setup key slot and certDb */
                    cssu::Reference< cssl::XUnoTunnel > xEnvTunnel( xSecEnv , cssu::UNO_QUERY ) ;
                    if( !xEnvTunnel.is() )
                    {
                        PK11_FreeSymKey( pSymKey ) ;
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    SecurityEnvironment_NssImpl* pSecEnv = ( SecurityEnvironment_NssImpl* )xEnvTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() ) ;
                    if( pSecEnv == NULL )
                    {
                        PK11_FreeSymKey( pSymKey ) ;
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    // search the internal slot.
                    //PR_fprintf(PR_STDOUT, "Token:%s\n",PK11_GetSlotName(pSlot));
                    //found = PK11_IsInternal(pSlot) ; //This method will return two true result.
                    if((!strcmp(PK11_GetSlotName(pInternalSlot),PK11_GetSlotName(pSlot))&&(!strcmp(PK11_GetTokenName(pInternalSlot),PK11_GetTokenName(pSlot)))))
                    {
                        found = PR_TRUE;
                    }

                    pSecEnv->setCryptoSlot( pSlot ) ;
                    PK11_FreeSlot( pSlot ) ;
                    pSlot = NULL;

                    pSecEnv->setCertDb( pCertHandle ) ;

                    pSecEnv->adoptSymKey( pSymKey ) ;
                    PK11_FreeSymKey( pSymKey ) ;
                    pSymKey = NULL;

                    sal_Int32 n = xSecCtx->addSecurityEnvironment( xSecEnv ) ;

                    if(found != PR_FALSE)
                    {
                        xSecCtx->setDefaultSecurityEnvironmentIndex( n ) ;
                    }

                }// end of if(pSlot != NULL)
            }// end of for
        }// end of if( soltList != NULL )

        if(pInternalSlot != NULL)
        {
            PK11_FreeSlot(pInternalSlot) ;
            pInternalSlot = NULL ;
        }

        return xSecCtx;
    }
    catch( cssu::Exception& )
    {
        if (pSymKey != NULL)
        {
            PK11_FreeSymKey( pSymKey ) ;
        }

        if (pSlot != NULL)
        {
            PK11_FreeSlot( pSlot ) ;
        }

        if(pInternalSlot != NULL)
        {
            PK11_FreeSlot(pInternalSlot) ;
            pInternalSlot = NULL ;
        }

        //PK11_LogoutAll();
        //NSS_Shutdown();
        return NULL;
    }
}

void SAL_CALL SEInitializer_NssImpl::freeSecurityContext( const cssu::Reference< cssxc::XXMLSecurityContext >& securityContext )
    throw (cssu::RuntimeException)
{
    /*
     * because the security context will free all its content when it
     * is destructed, so here no free process for the security context
     * is needed.
     */
    //PK11_LogoutAll();
    //NSS_Shutdown();
}

rtl::OUString SEInitializer_NssImpl_getImplementationName ()
    throw (cssu::RuntimeException)
{
    return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
}

sal_Bool SAL_CALL SEInitializer_NssImpl_supportsService( const rtl::OUString& ServiceName )
    throw (cssu::RuntimeException)
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
}

cssu::Sequence< rtl::OUString > SAL_CALL SEInitializer_NssImpl_getSupportedServiceNames(  )
    throw (cssu::RuntimeException)
{
    cssu::Sequence < rtl::OUString > aRet(1);
    rtl::OUString* pArray = aRet.getArray();
    pArray[0] =  rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
    return aRet;
}
#undef SERVICE_NAME

cssu::Reference< cssu::XInterface > SAL_CALL SEInitializer_NssImpl_createInstance( const cssu::Reference< cssl::XMultiServiceFactory > & rSMgr)
    throw( cssu::Exception )
{
    return (cppu::OWeakObject*) new SEInitializer_NssImpl(rSMgr);
}

/* XServiceInfo */
rtl::OUString SAL_CALL SEInitializer_NssImpl::getImplementationName(  )
    throw (cssu::RuntimeException)
{
    return SEInitializer_NssImpl_getImplementationName();
}
sal_Bool SAL_CALL SEInitializer_NssImpl::supportsService( const rtl::OUString& rServiceName )
    throw (cssu::RuntimeException)
{
    return SEInitializer_NssImpl_supportsService( rServiceName );
}
cssu::Sequence< rtl::OUString > SAL_CALL SEInitializer_NssImpl::getSupportedServiceNames(  )
    throw (cssu::RuntimeException)
{
    return SEInitializer_NssImpl_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS systemmozilla (1.11.22); FILE MERGED 2005/03/12 00:00:34 rene 1.11.22.2: RESYNC: (1.11-1.12); FILE MERGED 2005/01/17 13:32:05 rene 1.11.22.1: implement MOZ_NSS_HACK to build even without PK11_GetCertFromPrivateKey missing from mozilla and use nssrenam.h, needed for e.g. CERT_DecodeDERCertificate availavailablity<commit_after>/*************************************************************************
 *
 *  $RCSfile: seinitializer_nssimpl.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: rt $ $Date: 2005-03-30 11:37:03 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

/*
 * Turn off DEBUG Assertions
 */
#ifdef _DEBUG
    #define _DEBUG_WAS_DEFINED _DEBUG
    #undef _DEBUG
#else
    #undef _DEBUG_WAS_DEFINED
#endif

/*
 * and turn off the additional virtual methods which are part of some interfaces when compiled
 * with debug
 */
#ifdef DEBUG
    #define DEBUG_WAS_DEFINED DEBUG
    #undef DEBUG
#else
    #undef DEBUG_WAS_DEFINED
#endif

#include <sal/types.h>

#include <tools/debug.hxx>

#include "seinitializer_nssimpl.hxx"

#include "securityenvironment_nssimpl.hxx"

#ifndef _COM_SUN_STAR_MOZILLA_XMOZILLABOOTSTRAP_HPP_
#include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
#endif

#include "nspr.h"
#include "prtypes.h"
#include "pk11func.h"
#ifdef SYSTEM_MOZILLA
#include "nssrenam.h"
#endif
#include "cert.h"
#include "cryptohi.h"
#include "certdb.h"
#include "nss.h"

namespace cssu = com::sun::star::uno;
namespace cssl = com::sun::star::lang;
namespace cssxc = com::sun::star::xml::crypto;

using namespace com::sun::star;

#define SERVICE_NAME "com.sun.star.xml.crypto.SEInitializer"
#define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.SEInitializer_NssImpl"
#define SECURITY_ENVIRONMENT "com.sun.star.xml.crypto.SecurityEnvironment"
#define SECURITY_CONTEXT "com.sun.star.xml.crypto.XMLSecurityContext"

bool nsscrypto_initialize( const char* token ) {
    static char initialized = 0 ;

    //PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
    if( !initialized ) {
        PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;

        if( NSS_Init( token ) != SECSuccess )
            return false ;

        initialized = 1 ;
    }

    return true ;
}

void nsscrypto_finalize() {
    PK11_LogoutAll();
    NSS_Shutdown();
}

//bool getMozillaCurrentProfile(rtl::OUString& profilePath);
bool getMozillaCurrentProfile(
    const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF,
    rtl::OUString& profilePath);

SEInitializer_NssImpl::SEInitializer_NssImpl(
    const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF)
    :mxMSF( rxMSF )
{
}

SEInitializer_NssImpl::~SEInitializer_NssImpl()
{
}

/* XSEInitializer */
cssu::Reference< cssxc::XXMLSecurityContext > SAL_CALL
    SEInitializer_NssImpl::createSecurityContext(
    const rtl::OUString& sCertDB )
    throw (cssu::RuntimeException)
{
    CERTCertDBHandle    *pCertHandle = NULL ;
    PK11SlotInfo        *pSlot = NULL , *pInternalSlot = NULL ;
    PK11SymKey          *pSymKey = NULL ;
    PRBool              found;

    rtl::OString sCertDir;
    if( sCertDB.getLength() )
    {
        sCertDir = rtl::OString(sCertDB, sCertDB.getLength(), RTL_TEXTENCODING_ASCII_US);
    }
    else
    {
        static rtl::OString* pDefaultCertDir = NULL;
        if ( !pDefaultCertDir )
        {
            pDefaultCertDir = new rtl::OString;
            rtl::OUString ouCertDir;

#if 0
            /*
             * a dialog should be displayed to let user select a product, from
             * 1) Mozilla (mozilla::MozillaProductType_Mozilla),
             * 2) Thunderbird (mozilla::MozillaProductType_Thunderbird),
             * 3) Firefox(mozilla::MozillaProductType_Firefox),
             *
             * At this moment, I just use Mozilla
             */
            mozilla::MozillaProductType profileType = mozilla::MozillaProductType_Firefox;

            char* productNames[4] = {
                "Mozilla","Thunderbird","Firefox","Default"
            };

            mozilla::MozillaProductType productTypes[4] = {
                mozilla::MozillaProductType_Mozilla,
                mozilla::MozillaProductType_Thunderbird,
                mozilla::MozillaProductType_Firefox,
                mozilla::MozillaProductType_Default };

            int nProduct = 4;

            fprintf( stdout, "\nSelect a product from the following list\n" ) ;
            fprintf( stdout, "================================================================================" ) ;
            for( int i = 0; i < nProduct; ++i )
            {
                fprintf( stdout, "%d : [%s]\n", i+1, productNames[i]);
            }

            fprintf( stdout, "================================================================================\n" ) ;
            bool bInvalid = false;
            int sel = 0;

            do
            {
                if (bInvalid)
                {
                    fprintf( stdout, "Invalid value! " );
                }

                fprintf( stdout, "Select <1-%d>:", nProduct ) ;
                fscanf( stdin, "%d", &sel ) ;
                bInvalid = true;
            }while(sel<1 || sel>nProduct);

            profileType = productTypes[sel-1];
#endif

            if ( getMozillaCurrentProfile(mxMSF, ouCertDir) )
                *pDefaultCertDir = rtl::OString(ouCertDir, ouCertDir.getLength(), RTL_TEXTENCODING_ASCII_US);
        }
        sCertDir = *pDefaultCertDir;

    }

    if( !sCertDir.getLength() )
        return NULL;

    /* Initialize NSPR and NSS */
    /* Replaced with new methods by AF. ----
    //PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
    PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;

    if (NSS_Init(sCertDir.getStr()) != SECSuccess )
    {
        PK11_LogoutAll();
        return NULL;
    }
    ----*/
    if( !nsscrypto_initialize( sCertDir.getStr() ) )
        return NULL ;
    else
        atexit( nsscrypto_finalize ) ;

    pCertHandle = CERT_GetDefaultCertDB() ;

    /*- i39448 - we will get all slots defined in the profile
    * ---------- and alloc them in each SecurityEnviroment .
    * ---------- By CP/20050105
    --------------------------*/
    pInternalSlot = PK11_GetInternalKeySlot() ;
    if (pInternalSlot == NULL)
    {
    //  PK11_LogoutAll();
    //  NSS_Shutdown();
        return NULL;
    }
    try
    {
        PK11SlotList* soltList ;
        PK11SlotListElement* soltEle ;

        /* Build XML Security Context */
        const rtl::OUString sSecyrutyContext ( RTL_CONSTASCII_USTRINGPARAM( SECURITY_CONTEXT ) );
        cssu::Reference< cssxc::XXMLSecurityContext > xSecCtx( mxMSF->createInstance ( sSecyrutyContext ), cssu::UNO_QUERY );
        if( !xSecCtx.is() )
        {
        //  PK11_LogoutAll();
        //  NSS_Shutdown();
            return NULL;
        }

        soltList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL ) ;
        if( soltList != NULL ) {
            for( soltEle = soltList->head ; soltEle != NULL; soltEle = soltEle->next ) {

                found = PR_FALSE;

                pSlot = soltEle->slot ;

                if(pSlot != NULL){

                    pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC, NULL, 128, NULL ) ;
                    if( pSymKey == NULL )
                    {
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    /* Build Security Environment */
                    const rtl::OUString sSecyrutyEnvironment ( RTL_CONSTASCII_USTRINGPARAM( SECURITY_ENVIRONMENT ) );
                    cssu::Reference< cssxc::XSecurityEnvironment > xSecEnv( mxMSF->createInstance ( sSecyrutyEnvironment ), cssu::UNO_QUERY );
                    if( !xSecEnv.is() )
                    {
                        PK11_FreeSymKey( pSymKey ) ;
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    /* Setup key slot and certDb */
                    cssu::Reference< cssl::XUnoTunnel > xEnvTunnel( xSecEnv , cssu::UNO_QUERY ) ;
                    if( !xEnvTunnel.is() )
                    {
                        PK11_FreeSymKey( pSymKey ) ;
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    SecurityEnvironment_NssImpl* pSecEnv = ( SecurityEnvironment_NssImpl* )xEnvTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() ) ;
                    if( pSecEnv == NULL )
                    {
                        PK11_FreeSymKey( pSymKey ) ;
                        PK11_FreeSlot( pSlot ) ;
                    //  PK11_LogoutAll();
                    //  NSS_Shutdown();
                        return NULL;
                    }

                    // search the internal slot.
                    //PR_fprintf(PR_STDOUT, "Token:%s\n",PK11_GetSlotName(pSlot));
                    //found = PK11_IsInternal(pSlot) ; //This method will return two true result.
                    if((!strcmp(PK11_GetSlotName(pInternalSlot),PK11_GetSlotName(pSlot))&&(!strcmp(PK11_GetTokenName(pInternalSlot),PK11_GetTokenName(pSlot)))))
                    {
                        found = PR_TRUE;
                    }

                    pSecEnv->setCryptoSlot( pSlot ) ;
                    PK11_FreeSlot( pSlot ) ;
                    pSlot = NULL;

                    pSecEnv->setCertDb( pCertHandle ) ;

                    pSecEnv->adoptSymKey( pSymKey ) ;
                    PK11_FreeSymKey( pSymKey ) ;
                    pSymKey = NULL;

                    sal_Int32 n = xSecCtx->addSecurityEnvironment( xSecEnv ) ;

                    if(found != PR_FALSE)
                    {
                        xSecCtx->setDefaultSecurityEnvironmentIndex( n ) ;
                    }

                }// end of if(pSlot != NULL)
            }// end of for
        }// end of if( soltList != NULL )

        if(pInternalSlot != NULL)
        {
            PK11_FreeSlot(pInternalSlot) ;
            pInternalSlot = NULL ;
        }

        return xSecCtx;
    }
    catch( cssu::Exception& )
    {
        if (pSymKey != NULL)
        {
            PK11_FreeSymKey( pSymKey ) ;
        }

        if (pSlot != NULL)
        {
            PK11_FreeSlot( pSlot ) ;
        }

        if(pInternalSlot != NULL)
        {
            PK11_FreeSlot(pInternalSlot) ;
            pInternalSlot = NULL ;
        }

        //PK11_LogoutAll();
        //NSS_Shutdown();
        return NULL;
    }
}

void SAL_CALL SEInitializer_NssImpl::freeSecurityContext( const cssu::Reference< cssxc::XXMLSecurityContext >& securityContext )
    throw (cssu::RuntimeException)
{
    /*
     * because the security context will free all its content when it
     * is destructed, so here no free process for the security context
     * is needed.
     */
    //PK11_LogoutAll();
    //NSS_Shutdown();
}

rtl::OUString SEInitializer_NssImpl_getImplementationName ()
    throw (cssu::RuntimeException)
{
    return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
}

sal_Bool SAL_CALL SEInitializer_NssImpl_supportsService( const rtl::OUString& ServiceName )
    throw (cssu::RuntimeException)
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
}

cssu::Sequence< rtl::OUString > SAL_CALL SEInitializer_NssImpl_getSupportedServiceNames(  )
    throw (cssu::RuntimeException)
{
    cssu::Sequence < rtl::OUString > aRet(1);
    rtl::OUString* pArray = aRet.getArray();
    pArray[0] =  rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
    return aRet;
}
#undef SERVICE_NAME

cssu::Reference< cssu::XInterface > SAL_CALL SEInitializer_NssImpl_createInstance( const cssu::Reference< cssl::XMultiServiceFactory > & rSMgr)
    throw( cssu::Exception )
{
    return (cppu::OWeakObject*) new SEInitializer_NssImpl(rSMgr);
}

/* XServiceInfo */
rtl::OUString SAL_CALL SEInitializer_NssImpl::getImplementationName(  )
    throw (cssu::RuntimeException)
{
    return SEInitializer_NssImpl_getImplementationName();
}
sal_Bool SAL_CALL SEInitializer_NssImpl::supportsService( const rtl::OUString& rServiceName )
    throw (cssu::RuntimeException)
{
    return SEInitializer_NssImpl_supportsService( rServiceName );
}
cssu::Sequence< rtl::OUString > SAL_CALL SEInitializer_NssImpl::getSupportedServiceNames(  )
    throw (cssu::RuntimeException)
{
    return SEInitializer_NssImpl_getSupportedServiceNames();
}

<|endoftext|>


<commit_before>// ***************************************************************************
// FastaIndex.cpp (c) 2010 Erik Garrison <erik.garrison@bc.edu>
// Marth Lab, Department of Biology, Boston College
// All rights reserved.
// ---------------------------------------------------------------------------
// Last modified: 9 February 2010 (EG)
// ---------------------------------------------------------------------------

#include "Fasta.h"

FastaIndexEntry::FastaIndexEntry(string name, int length, long long offset, int line_blen, int line_len)
    : name(name)
    , length(length)
    , offset(offset)
    , line_blen(line_blen)
    , line_len(line_len)
{}

FastaIndexEntry::FastaIndexEntry(void) // empty constructor
{ clear(); }

FastaIndexEntry::~FastaIndexEntry(void)
{}

void FastaIndexEntry::clear(void)
{
    name = "";
    length = 0;
    offset = -1;  // no real offset will ever be below 0, so this allows us to
                  // check if we have already recorded a real offset
    line_blen = 0;
    line_len = 0;
}

ostream& operator<<(ostream& output, const FastaIndexEntry& e) {
    // just write the first component of the name, for compliance with other tools
    output << split(e.name, ' ').at(0) << "\t" << e.length << "\t" << e.offset << "\t" <<
        e.line_blen << "\t" << e.line_len;
    return output;  // for multiple << operators.
}

FastaIndex::FastaIndex(void)
{}

void FastaIndex::readIndexFile(string fname) {
    string line;
    long long linenum = 0;
    indexFile.open(fname.c_str(), ifstream::in);
    if (indexFile.is_open()) {
        while (getline (indexFile, line)) {
            ++linenum;
            // the fai format defined in samtools is tab-delimited, every line being:
            // fai->name[i], (int)x.len, (long long)x.offset, (int)x.line_blen, (int)x.line_len
            vector<string> fields = split(line, '\t');
            if (fields.size() == 5) {  // if we don't get enough fields then there is a problem with the file
                // note that fields[0] is the sequence name
                char* end;
                string name = split(fields[0], " \t").at(0);  // key by first token of name
                sequenceNames.push_back(name);
                this->insert(make_pair(name, FastaIndexEntry(fields[0], atoi(fields[1].c_str()),
                                                    strtoll(fields[2].c_str(), &end, 10),
                                                    atoi(fields[3].c_str()),
                                                    atoi(fields[4].c_str()))));
            } else {
                cerr << "Warning: malformed fasta index file " << fname <<
                    "does not have enough fields @ line " << linenum << endl;
                cerr << line << endl;
                exit(1);
            }
        }
    } else {
        cerr << "could not open index file " << fname << endl;
        exit(1);
    }
}

// for consistency this should be a class method
bool fastaIndexEntryCompare ( FastaIndexEntry a, FastaIndexEntry b) { return (a.offset<b.offset); }

ostream& operator<<(ostream& output, FastaIndex& fastaIndex) {
    vector<FastaIndexEntry> sortedIndex;
    for(vector<string>::const_iterator it = fastaIndex.sequenceNames.begin(); it != fastaIndex.sequenceNames.end(); ++it)
    {
        sortedIndex.push_back(fastaIndex[*it]);
    }
    sort(sortedIndex.begin(), sortedIndex.end(), fastaIndexEntryCompare);
    for( vector<FastaIndexEntry>::iterator fit = sortedIndex.begin(); fit != sortedIndex.end(); ++fit) {
        output << *fit << endl;
    }
}

void FastaIndex::indexReference(string refname) {
    // overview:
    //  for line in the reference fasta file
    //  track byte offset from the start of the file
    //  if line is a fasta header, take the name and dump the last sequnece to the index
    //  if line is a sequence, add it to the current sequence
    //cerr << "indexing fasta reference " << refname << endl;
    string line;
    FastaIndexEntry entry;  // an entry buffer used in processing
    entry.clear();
    int line_length = 0;
    long long offset = 0;  // byte offset from start of file
    long long line_number = 0; // current line number
    bool mismatchedLineLengths = false; // flag to indicate if our line length changes mid-file
                                        // this will be used to raise an error
                                        // if we have a line length change at
                                        // any line other than the last line in
                                        // the sequence
    bool emptyLine = false;  // flag to catch empty lines, which we allow for
                             // index generation only on the last line of the sequence
    ifstream refFile;
    refFile.open(refname.c_str());
    if (refFile.is_open()) {
        while (getline(refFile, line)) {
            ++line_number;
            line_length = line.length();
            if (line[0] == ';') {
                // fasta comment, skip
            } else if (line[0] == '+') {
                // fastq quality header
                getline(refFile, line);
                line_length = line.length();
                offset += line_length + 1;
                // get and don't handle the quality line
                getline(refFile, line);
                line_length = line.length();
            } else if (line[0] == '>' || line[0] == '@') { // fasta /fastq header
                // if we aren't on the first entry, push the last sequence into the index
                if (entry.name != "") {
                    mismatchedLineLengths = false; // reset line length error tracker for every new sequence
                    emptyLine = false;
                    flushEntryToIndex(entry);
                    entry.clear();
                }
                entry.name = line.substr(1, line_length - 1);
            } else { // we assume we have found a sequence line
                if (entry.offset == -1) // NB initially the offset is -1
                    entry.offset = offset;
                entry.length += line_length;
                if (entry.line_len) {
                    //entry.line_len = entry.line_len ? entry.line_len : line_length + 1;
                    if (mismatchedLineLengths || emptyLine) {
                        if (line_length == 0) {
                            emptyLine = true; // flag empty lines, raise error only if this is embedded in the sequence
                        } else {
                            if (emptyLine) {
                                cerr << "ERROR: embedded newline";
                            } else {
                                cerr << "ERROR: mismatched line lengths";
                            }
                            cerr << " at line " << line_number << " within sequence " << entry.name <<
                                endl << "File not suitable for fasta index generation." << endl;
                            exit(1);
                        }
                    }
                    // this flag is set here and checked on the next line
                    // because we may have reached the end of the sequence, in
                    // which case a mismatched line length is OK
                    if (entry.line_len != line_length + 1) {
                        mismatchedLineLengths = true;
                        if (line_length == 0) {
                            emptyLine = true; // flag empty lines, raise error only if this is embedded in the sequence
                        }
                    }
                } else {
                    entry.line_len = line_length + 1; // first line
                }
                entry.line_blen = entry.line_len - 1;
            }
            offset += line_length + 1;
        }
        // we've hit the end of the fasta file!
        // flush the last entry
        flushEntryToIndex(entry);
    } else {
        cerr << "could not open reference file " << refname << " for indexing!" << endl;
        exit(1);
    }
}

void FastaIndex::flushEntryToIndex(FastaIndexEntry& entry) {
    string name = split(entry.name, " \t").at(0);  // key by first token of name
    sequenceNames.push_back(name);
    this->insert(make_pair(name, FastaIndexEntry(entry.name, entry.length,
                        entry.offset, entry.line_blen,
                        entry.line_len)));

}

void FastaIndex::writeIndexFile(string fname) {
    //cerr << "writing fasta index file " << fname << endl;
    ofstream file;
    file.open(fname.c_str());
    if (file.is_open()) {
        file << *this;
    } else {
        cerr << "could not open index file " << fname << " for writing!" << endl;
        exit(1);
    }
}

FastaIndex::~FastaIndex(void) {
    indexFile.close();
}

FastaIndexEntry FastaIndex::entry(string name) {
    FastaIndex::iterator e = this->find(name);
    if (e == this->end()) {
        cerr << "unable to find FASTA index entry for '" << name << "'" << endl;
        exit(1);
    } else {
        return e->second;
    }
}

string FastaIndex::indexFileExtension() { return ".fai"; }

/*
FastaReference::FastaReference(string reffilename) {
}
*/

void FastaReference::open(string reffilename) {
    filename = reffilename;
    if (!(file = fopen(filename.c_str(), "r"))) {
        cerr << "could not open " << filename << endl;
        exit(1);
    }
    index = new FastaIndex();
    struct stat stFileInfo;
    string indexFileName = filename + index->indexFileExtension();
    // if we can find an index file, use it
    if(stat(indexFileName.c_str(), &stFileInfo) == 0) {
        index->readIndexFile(indexFileName);
    } else { // otherwise, read the reference and generate the index file in the cwd
        cerr << "index file " << indexFileName << " not found, generating..." << endl;
        index->indexReference(filename);
        index->writeIndexFile(indexFileName);
    }
}

FastaReference::~FastaReference(void) {
    fclose(file);
    delete index;
}

string FastaReference::getSequence(string seqname) {
    FastaIndexEntry entry = index->entry(seqname);
    int newlines_in_sequence = entry.length / entry.line_blen;
    int seqlen = newlines_in_sequence  + entry.length;
    char* seq = (char*) calloc (seqlen + 1, sizeof(char));
    fseek64(file, entry.offset, SEEK_SET);
    fread(seq, sizeof(char), seqlen, file);
    seq[seqlen] = '\0';
    char* pbegin = seq;
    char* pend = seq + (seqlen/sizeof(char));
    pend = remove(pbegin, pend, '\n');
    pend = remove(pbegin, pend, '\0');
    string s = seq;
    free(seq);
    s.resize((pend - pbegin)/sizeof(char));
    return s;
}

// TODO cleanup; odd function.  use a map
string FastaReference::sequenceNameStartingWith(string seqnameStart) {
    try {
        return (*index)[seqnameStart].name;
    } catch (exception& e) {
        cerr << e.what() << ": unable to find index entry for " << seqnameStart << endl;
        exit(1);
    }
}

string FastaReference::getTargetSubSequence(FastaRegion& target) {
    if (target.startPos == -1) {
        return getSequence(target.startSeq);
    } else {
        return getSubSequence(target.startSeq, target.startPos - 1, target.length());
    }
}

string FastaReference::getSubSequence(string seqname, int start, int length) {
    FastaIndexEntry entry = index->entry(seqname);
    length = min(length, entry.length - start);
    if (start < 0 || length < 1) {
        //cerr << "Empty sequence" << endl;
        return "";
    }
    // we have to handle newlines
    // approach: count newlines before start
    //           count newlines by end of read
    //             subtracting newlines before start find count of embedded newlines
    int newlines_before = start > 0 ? (start - 1) / entry.line_blen : 0;
    int newlines_by_end = (start + length - 1) / entry.line_blen;
    int newlines_inside = newlines_by_end - newlines_before;
    int seqlen = length + newlines_inside;
    char* seq = (char*) calloc (seqlen + 1, sizeof(char));
    fseek64(file, (off_t) (entry.offset + newlines_before + start), SEEK_SET);
    fread(seq, sizeof(char), (off_t) seqlen, file);
    seq[seqlen] = '\0';
    char* pbegin = seq;
    char* pend = seq + (seqlen/sizeof(char));
    pend = remove(pbegin, pend, '\n');
    pend = remove(pbegin, pend, '\0');
    string s = seq;
    free(seq);
    s.resize((pend - pbegin)/sizeof(char));
    return s;
}

long unsigned int FastaReference::sequenceLength(string seqname) {
    FastaIndexEntry entry = index->entry(seqname);
    return entry.length;
}

<commit_msg>cleanup build, avoid segfault on read failure<commit_after>// ***************************************************************************
// FastaIndex.cpp (c) 2010 Erik Garrison <erik.garrison@bc.edu>
// Marth Lab, Department of Biology, Boston College
// All rights reserved.
// ---------------------------------------------------------------------------
// Last modified: 9 February 2010 (EG)
// ---------------------------------------------------------------------------

#include "Fasta.h"

FastaIndexEntry::FastaIndexEntry(string name, int length, long long offset, int line_blen, int line_len)
    : name(name)
    , length(length)
    , offset(offset)
    , line_blen(line_blen)
    , line_len(line_len)
{}

FastaIndexEntry::FastaIndexEntry(void) // empty constructor
{ clear(); }

FastaIndexEntry::~FastaIndexEntry(void)
{}

void FastaIndexEntry::clear(void)
{
    name = "";
    length = 0;
    offset = -1;  // no real offset will ever be below 0, so this allows us to
                  // check if we have already recorded a real offset
    line_blen = 0;
    line_len = 0;
}

ostream& operator<<(ostream& output, const FastaIndexEntry& e) {
    // just write the first component of the name, for compliance with other tools
    output << split(e.name, ' ').at(0) << "\t" << e.length << "\t" << e.offset << "\t" <<
        e.line_blen << "\t" << e.line_len;
    return output;  // for multiple << operators.
}

FastaIndex::FastaIndex(void)
{}

void FastaIndex::readIndexFile(string fname) {
    string line;
    long long linenum = 0;
    indexFile.open(fname.c_str(), ifstream::in);
    if (indexFile.is_open()) {
        while (getline (indexFile, line)) {
            ++linenum;
            // the fai format defined in samtools is tab-delimited, every line being:
            // fai->name[i], (int)x.len, (long long)x.offset, (int)x.line_blen, (int)x.line_len
            vector<string> fields = split(line, '\t');
            if (fields.size() == 5) {  // if we don't get enough fields then there is a problem with the file
                // note that fields[0] is the sequence name
                char* end;
                string name = split(fields[0], " \t").at(0);  // key by first token of name
                sequenceNames.push_back(name);
                this->insert(make_pair(name, FastaIndexEntry(fields[0], atoi(fields[1].c_str()),
                                                    strtoll(fields[2].c_str(), &end, 10),
                                                    atoi(fields[3].c_str()),
                                                    atoi(fields[4].c_str()))));
            } else {
                cerr << "Warning: malformed fasta index file " << fname <<
                    "does not have enough fields @ line " << linenum << endl;
                cerr << line << endl;
                exit(1);
            }
        }
    } else {
        cerr << "could not open index file " << fname << endl;
        exit(1);
    }
}

// for consistency this should be a class method
bool fastaIndexEntryCompare ( FastaIndexEntry a, FastaIndexEntry b) { return (a.offset<b.offset); }

ostream& operator<<(ostream& output, FastaIndex& fastaIndex) {
    vector<FastaIndexEntry> sortedIndex;
    for(vector<string>::const_iterator it = fastaIndex.sequenceNames.begin(); it != fastaIndex.sequenceNames.end(); ++it)
    {
        sortedIndex.push_back(fastaIndex[*it]);
    }
    sort(sortedIndex.begin(), sortedIndex.end(), fastaIndexEntryCompare);
    for( vector<FastaIndexEntry>::iterator fit = sortedIndex.begin(); fit != sortedIndex.end(); ++fit) {
        output << *fit << endl;
    }
}

void FastaIndex::indexReference(string refname) {
    // overview:
    //  for line in the reference fasta file
    //  track byte offset from the start of the file
    //  if line is a fasta header, take the name and dump the last sequnece to the index
    //  if line is a sequence, add it to the current sequence
    //cerr << "indexing fasta reference " << refname << endl;
    string line;
    FastaIndexEntry entry;  // an entry buffer used in processing
    entry.clear();
    int line_length = 0;
    long long offset = 0;  // byte offset from start of file
    long long line_number = 0; // current line number
    bool mismatchedLineLengths = false; // flag to indicate if our line length changes mid-file
                                        // this will be used to raise an error
                                        // if we have a line length change at
                                        // any line other than the last line in
                                        // the sequence
    bool emptyLine = false;  // flag to catch empty lines, which we allow for
                             // index generation only on the last line of the sequence
    ifstream refFile;
    refFile.open(refname.c_str());
    if (refFile.is_open()) {
        while (getline(refFile, line)) {
            ++line_number;
            line_length = line.length();
            if (line[0] == ';') {
                // fasta comment, skip
            } else if (line[0] == '+') {
                // fastq quality header
                getline(refFile, line);
                line_length = line.length();
                offset += line_length + 1;
                // get and don't handle the quality line
                getline(refFile, line);
                line_length = line.length();
            } else if (line[0] == '>' || line[0] == '@') { // fasta /fastq header
                // if we aren't on the first entry, push the last sequence into the index
                if (entry.name != "") {
                    mismatchedLineLengths = false; // reset line length error tracker for every new sequence
                    emptyLine = false;
                    flushEntryToIndex(entry);
                    entry.clear();
                }
                entry.name = line.substr(1, line_length - 1);
            } else { // we assume we have found a sequence line
                if (entry.offset == -1) // NB initially the offset is -1
                    entry.offset = offset;
                entry.length += line_length;
                if (entry.line_len) {
                    //entry.line_len = entry.line_len ? entry.line_len : line_length + 1;
                    if (mismatchedLineLengths || emptyLine) {
                        if (line_length == 0) {
                            emptyLine = true; // flag empty lines, raise error only if this is embedded in the sequence
                        } else {
                            if (emptyLine) {
                                cerr << "ERROR: embedded newline";
                            } else {
                                cerr << "ERROR: mismatched line lengths";
                            }
                            cerr << " at line " << line_number << " within sequence " << entry.name <<
                                endl << "File not suitable for fasta index generation." << endl;
                            exit(1);
                        }
                    }
                    // this flag is set here and checked on the next line
                    // because we may have reached the end of the sequence, in
                    // which case a mismatched line length is OK
                    if (entry.line_len != line_length + 1) {
                        mismatchedLineLengths = true;
                        if (line_length == 0) {
                            emptyLine = true; // flag empty lines, raise error only if this is embedded in the sequence
                        }
                    }
                } else {
                    entry.line_len = line_length + 1; // first line
                }
                entry.line_blen = entry.line_len - 1;
            }
            offset += line_length + 1;
        }
        // we've hit the end of the fasta file!
        // flush the last entry
        flushEntryToIndex(entry);
    } else {
        cerr << "could not open reference file " << refname << " for indexing!" << endl;
        exit(1);
    }
}

void FastaIndex::flushEntryToIndex(FastaIndexEntry& entry) {
    string name = split(entry.name, " \t").at(0);  // key by first token of name
    sequenceNames.push_back(name);
    this->insert(make_pair(name, FastaIndexEntry(entry.name, entry.length,
                        entry.offset, entry.line_blen,
                        entry.line_len)));

}

void FastaIndex::writeIndexFile(string fname) {
    //cerr << "writing fasta index file " << fname << endl;
    ofstream file;
    file.open(fname.c_str());
    if (file.is_open()) {
        file << *this;
    } else {
        cerr << "could not open index file " << fname << " for writing!" << endl;
        exit(1);
    }
}

FastaIndex::~FastaIndex(void) {
    indexFile.close();
}

FastaIndexEntry FastaIndex::entry(string name) {
    FastaIndex::iterator e = this->find(name);
    if (e == this->end()) {
        cerr << "unable to find FASTA index entry for '" << name << "'" << endl;
        exit(1);
    } else {
        return e->second;
    }
}

string FastaIndex::indexFileExtension() { return ".fai"; }

/*
FastaReference::FastaReference(string reffilename) {
}
*/

void FastaReference::open(string reffilename) {
    filename = reffilename;
    if (!(file = fopen(filename.c_str(), "r"))) {
        cerr << "could not open " << filename << endl;
        exit(1);
    }
    index = new FastaIndex();
    struct stat stFileInfo;
    string indexFileName = filename + index->indexFileExtension();
    // if we can find an index file, use it
    if(stat(indexFileName.c_str(), &stFileInfo) == 0) {
        index->readIndexFile(indexFileName);
    } else { // otherwise, read the reference and generate the index file in the cwd
        cerr << "index file " << indexFileName << " not found, generating..." << endl;
        index->indexReference(filename);
        index->writeIndexFile(indexFileName);
    }
}

FastaReference::~FastaReference(void) {
    fclose(file);
    delete index;
}

string FastaReference::getSequence(string seqname) {
    FastaIndexEntry entry = index->entry(seqname);
    int newlines_in_sequence = entry.length / entry.line_blen;
    int seqlen = newlines_in_sequence  + entry.length;
    char* seq = (char*) calloc (seqlen + 1, sizeof(char));
    fseek64(file, entry.offset, SEEK_SET);
    string s;
    if (fread(seq, sizeof(char), seqlen, file)) {
        seq[seqlen] = '\0';
        char* pbegin = seq;
        char* pend = seq + (seqlen/sizeof(char));
        pend = remove(pbegin, pend, '\n');
        pend = remove(pbegin, pend, '\0');
        s = seq;
        free(seq);
        s.resize((pend - pbegin)/sizeof(char));
    }
    return s;
}

// TODO cleanup; odd function.  use a map
string FastaReference::sequenceNameStartingWith(string seqnameStart) {
    try {
        return (*index)[seqnameStart].name;
    } catch (exception& e) {
        cerr << e.what() << ": unable to find index entry for " << seqnameStart << endl;
        exit(1);
    }
}

string FastaReference::getTargetSubSequence(FastaRegion& target) {
    if (target.startPos == -1) {
        return getSequence(target.startSeq);
    } else {
        return getSubSequence(target.startSeq, target.startPos - 1, target.length());
    }
}

string FastaReference::getSubSequence(string seqname, int start, int length) {
    FastaIndexEntry entry = index->entry(seqname);
    length = min(length, entry.length - start);
    if (start < 0 || length < 1) {
        //cerr << "Empty sequence" << endl;
        return "";
    }
    // we have to handle newlines
    // approach: count newlines before start
    //           count newlines by end of read
    //             subtracting newlines before start find count of embedded newlines
    int newlines_before = start > 0 ? (start - 1) / entry.line_blen : 0;
    int newlines_by_end = (start + length - 1) / entry.line_blen;
    int newlines_inside = newlines_by_end - newlines_before;
    int seqlen = length + newlines_inside;
    char* seq = (char*) calloc (seqlen + 1, sizeof(char));
    fseek64(file, (off_t) (entry.offset + newlines_before + start), SEEK_SET);
    string s;
    if (fread(seq, sizeof(char), (off_t) seqlen, file)) {
        seq[seqlen] = '\0';
        char* pbegin = seq;
        char* pend = seq + (seqlen/sizeof(char));
        pend = remove(pbegin, pend, '\n');
        pend = remove(pbegin, pend, '\0');
        s = seq;
        free(seq);
        s.resize((pend - pbegin)/sizeof(char));
    }
    return s;
}

long unsigned int FastaReference::sequenceLength(string seqname) {
    FastaIndexEntry entry = index->entry(seqname);
    return entry.length;
}

<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"

namespace cv
{

BOWTrainer::BOWTrainer()
{}

BOWTrainer::~BOWTrainer()
{}

void BOWTrainer::add( const Mat& _descriptors )
{
    CV_Assert( !_descriptors.empty() );
    if( !descriptors.empty() )
    {
        CV_Assert( descriptors[0].cols == _descriptors.cols );
        CV_Assert( descriptors[0].type() == _descriptors.type() );
        size += _descriptors.rows;
    }
    else
    {
        size = _descriptors.rows;
    }

    descriptors.push_back(_descriptors);
}

const std::vector<Mat>& BOWTrainer::getDescriptors() const
{
    return descriptors;
}

int BOWTrainer::descriptorsCount() const
{
    return descriptors.empty() ? 0 : size;
}

void BOWTrainer::clear()
{
    descriptors.clear();
}

BOWKMeansTrainer::BOWKMeansTrainer( int _clusterCount, const TermCriteria& _termcrit,
                                    int _attempts, int _flags ) :
    clusterCount(_clusterCount), termcrit(_termcrit), attempts(_attempts), flags(_flags)
{}

Mat BOWKMeansTrainer::cluster() const
{
    CV_Assert( !descriptors.empty() );

    int descCount = 0;
    for( size_t i = 0; i < descriptors.size(); i++ )
        descCount += descriptors[i].rows;

    Mat mergedDescriptors( descCount, descriptors[0].cols, descriptors[0].type() );
    for( size_t i = 0, start = 0; i < descriptors.size(); i++ )
    {
        Mat submut = mergedDescriptors.rowRange((int)start, (int)(start + descriptors[i].rows));
        descriptors[i].copyTo(submut);
        start += descriptors[i].rows;
    }
    return cluster( mergedDescriptors );
}

BOWKMeansTrainer::~BOWKMeansTrainer()
{}

Mat BOWKMeansTrainer::cluster( const Mat& _descriptors ) const
{
    Mat labels, vocabulary;
    kmeans( _descriptors, clusterCount, labels, termcrit, attempts, flags, vocabulary );
    return vocabulary;
}

BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor>& _dextractor,
                                                      const Ptr<DescriptorMatcher>& _dmatcher ) :
    dextractor(_dextractor), dmatcher(_dmatcher)
{}

BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorMatcher>& _dmatcher ) :
    dmatcher(_dmatcher)
{}

BOWImgDescriptorExtractor::~BOWImgDescriptorExtractor()
{}

void BOWImgDescriptorExtractor::setVocabulary( const Mat& _vocabulary )
{
    dmatcher->clear();
    vocabulary = _vocabulary;
    dmatcher->add( std::vector<Mat>(1, vocabulary) );
}

const Mat& BOWImgDescriptorExtractor::getVocabulary() const
{
    return vocabulary;
}

void BOWImgDescriptorExtractor::compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray imgDescriptor,
                                         std::vector<std::vector<int> >* pointIdxsOfClusters, Mat* descriptors )
{
    imgDescriptor.release();

    if( keypoints.empty() )
        return;

    // Compute descriptors for the image.
    Mat _descriptors;
    dextractor->compute( image, keypoints, _descriptors );

    compute( _descriptors, imgDescriptor, pointIdxsOfClusters );

    // Add the descriptors of image keypoints
    if (descriptors) {
        *descriptors = _descriptors.clone();
    }
}

int BOWImgDescriptorExtractor::descriptorSize() const
{
    return vocabulary.empty() ? 0 : vocabulary.rows;
}

int BOWImgDescriptorExtractor::descriptorType() const
{
    return CV_32FC1;
}

void BOWImgDescriptorExtractor::compute( InputArray keypointDescriptors, OutputArray _imgDescriptor, std::vector<std::vector<int> >* pointIdxsOfClusters )
{
    CV_Assert( vocabulary.empty() != false );

    int clusterCount = descriptorSize(); // = vocabulary.rows

    // Match keypoint descriptors to cluster center (to vocabulary)
    std::vector<DMatch> matches;
    dmatcher->match( keypointDescriptors, matches );

    // Compute image descriptor
    if( pointIdxsOfClusters )
    {
        pointIdxsOfClusters->clear();
        pointIdxsOfClusters->resize(clusterCount);
    }

    _imgDescriptor.create(1, clusterCount, descriptorType());
    _imgDescriptor.setTo(Scalar::all(0));

    Mat imgDescriptor = _imgDescriptor.getMat();

    float *dptr = (float*)imgDescriptor.data;
    for( size_t i = 0; i < matches.size(); i++ )
    {
        int queryIdx = matches[i].queryIdx;
        int trainIdx = matches[i].trainIdx; // cluster index
        CV_Assert( queryIdx == (int)i );

        dptr[trainIdx] = dptr[trainIdx] + 1.f;
        if( pointIdxsOfClusters )
            (*pointIdxsOfClusters)[trainIdx].push_back( queryIdx );
    }

    // Normalize image descriptor.
    imgDescriptor /= keypointDescriptors.size().height;
}

}
<commit_msg>Fixed CV_ASSERT condition in the code for bag of words<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"

namespace cv
{

BOWTrainer::BOWTrainer()
{}

BOWTrainer::~BOWTrainer()
{}

void BOWTrainer::add( const Mat& _descriptors )
{
    CV_Assert( !_descriptors.empty() );
    if( !descriptors.empty() )
    {
        CV_Assert( descriptors[0].cols == _descriptors.cols );
        CV_Assert( descriptors[0].type() == _descriptors.type() );
        size += _descriptors.rows;
    }
    else
    {
        size = _descriptors.rows;
    }

    descriptors.push_back(_descriptors);
}

const std::vector<Mat>& BOWTrainer::getDescriptors() const
{
    return descriptors;
}

int BOWTrainer::descriptorsCount() const
{
    return descriptors.empty() ? 0 : size;
}

void BOWTrainer::clear()
{
    descriptors.clear();
}

BOWKMeansTrainer::BOWKMeansTrainer( int _clusterCount, const TermCriteria& _termcrit,
                                    int _attempts, int _flags ) :
    clusterCount(_clusterCount), termcrit(_termcrit), attempts(_attempts), flags(_flags)
{}

Mat BOWKMeansTrainer::cluster() const
{
    CV_Assert( !descriptors.empty() );

    int descCount = 0;
    for( size_t i = 0; i < descriptors.size(); i++ )
        descCount += descriptors[i].rows;

    Mat mergedDescriptors( descCount, descriptors[0].cols, descriptors[0].type() );
    for( size_t i = 0, start = 0; i < descriptors.size(); i++ )
    {
        Mat submut = mergedDescriptors.rowRange((int)start, (int)(start + descriptors[i].rows));
        descriptors[i].copyTo(submut);
        start += descriptors[i].rows;
    }
    return cluster( mergedDescriptors );
}

BOWKMeansTrainer::~BOWKMeansTrainer()
{}

Mat BOWKMeansTrainer::cluster( const Mat& _descriptors ) const
{
    Mat labels, vocabulary;
    kmeans( _descriptors, clusterCount, labels, termcrit, attempts, flags, vocabulary );
    return vocabulary;
}

BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor>& _dextractor,
                                                      const Ptr<DescriptorMatcher>& _dmatcher ) :
    dextractor(_dextractor), dmatcher(_dmatcher)
{}

BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorMatcher>& _dmatcher ) :
    dmatcher(_dmatcher)
{}

BOWImgDescriptorExtractor::~BOWImgDescriptorExtractor()
{}

void BOWImgDescriptorExtractor::setVocabulary( const Mat& _vocabulary )
{
    dmatcher->clear();
    vocabulary = _vocabulary;
    dmatcher->add( std::vector<Mat>(1, vocabulary) );
}

const Mat& BOWImgDescriptorExtractor::getVocabulary() const
{
    return vocabulary;
}

void BOWImgDescriptorExtractor::compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray imgDescriptor,
                                         std::vector<std::vector<int> >* pointIdxsOfClusters, Mat* descriptors )
{
    imgDescriptor.release();

    if( keypoints.empty() )
        return;

    // Compute descriptors for the image.
    Mat _descriptors;
    dextractor->compute( image, keypoints, _descriptors );

    compute( _descriptors, imgDescriptor, pointIdxsOfClusters );

    // Add the descriptors of image keypoints
    if (descriptors) {
        *descriptors = _descriptors.clone();
    }
}

int BOWImgDescriptorExtractor::descriptorSize() const
{
    return vocabulary.empty() ? 0 : vocabulary.rows;
}

int BOWImgDescriptorExtractor::descriptorType() const
{
    return CV_32FC1;
}

void BOWImgDescriptorExtractor::compute( InputArray keypointDescriptors, OutputArray _imgDescriptor, std::vector<std::vector<int> >* pointIdxsOfClusters )
{
    CV_Assert( !vocabulary.empty() );

    int clusterCount = descriptorSize(); // = vocabulary.rows

    // Match keypoint descriptors to cluster center (to vocabulary)
    std::vector<DMatch> matches;
    dmatcher->match( keypointDescriptors, matches );

    // Compute image descriptor
    if( pointIdxsOfClusters )
    {
        pointIdxsOfClusters->clear();
        pointIdxsOfClusters->resize(clusterCount);
    }

    _imgDescriptor.create(1, clusterCount, descriptorType());
    _imgDescriptor.setTo(Scalar::all(0));

    Mat imgDescriptor = _imgDescriptor.getMat();

    float *dptr = (float*)imgDescriptor.data;
    for( size_t i = 0; i < matches.size(); i++ )
    {
        int queryIdx = matches[i].queryIdx;
        int trainIdx = matches[i].trainIdx; // cluster index
        CV_Assert( queryIdx == (int)i );

        dptr[trainIdx] = dptr[trainIdx] + 1.f;
        if( pointIdxsOfClusters )
            (*pointIdxsOfClusters)[trainIdx].push_back( queryIdx );
    }

    // Normalize image descriptor.
    imgDescriptor /= keypointDescriptors.size().height;
}

}
<|endoftext|>