<commit_before>
/*
 * Copyright (C) 2010, Victor Semionov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions 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.
 *
 * 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 COPYRIGHT HOLDER 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.
 */

#include <climits>

#include <string>
#include <vector>
#include <set>
#include <ostream>
#include <iostream>

#include "Poco/Util/ServerApplication.h"
#include "Poco/URI.h"
#include "Poco/File.h"
#include "Poco/DirectoryIterator.h"
#include "Poco/NumberFormatter.h"

#include "IndigoRequestHandler.h"
#include "IndigoConfiguration.h"

using namespace std;

using namespace Poco;
using namespace Poco::Util;
using namespace Poco::Net;

POCO_DECLARE_EXCEPTION(, ShareNotFoundException, ApplicationException)
POCO_IMPLEMENT_EXCEPTION(ShareNotFoundException, ApplicationException, "ShareNotFoundException")

IndigoRequestHandler::IndigoRequestHandler()
{
}

void IndigoRequestHandler::handleRequest(HTTPServerRequest &request, HTTPServerResponse &response)
{
	logRequest(request);

	const string &method = request.getMethod();

	if (method != HTTPRequest::HTTP_GET)
	{
		sendMethodNotAllowed(response);
		return;
	}

	URI uri;
	try
	{
		uri = request.getURI();
	}
	catch (SyntaxException &se)
	{
		sendBadRequest(response);
		return;
	}

	Path uriPath(uri.getPath(), Path::PATH_UNIX);

	if (!uriPath.isAbsolute())
	{
		sendBadRequest(response);
		return;
	}

	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	try
	{
		if (uriPath.isDirectory() && uriPath.depth() == 0)
		{
			if (configuration.virtualRoot())
			{
				sendVirtualIndex(response);
				return;
			}
		}

		const Path &fsPath = resolveFSPath(uriPath);
		const string &target = fsPath.toString();

		File f(target);
		if (f.isDirectory())
		{
			if (uriPath.isDirectory())
			{
				sendDirectoryIndex(response, target, uriPath.toString(Path::PATH_UNIX));
			}
			else
			{
				Path uriDirPath = uriPath;
				uriDirPath.makeDirectory();
				redirectToDirectory(response, uriDirPath.toString(Path::PATH_UNIX), false);
			}
		}
		else
		{
			sendFile(response, target);
		}
	}
	catch (ShareNotFoundException &snfe)
	{
		sendNotFound(response);
	}
	catch (FileNotFoundException &fnfe)
	{
		sendNotFound(response);
	}
	catch (FileAccessDeniedException &fade)
	{
		sendForbidden(response);
	}
	catch (FileException &fe)
	{
		sendInternalServerError(response);
	}
	catch (PathSyntaxException &pse)
	{
		sendNotImplemented(response);
	}
	catch (...)
	{
		sendInternalServerError(response);
	}
}

Path IndigoRequestHandler::resolveFSPath(const Path &uriPath)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const string &shareName = uriPath[0];
	string base = configuration.getSharePath(shareName);
	bool share = true;

	if (base.empty())
	{
		base = configuration.getRoot();
		if (base.empty())
			throw ShareNotFoundException();

		share = false;
	}

	Path fsPath(base);

	if (share)
	{
		fsPath.makeDirectory();

		const int d = uriPath.depth();
		for (int i = 1; i <= d; i++)
			fsPath.pushDirectory(uriPath[i]);
	}
	else
	{
		fsPath.append(uriPath);
	}

	fsPath.makeFile();
	return fsPath;
}

void IndigoRequestHandler::sendFile(HTTPServerResponse &response, const string &path)
{
	const string &ext = Path(path).getExtension();
	const string &mediaType = IndigoConfiguration::get().getMimeType(ext);
	response.sendFile(path, mediaType);
}

void IndigoRequestHandler::sendDirectoryListing(HTTPServerResponse &response, const string &dirURI, const vector<string> &entries)
{
	bool root = (dirURI == "/");

	response.setContentType("text/html");
	response.setContentLength(HTTPResponse::UNKNOWN_CONTENT_LENGTH);
	response.setChunkedTransferEncoding(true);

	ostream &out = response.send();

	out << "" << endl;
	out << "" << endl;
	out << "<title>";
	out << "Index of " << dirURI;
	out << "</title>" << endl;
	out << "" << endl;
	out << "" << endl;
	out << "
";
	out << "Index of " << dirURI;
	out << "
" << endl;

	if (!root)
	{
		out << "<Parent Directory>
" << endl;
	}

	const int l = entries.size();
	for (int i = 0; i < l; i++)
	{
		out << "<a href=\"" << entries[i] << "\">" << entries[i] << "" << "
" << endl;
	}

	out << "" << endl;
	out << "" << endl;
}

string IndigoRequestHandler::findVirtualIndex()
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const set<string> indexes = configuration.getIndexes();

	set<string>::const_iterator it;
	set<string>::const_iterator end = indexes.end();
	for (it = indexes.begin(); it != end; ++it)
	{
		try
		{
			const Path &index = resolveFSPath(Path("/" + *it, Path::PATH_UNIX));
			File f(index);
			if (f.isFile())
			{
				return index.toString();
			}
		}
		catch (ShareNotFoundException &snfe)
		{
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}
	}

	return "";
}

void IndigoRequestHandler::sendVirtualIndex(HTTPServerResponse &response)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const string &index = findVirtualIndex();
	if (!index.empty())
	{
		sendFile(response, index);
		return;
	}

	if (!configuration.getAutoIndex())
		throw ShareNotFoundException();

	const set<string> &shares = configuration.getShares();
	vector<string> entries;

	set<string>::const_iterator it;
	const set<string>::const_iterator &end = shares.end();
	for (it = shares.begin(); it != end; ++it)
	{
		const string &shareName = *it;
		try
		{
			const Path &fsPath = resolveFSPath(Path("/" + shareName, Path::PATH_UNIX));
			File f(fsPath);

			if (!f.isHidden())
			{
				string entry = shareName;
				if (f.isDirectory())
					entry += '/';

				entries.push_back(entry);
			}
		}
		catch (ShareNotFoundException &snfe)
		{
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}
	}

	sendDirectoryListing(response, "/", entries);
}

string IndigoRequestHandler::findDirectoryIndex(const string &base)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const set<string> indexes = configuration.getIndexes(true);

	set<string>::const_iterator it;
	set<string>::const_iterator end = indexes.end();
	for (it = indexes.begin(); it != end; ++it)
	{
		try
		{
			string index = base;
			if (index[index.length() - 1] != Path::separator())
				index += Path::separator();
			index += *it;

			File f(index);
			if (f.isFile())
			{
				return index;
			}
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}
	}

	return "";
}

void IndigoRequestHandler::sendDirectoryIndex(HTTPServerResponse &response, const string &path, const string &dirURI)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const string &index = findDirectoryIndex(path);
	if (!index.empty())
	{
		sendFile(response, index);
		return;
	}

	if (!configuration.getAutoIndex())
		throw FileNotFoundException();

	vector<string> entries;

	DirectoryIterator it(path);
	DirectoryIterator end;
	while (it != end)
	{
		try
		{
			if (!it->isHidden())
			{
				string entry = it.name();
				if (it->isDirectory())
					entry += '/';

				entries.push_back(entry);
			}
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}

		++it;
	}

	sendDirectoryListing(response, dirURI, entries);
}

void IndigoRequestHandler::redirectToDirectory(HTTPServerResponse &response, const string &dirURI, bool permanent)
{
	if (!permanent)
	{
		response.redirect(dirURI);
	}
	else
	{
		response.setStatusAndReason(HTTPResponse::HTTP_MOVED_PERMANENTLY);
		response.setContentLength(0);
		response.setChunkedTransferEncoding(false);
		response.set("Location", dirURI);
		response.send();
	}
}

void IndigoRequestHandler::logRequest(const HTTPServerRequest &request)
{
	const ServerApplication &app = dynamic_cast<ServerApplication &>(Application::instance());
	if (app.isInteractive())
	{
		const string &method = request.getMethod();
		const string &uri = request.getURI();
		const string &host = request.clientAddress().host().toString();

		string logString = host + " - " + method + " " + uri;

		app.logger().information(logString);
	}
}

void IndigoRequestHandler::sendError(HTTPServerResponse &response, int code)
{
	if (response.sent())
		return;

	response.setStatusAndReason(HTTPResponse::HTTPStatus(code));
	response.setChunkedTransferEncoding(true);
	response.setContentType("text/html");

	const string &reason = response.getReason();

	ostream &out = response.send();
	out << "";
	out << "<title>" + NumberFormatter::format(code) + " " + reason + "</title>";
	out << "
" + reason + "
";
	out << "";
}

void IndigoRequestHandler::sendMethodNotAllowed(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_METHOD_NOT_ALLOWED);
}

void IndigoRequestHandler::sendRequestURITooLong(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_REQUESTURITOOLONG);
}

void IndigoRequestHandler::sendBadRequest(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_BAD_REQUEST);
}

void IndigoRequestHandler::sendNotImplemented(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_NOT_IMPLEMENTED);
}

void IndigoRequestHandler::sendNotFound(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_NOT_FOUND);
}

void IndigoRequestHandler::sendForbidden(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_FORBIDDEN);
}

void IndigoRequestHandler::sendInternalServerError(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
}
<commit_msg>Refactoring.<commit_after>
/*
 * Copyright (C) 2010, Victor Semionov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions 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.
 *
 * 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 COPYRIGHT HOLDER 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.
 */

#include <climits>

#include <string>
#include <vector>
#include <set>
#include <ostream>
#include <iostream>

#include "Poco/Util/ServerApplication.h"
#include "Poco/URI.h"
#include "Poco/File.h"
#include "Poco/DirectoryIterator.h"
#include "Poco/NumberFormatter.h"

#include "IndigoRequestHandler.h"
#include "IndigoConfiguration.h"

using namespace std;

using namespace Poco;
using namespace Poco::Util;
using namespace Poco::Net;

POCO_DECLARE_EXCEPTION(, ShareNotFoundException, ApplicationException)
POCO_IMPLEMENT_EXCEPTION(ShareNotFoundException, ApplicationException, "ShareNotFoundException")

IndigoRequestHandler::IndigoRequestHandler()
{
}

