lrc / src / compiler / InFileParser.cxx

//      InFileParser.cxx
//
//      Copyright 2011, 2012, 2013 Andreas Tscharner <andy@vis.ethz.ch>
//
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU Lesser General Public License as
//      published by the Free Software Foundation; either version 3 of the
//      License, or (at your option) any later version.
//
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//
//      You should have received a copy of the GNU Lesser General Public
//      License along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.


#include <tuple>
#include <cstring>
#include <cstdio>
#include "../StatusCodes.hxx"
#include "../Utils.hxx"
#include "InFileParser.hxx"


void InFileParser::clear_internal_error(void)
{
	m_errorPosition = std::make_tuple(-1, -1);
	m_lastError = NO_ERROR;
	m_internalError = ieNone;
}


InFileParser::InFileParser(char *p_filename) throw(lrcFileNotFoundException)
{
	size_t len;


	DEBUG_PRINT(("Constructor of InFileParser. Checking filename %s\n", p_filename))

	if (!file_exists(p_filename)) {
		throw lrcFileNotFoundException(p_filename);
	};
	len = strlen(p_filename)+1;
	m_filename = new char[len];
	memset(m_filename, 0, len);
	strncpy(m_filename, p_filename, (len-1));

	m_resEntries = new std::vector<ResourceData *>;

	this->clear_internal_error();
}

InFileParser::~InFileParser(void)
{
	if (m_resEntries) {
		delete m_resEntries;
	};
	if (m_filename) {
		delete[] m_filename;
	};
}

lrc::CompressionType InFileParser::eval_compression_type(const char *p_compStr)
{
	DEBUG_PRINT(("Evaluating compression string: %s\n", p_compStr))

	if (strcmp("None", p_compStr) == 0) {
		return lrc::NoneCompression;
	};

	for (unsigned int iter = lrc::NoneCompression; iter < lrc::lastCompression; iter++) {
		if (strcmp(lrc::CompressionTypeNames[iter], p_compStr) == 0) {
			return static_cast<lrc::CompressionType>(iter);
		};
	};

	return lrc::NoneCompression;
}

lrc::EncryptionType InFileParser::eval_encryption_type(const char * p_encStr)
{
	DEBUG_PRINT(("Evaluating encryption string: %s\n", p_encStr))

	if (strcmp("None", p_encStr) == 0) {
		return lrc::NoneEncryption;
	};

	for (unsigned int iter = lrc::NoneEncryption; iter < lrc::lastEncryption; iter++) {
		if (strcmp(lrc::EncryptionTypeNames[iter], p_encStr) == 0) {
			return static_cast<lrc::EncryptionType>(iter);
		};
	};

	return lrc::NoneEncryption;
}

unsigned char *InFileParser::get_password(const char *p_passwdStr) throw(lrcFileNotFoundException)
{
	char *pwdFilename;
	unsigned char *retPasswd;
	size_t pwdLen;
	FILE *pwdFile;
	int pwdFileSize;


	if (!p_passwdStr) {
		return nullptr;
	};

	pwdLen = strlen(p_passwdStr);
	if (pwdLen == 0) {
		return nullptr;
	};

	if (*p_passwdStr != '@') {
		retPasswd = new unsigned char[pwdLen+1];
		memset(retPasswd, 0, (pwdLen+1));
		memcpy(retPasswd, p_passwdStr, pwdLen);
		return retPasswd;
	};

	DEBUG_PRINT(("Password file notation found: %s\n", p_passwdStr))
	pwdFilename = new char[pwdLen];
	memset(pwdFilename, 0, pwdLen);
	memcpy(pwdFilename, &(p_passwdStr[1]), (pwdLen-1));

	if (!file_exists(pwdFilename)) {
		delete[] pwdFilename;
		throw lrcFileNotFoundException((char *)&(p_passwdStr[1]));
	};

	pwdFileSize = file_size(pwdFilename);
	retPasswd = new unsigned char[pwdFileSize+1];
	memset(retPasswd, 0, (pwdFileSize+1));

	pwdFile = fopen(pwdFilename, "rb");
	if (!pwdFile) {
		delete[] retPasswd;
		delete[] pwdFilename;

		return nullptr;
	};
	if (fread(retPasswd, sizeof(unsigned char), pwdFileSize, pwdFile) != pwdFileSize) {
		fclose(pwdFile);
		delete[] retPasswd;
		delete[] pwdFilename;

		return nullptr;
	};
	fclose(pwdFile);
	delete[] pwdFilename;

	DEBUG_PRINT(("Returned password [%s]\n", retPasswd))
	return retPasswd;
}

int InFileParser::get_internal_error(inFilePosition &p_errPos, char **errMsg)
{
	const int MAX_ERRMSG_LEN = 512;
	const char *STD_ERR_FORMAT = "%s:%u:%u: error: %s.\n";
	const char *INVALID_ELEMENT = "The root element or one of the sub elements has an invalid name";
	const char *IDENT_NOT_FOUND = "Mandatory resource identifier not specified";
	const char *FILENAME_NOT_FOUND = "Mandatory filename for resource not specified";
	const char *MISSING_PASSWORD = "A password must be provided if encryption is required";
	const char *MISSING_PASSWD_FILE = "The specified file in the password field could not be found";

	int lastError, sLen;
	char errorMesg[MAX_ERRMSG_LEN];


	switch (m_lastError) {
		case ERROR_FILE_OPEN:
			snprintf(errorMesg, MAX_ERRMSG_LEN, "Could not open file: %s\n",
			         m_filename);
			break;

		case ERROR_PARSE:
			switch (m_internalError) {
				case ieInvalidElement:
					snprintf(errorMesg, MAX_ERRMSG_LEN, STD_ERR_FORMAT, m_filename,
				             std::get<0>(m_errorPosition), std::get<1>(m_errorPosition),
				             INVALID_ELEMENT);
					break;
				case ieIdentNotFound:
					snprintf(errorMesg, MAX_ERRMSG_LEN, STD_ERR_FORMAT, m_filename,
				             std::get<0>(m_errorPosition), std::get<1>(m_errorPosition),
				             IDENT_NOT_FOUND);
					break;
				case ieFilenameNotFound:
					snprintf(errorMesg, MAX_ERRMSG_LEN, STD_ERR_FORMAT, m_filename,
				             std::get<0>(m_errorPosition), std::get<1>(m_errorPosition),
				             FILENAME_NOT_FOUND);
					break;
				case ieMissingPassword:
					snprintf(errorMesg, MAX_ERRMSG_LEN, STD_ERR_FORMAT, m_filename,
					         std::get<0>(m_errorPosition), std::get<1>(m_errorPosition),
					         MISSING_PASSWORD);
					break;
				case iePasswordFileNotFound:
					snprintf(errorMesg, MAX_ERRMSG_LEN, STD_ERR_FORMAT, m_filename,
					         std::get<0>(m_errorPosition), std::get<1>(m_errorPosition),
					         MISSING_PASSWD_FILE);
					break;
				};
			break;

		default:
			lastError = NO_ERROR;
	};

	lastError = m_lastError;

	p_errPos = m_errorPosition;

	sLen = strlen(errorMesg);
	*errMsg = new char[sLen+1];
	strncpy(*errMsg, errorMesg, sLen);

	this->clear_internal_error();
	return lastError;
}

std::vector<ResourceData *> *InFileParser::get_resource_entries(void)
{
	return m_resEntries;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.