void IndigoRequestHandler::handleRequest(HTTPServerRequest &request, HTTPServerResponse &response)
{
	logRequest(request);

	const string &method = request.getMethod();

	if (method != HTTPRequest::HTTP_GET)
	{
		sendMethodNotAllowed(response);
		return;
	}

	URI uri;
	try
	{
		uri = request.getURI();
	}
	catch (SyntaxException &se)
	{
		sendBadRequest(response);
		return;
	}

	Path uriPath(uri.getPath(), Path::PATH_UNIX);

	if (!uriPath.isAbsolute())
	{
		sendBadRequest(response);
		return;
	}

	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	try
	{
		if (uriPath.isDirectory() && uriPath.depth() == 0)
		{
			if (configuration.virtualRoot())
			{
				sendVirtualIndex(response);
				return;
			}
		}

		const Path &fsPath = resolveFSPath(uriPath);
		const string &target = fsPath.toString();

		File f(target);
		if (f.isDirectory())
		{
			if (uriPath.isDirectory())
			{
				sendDirectoryIndex(response, target, uriPath.toString(Path::PATH_UNIX));
			}
			else
			{
				Path uriDirPath = uriPath;
				uriDirPath.makeDirectory();
				redirectToDirectory(response, uriDirPath.toString(Path::PATH_UNIX), false);
			}
		}
		else
		{
			sendFile(response, target);
		}
	}
	catch (ShareNotFoundException &snfe)
	{
		sendNotFound(response);
	}
	catch (FileNotFoundException &fnfe)
	{
		sendNotFound(response);
	}
	catch (FileAccessDeniedException &fade)
	{
		sendForbidden(response);
	}
	catch (FileException &fe)
	{
		sendInternalServerError(response);
	}
	catch (PathSyntaxException &pse)
	{
		sendNotImplemented(response);
	}
	catch (...)
	{
		sendInternalServerError(response);
	}
}

Path IndigoRequestHandler::resolveFSPath(const Path &uriPath)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const string &shareName = uriPath[0];
	string base = configuration.getSharePath(shareName);
	bool share = true;

	if (base.empty())
	{
		base = configuration.getRoot();
		if (base.empty())
			throw ShareNotFoundException();

		share = false;
	}

	Path fsPath(base);

	if (share)
	{
		fsPath.makeDirectory();

		const int d = uriPath.depth();
		for (int i = 1; i <= d; i++)
			fsPath.pushDirectory(uriPath[i]);
	}
	else
	{
		fsPath.append(uriPath);
	}

	fsPath.makeFile();
	return fsPath;
}

void IndigoRequestHandler::sendFile(HTTPServerResponse &response, const string &path)
{
	const string &ext = Path(path).getExtension();
	const string &mediaType = IndigoConfiguration::get().getMimeType(ext);
	response.sendFile(path, mediaType);
}

void IndigoRequestHandler::sendDirectoryListing(HTTPServerResponse &response, const string &dirURI, const vector<string> &entries)
{
	bool root = (dirURI == "/");

	response.setContentType("text/html");
	response.setContentLength(HTTPResponse::UNKNOWN_CONTENT_LENGTH);
	response.setChunkedTransferEncoding(true);

	ostream &out = response.send();

	out << "" << endl;
	out << "" << endl;
	out << "<title>";
	out << "Index of " << dirURI;
	out << "</title>" << endl;
	out << "" << endl;
	out << "" << endl;
	out << "
";
	out << "Index of " << dirURI;
	out << "
" << endl;

	if (!root)
	{
		out << "<Parent Directory>
" << endl;
	}

	const int l = entries.size();
	for (int i = 0; i < l; i++)
	{
		out << "<a href=\"" << entries[i] << "\">" << entries[i] << "" << "
" << endl;
	}

	out << "" << endl;
	out << "" << endl;
}

string IndigoRequestHandler::findVirtualIndex()
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const set<string> indexes = configuration.getIndexes();

	set<string>::const_iterator it;
	set<string>::const_iterator end = indexes.end();
	for (it = indexes.begin(); it != end; ++it)
	{
		try
		{
			const Path indexURI = Path('/' + *it, Path::PATH_UNIX);
			const Path &index = resolveFSPath(indexURI);
			File f(index);
			if (f.isFile())
			{
				return index.toString();
			}
		}
		catch (ShareNotFoundException &snfe)
		{
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}
	}

	return "";
}

void IndigoRequestHandler::sendVirtualIndex(HTTPServerResponse &response)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const string &index = findVirtualIndex();
	if (!index.empty())
	{
		sendFile(response, index);
		return;
	}

	if (!configuration.getAutoIndex())
		throw ShareNotFoundException();

	const set<string> &shares = configuration.getShares();
	vector<string> entries;

	set<string>::const_iterator it;
	const set<string>::const_iterator &end = shares.end();
	for (it = shares.begin(); it != end; ++it)
	{
		const string &shareName = *it;
		try
		{
			const Path shareURI = Path('/' + shareName, Path::PATH_UNIX);
			const Path &fsPath = resolveFSPath(shareURI);
			File f(fsPath);

			if (!f.isHidden())
			{
				string entry = shareName;
				if (f.isDirectory())
					entry += '/';

				entries.push_back(entry);
			}
		}
		catch (ShareNotFoundException &snfe)
		{
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}
	}

	sendDirectoryListing(response, "/", entries);
}

string IndigoRequestHandler::findDirectoryIndex(const string &base)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const set<string> indexes = configuration.getIndexes(true);

	set<string>::const_iterator it;
	set<string>::const_iterator end = indexes.end();
	for (it = indexes.begin(); it != end; ++it)
	{
		try
		{
			string index = base;
			if (index[index.length() - 1] != Path::separator())
				index += Path::separator();
			index += *it;

			File f(index);
			if (f.isFile())
			{
				return index;
			}
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}
	}

	return "";
}

void IndigoRequestHandler::sendDirectoryIndex(HTTPServerResponse &response, const string &path, const string &dirURI)
{
	const IndigoConfiguration &configuration = IndigoConfiguration::get();

	const string &index = findDirectoryIndex(path);
	if (!index.empty())
	{
		sendFile(response, index);
		return;
	}

	if (!configuration.getAutoIndex())
		throw FileNotFoundException();

	vector<string> entries;

	DirectoryIterator it(path);
	DirectoryIterator end;
	while (it != end)
	{
		try
		{
			if (!it->isHidden())
			{
				string entry = it.name();
				if (it->isDirectory())
					entry += '/';

				entries.push_back(entry);
			}
		}
		catch (FileException &fe)
		{
		}
		catch (PathSyntaxException &pse)
		{
		}

		++it;
	}

	sendDirectoryListing(response, dirURI, entries);
}

void IndigoRequestHandler::redirectToDirectory(HTTPServerResponse &response, const string &dirURI, bool permanent)
{
	if (!permanent)
	{
		response.redirect(dirURI);
	}
	else
	{
		response.setStatusAndReason(HTTPResponse::HTTP_MOVED_PERMANENTLY);
		response.setContentLength(0);
		response.setChunkedTransferEncoding(false);
		response.set("Location", dirURI);
		response.send();
	}
}

void IndigoRequestHandler::logRequest(const HTTPServerRequest &request)
{
	const ServerApplication &app = dynamic_cast<ServerApplication &>(Application::instance());
	if (app.isInteractive())
	{
		const string &method = request.getMethod();
		const string &uri = request.getURI();
		const string &host = request.clientAddress().host().toString();

		string logString = host + " - " + method + " " + uri;

		app.logger().information(logString);
	}
}

void IndigoRequestHandler::sendError(HTTPServerResponse &response, int code)
{
	if (response.sent())
		return;

	response.setStatusAndReason(HTTPResponse::HTTPStatus(code));
	response.setChunkedTransferEncoding(true);
	response.setContentType("text/html");

	const string &reason = response.getReason();

	ostream &out = response.send();
	out << "";
	out << "<title>" + NumberFormatter::format(code) + " " + reason + "</title>";
	out << "
" + reason + "
";
	out << "";
}

void IndigoRequestHandler::sendMethodNotAllowed(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_METHOD_NOT_ALLOWED);
}

void IndigoRequestHandler::sendRequestURITooLong(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_REQUESTURITOOLONG);
}

void IndigoRequestHandler::sendBadRequest(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_BAD_REQUEST);
}

void IndigoRequestHandler::sendNotImplemented(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_NOT_IMPLEMENTED);
}

void IndigoRequestHandler::sendNotFound(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_NOT_FOUND);
}

void IndigoRequestHandler::sendForbidden(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_FORBIDDEN);
}

void IndigoRequestHandler::sendInternalServerError(HTTPServerResponse &response)
{
	sendError(response, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
}
<|endoftext|>


<commit_before>// This is actually a C++ file - it's got a .c extension to make make happy

// This is actually DES-X, not triple DES.

#include <iostream> // for couts for debugging

#include "modes.h"
#include "des.h"
#include "filters.h"

//extern "C"
//{
#include "Python.h"
//}

USING_NAMESPACE(CryptoPP)

PyObject *TripleDESCBCError;

class MemoryException : public std::exception
{
public:
	explicit MemoryException() {}
	virtual ~MemoryException() throw() {}
};

#define xdelete(p) delete (p); p = NULL
#define xdeletear(p) delete[] (p); p = NULL

typedef struct
{
	PyObject_HEAD
	byte *key;
} tripledescbc;

static PyObject *tripledescbc_new(tripledescbc *self, PyObject *args);

static void tripledescbc_delete(tripledescbc *self);

static PyObject *tripledescbc_encrypt(tripledescbc *self, PyObject *args);

static PyObject *tripledescbc_decrypt(tripledescbc *self, PyObject *args);

static PyObject *tripledescbc_getattr(tripledescbc *self, char* name);

statichere PyTypeObject tripledescbc_type = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,                        /*ob_size*/
        "DES-XEX3CBC",                  /*tp_name*/
        sizeof(tripledescbc),        /*tp_size*/
        0,                        /*tp_itemsize*/
        /* methods */
        (destructor)tripledescbc_delete,  /*tp_dealloc*/
        0,                        /*tp_print*/
        (getattrfunc)tripledescbc_getattr, /*tp_getattr*/
        0,                        /*tp_setattr*/
        0,                        /*tp_compare*/
        0,                        /*tp_repr*/
        0,                        /*tp_as_number*/
        0,                        /*tp_as_sequence*/
        0,                        /*tp_as_mapping*/
        0,                        /*tp_hash*/
        0,                        /*tp_call*/
        0,                        /*tp_str*/
        0,                        /*tp_getattro*/
        0,                        /*tp_setattro*/
        0,                        /*tp_as_buffer*/
        0,                        /*tp_xxx4*/
        0,                        /*tp_doc*/
};

static PyMethodDef tripledescbc_methods[] = {
  {"encrypt", (PyCFunction)tripledescbc_encrypt, METH_VARARGS,
   "Returns an encrypted string.\n"
   "Accepts an IV string of length 8 and a plaintext string.\n"
   "Encrypts in CBC mode with ciphertext stealing.\n"
   "Always returns a ciphertext of the exact same length as the plaintext."
  },
  {"decrypt", (PyCFunction)tripledescbc_decrypt, METH_VARARGS,
   "Returns a decrypted string.\n"
   "Accepts an IV string of length 8 and a ciphertext string.\n"
   "Decrypts in CBC mode with ciphertext stealing.\n"
   "Always returns a plaintext of the exact same length as the ciphertext."
  },
  {NULL, NULL}	/* sentinel */
};

static PyObject *tripledescbc_getattr(tripledescbc *self, char* name)
{
	return Py_FindMethod(tripledescbc_methods, (PyObject *)self, name);
}

static void tripledescbc_delete(tripledescbc *self) {
	if(self != NULL) {
		xdeletear(self->key);
		PyMem_DEL(self);
	}
}

static PyObject *tripledescbc_new(tripledescbc *self, PyObject *args) {
	tripledescbc *newself = NULL;
	try {
		byte *key;
		int keylength;
		if(!PyArg_ParseTuple(args, "s#", &key, &keylength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(keylength != 24) {
			throw Exception(Exception::INVALID_ARGUMENT, "triple DES key length must be 24");
		}
		if(!(newself = PyObject_NEW(tripledescbc, &tripledescbc_type))) {
		  throw MemoryException();
		}
		byte *keycopy = new byte[24];
		memcpy(keycopy, key, 24);
		//		printf("in tripledescbc_new(); keycopy: %p, key: %p\n", keycopy, key);
		newself->key = keycopy;
		return (PyObject *)newself;
	}
	catch(CryptoPP::Exception &e) {
		tripledescbc_delete(newself);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e)
	{
		tripledescbc_delete(newself);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do set up keys for en/decryption");
		return NULL;
	}
}

#define _MIN_UNSAFE(x, y) ((x)<(y)?(x):(y))
static PyObject *tripledescbc_encrypt(tripledescbc *self, PyObject *args) {
	//	std::cout << "hello enc 0" << std::endl; std::cout.flush();
	PyObject *result = NULL;
	byte *ciphertext = NULL;
	try {
		byte *iv;
		unsigned int ivlength;
		byte *text;
		unsigned int textlength;
		if(!PyArg_ParseTuple(args, "s#s#", &iv, &ivlength, &text, &textlength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(ivlength != 8) {
			throw Exception(Exception::INVALID_ARGUMENT, "IV length must be 8");
		}
		//		std::cout << "hello enc 0.7" << std::endl; std::cout.flush();
		//		std::cout << "hello enc 0.7.1, self: " << self << std::endl; std::cout.flush();
		//		std::cout << "hello enc 0.7.2, self->key: ";
		//		std::cout << self->key;
		//		std::cout << std::endl;
		//		std::cout.flush();
		//	std::cout << "hello enc 0.7.3, iv: " << iv << std::endl; std::cout.flush();
		CBC_CTS_Mode<DES_XEX3>::Encryption encryption(self->key, 24, iv);
		//		std::cout << "hello enc 0.8" << std::endl; std::cout.flush();
		ciphertext = new byte[textlength];
		//		std::cout << "hello enc 0.9" << std::endl; std::cout.flush();
		if (ciphertext == NULL) {
			throw MemoryException();
		}
		//		std::cout << "hello enc 1" << std::endl; std::cout.flush();
		StreamTransformationFilter encryptor(encryption, new ArraySink(ciphertext, textlength));
		//		std::cout << "hello enc 2" << std::endl; std::cout.flush();
		encryptor.PutMessageEnd(text, textlength);
		//		std::cout << "hello enc 3" << std::endl; std::cout.flush();
		result = Py_BuildValue("s#", ciphertext, textlength);
		//		std::cout << "hello enc 4" << std::endl; std::cout.flush();
		if(result == NULL) {
			throw MemoryException();
		}
		//		std::cout << "hello enc 5" << std::endl; std::cout.flush();
		xdeletear(ciphertext);
		//		std::cout << "hello enc 6" << std::endl; std::cout.flush();
		return result;
	}
	catch(CryptoPP::Exception &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(ciphertext);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(ciphertext);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do encryption");
		return NULL;
	}
	std::cout << "goodbye enc" << std::endl; std::cout.flush();
}

static PyObject *tripledescbc_decrypt(tripledescbc *self, PyObject *args) {
	std::cout << "hello dec 0" << std::endl; std::cout.flush();
	PyObject *result = NULL;
	byte *plaintext = NULL;
	try {
		byte *iv;
		unsigned int ivlength;
		byte *text;
		unsigned int textlength;
		if(!PyArg_ParseTuple(args, "s#s#", &iv, &ivlength, &text, &textlength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(ivlength != 8) {
			throw Exception(Exception::INVALID_ARGUMENT, "IV length must be 8");
		}
		CBC_CTS_Mode<DES_XEX3>::Decryption decryption(self->key, 24, iv);
		plaintext = new byte[textlength];
		if (plaintext == NULL) {
			throw MemoryException();
		}
		StreamTransformationFilter decryptor(decryption, new ArraySink(plaintext, textlength));
		decryptor.PutMessageEnd(text, textlength);
		result = Py_BuildValue("s#", plaintext, textlength);
		if(result == NULL) {
			throw MemoryException();
		}
		xdeletear(plaintext);
		return result;
	}
	catch(CryptoPP::Exception &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(plaintext);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(plaintext);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do decryption");
		return NULL;
	}
}

PyMethodDef tripledescbc_functions[] = {
  {"new", (PyCFunction)tripledescbc_new, METH_VARARGS,
   "Constructs a new tripledescbc.\n"
   "Accepts a key of length 24."
  },
  {NULL, NULL}	/* Sentinel */
};

char* tripledescbc_doc =
"Does 3DES encryption and decyption in CBC mode with ciphertext stealing.\n"
"Always uses a key of length 24 and initialization vectors of length 8.\n"
"\n"
"Class methods are - \n"
"new(key) - constructor\n"
"\n"
"Instance methods are - \n"
"encrypt(iv, plaintext) - encrypt a string\n"
"decrypt(iv, ciphertext) - decrypt a string";

/* Initialize this module. */

extern "C"
{
DL_EXPORT(void)
inittripledescbc()
{
        PyObject *m, *d;
	m = Py_InitModule3("tripledescbc", tripledescbc_functions, tripledescbc_doc);
        d = PyModule_GetDict(m);
        TripleDESCBCError = PyErr_NewException("tripledescbc.Error", NULL, NULL);
        PyDict_SetItemString(d, "Error", TripleDESCBCError);
}
}

<commit_msg> * comment out debug printouts in tripledescbc.cpp (already committed to Mnet v0.6)<commit_after>// This is actually a C++ file - it's got a .c extension to make make happy

// This is actually DES-X, not triple DES.

#include <iostream> // for couts for debugging

#include "modes.h"
#include "des.h"
#include "filters.h"

//extern "C"
//{
#include "Python.h"
//}

USING_NAMESPACE(CryptoPP)

PyObject *TripleDESCBCError;

class MemoryException : public std::exception
{
public:
	explicit MemoryException() {}
	virtual ~MemoryException() throw() {}
};

#define xdelete(p) delete (p); p = NULL
#define xdeletear(p) delete[] (p); p = NULL

typedef struct
{
	PyObject_HEAD
	byte *key;
} tripledescbc;

static PyObject *tripledescbc_new(tripledescbc *self, PyObject *args);

static void tripledescbc_delete(tripledescbc *self);

static PyObject *tripledescbc_encrypt(tripledescbc *self, PyObject *args);

static PyObject *tripledescbc_decrypt(tripledescbc *self, PyObject *args);

static PyObject *tripledescbc_getattr(tripledescbc *self, char* name);

statichere PyTypeObject tripledescbc_type = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,                        /*ob_size*/
        "DES-XEX3CBC",                  /*tp_name*/
        sizeof(tripledescbc),        /*tp_size*/
        0,                        /*tp_itemsize*/
        /* methods */
        (destructor)tripledescbc_delete,  /*tp_dealloc*/
        0,                        /*tp_print*/
        (getattrfunc)tripledescbc_getattr, /*tp_getattr*/
        0,                        /*tp_setattr*/
        0,                        /*tp_compare*/
        0,                        /*tp_repr*/
        0,                        /*tp_as_number*/
        0,                        /*tp_as_sequence*/
        0,                        /*tp_as_mapping*/
        0,                        /*tp_hash*/
        0,                        /*tp_call*/
        0,                        /*tp_str*/
        0,                        /*tp_getattro*/
        0,                        /*tp_setattro*/
        0,                        /*tp_as_buffer*/
        0,                        /*tp_xxx4*/
        0,                        /*tp_doc*/
};

static PyMethodDef tripledescbc_methods[] = {
  {"encrypt", (PyCFunction)tripledescbc_encrypt, METH_VARARGS,
   "Returns an encrypted string.\n"
   "Accepts an IV string of length 8 and a plaintext string.\n"
   "Encrypts in CBC mode with ciphertext stealing.\n"
   "Always returns a ciphertext of the exact same length as the plaintext."
  },
  {"decrypt", (PyCFunction)tripledescbc_decrypt, METH_VARARGS,
   "Returns a decrypted string.\n"
   "Accepts an IV string of length 8 and a ciphertext string.\n"
   "Decrypts in CBC mode with ciphertext stealing.\n"
   "Always returns a plaintext of the exact same length as the ciphertext."
  },
  {NULL, NULL}	/* sentinel */
};

static PyObject *tripledescbc_getattr(tripledescbc *self, char* name)
{
	return Py_FindMethod(tripledescbc_methods, (PyObject *)self, name);
}

static void tripledescbc_delete(tripledescbc *self) {
	if(self != NULL) {
		xdeletear(self->key);
		PyMem_DEL(self);
	}
}

static PyObject *tripledescbc_new(tripledescbc *self, PyObject *args) {
	tripledescbc *newself = NULL;
	try {
		byte *key;
		int keylength;
		if(!PyArg_ParseTuple(args, "s#", &key, &keylength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(keylength != 24) {
			throw Exception(Exception::INVALID_ARGUMENT, "triple DES key length must be 24");
		}
		if(!(newself = PyObject_NEW(tripledescbc, &tripledescbc_type))) {
		  throw MemoryException();
		}
		byte *keycopy = new byte[24];
		memcpy(keycopy, key, 24);
		//		printf("in tripledescbc_new(); keycopy: %p, key: %p\n", keycopy, key);
		newself->key = keycopy;
		return (PyObject *)newself;
	}
	catch(CryptoPP::Exception &e) {
		tripledescbc_delete(newself);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e)
	{
		tripledescbc_delete(newself);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do set up keys for en/decryption");
		return NULL;
	}
}

#define _MIN_UNSAFE(x, y) ((x)<(y)?(x):(y))
static PyObject *tripledescbc_encrypt(tripledescbc *self, PyObject *args) {
	//	std::cout << "hello enc 0" << std::endl; std::cout.flush();
	PyObject *result = NULL;
	byte *ciphertext = NULL;
	try {
		byte *iv;
		unsigned int ivlength;
		byte *text;
		unsigned int textlength;
		if(!PyArg_ParseTuple(args, "s#s#", &iv, &ivlength, &text, &textlength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(ivlength != 8) {
			throw Exception(Exception::INVALID_ARGUMENT, "IV length must be 8");
		}
		//		std::cout << "hello enc 0.7" << std::endl; std::cout.flush();
		//		std::cout << "hello enc 0.7.1, self: " << self << std::endl; std::cout.flush();
		//		std::cout << "hello enc 0.7.2, self->key: ";
		//		std::cout << self->key;
		//		std::cout << std::endl;
		//		std::cout.flush();
		//	std::cout << "hello enc 0.7.3, iv: " << iv << std::endl; std::cout.flush();
		CBC_CTS_Mode<DES_XEX3>::Encryption encryption(self->key, 24, iv);
		//		std::cout << "hello enc 0.8" << std::endl; std::cout.flush();
		ciphertext = new byte[textlength];
		//		std::cout << "hello enc 0.9" << std::endl; std::cout.flush();
		if (ciphertext == NULL) {
			throw MemoryException();
		}
		//		std::cout << "hello enc 1" << std::endl; std::cout.flush();
		StreamTransformationFilter encryptor(encryption, new ArraySink(ciphertext, textlength));
		//		std::cout << "hello enc 2" << std::endl; std::cout.flush();
		encryptor.PutMessageEnd(text, textlength);
		//		std::cout << "hello enc 3" << std::endl; std::cout.flush();
		result = Py_BuildValue("s#", ciphertext, textlength);
		//		std::cout << "hello enc 4" << std::endl; std::cout.flush();
		if(result == NULL) {
			throw MemoryException();
		}
		//		std::cout << "hello enc 5" << std::endl; std::cout.flush();
		xdeletear(ciphertext);
		//		std::cout << "hello enc 6" << std::endl; std::cout.flush();
		return result;
	}
	catch(CryptoPP::Exception &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(ciphertext);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(ciphertext);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do encryption");
		return NULL;
	}
	//	std::cout << "goodbye enc" << std::endl; std::cout.flush();
}

static PyObject *tripledescbc_decrypt(tripledescbc *self, PyObject *args) {
	//	std::cout << "hello dec 0" << std::endl; std::cout.flush();
	PyObject *result = NULL;
	byte *plaintext = NULL;
	try {
		byte *iv;
		unsigned int ivlength;
		byte *text;
		unsigned int textlength;
		if(!PyArg_ParseTuple(args, "s#s#", &iv, &ivlength, &text, &textlength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(ivlength != 8) {
			throw Exception(Exception::INVALID_ARGUMENT, "IV length must be 8");
		}
		CBC_CTS_Mode<DES_XEX3>::Decryption decryption(self->key, 24, iv);
		plaintext = new byte[textlength];
		if (plaintext == NULL) {
			throw MemoryException();
		}
		StreamTransformationFilter decryptor(decryption, new ArraySink(plaintext, textlength));
		decryptor.PutMessageEnd(text, textlength);
		result = Py_BuildValue("s#", plaintext, textlength);
		if(result == NULL) {
			throw MemoryException();
		}
		xdeletear(plaintext);
		return result;
	}
	catch(CryptoPP::Exception &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(plaintext);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(plaintext);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do decryption");
		return NULL;
	}
}

PyMethodDef tripledescbc_functions[] = {
  {"new", (PyCFunction)tripledescbc_new, METH_VARARGS,
   "Constructs a new tripledescbc.\n"
   "Accepts a key of length 24."
  },
  {NULL, NULL}	/* Sentinel */
};

char* tripledescbc_doc =
"Does 3DES encryption and decyption in CBC mode with ciphertext stealing.\n"
"Always uses a key of length 24 and initialization vectors of length 8.\n"
"\n"
"Class methods are - \n"
"new(key) - constructor\n"
"\n"
"Instance methods are - \n"
"encrypt(iv, plaintext) - encrypt a string\n"
"decrypt(iv, ciphertext) - decrypt a string";

/* Initialize this module. */

extern "C"
{
DL_EXPORT(void)
inittripledescbc()
{
        PyObject *m, *d;
	m = Py_InitModule3("tripledescbc", tripledescbc_functions, tripledescbc_doc);
        d = PyModule_GetDict(m);
        TripleDESCBCError = PyErr_NewException("tripledescbc.Error", NULL, NULL);
        PyDict_SetItemString(d, "Error", TripleDESCBCError);
}
}

<|endoftext|>


<commit_before>/* This file is part of Zanshin Todo.

   Copyright 2011 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   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 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 "zanshinrunner.h"

#include <KDE/Akonadi/CollectionFetchJob>
#include <KDE/Akonadi/CollectionFetchScope>
#include <KDE/Akonadi/Item>
#include <KDE/Akonadi/ItemCreateJob>

#include <KDE/KCalCore/Todo>

#include <KDE/KDebug>
#include <KDE/KIcon>
#include <KDE/KLocale>

ZanshinRunner::ZanshinRunner(QObject *parent, const QVariantList &args)
    : Plasma::AbstractRunner(parent, args)
{
    setObjectName(QLatin1String("Zanshin"));
    setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File |
                    Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Help);

    connect(this, SIGNAL(prepare()), this, SLOT(prep()));
    connect(this, SIGNAL(teardown()), this, SLOT(down()));
}

ZanshinRunner::~ZanshinRunner()
{
}

void ZanshinRunner::match(Plasma::RunnerContext &context)
{
    const QString command = context.query().trimmed();

    if (!command.startsWith("todo:", Qt::CaseInsensitive)) {
        return;
    }

    const QString summary = command.mid(5).trimmed();

    if (summary.isEmpty()) {
        return;
    }

    QList<Plasma::QueryMatch> matches;

    Plasma::QueryMatch match(this);
    match.setData(summary);
    match.setType(Plasma::QueryMatch::ExactMatch);
    match.setIcon(KIcon("office-calendar"));
    match.setText(i18n("Add \"%1\" to your todo list", summary));
    match.setRelevance(1.0);

    matches << match;
    context.addMatches(context.query(), matches);
}

void ZanshinRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
    Q_UNUSED(context)

    Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(),
                                                                       Akonadi::CollectionFetchJob::Recursive);
    job->fetchScope().setContentMimeTypes(QStringList() << "application/x-vnd.akonadi.calendar.todo");
    job->exec();

    Akonadi::Collection::List cols = job->collections();

    if (cols.isEmpty()) {
        return;
    }

    KCalCore::Todo::Ptr todo(new KCalCore::Todo);
    todo->setSummary(match.data().toString());

    Akonadi::Item item;
    item.setMimeType("application/x-vnd.akonadi.calendar.todo");
    item.setPayload<KCalCore::Todo::Ptr>(todo);

    new Akonadi::ItemCreateJob(item, cols.first());
}

#include "zanshinrunner.moc"
<commit_msg>Add todo in default collection<commit_after>/* This file is part of Zanshin Todo.

   Copyright 2011 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   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 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 "zanshinrunner.h"

#include <KDE/Akonadi/CollectionFetchJob>
#include <KDE/Akonadi/CollectionFetchScope>
#include <KDE/Akonadi/Item>
#include <KDE/Akonadi/ItemCreateJob>

#include <KDE/KCalCore/Todo>

#include <KDE/KDebug>
#include <KDE/KIcon>
#include <KDE/KLocale>

ZanshinRunner::ZanshinRunner(QObject *parent, const QVariantList &args)
    : Plasma::AbstractRunner(parent, args)
{
    setObjectName(QLatin1String("Zanshin"));
    setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File |
                    Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Help);

    connect(this, SIGNAL(prepare()), this, SLOT(prep()));
    connect(this, SIGNAL(teardown()), this, SLOT(down()));
}

ZanshinRunner::~ZanshinRunner()
{
}

void ZanshinRunner::match(Plasma::RunnerContext &context)
{
    const QString command = context.query().trimmed();

    if (!command.startsWith("todo:", Qt::CaseInsensitive)) {
        return;
    }

    const QString summary = command.mid(5).trimmed();

    if (summary.isEmpty()) {
        return;
    }

    QList<Plasma::QueryMatch> matches;

    Plasma::QueryMatch match(this);
    match.setData(summary);
    match.setType(Plasma::QueryMatch::ExactMatch);
    match.setIcon(KIcon("office-calendar"));
    match.setText(i18n("Add \"%1\" to your todo list", summary));
    match.setRelevance(1.0);

    matches << match;
    context.addMatches(context.query(), matches);
}

void ZanshinRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
    Q_UNUSED(context)

    Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(),
                                                                       Akonadi::CollectionFetchJob::Recursive);
    job->fetchScope().setContentMimeTypes(QStringList() << "application/x-vnd.akonadi.calendar.todo");
    job->exec();

    Akonadi::Collection::List cols = job->collections();

    if (cols.isEmpty()) {
        return;
    }

    Akonadi::Collection collection;

    KConfig zanshin("zanshinrc");
    KConfigGroup config(&zanshin, "General");

    qint64 defaultCollectionId = config.readEntry("defaultCollection", -1);

    if (defaultCollectionId > 0) {
        foreach (Akonadi::Collection col, cols) {
            if (col.id() == defaultCollectionId) {
                collection = col;
                break;
            }
        }
    }

    if (!collection.isValid()) {
        collection = cols.first();
    }

    KCalCore::Todo::Ptr todo(new KCalCore::Todo);
    todo->setSummary(match.data().toString());

    Akonadi::Item item;
    item.setMimeType("application/x-vnd.akonadi.calendar.todo");
    item.setPayload<KCalCore::Todo::Ptr>(todo);

    new Akonadi::ItemCreateJob(item, collection);
}

#include "zanshinrunner.moc"
<|endoftext|>


<commit_before>// Standard library
#include <iostream> /// @todo Remove

// Boost
#include <boost/python.hpp>

// PyCairo
#include <pycairo/pycairo.h>
// See http://www.cairographics.org/documentation/pycairo/2/pycairo_c_api.html
static Pycairo_CAPI_t* Pycairo_CAPI;

// DrawTurksHead
#include <TurksHead/TurksHead.hpp>

namespace {

class PythonTurksHead : public TurksHead::TurksHead, public boost::python::wrapper< TurksHead::TurksHead > {
public:
    PythonTurksHead( int leads, int bights, double innerRadius, double outerRadius, double lineWidth ) :
        TurksHead::TurksHead( leads, bights, innerRadius, outerRadius, lineWidth ),
        pythonComputeColorHsv( this->get_override( "" ) ),
        pythonComputeColorHsvInit( false )
    {
    }

    PythonTurksHead( const TurksHead::TurksHead& t ) :
        TurksHead::TurksHead( t ),
        pythonComputeColorHsv( this->get_override( "" ) ),
        pythonComputeColorHsvInit( false )
    {
    }

    void draw( boost::python::object context ) {
        TurksHead::draw( Cairo::RefPtr< Cairo::Context >( new Cairo::Context( PycairoContext_GET( context.ptr() ) ) ) );
    }

    double getAltitude( int k, int theta ) {
        return TurksHead::TurksHead::getAltitude(
            TurksHead::TurksHead::Path( k ),
            TurksHead::TurksHead::Theta( theta )
        );
    }

private:
    boost::tuple< double, double, double > computeColorHsv( int k, int theta ) const {
        if( !pythonComputeColorHsvInit ) {
            pythonComputeColorHsv = this->get_override( "computeColorHsv" );
            pythonComputeColorHsvInit = true;
        }
        if( pythonComputeColorHsv ) {
            boost::python::tuple r = pythonComputeColorHsv( k, theta );
            double h = boost::python::extract< double >( r[0] );
            double s = boost::python::extract< double >( r[1] );
            double v = boost::python::extract< double >( r[2] );
            return boost::make_tuple( h, s, v );
        } else {
            return TurksHead::TurksHead::computeColorHsv( k, theta );
        }
    }

private:
    mutable boost::python::override pythonComputeColorHsv;
    mutable bool pythonComputeColorHsvInit;
};

}

BOOST_PYTHON_MODULE( _turkshead ) {
    Pycairo_IMPORT; // Initialization of Pycairo_CAPI

    /// @todo Look at http://www.boost.org/doc/libs/1_43_0/libs/parameter/doc/html/python.html to add named parameters to the constructor
    boost::python::class_< PythonTurksHead >( "TurksHead", boost::python::init< int, int, double, double, double >() )
        .def( "draw", &PythonTurksHead::draw )
        .add_property( "p", &TurksHead::TurksHead::getP )
        .add_property( "q", &TurksHead::TurksHead::getQ )
        .add_property( "d", &TurksHead::TurksHead::getD )
        .def( "getAltitude", &PythonTurksHead::getAltitude )
    ;
}
<commit_msg>Remove namespace/class ambiguities<commit_after>// Standard library
#include <iostream> /// @todo Remove

// Boost
#include <boost/python.hpp>

// PyCairo
#include <pycairo/pycairo.h>
// See http://www.cairographics.org/documentation/pycairo/2/pycairo_c_api.html
static Pycairo_CAPI_t* Pycairo_CAPI;

// DrawTurksHead
#include <TurksHead/TurksHead.hpp>

namespace {

class PythonTurksHead : public ::TurksHead::TurksHead, public boost::python::wrapper< ::TurksHead::TurksHead > {
public:
    PythonTurksHead( int leads, int bights, double innerRadius, double outerRadius, double lineWidth ) :
        ::TurksHead::TurksHead( leads, bights, innerRadius, outerRadius, lineWidth ),
        pythonComputeColorHsv( this->get_override( "" ) ),
        pythonComputeColorHsvInit( false )
    {
    }

    PythonTurksHead( const ::TurksHead::TurksHead& t ) :
        ::TurksHead::TurksHead( t ),
        pythonComputeColorHsv( this->get_override( "" ) ),
        pythonComputeColorHsvInit( false )
    {
    }

    void draw( boost::python::object context ) {
        ::TurksHead::TurksHead::draw( Cairo::RefPtr< Cairo::Context >( new Cairo::Context( PycairoContext_GET( context.ptr() ) ) ) );
    }

    double getAltitude( int k, int theta ) {
        return ::TurksHead::TurksHead::getAltitude(
            ::TurksHead::TurksHead::Path( k ),
            ::TurksHead::TurksHead::Theta( theta )
        );
    }

private:
    boost::tuple< double, double, double > computeColorHsv( int k, int theta ) const {
        if( !pythonComputeColorHsvInit ) {
            pythonComputeColorHsv = this->get_override( "computeColorHsv" );
            pythonComputeColorHsvInit = true;
        }
        if( pythonComputeColorHsv ) {
            boost::python::tuple r = pythonComputeColorHsv( k, theta );
            double h = boost::python::extract< double >( r[0] );
            double s = boost::python::extract< double >( r[1] );
            double v = boost::python::extract< double >( r[2] );
            return boost::make_tuple( h, s, v );
        } else {
            return ::TurksHead::TurksHead::computeColorHsv( k, theta );
        }
    }

private:
    mutable boost::python::override pythonComputeColorHsv;
    mutable bool pythonComputeColorHsvInit;
};

}

BOOST_PYTHON_MODULE( _turkshead ) {
    Pycairo_IMPORT; // Initialization of Pycairo_CAPI

    /// @todo Look at http://www.boost.org/doc/libs/1_43_0/libs/parameter/doc/html/python.html to add named parameters to the constructor
    boost::python::class_< PythonTurksHead >( "TurksHead", boost::python::init< int, int, double, double, double >() )
        .def( "draw", &PythonTurksHead::draw )
        .add_property( "p", &::TurksHead::TurksHead::getP )
        .add_property( "q", &::TurksHead::TurksHead::getQ )
        .add_property( "d", &::TurksHead::TurksHead::getD )
        .def( "getAltitude", &PythonTurksHead::getAltitude )
    ;
}
<|endoftext|>


<commit_before>#include "fileexplorer.h"
#include "ui_fileexplorer.h"

FileExplorer::FileExplorer(QFileSystemModel *filesmodel, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FileExplorer), files_model_(filesmodel)
{
    ui->setupUi(this);

    // path Edit
    ui->pathEdit->setText( QDir::homePath() );
    QCompleter *completer = new QCompleter(this);
    completer->setModel(new QDirModel(completer));
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    ui->pathEdit->setCompleter(completer);

    // short cut
    sc_editpath_ = new QShortcut(QKeySequence(tr("Ctrl+L", "Edit path")),this);
    connect(sc_editpath_, SIGNAL(activated()), ui->pathEdit, SLOT(setFocus()));

    // dir View
    dir_model_ = new QFileSystemModel(this);
    dir_proxy_model_ = new FSfilterProxyModel(this);
    dir_model_->setRootPath(QDir::rootPath());
    dir_model_->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
    dir_proxy_model_->setSourceModel(dir_model_);
    ui->dirView->setModel(dir_proxy_model_);
    ui->dirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    connect(ui->dirView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(onCurrentDirChanged(QModelIndex,QModelIndex)));

    // files View
    ui->filesView->setModel(files_model_);
    ui->filesView->setItemDelegate(new RankDelegate(this));

    ui->filesView->setEditTriggers(QAbstractItemView::DoubleClicked
                                | QAbstractItemView::SelectedClicked);
    ui->filesView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->filesView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    connect(ui->filesView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(onCurrentFileChanged(QModelIndex,QModelIndex)));

    // handle path change
    connect(this, SIGNAL(sigPath(QString)), this, SLOT(setPath(QString)));
}

FileExplorer::~FileExplorer()
{
    delete ui;
}

QString FileExplorer::currentPath() const
{
    return ui->pathEdit->text();
}

void FileExplorer::onCurrentDirChanged(QModelIndex current, QModelIndex previous)
{
    emit sigPath( dir_model_->filePath(dir_proxy_model_->mapToSource( current)) );
}

void FileExplorer::onCurrentFileChanged(QModelIndex current, QModelIndex previous)
{
    if (files_model_->filePath(current) != files_model_->filePath(previous))
        emit sigFilePath( files_model_->filePath(current));

    if (current.column() == 0){
        emit sigFileNameSelected(true);
    } else {
        emit sigFileNameSelected(false);
    }
}

void FileExplorer::setPath(QString path)
{
    ui->pathEdit->setText(path);

    QModelIndex din = dir_proxy_model_->mapFromSource(dir_model_->index(path));
    ui->dirView->scrollTo(din);
    ui->dirView->collapse(din);
    ui->dirView->setCurrentIndex(din);
    ui->dirView->resizeColumnToContents(din.column());

    ui->filesView->setRootIndex(files_model_->setRootPath(path));
}

void FileExplorer::on_pathEdit_editingFinished()
{
    finfo_.setFile(ui->pathEdit->text());
    if (finfo_.isDir()) {
        emit sigPath(finfo_.filePath());
    } else if ( finfo_.isFile()) {
        emit sigPath(finfo_.path());
        emit sigFilePath(finfo_.filePath());
    }
}
<commit_msg>filter dir completer.<commit_after>#include "fileexplorer.h"
#include "ui_fileexplorer.h"

FileExplorer::FileExplorer(QFileSystemModel *filesmodel, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FileExplorer), files_model_(filesmodel)
{
    ui->setupUi(this);

    // path Edit
    ui->pathEdit->setText( QDir::homePath() );
    QCompleter *completer = new QCompleter(this);
    QStringList fli("*");
    completer->setModel(new QDirModel(fli,
                                      QDir::NoDotAndDotDot | QDir::AllDirs,
                                      QDir::Name));
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    ui->pathEdit->setCompleter(completer);

    // short cut
    sc_editpath_ = new QShortcut(QKeySequence(tr("Ctrl+L", "Edit path")),this);
    connect(sc_editpath_, SIGNAL(activated()), ui->pathEdit, SLOT(setFocus()));

    // dir View
    dir_model_ = new QFileSystemModel(this);
    dir_proxy_model_ = new FSfilterProxyModel(this);
    dir_model_->setRootPath(QDir::rootPath());
    dir_model_->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
    dir_proxy_model_->setSourceModel(dir_model_);
    ui->dirView->setModel(dir_proxy_model_);
    ui->dirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    connect(ui->dirView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(onCurrentDirChanged(QModelIndex,QModelIndex)));

    // files View
    ui->filesView->setModel(files_model_);
    ui->filesView->setItemDelegate(new RankDelegate(this));

    ui->filesView->setEditTriggers(QAbstractItemView::DoubleClicked
                                | QAbstractItemView::SelectedClicked);
    ui->filesView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->filesView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    connect(ui->filesView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(onCurrentFileChanged(QModelIndex,QModelIndex)));

    // handle path change
    connect(this, SIGNAL(sigPath(QString)), this, SLOT(setPath(QString)));
}

FileExplorer::~FileExplorer()
{
    delete ui;
}

QString FileExplorer::currentPath() const
{
    return ui->pathEdit->text();
}

void FileExplorer::onCurrentDirChanged(QModelIndex current, QModelIndex previous)
{
    emit sigPath( dir_model_->filePath(dir_proxy_model_->mapToSource( current)) );
}

void FileExplorer::onCurrentFileChanged(QModelIndex current, QModelIndex previous)
{
    if (files_model_->filePath(current) != files_model_->filePath(previous))
        emit sigFilePath( files_model_->filePath(current));

    if (current.column() == 0){
        emit sigFileNameSelected(true);
    } else {
        emit sigFileNameSelected(false);
    }
}

void FileExplorer::setPath(QString path)
{
    ui->pathEdit->setText(path);

    QModelIndex din = dir_proxy_model_->mapFromSource(dir_model_->index(path));
    ui->dirView->scrollTo(din);
    ui->dirView->collapse(din);
    ui->dirView->setCurrentIndex(din);
    ui->dirView->resizeColumnToContents(din.column());

    ui->filesView->setRootIndex(files_model_->setRootPath(path));
}

void FileExplorer::on_pathEdit_editingFinished()
{
    finfo_.setFile(ui->pathEdit->text());
    if (finfo_.isDir()) {
        emit sigPath(finfo_.filePath());
    } else if ( finfo_.isFile()) {
        emit sigPath(finfo_.path());
        emit sigFilePath(finfo_.filePath());
    }
}
<|endoftext|>


<commit_before>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2016 cDc <cdc.seacave@gmail.com>, Pierre MOULON

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/cameras/Camera_Pinhole.hpp"
#include "openMVG/cameras/Camera_undistort_image.hpp"
#include "openMVG/image/image_io.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_io.hpp"

#define _USE_EIGEN
#include "InterfaceMVS.h"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"
#include "third_party/progress/progress_display.hpp"

using namespace openMVG;
using namespace openMVG::cameras;
using namespace openMVG::geometry;
using namespace openMVG::image;
using namespace openMVG::sfm;

#include <atomic>
#include <cstdlib>
#include <string>

#ifdef OPENMVG_USE_OPENMP
#include <omp.h>
#endif

bool exportToOpenMVS(
  const SfM_Data & sfm_data,
  const std::string & sOutFile,
  const std::string & sOutDir,
  const int iNumThreads = 0
  )
{
  // Create undistorted images directory structure
  if (!stlplus::is_folder(sOutDir))
  {
    stlplus::folder_create(sOutDir);
    if (!stlplus::is_folder(sOutDir))
    {
      std::cerr << "Cannot access to one of the desired output directory" << std::endl;
      return false;
    }
  }

  // Export data :
  MVS::Interface scene;
  size_t nPoses(0);
  const uint32_t nViews((uint32_t)sfm_data.GetViews().size());

  C_Progress_display my_progress_bar(nViews,
      std::cout, "\n- PROCESS VIEWS -\n");

  // OpenMVG can have not contiguous index, use a map to create the required OpenMVS contiguous ID index
  std::map<openMVG::IndexT, uint32_t> map_intrinsic, map_view;

  // define a platform with all the intrinsic group
  for (const auto& intrinsic: sfm_data.GetIntrinsics())
  {
    if (isPinhole(intrinsic.second->getType()))
    {
      const Pinhole_Intrinsic * cam = dynamic_cast<const Pinhole_Intrinsic*>(intrinsic.second.get());
      if (map_intrinsic.count(intrinsic.first) == 0)
        map_intrinsic.insert(std::make_pair(intrinsic.first, scene.platforms.size()));
      MVS::Interface::Platform platform;
      // add the camera
      MVS::Interface::Platform::Camera camera;
      camera.K = cam->K();
      // sub-pose
      camera.R = Mat3::Identity();
      camera.C = Vec3::Zero();
      platform.cameras.push_back(camera);
      scene.platforms.push_back(platform);
    }
  }

  // define images & poses
  scene.images.reserve(nViews);
  for (const auto& view : sfm_data.GetViews())
  {
    map_view[view.first] = scene.images.size();
    MVS::Interface::Image image;
    const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view.second->s_Img_path);
    image.name = stlplus::create_filespec(sOutDir, view.second->s_Img_path);
    image.platformID = map_intrinsic.at(view.second->id_intrinsic);
    MVS::Interface::Platform& platform = scene.platforms[image.platformID];
    image.cameraID = 0;
    if (!stlplus::is_file(srcImage))
    {
      std::cout << "Cannot read the corresponding image: " << srcImage << std::endl;
      return EXIT_FAILURE;
    }
    if (sfm_data.IsPoseAndIntrinsicDefined(view.second.get()))
    {
      MVS::Interface::Platform::Pose pose;
      image.poseID = platform.poses.size();
      const openMVG::geometry::Pose3 poseMVG(sfm_data.GetPoseOrDie(view.second.get()));
      pose.R = poseMVG.rotation();
      pose.C = poseMVG.center();
      platform.poses.push_back(pose);
      ++nPoses;
    }
    else
    {
      // image have not valid pose, so set an undefined pose
      image.poseID = NO_ID;
      // just copy the image
      //stlplus::file_copy(srcImage, image.name);
    }
    scene.images.emplace_back(image);
    ++my_progress_bar;
  }

  // Export undistorted images
  C_Progress_display my_progress_bar_images(sfm_data.views.size(),
      std::cout, "\n- UNDISTORT IMAGES -\n" );
  std::atomic<bool> bOk(true); // Use a boolean to track the status of the loop process
#ifdef OPENMVG_USE_OPENMP
  const unsigned int nb_max_thread = (iNumThreads > 0)? iNumThreads : omp_get_max_threads();

  #pragma omp parallel for schedule(dynamic) num_threads(nb_max_thread)
#endif
  for (int i = 0; i < static_cast<int>(sfm_data.views.size()); ++i)
  {
    ++my_progress_bar_images;

    if (!bOk)
      continue;

    Views::const_iterator iterViews = sfm_data.views.begin();
    std::advance(iterViews, i);
    const View * view = iterViews->second.get();

    // Get image paths
    const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path);
    const std::string imageName = stlplus::create_filespec(sOutDir, view->s_Img_path);

    if (!stlplus::is_file(srcImage))
    {
      std::cerr << "Cannot read the corresponding image: " << srcImage << std::endl;
      bOk = false;
      continue;
    }
    if (sfm_data.IsPoseAndIntrinsicDefined(view))
    {
      // export undistorted images
      const openMVG::cameras::IntrinsicBase * cam = sfm_data.GetIntrinsics().at(view->id_intrinsic).get();
      if (cam->have_disto())
      {
        // undistort image and save it
        Image<openMVG::image::RGBColor> imageRGB, imageRGB_ud;
        try
        {
          if (ReadImage(srcImage.c_str(), &imageRGB))
          {
            UndistortImage(imageRGB, cam, imageRGB_ud, BLACK);
            bOk = WriteImage(imageName.c_str(), imageRGB_ud);
          }
          else
          {
            bOk = false;
          }
        }
        catch (const std::bad_alloc& e)
        {
          bOk = false;
        }
      }
      else
      {
        // just copy image
        stlplus::file_copy(srcImage, imageName);
      }
    }
    else
    {
      // just copy the image
      stlplus::file_copy(srcImage, imageName);
    }
  }

  if (!bOk)
  {
    std::cerr << "Catched a memory error in the image conversion."
     << " Please consider to use less threads ([-n|--numThreads])." << std::endl;
    return EXIT_FAILURE;
  }

  // define structure
  scene.vertices.reserve(sfm_data.GetLandmarks().size());
  for (const auto& vertex: sfm_data.GetLandmarks())
  {
    const Landmark & landmark = vertex.second;
    MVS::Interface::Vertex vert;
    MVS::Interface::Vertex::ViewArr& views = vert.views;
    for (const auto& observation: landmark.obs)
    {
      const auto it(map_view.find(observation.first));
      if (it != map_view.end()) {
        MVS::Interface::Vertex::View view;
        view.imageID = it->second;
        view.confidence = 0;
        views.push_back(view);
      }
    }
    if (views.size() < 2)
      continue;
    std::sort(
      views.begin(), views.end(),
      [] (const MVS::Interface::Vertex::View& view0, const MVS::Interface::Vertex::View& view1)
      {
        return view0.imageID < view1.imageID;
      }
    );
    vert.X = landmark.X.cast<float>();
    scene.vertices.push_back(vert);
  }

  // normalize camera intrinsics
  for (size_t p=0; p<scene.platforms.size(); ++p)
  {
    MVS::Interface::Platform& platform = scene.platforms[p];
    for (size_t c=0; c<platform.cameras.size(); ++c) {
      MVS::Interface::Platform::Camera& camera = platform.cameras[c];
      // find one image using this camera
      MVS::Interface::Image* pImage(nullptr);
      for (MVS::Interface::Image& image: scene.images)
      {
        if (image.platformID == p && image.cameraID == c && image.poseID != NO_ID)
        {
          pImage = ℑ
          break;
        }
      }
      if (!pImage)
      {
        std::cerr << "error: no image using camera " << c << " of platform " << p << std::endl;
        continue;
      }
      // read image meta-data
      ImageHeader imageHeader;
      ReadImageHeader(pImage->name.c_str(), &imageHeader);
      const double fScale(1.0/std::max(imageHeader.width, imageHeader.height));
      camera.K(0, 0) *= fScale;
      camera.K(1, 1) *= fScale;
      camera.K(0, 2) *= fScale;
      camera.K(1, 2) *= fScale;
    }
  }

  // write OpenMVS data
  if (!MVS::ARCHIVE::SerializeSave(scene, sOutFile))
    return false;

  std::cout
    << "Scene saved to OpenMVS interface format:\n"
    << " #platforms: " << scene.platforms.size() << std::endl;
    for (int i = 0; i < scene.platforms.size(); ++i)
    {
      std::cout << "  platform ( " << i << " ) #cameras: " << scene.platforms[i].cameras.size() << std::endl;
    }
  std::cout
    << "  " << scene.images.size() << " images (" << nPoses << " calibrated)\n"
    << "  " << scene.vertices.size() << " Landmarks\n";
  return true;
}

int main(int argc, char *argv[])
{
  CmdLine cmd;
  std::string sSfM_Data_Filename;
  std::string sOutFile = "scene.mvs";
  std::string sOutDir = "undistorted_images";
  int iNumThreads = 0;

  cmd.add( make_option('i', sSfM_Data_Filename, "sfmdata") );
  cmd.add( make_option('o', sOutFile, "outfile") );
  cmd.add( make_option('d', sOutDir, "outdir") );
#ifdef OPENMVG_USE_OPENMP
  cmd.add( make_option('n', iNumThreads, "numThreads") );
#endif

  try {
      if (argc == 1) throw std::string("Invalid command line parameter.");
      cmd.process(argc, argv);
  } catch (const std::string& s) {
      std::cerr << "Usage: " << argv[0] << '\n'
      << "[-i|--sfmdata] filename, the SfM_Data file to convert\n"
      << "[-o|--outfile] OpenMVS scene file\n"
      << "[-d|--outdir] undistorted images path\n"
#ifdef OPENMVG_USE_OPENMP
      << "[-n|--numThreads] number of thread(s)\n"
#endif
      << std::endl;

      std::cerr << s << std::endl;
      return EXIT_FAILURE;
  }

  if (stlplus::extension_part(sOutFile) != "mvs") {
    std::cerr << std::endl
      << "Invalid output file extension: " << sOutFile << std::endl
      << "You must use a filename with a .mvs extension." << std::endl;
      return EXIT_FAILURE;
  }

  // Read the input SfM scene
  SfM_Data sfm_data;
  if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(ALL))) {
    std::cerr << std::endl
      << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  // Export OpenMVS data structure
  if (!exportToOpenMVS(sfm_data, sOutFile, sOutDir, iNumThreads))
  {
    std::cerr << std::endl
      << "The output openMVS scene file cannot be written" << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>[software] fix: main_openMVG2openMVS support grayscale images (#1709)<commit_after>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2016 cDc <cdc.seacave@gmail.com>, Pierre MOULON

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/cameras/Camera_Pinhole.hpp"
#include "openMVG/cameras/Camera_undistort_image.hpp"
#include "openMVG/image/image_io.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_io.hpp"

#define _USE_EIGEN
#include "InterfaceMVS.h"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"
#include "third_party/progress/progress_display.hpp"

using namespace openMVG;
using namespace openMVG::cameras;
using namespace openMVG::geometry;
using namespace openMVG::image;
using namespace openMVG::sfm;

#include <atomic>
#include <cstdlib>
#include <string>

#ifdef OPENMVG_USE_OPENMP
#include <omp.h>
#endif

bool exportToOpenMVS(
  const SfM_Data & sfm_data,
  const std::string & sOutFile,
  const std::string & sOutDir,
  const int iNumThreads = 0
  )
{
  // Create undistorted images directory structure
  if (!stlplus::is_folder(sOutDir))
  {
    stlplus::folder_create(sOutDir);
    if (!stlplus::is_folder(sOutDir))
    {
      std::cerr << "Cannot access to one of the desired output directory" << std::endl;
      return false;
    }
  }

  // Export data :
  MVS::Interface scene;
  size_t nPoses(0);
  const uint32_t nViews((uint32_t)sfm_data.GetViews().size());

  C_Progress_display my_progress_bar(nViews,
      std::cout, "\n- PROCESS VIEWS -\n");

  // OpenMVG can have not contiguous index, use a map to create the required OpenMVS contiguous ID index
  std::map<openMVG::IndexT, uint32_t> map_intrinsic, map_view;

  // define a platform with all the intrinsic group
  for (const auto& intrinsic: sfm_data.GetIntrinsics())
  {
    if (isPinhole(intrinsic.second->getType()))
    {
      const Pinhole_Intrinsic * cam = dynamic_cast<const Pinhole_Intrinsic*>(intrinsic.second.get());
      if (map_intrinsic.count(intrinsic.first) == 0)
        map_intrinsic.insert(std::make_pair(intrinsic.first, scene.platforms.size()));
      MVS::Interface::Platform platform;
      // add the camera
      MVS::Interface::Platform::Camera camera;
      camera.K = cam->K();
      // sub-pose
      camera.R = Mat3::Identity();
      camera.C = Vec3::Zero();
      platform.cameras.push_back(camera);
      scene.platforms.push_back(platform);
    }
  }

  // define images & poses
  scene.images.reserve(nViews);
  for (const auto& view : sfm_data.GetViews())
  {
    map_view[view.first] = scene.images.size();
    MVS::Interface::Image image;
    const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view.second->s_Img_path);
    image.name = stlplus::create_filespec(sOutDir, view.second->s_Img_path);
    image.platformID = map_intrinsic.at(view.second->id_intrinsic);
    MVS::Interface::Platform& platform = scene.platforms[image.platformID];
    image.cameraID = 0;
    if (!stlplus::is_file(srcImage))
    {
      std::cout << "Cannot read the corresponding image: " << srcImage << std::endl;
      return EXIT_FAILURE;
    }
    if (sfm_data.IsPoseAndIntrinsicDefined(view.second.get()))
    {
      MVS::Interface::Platform::Pose pose;
      image.poseID = platform.poses.size();
      const openMVG::geometry::Pose3 poseMVG(sfm_data.GetPoseOrDie(view.second.get()));
      pose.R = poseMVG.rotation();
      pose.C = poseMVG.center();
      platform.poses.push_back(pose);
      ++nPoses;
    }
    else
    {
      // image have not valid pose, so set an undefined pose
      image.poseID = NO_ID;
      // just copy the image
      //stlplus::file_copy(srcImage, image.name);
    }
    scene.images.emplace_back(image);
    ++my_progress_bar;
  }

  // Export undistorted images
  C_Progress_display my_progress_bar_images(sfm_data.views.size(),
      std::cout, "\n- UNDISTORT IMAGES -\n" );
  std::atomic<bool> bOk(true); // Use a boolean to track the status of the loop process
#ifdef OPENMVG_USE_OPENMP
  const unsigned int nb_max_thread = (iNumThreads > 0)? iNumThreads : omp_get_max_threads();

  #pragma omp parallel for schedule(dynamic) num_threads(nb_max_thread)
#endif
  for (int i = 0; i < static_cast<int>(sfm_data.views.size()); ++i)
  {
    ++my_progress_bar_images;

    if (!bOk)
      continue;

    Views::const_iterator iterViews = sfm_data.views.begin();
    std::advance(iterViews, i);
    const View * view = iterViews->second.get();

    // Get image paths
    const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path);
    const std::string imageName = stlplus::create_filespec(sOutDir, view->s_Img_path);

    if (!stlplus::is_file(srcImage))
    {
      std::cerr << "Cannot read the corresponding image: " << srcImage << std::endl;
      bOk = false;
      continue;
    }
    if (sfm_data.IsPoseAndIntrinsicDefined(view))
    {
      // export undistorted images
      const openMVG::cameras::IntrinsicBase * cam = sfm_data.GetIntrinsics().at(view->id_intrinsic).get();
      if (cam->have_disto())
      {
        // undistort image and save it
        Image<openMVG::image::RGBColor> imageRGB, imageRGB_ud;
        Image<uint8_t> image_gray, image_gray_ud;
        try
        {
          if (ReadImage(srcImage.c_str(), &imageRGB))
          {
            UndistortImage(imageRGB, cam, imageRGB_ud, BLACK);
            bOk = WriteImage(imageName.c_str(), imageRGB_ud);
          }
          else // If RGBColor reading fails, try to read as gray image
          if (ReadImage(srcImage.c_str(), &image_gray))
          {
            UndistortImage(image_gray, cam, image_gray_ud, BLACK);
            const bool bRes = WriteImage(imageName.c_str(), image_gray_ud);
            bOk = bOk & bRes;
          }
          else
          {
            bOk = false;
          }
        }
        catch (const std::bad_alloc& e)
        {
          bOk = false;
        }
      }
      else
      {
        // just copy image
        stlplus::file_copy(srcImage, imageName);
      }
    }
    else
    {
      // just copy the image
      stlplus::file_copy(srcImage, imageName);
    }
  }

  if (!bOk)
  {
    std::cerr << "Catched a memory error in the image conversion."
     << " Please consider to use less threads ([-n|--numThreads])." << std::endl;
    return EXIT_FAILURE;
  }

  // define structure
  scene.vertices.reserve(sfm_data.GetLandmarks().size());
  for (const auto& vertex: sfm_data.GetLandmarks())
  {
    const Landmark & landmark = vertex.second;
    MVS::Interface::Vertex vert;
    MVS::Interface::Vertex::ViewArr& views = vert.views;
    for (const auto& observation: landmark.obs)
    {
      const auto it(map_view.find(observation.first));
      if (it != map_view.end()) {
        MVS::Interface::Vertex::View view;
        view.imageID = it->second;
        view.confidence = 0;
        views.push_back(view);
      }
    }
    if (views.size() < 2)
      continue;
    std::sort(
      views.begin(), views.end(),
      [] (const MVS::Interface::Vertex::View& view0, const MVS::Interface::Vertex::View& view1)
      {
        return view0.imageID < view1.imageID;
      }
    );
    vert.X = landmark.X.cast<float>();
    scene.vertices.push_back(vert);
  }

  // normalize camera intrinsics
  for (size_t p=0; p<scene.platforms.size(); ++p)
  {
    MVS::Interface::Platform& platform = scene.platforms[p];
    for (size_t c=0; c<platform.cameras.size(); ++c) {
      MVS::Interface::Platform::Camera& camera = platform.cameras[c];
      // find one image using this camera
      MVS::Interface::Image* pImage(nullptr);
      for (MVS::Interface::Image& image: scene.images)
      {
        if (image.platformID == p && image.cameraID == c && image.poseID != NO_ID)
        {
          pImage = ℑ
          break;
        }
      }
      if (!pImage)
      {
        std::cerr << "error: no image using camera " << c << " of platform " << p << std::endl;
        continue;
      }
      // read image meta-data
      ImageHeader imageHeader;
      ReadImageHeader(pImage->name.c_str(), &imageHeader);
      const double fScale(1.0/std::max(imageHeader.width, imageHeader.height));
      camera.K(0, 0) *= fScale;
      camera.K(1, 1) *= fScale;
      camera.K(0, 2) *= fScale;
      camera.K(1, 2) *= fScale;
    }
  }

  // write OpenMVS data
  if (!MVS::ARCHIVE::SerializeSave(scene, sOutFile))
    return false;

  std::cout
    << "Scene saved to OpenMVS interface format:\n"
    << " #platforms: " << scene.platforms.size() << std::endl;
    for (int i = 0; i < scene.platforms.size(); ++i)
    {
      std::cout << "  platform ( " << i << " ) #cameras: " << scene.platforms[i].cameras.size() << std::endl;
    }
  std::cout
    << "  " << scene.images.size() << " images (" << nPoses << " calibrated)\n"
    << "  " << scene.vertices.size() << " Landmarks\n";
  return true;
}

int main(int argc, char *argv[])
{
  CmdLine cmd;
  std::string sSfM_Data_Filename;
  std::string sOutFile = "scene.mvs";
  std::string sOutDir = "undistorted_images";
  int iNumThreads = 0;

  cmd.add( make_option('i', sSfM_Data_Filename, "sfmdata") );
  cmd.add( make_option('o', sOutFile, "outfile") );
  cmd.add( make_option('d', sOutDir, "outdir") );
#ifdef OPENMVG_USE_OPENMP
  cmd.add( make_option('n', iNumThreads, "numThreads") );
#endif

  try {
      if (argc == 1) throw std::string("Invalid command line parameter.");
      cmd.process(argc, argv);
  } catch (const std::string& s) {
      std::cerr << "Usage: " << argv[0] << '\n'
      << "[-i|--sfmdata] filename, the SfM_Data file to convert\n"
      << "[-o|--outfile] OpenMVS scene file\n"
      << "[-d|--outdir] undistorted images path\n"
#ifdef OPENMVG_USE_OPENMP
      << "[-n|--numThreads] number of thread(s)\n"
#endif
      << std::endl;

      std::cerr << s << std::endl;
      return EXIT_FAILURE;
  }

  if (stlplus::extension_part(sOutFile) != "mvs") {
    std::cerr << std::endl
      << "Invalid output file extension: " << sOutFile << std::endl
      << "You must use a filename with a .mvs extension." << std::endl;
      return EXIT_FAILURE;
  }

  // Read the input SfM scene
  SfM_Data sfm_data;
  if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(ALL))) {
    std::cerr << std::endl
      << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  // Export OpenMVS data structure
  if (!exportToOpenMVS(sfm_data, sOutFile, sOutDir, iNumThreads))
  {
    std::cerr << std::endl
      << "The output openMVS scene file cannot be written" << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <cmath>

#include <glm/gtc/matrix_transform.hpp>
#include <SDL2/SDL.h>

#include <zombye/core/game.hpp>
#include <zombye/ecs/entity_manager.hpp>
#include <zombye/gameplay/states/play_state.hpp>
#include <zombye/input/input_manager.hpp>
#include <zombye/input/input_system.hpp>
#include <zombye/input/joystick.hpp>
#include <zombye/input/mouse.hpp>
#include <zombye/physics/shapes/box_shape.hpp>
#include <zombye/physics/physics_component.hpp>
#include <zombye/rendering/animation_component.hpp>
#include <zombye/rendering/camera_component.hpp>
#include <zombye/rendering/rendering_system.hpp>
#include <zombye/scripting/scripting_system.hpp>
#include <zombye/utils/logger.hpp>
#include <zombye/utils/state_machine.hpp>

zombye::play_state::play_state(zombye::state_machine *sm) : sm_(sm) {
    auto input = sm->get_game()->input();
    input_ = input->create_manager();

    /*input_->register_action("FIRE", []() {
        zombye::log("Peng Peng!");
    });*/
    input_->register_actions(*sm->get_game(), "scripts/input/play_state.as");

    input_->register_action("FIRE_END", []() {
        zombye::log("No more peng :(");
    });

    auto first_joystick = input->first_joystick();

    if(first_joystick) {
        input_->register_event("FIRE", first_joystick->button_A());
        input_->register_event("FIRE", first_joystick->button_B());

        input_->register_up_event("FIRE_END", first_joystick->button_A());
        input_->register_up_event("FIRE_END", first_joystick->button_B());
    }

    input_->register_event("FIRE", input->mouse()->left_button());
    input_->register_keyboard_event("FIRE", "space");
    input_->register_up_event("FIRE_END", input->mouse()->left_button());
    input_->register_keyboard_up_event("FIRE_END", "space");

    input_->register_keyboard_event("move_forward_begin", "w");
    input_->register_keyboard_up_event("move_forward_end", "w");
    input_->register_keyboard_event("move_backward_begin", "s");
    input_->register_keyboard_up_event("move_backward_end", "s");
    input_->register_keyboard_event("move_right_begin", "d");
    input_->register_keyboard_up_event("move_right_end", "d");
    input_->register_keyboard_event("move_left_begin", "a");
    input_->register_keyboard_up_event("move_left_end", "a");
}

void zombye::play_state::enter() {
    zombye::log("enter play state");

    auto& game = *sm_->get_game();

    auto& scripting_system = game.scripting_system();
    scripting_system.begin_module("MyModule");
    scripting_system.load_script("scripts/test.as");
    scripting_system.end_module();
    scripting_system.exec("void main()", "MyModule");
}

void zombye::play_state::leave() {
    zombye::log("leave play state");
}

void zombye::play_state::update(float delta_time) {
    input_->handle_input();
}
<commit_msg>Remove hardcoded action/key registration and load input config instead.<commit_after>#include <cmath>

#include <glm/gtc/matrix_transform.hpp>
#include <SDL2/SDL.h>

#include <zombye/core/game.hpp>
#include <zombye/ecs/entity_manager.hpp>
#include <zombye/gameplay/states/play_state.hpp>
#include <zombye/input/input_manager.hpp>
#include <zombye/input/input_system.hpp>
#include <zombye/input/joystick.hpp>
#include <zombye/input/mouse.hpp>
#include <zombye/physics/shapes/box_shape.hpp>
#include <zombye/physics/physics_component.hpp>
#include <zombye/rendering/animation_component.hpp>
#include <zombye/rendering/camera_component.hpp>
#include <zombye/rendering/rendering_system.hpp>
#include <zombye/scripting/scripting_system.hpp>
#include <zombye/utils/logger.hpp>
#include <zombye/utils/state_machine.hpp>

zombye::play_state::play_state(zombye::state_machine *sm) : sm_(sm) {
    auto input = sm->get_game()->input();
    input_ = input->create_manager();

    /*input_->register_action("FIRE", []() {
        zombye::log("Peng Peng!");
    });*/
    input_->register_actions(*sm->get_game(), "scripts/input/play_state.as");
    input_->load_config(*sm->get_game(), "config/input/play_state.json");

    input_->register_action("FIRE_END", []() {
        zombye::log("No more peng :(");
    });

    auto first_joystick = input->first_joystick();

    if(first_joystick) {
        input_->register_event("FIRE", first_joystick->button_A());
        input_->register_event("FIRE", first_joystick->button_B());

        input_->register_up_event("FIRE_END", first_joystick->button_A());
        input_->register_up_event("FIRE_END", first_joystick->button_B());
    }

    input_->register_event("FIRE", input->mouse()->left_button());
    input_->register_keyboard_event("FIRE", "space");
    input_->register_up_event("FIRE_END", input->mouse()->left_button());
    input_->register_keyboard_up_event("FIRE_END", "space");
}

void zombye::play_state::enter() {
    zombye::log("enter play state");

    auto& game = *sm_->get_game();

    auto& scripting_system = game.scripting_system();
    scripting_system.begin_module("MyModule");
    scripting_system.load_script("scripts/test.as");
    scripting_system.end_module();
    scripting_system.exec("void main()", "MyModule");
}

void zombye::play_state::leave() {
    zombye::log("leave play state");
}

void zombye::play_state::update(float delta_time) {
    input_->handle_input();
}
<|endoftext|>