<commit_before># ReSTify
# ReST interface for appengine
#
# ReSTify is a ready to deploy Rest interfae for your appengine datastore for testing purposes.
#
# Copyright 2013 Mevin Babu Chirayath <mevinbabuc@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

__author__ = 'mevinbabuc@gmail.com (Mevin Babu Chirayath)'
__version__ = "0.1"

import os
import sys

from google.appengine.api import users

import webapp2
import json

from model import *
import settings
get_model_from_URL = settings.MODEL_NAME_ALIAS

def get_model_from_URL(node_name):
    model_alias = settings.MODEL_NAME_ALIAS[node_name]
    return getattr(model, model_alias)

def CSOR_Jsonify(func):
    """ decorator to make all requests CSOR compatible and jsonfy the output """

    def wrapper(*args, **kw):

        def datetimeconvert(obj):
            """datetimeconvert JSON serializer."""

            import datetime

            if isinstance(obj, datetime.datetime):
                return obj.strftime("%Y/%m/%d %H:%M")

            return str(obj)

        dataObject=func(*args, **kw)

        try:
            _origin = args[0].request.headers['Origin']
        except:
            _origin = settings.ORIGIN_SITE_NAME

        args[0].response.headers.add_header("Access-Control-Allow-Origin", _origin)
        args[0].response.headers.add_header("Access-Control-Allow-Credentials", "true")
        args[0].response.headers.add_header("Access-Control-Allow-Headers",
         "origin, x-requested-with, content-type, accept")
        args[0].response.headers.add_header('Content-Type', 'application/json')

        if dataObject:
            args[0].response.write(json.dumps(dataObject, default = datetimeconvert))

    return wrapper

class ReST(webapp2.RequestHandler):
    """ Class to handle requests (GET, POST, DELETE, PUT) to the route /api/ """

    @CSOR_Jsonify
    def post(self,query=""):
        """Post Request handler to add data to the datastore

        Args:

        return:
            A status object which contains the data added and error messages if any.
            status['object']
            status['success']
            status['error']

        response status codes :
            201 -> Created   -> When a new object is succesfully saved in the datastore
            404 -> Not Found -> When the post body is invalid or null

        """

        status={}
        status["error"]=None
        status["success"]=True
        key=False
        json_args_dic = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        _model = get_model_from_URL(node[2])

        _json = self.request.body.encode("utf-8")

        try:
            json_args_dic = json.loads(_json,encoding="utf-8")
        except:
            json_args_dic = None
            self.abort(400)

        if json_args_dic:
            HashEntry=_model(author=users.get_current_user(), **json_args_dic)
            key=HashEntry.put()
            self.response.set_status(201,"Created")

            json_args_dic['id'] = key.id()
            status['object'] = json_args_dic

        if not key:
            status["success"] = False
            status["error"] = "Unable to Add your Tab.Try again"
            self.abort(404)

        return status

    @CSOR_Jsonify
    def get(self,query=""):
        """Get request handler to retrieve data from datastore

        Args:

        Return:
            An object containing all the entities of the logged in user.

        Response status codes :
            404 -> Not Found -> When there's no data in the datastore for the
                                particular user
            400 -> Bad Request->When the program is unable to search db etc.
                                Try again later.
            200 -> Ok -> When data is found and proper data is returned.

        """
        qry = None
        Object_by_id = None
        _model = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        if len(node) - 1 >= 2:
            if node[2]:
                try:
                    _model = get_model_from_URL(node[2])
                except:
                    _model = None

            if len(node) -1 > 2 and _model:
                Object_by_id = _model.get_by_id(int(node[3]))
            elif node[2] and _model:
                qry = _model.query().filter(_model.author == users.get_current_user())
            else:
                print str(_model)
                self.abort(404)

        dataList=[]

        if qry :
            for temp in qry:
                dataObject=temp.to_dict()
                dataObject["id"] = temp.key.id()
                dataList.append(dataObject)

        elif Object_by_id:
            dataObject=Object_by_id.to_dict()
            dataList.append(dataObject)

        if len(dataList)==0:
            self.abort(404)
            dataList = None
        elif not qry and not Object_by_id:
            self.abort(400)
        else :
            self.response.set_status(200,"Ok")

        return dataList

    @CSOR_Jsonify
    def delete(self,query=""):
        """Delete request handler to delete an entity from datastore

        Args:

        Return:
            Delete request is not supposed to return any value

        Response status codes :
            404 -> Not Found -> When the data to be deleted is not found
            204 -> No Content-> When data is found in the datastore and deleted,
                                so there's no content to return
            400 -> Bad Request->When invalid delete request was made

        """

        Object_by_id = None
        _model = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        if len(node) - 1 > 2:
            if node[2]:
                try:
                    _model = get_model_from_URL(node[2])
                except:
                    _model = None

            if _model:
                Object_by_id = _model.get_by_id(int(node[3]))
        else:
            self.abort(404)

        if Object_by_id:
            Object_by_id.key.delete()
            self.response.set_status(204,"No Content")
        elif not _model:
            self.abort(404)
        else:
            self.abort(400)

        return {}

    @CSOR_Jsonify
    def put(self,query=""):
        """PUT request handler to edit an entity from datastore

        Args:

        Return:
            returns the edited object

        Response status codes :
            404 -> Not Found -> When the data to be deleted is not found in the
                                datastore
            200 -> Ok        -> When data is found in the datastore and edited
            400 -> Bad Request->When invalid id or model name was used to make
                                put request

        """
        status={}
        status["error"]=None
        status["success"]=True
        Object_by_id = None
        _model = None
        _json = None
        json_args_dic = None
        HashEntry = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        if len(node) - 1 > 2:
            if node[2]:
                try:
                    _model = get_model_from_URL(node[2])
                except:
                    _model = None

            #check if the id is a valid one
            if _model:
                Object_by_id = _model.get_by_id(int(node[3]))
            else:
                self.abort(404)

            # if data already present in server, then modify
            if Object_by_id:
                _json = self.request.body.encode("utf-8")

                try:
                    json_args_dic = json.loads(_json,encoding="utf-8")
                except:
                    json_args_dic = None

                if json_args_dic :
                    json_args_dic["id"]=int(node[3])
                    status['object'] = json_args_dic
                    HashEntry=_model(author=users.get_current_user(), **json_args_dic)
                    key=HashEntry.put()
                else:
                    self.abort(400)
            else:
                self.abort(404)
        else:
            self.abort(404)

        if HashEntry:
            self.response.set_status(200,"Ok")
            return status
        else:
            self.abort(404)

    def options(self,query=""):

        try:
            _origin = self.request.headers['Origin']
        except:
            _origin = settings.ORIGIN_SITE_NAME

        self.response.set_status(200,"Ok")
        self.response.headers.add_header("Access-Control-Allow-Origin", _origin)
        self.response.headers.add_header("Access-Control-Allow-Methods",
         "GET, POST, OPTIONS, PUT, DELETE")
        self.response.headers.add_header("Access-Control-Allow-Credentials", "true")
        self.response.headers.add_header("Access-Control-Allow-Headers",
         "origin, x-requested-with, content-type, accept")
<commit_msg>Added URL to model name mapping.<commit_after># ReSTify
# ReST interface for appengine
#
# ReSTify is a ready to deploy Rest interfae for your appengine datastore for testing purposes.
#
# Copyright 2013 Mevin Babu Chirayath <mevinbabuc@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

__author__ = 'mevinbabuc@gmail.com (Mevin Babu Chirayath)'
__version__ = "0.1"

import os
import sys

from google.appengine.api import users

import webapp2
import json

from model import *
import settings

def get_model_from_URL(node_name):

    # Get the corresponding model name from URL
    model_alias = settings.MODEL_NAME_ALIAS[node_name]
    return getattr(model, model_alias)

def CSOR_Jsonify(func):
    """ decorator to make all requests CSOR compatible and jsonfy the output """

    def wrapper(*args, **kw):

        def datetimeconvert(obj):
            """datetimeconvert JSON serializer."""

            import datetime

            if isinstance(obj, datetime.datetime):
                return obj.strftime("%Y/%m/%d %H:%M")

            return str(obj)

        dataObject=func(*args, **kw)

        try:
            _origin = args[0].request.headers['Origin']
        except:
            _origin = settings.ORIGIN_SITE_NAME

        args[0].response.headers.add_header("Access-Control-Allow-Origin", _origin)
        args[0].response.headers.add_header("Access-Control-Allow-Credentials", "true")
        args[0].response.headers.add_header("Access-Control-Allow-Headers",
         "origin, x-requested-with, content-type, accept")
        args[0].response.headers.add_header('Content-Type', 'application/json')

        if dataObject:
            args[0].response.write(json.dumps(dataObject, default = datetimeconvert))

    return wrapper

class ReST(webapp2.RequestHandler):
    """ Class to handle requests (GET, POST, DELETE, PUT) to the route /api/ """

    @CSOR_Jsonify
    def post(self,query=""):
        """Post Request handler to add data to the datastore

        Args:

        return:
            A status object which contains the data added and error messages if any.
            status['object']
            status['success']
            status['error']

        response status codes :
            201 -> Created   -> When a new object is succesfully saved in the datastore
            404 -> Not Found -> When the post body is invalid or null

        """

        status={}
        status["error"]=None
        status["success"]=True
        key=False
        json_args_dic = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        _model = get_model_from_URL(node[2])

        _json = self.request.body.encode("utf-8")

        try:
            json_args_dic = json.loads(_json,encoding="utf-8")
        except:
            json_args_dic = None
            self.abort(400)

        if json_args_dic:
            HashEntry=_model(author=users.get_current_user(), **json_args_dic)
            key=HashEntry.put()
            self.response.set_status(201,"Created")

            json_args_dic['id'] = key.id()
            status['object'] = json_args_dic

        if not key:
            status["success"] = False
            status["error"] = "Unable to Add your Tab.Try again"
            self.abort(404)

        return status

    @CSOR_Jsonify
    def get(self,query=""):
        """Get request handler to retrieve data from datastore

        Args:

        Return:
            An object containing all the entities of the logged in user.

        Response status codes :
            404 -> Not Found -> When there's no data in the datastore for the
                                particular user
            400 -> Bad Request->When the program is unable to search db etc.
                                Try again later.
            200 -> Ok -> When data is found and proper data is returned.

        """
        qry = None
        Object_by_id = None
        _model = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        if len(node) - 1 >= 2:
            if node[2]:
                try:
                    _model = get_model_from_URL(node[2])
                except:
                    _model = None

            if len(node) -1 > 2 and _model:
                Object_by_id = _model.get_by_id(int(node[3]))
            elif node[2] and _model:
                qry = _model.query().filter(_model.author == users.get_current_user())
            else:
                print str(_model)
                self.abort(404)

        dataList=[]

        if qry :
            for temp in qry:
                dataObject=temp.to_dict()
                dataObject["id"] = temp.key.id()
                dataList.append(dataObject)

        elif Object_by_id:
            dataObject=Object_by_id.to_dict()
            dataList.append(dataObject)

        if len(dataList)==0:
            self.abort(404)
            dataList = None
        elif not qry and not Object_by_id:
            self.abort(400)
        else :
            self.response.set_status(200,"Ok")

        return dataList

    @CSOR_Jsonify
    def delete(self,query=""):
        """Delete request handler to delete an entity from datastore

        Args:

        Return:
            Delete request is not supposed to return any value

        Response status codes :
            404 -> Not Found -> When the data to be deleted is not found
            204 -> No Content-> When data is found in the datastore and deleted,
                                so there's no content to return
            400 -> Bad Request->When invalid delete request was made

        """

        Object_by_id = None
        _model = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        if len(node) - 1 > 2:
            if node[2]:
                try:
                    _model = get_model_from_URL(node[2])
                except:
                    _model = None

            if _model:
                Object_by_id = _model.get_by_id(int(node[3]))
        else:
            self.abort(404)

        if Object_by_id:
            Object_by_id.key.delete()
            self.response.set_status(204,"No Content")
        elif not _model:
            self.abort(404)
        else:
            self.abort(400)

        return {}

    @CSOR_Jsonify
    def put(self,query=""):
        """PUT request handler to edit an entity from datastore

        Args:

        Return:
            returns the edited object

        Response status codes :
            404 -> Not Found -> When the data to be deleted is not found in the
                                datastore
            200 -> Ok        -> When data is found in the datastore and edited
            400 -> Bad Request->When invalid id or model name was used to make
                                put request

        """
        status={}
        status["error"]=None
        status["success"]=True
        Object_by_id = None
        _model = None
        _json = None
        json_args_dic = None
        HashEntry = None

        node = self.request.path_info.split('/')
        if node[-1] == '':
            node.pop(-1)

        if len(node) - 1 > 2:
            if node[2]:
                try:
                    _model = get_model_from_URL(node[2])
                except:
                    _model = None

            #check if the id is a valid one
            if _model:
                Object_by_id = _model.get_by_id(int(node[3]))
            else:
                self.abort(404)

            # if data already present in server, then modify
            if Object_by_id:
                _json = self.request.body.encode("utf-8")

                try:
                    json_args_dic = json.loads(_json,encoding="utf-8")
                except:
                    json_args_dic = None

                if json_args_dic :
                    json_args_dic["id"]=int(node[3])
                    status['object'] = json_args_dic
                    HashEntry=_model(author=users.get_current_user(), **json_args_dic)
                    key=HashEntry.put()
                else:
                    self.abort(400)
            else:
                self.abort(404)
        else:
            self.abort(404)

        if HashEntry:
            self.response.set_status(200,"Ok")
            return status
        else:
            self.abort(404)

    def options(self,query=""):

        try:
            _origin = self.request.headers['Origin']
        except:
            _origin = settings.ORIGIN_SITE_NAME

        self.response.set_status(200,"Ok")
        self.response.headers.add_header("Access-Control-Allow-Origin", _origin)
        self.response.headers.add_header("Access-Control-Allow-Methods",
         "GET, POST, OPTIONS, PUT, DELETE")
        self.response.headers.add_header("Access-Control-Allow-Credentials", "true")
        self.response.headers.add_header("Access-Control-Allow-Headers",
         "origin, x-requested-with, content-type, accept")
<|endoftext|>


<commit_before>from __future__ import absolute_import, unicode_literals

import flask
import os
import logging

from flask_heroku import Heroku
from flask_redis import Redis
from flask_sqlalchemy import SQLAlchemy
from raven.contrib.flask import Sentry

from freight.api.controller import ApiController
from freight.constants import PROJECT_ROOT
from freight.utils.celery import ContextualCelery

api = ApiController(prefix='/api/0')
db = SQLAlchemy(session_options={})
celery = ContextualCelery()
heroku = Heroku()
redis = Redis()
sentry = Sentry(logging=True, level=logging.WARN)

def configure_logging(app):
    logging.getLogger().setLevel(getattr(logging, app.config['LOG_LEVEL']))

def create_app(_read_config=True, **config):
    from kombu import Queue

    app = flask.Flask(
        __name__,
        static_folder=None,
        template_folder=os.path.join(PROJECT_ROOT, 'templates'))

    # Utilized for sessions and other secrets
    # NOTE: This key is insecure and you should override it on the server
    app.config['SECRET_KEY'] = 't\xad\xe7\xff%\xd2.\xfe\x03\x02=\xec\xaf\\2+\xb8=\xf7\x8a\x9aLD\xb1'
    if 'SECRET_KEY' in os.environ:
        app.config['SECRET_KEY'] = os.environ['SECRET_KEY']

    # The api key to authorize end users against this system.
    # NOTE: This key is insecure and you should override it on the server
    app.config['API_KEY'] = '3e84744ab2714151b1db789df82b41c0021958fe4d77406e9c0947c34f5c5a70'
    if 'API_KEY' in os.environ:
        app.config['API_KEY'] = os.environ['API_KEY']

    # The private key to use when cloning repositories
    # TODO(dcramer): this should support an on-disk option, as well as be
    # possible to override per repo
    app.config['SSH_PRIVATE_KEY'] = os.environ.get('SSH_PRIVATE_KEY', '').replace("\\n", "\n")

    if 'REDISCLOUD_URL' in os.environ:
        app.config['REDIS_URL'] = os.environ['REDISCLOUD_URL']

    app.config['WORKSPACE_ROOT'] = os.environ.get('WORKSPACE_ROOT', '/tmp')

    app.config['DEFAULT_TIMEOUT'] = int(os.environ.get('DEFAULT_TIMEOUT', 300))

    app.config['LOG_LEVEL'] = os.environ.get('LOG_LEVEL', 'INFO' if config.get('DEBUG') else 'ERROR')

    # Currently authentication requires Google
    app.config['GOOGLE_CLIENT_ID'] = os.environ.get('GOOGLE_CLIENT_ID')
    app.config['GOOGLE_CLIENT_SECRET'] = os.environ.get('GOOGLE_CLIENT_SECRET')
    app.config['GOOGLE_DOMAIN'] = os.environ.get('GOOGLE_DOMAIN')

    app.config['GITHUB_TOKEN'] = None
    app.config['GITHUB_API_ROOT'] = 'https://api.github.com'

    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
    app.config['SQLALCHEMY_POOL_SIZE'] = 60
    app.config['SQLALCHEMY_MAX_OVERFLOW'] = 20

    app.config['BROKER_TRANSPORT'] = None

    app.config['CELERY_ACCEPT_CONTENT'] = ['json']
    app.config['CELERY_ACKS_LATE'] = True
    app.config['CELERY_DEFAULT_QUEUE'] = "default"
    app.config['CELERY_DEFAULT_EXCHANGE'] = "default"
    app.config['CELERY_DEFAULT_EXCHANGE_TYPE'] = "direct"
    app.config['CELERY_DEFAULT_ROUTING_KEY'] = "default"
    app.config['CELERY_DISABLE_RATE_LIMITS'] = True
    app.config['CELERY_IGNORE_RESULT'] = True
    app.config['CELERY_RESULT_BACKEND'] = None
    app.config['CELERY_RESULT_SERIALIZER'] = 'json'
    app.config['CELERY_SEND_EVENTS'] = False
    app.config['CELERY_TASK_RESULT_EXPIRES'] = 1
    app.config['CELERY_TASK_SERIALIZER'] = 'json'
    app.config['CELERY_TIMEZONE'] = 'UTC'
    app.config['CELERYD_PREFETCH_MULTIPLIER'] = 1
    app.config['CELERYD_MAX_TASKS_PER_CHILD'] = 10000

    app.config['CELERY_QUEUES'] = (
        Queue('default', routing_key='default'),
        Queue('freight.tasks', routing_key='freight.tasks'),
    )

    app.config['CELERY_IMPORTS'] = (
        'freight.tasks',
    )

    app.config['CELERY_ROUTES'] = {
        'freight.execute_task': {
            'queue': 'freight.tasks',
            'routing_key': 'freight.tasks',
        },
    }

    app.config['SENTRY_INCLUDE_PATHS'] = [
        'ds',
    ]

    # Pull in Heroku configuration
    heroku.init_app(app)

    # Set any remaining defaults that might not be present yet
    if not app.config.get('SQLALCHEMY_DATABASE_URI'):
        app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///ds'

    if not app.config.get('BROKER_URL'):
        app.config['BROKER_URL'] = 'redis://localhost/0'

    app.config.update(config)

    if _read_config:
        if os.environ.get('FREIGHT_CONF'):
            # FREIGHT_CONF=/etc/freight.conf.py
            app.config.from_envvar('FREIGHT_CONF')
        else:
            # Look for ~/.freight/freight.conf.py
            path = os.path.normpath(os.path.expanduser('~/.freight/freight.conf.py'))
            app.config.from_pyfile(path, silent=True)

    configure_logging(app)
    configure_sentry(app)
    configure_api(app)
    configure_celery(app)
    configure_redis(app)
    configure_sqlalchemy(app)
    configure_web_routes(app)

    return app

def configure_api(app):
    from freight.api.controller import ApiCatchall
    from freight.api.app_details import AppDetailsApiView
    from freight.api.app_index import AppIndexApiView
    from freight.api.task_details import TaskDetailsApiView
    from freight.api.task_index import TaskIndexApiView
    from freight.api.task_log import TaskLogApiView

    api.add_resource(AppIndexApiView, '/apps/')
    api.add_resource(AppDetailsApiView, '/apps/<app_id>/')
    api.add_resource(TaskIndexApiView, '/tasks/')
    api.add_resource(TaskDetailsApiView, '/tasks/<task_id>/')
    api.add_resource(TaskLogApiView, '/tasks/<task_id>/log/')
    # catchall should be the last resource
    api.add_resource(ApiCatchall, '/<path:path>')
    # init must be called after routes are registered
    api.init_app(app)

def configure_celery(app):
    celery.init_app(app)

def configure_redis(app):
    redis.init_app(app)

def configure_sentry(app):
    from flask import session
    from raven.contrib.celery import register_signal, register_logger_signal

    sentry.init_app(app)

    @app.before_request
    def capture_user(*args, **kwargs):
        if 'uid' in session:
            sentry.client.user_context({
                'id': session['uid'],
                'email': session['email'],
            })

    register_signal(sentry.client)
    register_logger_signal(sentry.client)

def configure_sqlalchemy(app):
    db.init_app(app)

def configure_web_routes(app):
    from freight.web.auth import AuthorizedView, LoginView, LogoutView
    from freight.web.index import IndexView
    from freight.web.static import StaticView

    static_root = os.path.join(PROJECT_ROOT, 'dist')

    app.add_url_rule(
        '/static/<path:filename>',
        view_func=StaticView.as_view(b'static', root=static_root))

    app.add_url_rule(
        '/auth/login/',
        view_func=LoginView.as_view(b'login', authorized_url='authorized'))
    app.add_url_rule(
        '/auth/logout/',
        view_func=LogoutView.as_view(b'logout', complete_url='index'))
    app.add_url_rule(
        '/auth/complete/',
        view_func=AuthorizedView.as_view(b'authorized', authorized_url='authorized', complete_url='index'))

    app.add_url_rule(
        '/',
        view_func=IndexView.as_view(b'index', login_url='login'))
<commit_msg>Read GITHUB_TOKEN from env<commit_after>from __future__ import absolute_import, unicode_literals

import flask
import os
import logging

from flask_heroku import Heroku
from flask_redis import Redis
from flask_sqlalchemy import SQLAlchemy
from raven.contrib.flask import Sentry

from freight.api.controller import ApiController
from freight.constants import PROJECT_ROOT
from freight.utils.celery import ContextualCelery

api = ApiController(prefix='/api/0')
db = SQLAlchemy(session_options={})
celery = ContextualCelery()
heroku = Heroku()
redis = Redis()
sentry = Sentry(logging=True, level=logging.WARN)

def configure_logging(app):
    logging.getLogger().setLevel(getattr(logging, app.config['LOG_LEVEL']))

def create_app(_read_config=True, **config):
    from kombu import Queue

    app = flask.Flask(
        __name__,
        static_folder=None,
        template_folder=os.path.join(PROJECT_ROOT, 'templates'))

    # Utilized for sessions and other secrets
    # NOTE: This key is insecure and you should override it on the server
    app.config['SECRET_KEY'] = 't\xad\xe7\xff%\xd2.\xfe\x03\x02=\xec\xaf\\2+\xb8=\xf7\x8a\x9aLD\xb1'
    if 'SECRET_KEY' in os.environ:
        app.config['SECRET_KEY'] = os.environ['SECRET_KEY']

    # The api key to authorize end users against this system.
    # NOTE: This key is insecure and you should override it on the server
    app.config['API_KEY'] = '3e84744ab2714151b1db789df82b41c0021958fe4d77406e9c0947c34f5c5a70'
    if 'API_KEY' in os.environ:
        app.config['API_KEY'] = os.environ['API_KEY']

    # The private key to use when cloning repositories
    # TODO(dcramer): this should support an on-disk option, as well as be
    # possible to override per repo
    app.config['SSH_PRIVATE_KEY'] = os.environ.get('SSH_PRIVATE_KEY', '').replace("\\n", "\n")

    if 'REDISCLOUD_URL' in os.environ:
        app.config['REDIS_URL'] = os.environ['REDISCLOUD_URL']

    app.config['WORKSPACE_ROOT'] = os.environ.get('WORKSPACE_ROOT', '/tmp')

    app.config['DEFAULT_TIMEOUT'] = int(os.environ.get('DEFAULT_TIMEOUT', 300))

    app.config['LOG_LEVEL'] = os.environ.get('LOG_LEVEL', 'INFO' if config.get('DEBUG') else 'ERROR')

    # Currently authentication requires Google
    app.config['GOOGLE_CLIENT_ID'] = os.environ.get('GOOGLE_CLIENT_ID')
    app.config['GOOGLE_CLIENT_SECRET'] = os.environ.get('GOOGLE_CLIENT_SECRET')
    app.config['GOOGLE_DOMAIN'] = os.environ.get('GOOGLE_DOMAIN')

    app.config['GITHUB_TOKEN'] = os.eniron.get('GITHUB_TOKEN')
    app.config['GITHUB_API_ROOT'] = 'https://api.github.com'

    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
    app.config['SQLALCHEMY_POOL_SIZE'] = 60
    app.config['SQLALCHEMY_MAX_OVERFLOW'] = 20

    app.config['BROKER_TRANSPORT'] = None

    app.config['CELERY_ACCEPT_CONTENT'] = ['json']
    app.config['CELERY_ACKS_LATE'] = True
    app.config['CELERY_DEFAULT_QUEUE'] = "default"
    app.config['CELERY_DEFAULT_EXCHANGE'] = "default"
    app.config['CELERY_DEFAULT_EXCHANGE_TYPE'] = "direct"
    app.config['CELERY_DEFAULT_ROUTING_KEY'] = "default"
    app.config['CELERY_DISABLE_RATE_LIMITS'] = True
    app.config['CELERY_IGNORE_RESULT'] = True
    app.config['CELERY_RESULT_BACKEND'] = None
    app.config['CELERY_RESULT_SERIALIZER'] = 'json'
    app.config['CELERY_SEND_EVENTS'] = False
    app.config['CELERY_TASK_RESULT_EXPIRES'] = 1
    app.config['CELERY_TASK_SERIALIZER'] = 'json'
    app.config['CELERY_TIMEZONE'] = 'UTC'
    app.config['CELERYD_PREFETCH_MULTIPLIER'] = 1
    app.config['CELERYD_MAX_TASKS_PER_CHILD'] = 10000

    app.config['CELERY_QUEUES'] = (
        Queue('default', routing_key='default'),
        Queue('freight.tasks', routing_key='freight.tasks'),
    )

    app.config['CELERY_IMPORTS'] = (
        'freight.tasks',
    )

    app.config['CELERY_ROUTES'] = {
        'freight.execute_task': {
            'queue': 'freight.tasks',
            'routing_key': 'freight.tasks',
        },
    }

    app.config['SENTRY_INCLUDE_PATHS'] = [
        'ds',
    ]

    # Pull in Heroku configuration
    heroku.init_app(app)

    # Set any remaining defaults that might not be present yet
    if not app.config.get('SQLALCHEMY_DATABASE_URI'):
        app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///ds'

    if not app.config.get('BROKER_URL'):
        app.config['BROKER_URL'] = 'redis://localhost/0'

    app.config.update(config)

    if _read_config:
        if os.environ.get('FREIGHT_CONF'):
            # FREIGHT_CONF=/etc/freight.conf.py
            app.config.from_envvar('FREIGHT_CONF')
        else:
            # Look for ~/.freight/freight.conf.py
            path = os.path.normpath(os.path.expanduser('~/.freight/freight.conf.py'))
            app.config.from_pyfile(path, silent=True)

    configure_logging(app)
    configure_sentry(app)
    configure_api(app)
    configure_celery(app)
    configure_redis(app)
    configure_sqlalchemy(app)
    configure_web_routes(app)

    return app

def configure_api(app):
    from freight.api.controller import ApiCatchall
    from freight.api.app_details import AppDetailsApiView
    from freight.api.app_index import AppIndexApiView
    from freight.api.task_details import TaskDetailsApiView
    from freight.api.task_index import TaskIndexApiView
    from freight.api.task_log import TaskLogApiView

    api.add_resource(AppIndexApiView, '/apps/')
    api.add_resource(AppDetailsApiView, '/apps/<app_id>/')
    api.add_resource(TaskIndexApiView, '/tasks/')
    api.add_resource(TaskDetailsApiView, '/tasks/<task_id>/')
    api.add_resource(TaskLogApiView, '/tasks/<task_id>/log/')
    # catchall should be the last resource
    api.add_resource(ApiCatchall, '/<path:path>')
    # init must be called after routes are registered
    api.init_app(app)

def configure_celery(app):
    celery.init_app(app)

def configure_redis(app):
    redis.init_app(app)

def configure_sentry(app):
    from flask import session
    from raven.contrib.celery import register_signal, register_logger_signal

    sentry.init_app(app)

    @app.before_request
    def capture_user(*args, **kwargs):
        if 'uid' in session:
            sentry.client.user_context({
                'id': session['uid'],
                'email': session['email'],
            })

    register_signal(sentry.client)
    register_logger_signal(sentry.client)

def configure_sqlalchemy(app):
    db.init_app(app)

def configure_web_routes(app):
    from freight.web.auth import AuthorizedView, LoginView, LogoutView
    from freight.web.index import IndexView
    from freight.web.static import StaticView

    static_root = os.path.join(PROJECT_ROOT, 'dist')

    app.add_url_rule(
        '/static/<path:filename>',
        view_func=StaticView.as_view(b'static', root=static_root))

    app.add_url_rule(
        '/auth/login/',
        view_func=LoginView.as_view(b'login', authorized_url='authorized'))
    app.add_url_rule(
        '/auth/logout/',
        view_func=LogoutView.as_view(b'logout', complete_url='index'))
    app.add_url_rule(
        '/auth/complete/',
        view_func=AuthorizedView.as_view(b'authorized', authorized_url='authorized', complete_url='index'))

    app.add_url_rule(
        '/',
        view_func=IndexView.as_view(b'index', login_url='login'))
<|endoftext|>


<commit_before>"""
 _   _ _   _ _ _ _          ______      _ _
| | | | | (_) (_) |         | ___ \    | | |
| | | | |_ _| |_| |_ _   _  | |_/ / ___| | |_
| | | | __| | | | __| | | | | ___ \/ _ \ | __|
| |_| | |_| | | | |_| |_| | | |_/ /  __/ | |_
 \___/ \__|_|_|_|\__|\__, | \____/ \___|_|\__|
                      __/ |
                     |___/

A library to make you a Python CND Batman
"""

import re
import socket

import pygeoip
import requests
from bs4 import BeautifulSoup
from netaddr import IPAddress
from netaddr import IPNetwork
from netaddr import IPRange

gi = pygeoip.GeoIP("data/GeoLiteCity.dat", pygeoip.MEMORY_CACHE)

# Indicators
re_ipv4 = re.compile('(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', re.I | re.S | re.M)
re_email = re.compile("\\b[A-Za-z0-9_.]+@[0-9a-z.-]+\\b", re.I | re.S | re.M)
re_fqdn = re.compile('(?=^.{4,255}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)', re.I | re.S | re.M)
re_cve = re.compile("(CVE-(19|20)\\d{2}-\\d{4,7})", re.I | re.S | re.M)
re_url = re.compile("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", re.I | re.S | re.M)

# Hashes
re_md5 = re.compile("\\b[a-f0-9]{32}\\b", re.I | re.S | re.M)
re_sha1 = re.compile("\\b[a-f0-9]{40}\\b", re.I | re.S | re.M)
re_sha256 = re.compile("\\b[a-f0-9]{64}\\b", re.I | re.S | re.M)
re_sha512 = re.compile("\\b[a-f0-9]{128}\\b", re.I | re.S | re.M)
re_ssdeep = re.compile("\\b\\d{2}:[A-Za-z0-9/+]{3,}:[A-Za-z0-9/+]{3,}\\b", re.I | re.S | re.M)

# File Types
re_doc = '\W([\w-]+\.)(docx|doc|csv|pdf|xlsx|xls|rtf|txt|pptx|ppt)'
re_web = '\W([\w-]+\.)(html|php|js)'
re_exe = '\W([\w-]+\.)(exe|dll|jar)'
re_zip = '\W([\w-]+\.)(zip|zipx|7z|rar|tar|gz)'
re_img = '\W([\w-]+\.)(jpeg|jpg|gif|png|tiff|bmp)'
re_flash = '\W([\w-]+\.)(flv|swf)'

whitelist = [{'net': IPNetwork('10.0.0.0/8'), 'org': 'Private per RFC 1918'},
             {'net': IPNetwork('172.16.0.0/12'), 'org': 'Private per RFC 1918'},
             {'net': IPNetwork('192.168.0.0/16'), 'org': 'Private per RFC 1918'},
             {'net': IPNetwork('0.0.0.0/8'), 'org': 'Invalid per RFC 1122'},
             {'net': IPNetwork('127.0.0.0/8'), 'org': 'Loopback per RFC 1122'},
             {'net': IPNetwork('169.254.0.0/16'), 'org': 'Link-local per RFC 3927'},
             {'net': IPNetwork('100.64.0.0/10'), 'org': 'Shared address space per RFC 6598'},
             {'net': IPNetwork('192.0.0.0/24'), 'org': 'IETF Protocol Assignments per RFC 6890'},
             {'net': IPNetwork('192.0.2.0/24'), 'org': 'Documentation and examples per RFC 6890'},
             {'net': IPNetwork('192.88.99.0/24'), 'org': 'IPv6 to IPv4 relay per RFC 3068'},
             {'net': IPNetwork('198.18.0.0/15'), 'org': 'Network benchmark tests per RFC 2544'},
             {'net': IPNetwork('198.51.100.0/24'), 'org': 'Documentation and examples per RFC 5737'},
             {'net': IPNetwork('203.0.113.0/24'), 'org': 'Documentation and examples per RFC 5737'},
             {'net': IPNetwork('224.0.0.0/4'), 'org': 'IP multicast per RFC 5771'},
             {'net': IPNetwork('240.0.0.0/4'), 'org': 'Reserved per RFC 1700'},
             {'net': IPNetwork('255.255.255.255/32'), 'org': 'Broadcast address per RFC 919'}]

useragent = 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0'

def ip_to_long(ip):
    """Convert an IPv4Address string to long"""
    return int(IPAddress(ip))

def ip_between(ip, start, finish):
    """Checks to see if IP is between start and finish"""

    if is_IPv4Address(ip) and is_IPv4Address(start) and is_IPv4Address(finish):
        return IPAddress(ip) in IPRange(start, finish)
    else:
        return False

def is_rfc1918(ip):
    if ip_between(ip, "10.0.0.0", "10.255.255.255"):
        return True
    elif ip_between(ip, "172.16.0.0", "172.31.255.255"):
        return True
    elif ip_between(ip, "192.168.0.0", "192.168.255.255"):
        return True
    else:
        return False

def is_reserved(ip):
    if ip_between(ip, "0.0.0.0", "0.255.255.255"):
        return True
    elif ip_between(ip, "10.0.0.0", "10.255.255.255"):
        return True
    elif ip_between(ip, "100.64.0.0", "100.127.255.255"):
        return True
    elif ip_between(ip, "127.0.0.0", "127.255.255.255"):
        return True
    elif ip_between(ip, "169.254.0.0", "169.254.255.255"):
        return True
    elif ip_between(ip, "172.16.0.0", "172.31.255.255"):
        return True
    elif ip_between(ip, "192.0.0.0", "192.0.0.255"):
        return True
    elif ip_between(ip, "192.0.2.0", "192.0.2.255"):
        return True
    elif ip_between(ip, "192.88.99.0", "192.88.99.255"):
        return True
    elif ip_between(ip, "192.168.0.0", "192.168.255.255"):
        return True
    elif ip_between(ip, "198.18.0.0", "198.19.255.255"):
        return True
    elif ip_between(ip, "198.51.100.0", "198.51.100.255"):
        return True
    elif ip_between(ip, "203.0.113.0", "203.0.113.255"):
        return True
    elif ip_between(ip, "224.0.0.0", "255.255.255.255"):
        return True
    else:
        return False

def is_IPv4Address(ipv4address):
    """Returns true for valid IPv4 Addresses, false for invalid."""

    # alternately: catch AddrConversionError from IPAddress(ipv4address).ipv4()
    return bool(re.match(re_ipv4, ipv4address))

def is_fqdn(address):
    """Returns true for valid DNS addresses, false for invalid."""

    return re.match(re_fqdn, address)

def is_url(url):
    """Returns true for valid URLs, false for invalid."""

    return bool(re.match(re_url, url))

def ip_to_geo(ipaddress):
    """Convert IP to Geographic Information"""

    return gi.record_by_addr(ipaddress)

def domain_to_geo(domain):
    """Convert Domain to Geographic Information"""

    return gi.record_by_name(domain)

def ip_to_geojson(ipaddress, name="Point"):
    """Generate GeoJSON for given IP address"""

    geo = ip_to_geo(ipaddress)

    point = {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {
                    "name": name
                },
                "geometry": {
                    "type": "Point",
                    "coordinates": [
                        geo["longitude"],
                        geo["latitude"]
                    ]
                }
            }
        ]
    }

    return point

def ips_to_geojson(ipaddresses):
    """Generate GeoJSON for given IP address"""

    features = []

    for ipaddress in ipaddresses:
        geo = gi.record_by_addr(ipaddress)

        features.append({
            "type": "Feature",
            "properties": {
                "name": ipaddress
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    geo["longitude"],
                    geo["latitude"]
                ]
            }
        })

    points = {
        "type": "FeatureCollection",
        "features": features
    }

    return points

def reverse_dns_sna(ipaddress):
    """Returns a list of the dns names that point to a given ipaddress using StatDNS API"""

    r = requests.get("http://api.statdns.com/x/%s" % ipaddress)

    if r.status_code == 200:
        names = []

        for item in r.json()['answer']:
            name = str(item['rdata']).strip(".")
            names.append(name)

        return names
    elif r.json()['code'] == 503:
        # NXDOMAIN - no PTR record
        return None

def reverse_dns(ipaddress):
    """Returns a list of the dns names that point to a given ipaddress"""

    name = socket.gethostbyaddr(ipaddress)[0]
    return [str(name)]

def vt_ip_check(ip, vt_api):
    """Checks VirusTotal for occurrences of an IP address"""
    if not is_IPv4Address(ip):
        return None

    url = 'https://www.virustotal.com/vtapi/v2/ip-address/report'
    parameters = {'ip': ip, 'apikey': vt_api}
    response = requests.get(url, params=parameters)
    return response.json()

def vt_name_check(domain, vt_api):
    """Checks VirusTotal for occurrences of a domain name"""
    if not is_fqdn(domain):
        return None

    url = 'https://www.virustotal.com/vtapi/v2/domain/report'
    parameters = {'domain': domain, 'apikey': vt_api}
    response = requests.get(url, params=parameters)
    return response.json()

def ipinfo_ip_check(ip):
    """Checks ipinfo.io for basic WHOIS-type data on an IP address"""
    if not is_IPv4Address(ip):
        return None

    response = requests.get('http://ipinfo.io/%s/json' % ip)
    return response.json()

def ipvoid_check(ip):
    """Checks IPVoid.com for info on an IP address"""
    if not is_IPv4Address(ip):
        return None

    return_dict = {}
    headers = {'User-Agent': useragent}
    url = 'http://ipvoid.com/scan/%s/' % ip
    response = requests.get(url, headers=headers)
    data = BeautifulSoup(response.text)
    if data.findAll('span', attrs={'class': 'label label-success'}):
        return None
    elif data.findAll('span', attrs={'class': 'label label-danger'}):
        for each in data.findAll('img', alt='Alert'):
            detect_site = each.parent.parent.td.text.lstrip()
            detect_url = each.parent.a['href']
            return_dict[detect_site] = detect_url

    return return_dict

def urlvoid_check(name):
    """Checks URLVoid.com for info on a domain"""
    if not is_fqdn(name):
        return None

    return_dict = {}
    headers = {'User-Agent': useragent}
    url = 'http://urlvoid.com/scan/%s/' % name
    response = requests.get(url, headers=headers)
    data = BeautifulSoup(response.text)
    if data.findAll('div', attrs={'class': 'bs-callout bs-callout-info'}):
        return None
    elif data.findAll('div', attrs={'class': 'bs-callout bs-callout-danger'}):
        for each in data.findAll('img', alt='Alert'):
            detect_site = each.parent.parent.td.text.lstrip()
            detect_url = each.parent.a['href']
            return_dict[detect_site] = detect_url

    return return_dict

def urlvoid_ip_check(ip):
    """Checks URLVoid.com for info on an IP address"""
    if not is_IPv4Address(ip):
        return None

    return_dict = {}
    headers = {'User-Agent': useragent}
    url = 'http://urlvoid.com/ip/%s/' % ip
    response = requests.get(url, headers=headers)
    data = BeautifulSoup(response.text)
    h1 = data.findAll('h1')[0].text
    if h1 == 'Report not found':
        return None
    elif re.match('^IP', h1):
        return_dict['bad_names'] = []
        return_dict['other_names'] = []
        for each in data.findAll('img', alt='Alert'):
            return_dict['bad_names'].append(each.parent.text.strip())
        for each in data.findAll('img', alt='Valid'):
            return_dict['other_names'].append(each.parent.text.strip())

    return return_dict
<commit_msg>adds support for isc/dshield query of an ip address<commit_after>"""
 _   _ _   _ _ _ _          ______      _ _
| | | | | (_) (_) |         | ___ \    | | |
| | | | |_ _| |_| |_ _   _  | |_/ / ___| | |_
| | | | __| | | | __| | | | | ___ \/ _ \ | __|
| |_| | |_| | | | |_| |_| | | |_/ /  __/ | |_
 \___/ \__|_|_|_|\__|\__, | \____/ \___|_|\__|
                      __/ |
                     |___/

A library to make you a Python CND Batman
"""

import re
import socket

import pygeoip
import requests
from bs4 import BeautifulSoup
from netaddr import IPAddress
from netaddr import IPNetwork
from netaddr import IPRange

gi = pygeoip.GeoIP("data/GeoLiteCity.dat", pygeoip.MEMORY_CACHE)

# Indicators
re_ipv4 = re.compile('(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', re.I | re.S | re.M)
re_email = re.compile("\\b[A-Za-z0-9_.]+@[0-9a-z.-]+\\b", re.I | re.S | re.M)
re_fqdn = re.compile('(?=^.{4,255}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)', re.I | re.S | re.M)
re_cve = re.compile("(CVE-(19|20)\\d{2}-\\d{4,7})", re.I | re.S | re.M)
re_url = re.compile("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", re.I | re.S | re.M)

# Hashes
re_md5 = re.compile("\\b[a-f0-9]{32}\\b", re.I | re.S | re.M)
re_sha1 = re.compile("\\b[a-f0-9]{40}\\b", re.I | re.S | re.M)
re_sha256 = re.compile("\\b[a-f0-9]{64}\\b", re.I | re.S | re.M)
re_sha512 = re.compile("\\b[a-f0-9]{128}\\b", re.I | re.S | re.M)
re_ssdeep = re.compile("\\b\\d{2}:[A-Za-z0-9/+]{3,}:[A-Za-z0-9/+]{3,}\\b", re.I | re.S | re.M)

# File Types
re_doc = '\W([\w-]+\.)(docx|doc|csv|pdf|xlsx|xls|rtf|txt|pptx|ppt)'
re_web = '\W([\w-]+\.)(html|php|js)'
re_exe = '\W([\w-]+\.)(exe|dll|jar)'
re_zip = '\W([\w-]+\.)(zip|zipx|7z|rar|tar|gz)'
re_img = '\W([\w-]+\.)(jpeg|jpg|gif|png|tiff|bmp)'
re_flash = '\W([\w-]+\.)(flv|swf)'

whitelist = [{'net': IPNetwork('10.0.0.0/8'), 'org': 'Private per RFC 1918'},
             {'net': IPNetwork('172.16.0.0/12'), 'org': 'Private per RFC 1918'},
             {'net': IPNetwork('192.168.0.0/16'), 'org': 'Private per RFC 1918'},
             {'net': IPNetwork('0.0.0.0/8'), 'org': 'Invalid per RFC 1122'},
             {'net': IPNetwork('127.0.0.0/8'), 'org': 'Loopback per RFC 1122'},
             {'net': IPNetwork('169.254.0.0/16'), 'org': 'Link-local per RFC 3927'},
             {'net': IPNetwork('100.64.0.0/10'), 'org': 'Shared address space per RFC 6598'},
             {'net': IPNetwork('192.0.0.0/24'), 'org': 'IETF Protocol Assignments per RFC 6890'},
             {'net': IPNetwork('192.0.2.0/24'), 'org': 'Documentation and examples per RFC 6890'},
             {'net': IPNetwork('192.88.99.0/24'), 'org': 'IPv6 to IPv4 relay per RFC 3068'},
             {'net': IPNetwork('198.18.0.0/15'), 'org': 'Network benchmark tests per RFC 2544'},
             {'net': IPNetwork('198.51.100.0/24'), 'org': 'Documentation and examples per RFC 5737'},
             {'net': IPNetwork('203.0.113.0/24'), 'org': 'Documentation and examples per RFC 5737'},
             {'net': IPNetwork('224.0.0.0/4'), 'org': 'IP multicast per RFC 5771'},
             {'net': IPNetwork('240.0.0.0/4'), 'org': 'Reserved per RFC 1700'},
             {'net': IPNetwork('255.255.255.255/32'), 'org': 'Broadcast address per RFC 919'}]

useragent = 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0'

def ip_to_long(ip):
    """Convert an IPv4Address string to long"""
    return int(IPAddress(ip))

def ip_between(ip, start, finish):
    """Checks to see if IP is between start and finish"""

    if is_IPv4Address(ip) and is_IPv4Address(start) and is_IPv4Address(finish):
        return IPAddress(ip) in IPRange(start, finish)
    else:
        return False

def is_rfc1918(ip):
    if ip_between(ip, "10.0.0.0", "10.255.255.255"):
        return True
    elif ip_between(ip, "172.16.0.0", "172.31.255.255"):
        return True
    elif ip_between(ip, "192.168.0.0", "192.168.255.255"):
        return True
    else:
        return False

def is_reserved(ip):
    if ip_between(ip, "0.0.0.0", "0.255.255.255"):
        return True
    elif ip_between(ip, "10.0.0.0", "10.255.255.255"):
        return True
    elif ip_between(ip, "100.64.0.0", "100.127.255.255"):
        return True
    elif ip_between(ip, "127.0.0.0", "127.255.255.255"):
        return True
    elif ip_between(ip, "169.254.0.0", "169.254.255.255"):
        return True
    elif ip_between(ip, "172.16.0.0", "172.31.255.255"):
        return True
    elif ip_between(ip, "192.0.0.0", "192.0.0.255"):
        return True
    elif ip_between(ip, "192.0.2.0", "192.0.2.255"):
        return True
    elif ip_between(ip, "192.88.99.0", "192.88.99.255"):
        return True
    elif ip_between(ip, "192.168.0.0", "192.168.255.255"):
        return True
    elif ip_between(ip, "198.18.0.0", "198.19.255.255"):
        return True
    elif ip_between(ip, "198.51.100.0", "198.51.100.255"):
        return True
    elif ip_between(ip, "203.0.113.0", "203.0.113.255"):
        return True
    elif ip_between(ip, "224.0.0.0", "255.255.255.255"):
        return True
    else:
        return False

def is_IPv4Address(ipv4address):
    """Returns true for valid IPv4 Addresses, false for invalid."""

    # alternately: catch AddrConversionError from IPAddress(ipv4address).ipv4()
    return bool(re.match(re_ipv4, ipv4address))

def is_fqdn(address):
    """Returns true for valid DNS addresses, false for invalid."""

    return re.match(re_fqdn, address)

def is_url(url):
    """Returns true for valid URLs, false for invalid."""

    return bool(re.match(re_url, url))

def ip_to_geo(ipaddress):
    """Convert IP to Geographic Information"""

    return gi.record_by_addr(ipaddress)

def domain_to_geo(domain):
    """Convert Domain to Geographic Information"""

    return gi.record_by_name(domain)

def ip_to_geojson(ipaddress, name="Point"):
    """Generate GeoJSON for given IP address"""

    geo = ip_to_geo(ipaddress)

    point = {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {
                    "name": name
                },
                "geometry": {
                    "type": "Point",
                    "coordinates": [
                        geo["longitude"],
                        geo["latitude"]
                    ]
                }
            }
        ]
    }

    return point

def ips_to_geojson(ipaddresses):
    """Generate GeoJSON for given IP address"""

    features = []

    for ipaddress in ipaddresses:
        geo = gi.record_by_addr(ipaddress)

        features.append({
            "type": "Feature",
            "properties": {
                "name": ipaddress
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    geo["longitude"],
                    geo["latitude"]
                ]
            }
        })

    points = {
        "type": "FeatureCollection",
        "features": features
    }

    return points

def reverse_dns_sna(ipaddress):
    """Returns a list of the dns names that point to a given ipaddress using StatDNS API"""

    r = requests.get("http://api.statdns.com/x/%s" % ipaddress)

    if r.status_code == 200:
        names = []

        for item in r.json()['answer']:
            name = str(item['rdata']).strip(".")
            names.append(name)

        return names
    elif r.json()['code'] == 503:
        # NXDOMAIN - no PTR record
        return None

def reverse_dns(ipaddress):
    """Returns a list of the dns names that point to a given ipaddress"""

    name = socket.gethostbyaddr(ipaddress)[0]
    return [str(name)]

def vt_ip_check(ip, vt_api):
    """Checks VirusTotal for occurrences of an IP address"""
    if not is_IPv4Address(ip):
        return None

    url = 'https://www.virustotal.com/vtapi/v2/ip-address/report'
    parameters = {'ip': ip, 'apikey': vt_api}
    response = requests.get(url, params=parameters)
    return response.json()

def vt_name_check(domain, vt_api):
    """Checks VirusTotal for occurrences of a domain name"""
    if not is_fqdn(domain):
        return None

    url = 'https://www.virustotal.com/vtapi/v2/domain/report'
    parameters = {'domain': domain, 'apikey': vt_api}
    response = requests.get(url, params=parameters)
    return response.json()

def ipinfo_ip_check(ip):
    """Checks ipinfo.io for basic WHOIS-type data on an IP address"""
    if not is_IPv4Address(ip):
        return None

    response = requests.get('http://ipinfo.io/%s/json' % ip)
    return response.json()

def ipvoid_check(ip):
    """Checks IPVoid.com for info on an IP address"""
    if not is_IPv4Address(ip):
        return None

    return_dict = {}
    headers = {'User-Agent': useragent}
    url = 'http://ipvoid.com/scan/%s/' % ip
    response = requests.get(url, headers=headers)
    data = BeautifulSoup(response.text)
    if data.findAll('span', attrs={'class': 'label label-success'}):
        return None
    elif data.findAll('span', attrs={'class': 'label label-danger'}):
        for each in data.findAll('img', alt='Alert'):
            detect_site = each.parent.parent.td.text.lstrip()
            detect_url = each.parent.a['href']
            return_dict[detect_site] = detect_url

    return return_dict

def urlvoid_check(name):
    """Checks URLVoid.com for info on a domain"""
    if not is_fqdn(name):
        return None

    return_dict = {}
    headers = {'User-Agent': useragent}
    url = 'http://urlvoid.com/scan/%s/' % name
    response = requests.get(url, headers=headers)
    data = BeautifulSoup(response.text)
    if data.findAll('div', attrs={'class': 'bs-callout bs-callout-info'}):
        return None
    elif data.findAll('div', attrs={'class': 'bs-callout bs-callout-danger'}):
        for each in data.findAll('img', alt='Alert'):
            detect_site = each.parent.parent.td.text.lstrip()
            detect_url = each.parent.a['href']
            return_dict[detect_site] = detect_url

    return return_dict

def urlvoid_ip_check(ip):
    """Checks URLVoid.com for info on an IP address"""
    if not is_IPv4Address(ip):
        return None

    return_dict = {}
    headers = {'User-Agent': useragent}
    url = 'http://urlvoid.com/ip/%s/' % ip
    response = requests.get(url, headers=headers)
    data = BeautifulSoup(response.text)
    h1 = data.findAll('h1')[0].text
    if h1 == 'Report not found':
        return None
    elif re.match('^IP', h1):
        return_dict['bad_names'] = []
        return_dict['other_names'] = []
        for each in data.findAll('img', alt='Alert'):
            return_dict['bad_names'].append(each.parent.text.strip())
        for each in data.findAll('img', alt='Valid'):
            return_dict['other_names'].append(each.parent.text.strip())

    return return_dict

def dshield_ip_check(ip):
    """Checks dshield for info on an IP address"""
    if not is_IPv4Address(ip):
        return None

    headers = {'User-Agent': useragent}
    url = 'https://isc.sans.edu/api/ip/'
    response = requests.get('{0}{1}?json'.format(url, ip), headers=headers)
    return response.json()<|endoftext|>


<commit_before>#!/usr/bin/python
"""
Registrationshop

3D registration tool for medical purposes.

@author: Berend Klein Haneveld 2013
"""

import sys
try:
	from PySide import QtCore
	from PySide.QtGui import QMainWindow
	from PySide.QtGui import QApplication
	from PySide.QtGui import QTextEdit
	from PySide.QtGui import QDockWidget
	from PySide.QtGui import QAction
	from PySide.QtGui import QIcon
except ImportError, e:
	raise e

# Import ui elements
from core.AppVars import AppVars
from core.ProjectController import ProjectController
from ui.TransformationWidget import TransformationWidget
from ui.VisualizationParametersWidget import VisualizationParametersWidget
from ui.DataSetsWidget import DataSetsWidget

# Define settings parameters
APPNAME = "RegistrationShop"
ORGNAME = "TU Delft"
ORGDOMAIN = "tudelft.nl"

class RegistrationShop(QMainWindow):
	"""
	Main class that starts up the application.
	Creates UI and starts project/plugin managers.
	"""
	# Singletons
	settings = QtCore.QSettings()
	projectController = ProjectController.Instance()

	# TODO: research why this doesn't seem to work
	# @staticmethod
	# def mainSettings():
	# 	return RegistrationShop.settings

	# @staticmethod
	# def projectController():
	# 	return RegistrationShop.projectController

	def __init__(self, arg):
		"""
		Sets app specific properties.
		Initializes the UI.
		"""
		super(RegistrationShop, self).__init__()
		self.arg = arg
		self.setApplicationPath()

		# Initialize the user interface
		self.initUI()

		# TODO: this is for testing purposes only
		projCont = ProjectController.Instance()
		proj = projCont.currentProject()
		proj.setName("New project")
		pass

	# UI setup methods

	def initUI(self):
		"""
		Initializes the UI. Makes sure previous state of
		application is restored.
		"""
		# Create actions and elements
		self.createElements()
		self.createActions()
		self.createMenus()
		self.createToolbar()
		self.restoreState()

		# Set some window/application properties
		self.setUnifiedTitleAndToolBarOnMac(True)
		self.setWindowTitle(APPNAME)
		self.setWindowState(QtCore.Qt.WindowActive)
		self.raise_()
		self.show()
		pass

	def createElements(self):
		"""
		Creates the widgets and docks of which the
		main window is composed.
		"""
		# Initialize the main window
		self.mainWindow = QMainWindow()
		self.mainWindow.setCentralWidget(QTextEdit())
		self.mainWindow.setWindowFlags(QtCore.Qt.Widget)
		self.setCentralWidget(self.mainWindow)

		# Toolbox on the left side of the window
		self.dockTransformations = QDockWidget()
		self.dockTransformations.setWindowTitle("Transformations")
		self.dockTransformations.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
		self.dockTransformations.setFeatures(QDockWidget.NoDockWidgetFeatures)
		self.dockTransformations.setHidden(RegistrationShop.settings.value("ui/dock/transformation/hidden", False))

		# Toolbox on the bottom of the window
		self.dockDataSets = QDockWidget()
		self.dockDataSets.setWindowTitle("Data sets")
		self.dockDataSets.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
		self.dockDataSets.setFeatures(QDockWidget.NoDockWidgetFeatures)
		self.dockDataSets.setHidden(RegistrationShop.settings.value("ui/dock/dataSets/hidden", False))

		# Toolbox on the right side of the window
		self.dockVisualParameters = QDockWidget()
		self.dockVisualParameters.setWindowTitle("Visualization Parameters")
		self.dockVisualParameters.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
		self.dockVisualParameters.setFeatures(QDockWidget.NoDockWidgetFeatures)
		self.dockVisualParameters.setHidden(RegistrationShop.settings.value("ui/dock/visualParameters/hidden", False))

		# Add the dock widgets to their main windows. The one of the left is added to
		# the top most 'main window' so that it stretches out across the whole left side
		self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockTransformations)
		self.mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockVisualParameters)
		self.mainWindow.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dockDataSets)

		# Create the dock widgets
		self.transformationWidget = TransformationWidget()
		self.visualizationParamWidget = VisualizationParametersWidget()
		self.dataSetsWidget = DataSetsWidget()

		# Assign the dock widgets to their docks
		self.dockTransformations.setWidget(self.transformationWidget)
		self.dockVisualParameters.setWidget(self.visualizationParamWidget)
		self.dockDataSets.setWidget(self.dataSetsWidget)

		pass

	def createActions(self):
		"""
		Create actions that can be attached to buttons and menus.
		"""
		# Dock toggle actions
		self.actionToggleLeftBar = QAction('Toggle left bar', self, shortcut='Ctrl+0')
		self.actionToggleLeftBar.setIcon(QIcon(AppVars.imagePath() + 'ToolbarLeft.png'))
		self.actionToggleLeftBar.triggered.connect(self.toggleLeftSidePanel)
		self.actionToggleLeftBar.setCheckable(True)
		self.actionToggleLeftBar.setChecked(not(self.dockTransformations.isHidden()))

		self.actionToggleRightBar = QAction('Toggle right bar', self, shortcut='Ctrl+Alt+0')
		self.actionToggleRightBar.setIcon(QIcon(AppVars.imagePath() + 'ToolbarRight.png'))
		self.actionToggleRightBar.triggered.connect(self.toggleRightSidePanel)
		self.actionToggleRightBar.setCheckable(True)
		self.actionToggleRightBar.setChecked(not(self.dockVisualParameters.isHidden()))

		self.actionToggleBottomBar = QAction('Toggle bottom bar', self, shortcut='Ctrl+Shift+0')
		self.actionToggleBottomBar.setIcon(QIcon(AppVars.imagePath() + 'ToolbarBottom.png'))
		self.actionToggleBottomBar.triggered.connect(self.toggleBottomPanel)
		self.actionToggleBottomBar.setCheckable(True)
		self.actionToggleBottomBar.setChecked(not(self.dockDataSets.isHidden()))
		pass

	def createMenus(self):
		"""
		Creates menus from actions.
		"""
		pass

	def createToolbar(self):
		"""
		Creates the main toolbar and sets the toolbar buttons.
		"""
		# Add toolbar
		self.toolbar = self.addToolBar('Main tools')

		# Add the toolbar actions
		self.toolbar.addAction(self.actionToggleLeftBar)
		self.toolbar.addAction(self.actionToggleBottomBar)
		self.toolbar.addAction(self.actionToggleRightBar)
		pass

	def restoreState(self):
		"""
		Restores the window size and position of the last time the
		application was run. If the application is started for the first time
		it applies some 'sane' initial values.
		"""
		xPosition 	= RegistrationShop.settings.value("ui/window/origin/x", 0)
		yPosition 	= RegistrationShop.settings.value("ui/window/origin/y", 0)
		width 		= RegistrationShop.settings.value("ui/window/width", 800)
		height 		= RegistrationShop.settings.value("ui/window/height", 600)

		self.setGeometry(xPosition, yPosition, width, height)
		pass

	# Events

	def resizeEvent(self, ev):
		"""
		Saves the size and position of the window when it is resized so that
		it can be restored on subsequent launches.

		@type ev: QResizeEvent
		"""
		width 	= self.width()
		height 	= self.height()

		xPosition = self.geometry().x()
		yPosition = self.geometry().y()

		RegistrationShop.settings.setValue("ui/window/origin/x", xPosition)
		RegistrationShop.settings.setValue("ui/window/origin/y", yPosition)
		RegistrationShop.settings.setValue("ui/window/width", width)
		RegistrationShop.settings.setValue("ui/window/height", height)

	def moveEvent(self, ev):
		"""
		Saves the position of the window when it is moved so that it can be
		restored on subsequent launches.

		@type ev: QMoveEvent
		"""
		xPosition = self.geometry().x()
		yPosition = self.geometry().y()

		RegistrationShop.settings.setValue("ui/window/origin/x", xPosition)
		RegistrationShop.settings.setValue("ui/window/origin/y", yPosition)

	def closeEvent(self, ev):
		"""
		TODO: ask if app should really quit.
		@type ev: QCloseEvent
		"""
		pass

	# Private Functions
	def setApplicationPath(self):
		"""
		Tries to find the path to the application. This is done so that it
		can figure out where certain resources are located.
		QCoreApplication::applicationDirPath() on OS X does not return the
		desired path to the actual application but to the python executable
		in /Library/FrameWorks. This is inconvenient because images can't be
		located that way.
		This method assumes that the application path is passed on to arg[0].
		Otherwise it will not set a path and will depend that the image's relative
		paths will work.
		"""
		# Check to see if we can deduce the application path from the
		# sys arguments
		if isinstance(self.arg[0], basestring) and self.arg[0].endswith("RegistrationShop.py"):
			# Assume that first argument is the entry point
			path = self.arg[0]
			# Find index of the application name
			start = path.rfind("RegistrationShop.py")
			if start > -1:
				AppVars.setPath(path[:start])
				# AppVars.applicationPath = path[:start]
		pass

	# Action callbacks

	def toggleLeftSidePanel(self):
		"""
		Toggles the visibility of the transformation panel on the left. Makes sure that
		the state of the toolbar button is updated and saves the state in the settings.
		"""
		self.dockTransformations.setHidden(not(self.dockTransformations.isHidden()))
		self.actionToggleLeftBar.setChecked(not(self.dockTransformations.isHidden()))
		RegistrationShop.settings.setValue("ui/dock/transformation/hidden", self.dockTransformations.isHidden())
		pass

	def toggleRightSidePanel(self):
		"""
		Toggles the visibility of the visualization parameters panel on the right. Makes sure that
		the state of the toolbar button is updated and saves the state in the settings.
		"""
		self.dockVisualParameters.setHidden(not(self.dockVisualParameters.isHidden()))
		self.actionToggleRightBar.setChecked(not(self.dockVisualParameters.isHidden()))
		RegistrationShop.settings.setValue("ui/dock/visualParameters/hidden", self.dockVisualParameters.isHidden())
		pass

	def toggleBottomPanel(self):
		"""
		Toggles the visibility of the datasets panel on the bottom. Makes sure that
		the state of the toolbar button is updated and saves the state in the settings.
		"""
		self.dockDataSets.setHidden(not(self.dockDataSets.isHidden()))
		self.actionToggleBottomBar.setChecked(not(self.dockDataSets.isHidden()))
		RegistrationShop.settings.setValue("ui/dock/dataSets/hidden", self.dockDataSets.isHidden())
		pass

def main():
	app = QApplication(sys.argv)
	app.setObjectName(APPNAME)
	app.setApplicationName(APPNAME)
	app.setOrganizationName(ORGNAME)
	app.setOrganizationDomain(ORGDOMAIN)

	mainWindow = RegistrationShop(sys.argv)
	sys.exit(app.exec_())

if __name__ == '__main__':
	main()
<commit_msg>Added menu items for loading fixed and moving data sets.<commit_after>#!/usr/bin/python
"""
Registrationshop

3D registration tool for medical purposes.

@author: Berend Klein Haneveld 2013
"""

import sys
try:
	from PySide import QtCore
	from PySide.QtGui import QMainWindow
	from PySide.QtGui import QApplication
	from PySide.QtGui import QTextEdit
	from PySide.QtGui import QDockWidget
	from PySide.QtGui import QAction
	from PySide.QtGui import QIcon
	from PySide.QtGui import QFileDialog
	from PySide.QtGui import QMenuBar
except ImportError, e:
	raise e

# Import ui elements
from core.AppVars import AppVars
from core.ProjectController import ProjectController
from ui.TransformationWidget import TransformationWidget
from ui.VisualizationParametersWidget import VisualizationParametersWidget
from ui.DataSetsWidget import DataSetsWidget

# Define settings parameters
APPNAME = "RegistrationShop"
ORGNAME = "TU Delft"
ORGDOMAIN = "tudelft.nl"

class RegistrationShop(QMainWindow):
	"""
	Main class that starts up the application.
	Creates UI and starts project/plugin managers.
	"""
	# Singletons
	settings = QtCore.QSettings()
	# projectController = ProjectController.Instance()

	def __init__(self, arg):
		"""
		Sets app specific properties.
		Initializes the UI.
		"""
		super(RegistrationShop, self).__init__()
		self.arg = arg
		self.setApplicationPath()
		# Make sure there is a project controller instance
		ProjectController.Instance()

		# Initialize the user interface
		self.initUI()

		# TODO: this is for testing purposes only
		# projCont = ProjectController.Instance()
		# proj = projCont.currentProject()
		# proj.setName("New project")
		pass

	# UI setup methods

	def initUI(self):
		"""
		Initializes the UI. Makes sure previous state of
		application is restored.
		"""
		# Create actions and elements
		self.createElements()
		self.createActions()
		self.createMenus()
		self.createToolbar()
		self.restoreState()

		# Set some window/application properties
		self.setUnifiedTitleAndToolBarOnMac(True)
		self.setWindowTitle(APPNAME)
		self.setWindowState(QtCore.Qt.WindowActive)
		self.raise_()
		self.show()
		pass

	def createElements(self):
		"""
		Creates the widgets and docks of which the
		main window is composed.
		"""
		# Initialize the main window
		self.mainWindow = QMainWindow()
		self.mainWindow.setCentralWidget(QTextEdit())
		self.mainWindow.setWindowFlags(QtCore.Qt.Widget)
		self.setCentralWidget(self.mainWindow)

		# Toolbox on the left side of the window
		self.dockTransformations = QDockWidget()
		self.dockTransformations.setWindowTitle("Transformations")
		self.dockTransformations.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
		self.dockTransformations.setFeatures(QDockWidget.NoDockWidgetFeatures)
		self.dockTransformations.setHidden(RegistrationShop.settings.value("ui/dock/transformation/hidden", False))

		# Toolbox on the bottom of the window
		self.dockDataSets = QDockWidget()
		self.dockDataSets.setWindowTitle("Data sets")
		self.dockDataSets.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
		self.dockDataSets.setFeatures(QDockWidget.NoDockWidgetFeatures)
		self.dockDataSets.setHidden(RegistrationShop.settings.value("ui/dock/dataSets/hidden", False))

		# Toolbox on the right side of the window
		self.dockVisualParameters = QDockWidget()
		self.dockVisualParameters.setWindowTitle("Visualization Parameters")
		self.dockVisualParameters.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
		self.dockVisualParameters.setFeatures(QDockWidget.NoDockWidgetFeatures)
		self.dockVisualParameters.setHidden(RegistrationShop.settings.value("ui/dock/visualParameters/hidden", False))

		# Add the dock widgets to their main windows. The one of the left is added to
		# the top most 'main window' so that it stretches out across the whole left side
		self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockTransformations)
		self.mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockVisualParameters)
		self.mainWindow.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dockDataSets)

		# Create the dock widgets
		self.transformationWidget = TransformationWidget()
		self.visualizationParamWidget = VisualizationParametersWidget()
		self.dataSetsWidget = DataSetsWidget()

		# Assign the dock widgets to their docks
		self.dockTransformations.setWidget(self.transformationWidget)
		self.dockVisualParameters.setWidget(self.visualizationParamWidget)
		self.dockDataSets.setWidget(self.dataSetsWidget)

		pass

	def createActions(self):
		"""
		Create actions that can be attached to buttons and menus.
		"""
		# Dock toggle actions
		self.actionToggleLeftBar = QAction('Toggle left bar', self, shortcut='Ctrl+0')
		self.actionToggleLeftBar.setIcon(QIcon(AppVars.imagePath() + 'ToolbarLeft.png'))
		self.actionToggleLeftBar.triggered.connect(self.toggleLeftSidePanel)
		self.actionToggleLeftBar.setCheckable(True)
		self.actionToggleLeftBar.setChecked(not(self.dockTransformations.isHidden()))

		self.actionToggleRightBar = QAction('Toggle right bar', self, shortcut='Ctrl+Alt+0')
		self.actionToggleRightBar.setIcon(QIcon(AppVars.imagePath() + 'ToolbarRight.png'))
		self.actionToggleRightBar.triggered.connect(self.toggleRightSidePanel)
		self.actionToggleRightBar.setCheckable(True)
		self.actionToggleRightBar.setChecked(not(self.dockVisualParameters.isHidden()))

		self.actionToggleBottomBar = QAction('Toggle bottom bar', self, shortcut='Ctrl+Shift+0')
		self.actionToggleBottomBar.setIcon(QIcon(AppVars.imagePath() + 'ToolbarBottom.png'))
		self.actionToggleBottomBar.triggered.connect(self.toggleBottomPanel)
		self.actionToggleBottomBar.setCheckable(True)
		self.actionToggleBottomBar.setChecked(not(self.dockDataSets.isHidden()))

		self.actionLoadFixedData = QAction('Load fixed data', self, shortcut='Ctrl+Shift+F')
		# self.actionLoadFixedData.setIcon(QIcon(AppVars.imagePath() + 'AddButton.png'))
		self.actionLoadFixedData.triggered.connect(self.loadFixedDataSetFile)

		self.actionLoadMovingData = QAction('Load moving data', self, shortcut='Ctrl+Shift+M')
		# self.actionLoadMovingData.setIcon(QIcon(AppVars.imagePath() + 'AddButton.png'))
		self.actionLoadMovingData.triggered.connect(self.loadMovingDataSetFile)

		pass

	def createMenus(self):
		"""
		Creates menus from actions.
		"""
		self.menuBar = QMenuBar()
		self.menuItemFile = self.menuBar.addMenu('&File')
		self.menuItemFile.addAction(self.actionLoadFixedData)
		self.menuItemFile.addAction(self.actionLoadMovingData)
		pass

	def createToolbar(self):
		"""
		Creates the main toolbar and sets the toolbar buttons.
		"""
		# Add toolbar
		self.toolbar = self.addToolBar('Main tools')

		# Add the toolbar actions
		self.toolbar.addAction(self.actionToggleLeftBar)
		self.toolbar.addAction(self.actionToggleBottomBar)
		self.toolbar.addAction(self.actionToggleRightBar)
		pass

	def restoreState(self):
		"""
		Restores the window size and position of the last time the
		application was run. If the application is started for the first time
		it applies some 'sane' initial values.
		"""
		xPosition 	= RegistrationShop.settings.value("ui/window/origin/x", 0)
		yPosition 	= RegistrationShop.settings.value("ui/window/origin/y", 0)
		width 		= RegistrationShop.settings.value("ui/window/width", 800)
		height 		= RegistrationShop.settings.value("ui/window/height", 600)

		self.setGeometry(xPosition, yPosition, width, height)
		pass

	# Events

	def resizeEvent(self, ev):
		"""
		Saves the size and position of the window when it is resized so that
		it can be restored on subsequent launches.

		@type ev: QResizeEvent
		"""
		width 	= self.width()
		height 	= self.height()

		xPosition = self.geometry().x()
		yPosition = self.geometry().y()

		RegistrationShop.settings.setValue("ui/window/origin/x", xPosition)
		RegistrationShop.settings.setValue("ui/window/origin/y", yPosition)
		RegistrationShop.settings.setValue("ui/window/width", width)
		RegistrationShop.settings.setValue("ui/window/height", height)

	def moveEvent(self, ev):
		"""
		Saves the position of the window when it is moved so that it can be
		restored on subsequent launches.

		@type ev: QMoveEvent
		"""
		xPosition = self.geometry().x()
		yPosition = self.geometry().y()

		RegistrationShop.settings.setValue("ui/window/origin/x", xPosition)
		RegistrationShop.settings.setValue("ui/window/origin/y", yPosition)

	def closeEvent(self, ev):
		"""
		TODO: ask if app should really quit.
		@type ev: QCloseEvent
		"""
		pass

	# Private Functions
	def setApplicationPath(self):
		"""
		Tries to find the path to the application. This is done so that it
		can figure out where certain resources are located.
		QCoreApplication::applicationDirPath() on OS X does not return the
		desired path to the actual application but to the python executable
		in /Library/FrameWorks. This is inconvenient because images can't be
		located that way.
		This method assumes that the application path is passed on to arg[0].
		Otherwise it will not set a path and will depend that the image's relative
		paths will work.
		"""
		# Check to see if we can deduce the application path from the
		# sys arguments
		if isinstance(self.arg[0], basestring) and self.arg[0].endswith("RegistrationShop.py"):
			# Assume that first argument is the entry point
			path = self.arg[0]
			# Find index of the application name
			start = path.rfind("RegistrationShop.py")
			if start > -1:
				AppVars.setPath(path[:start])
				# AppVars.applicationPath = path[:start]
		pass

	# Action callbacks

	def toggleLeftSidePanel(self):
		"""
		Toggles the visibility of the transformation panel on the left. Makes sure that
		the state of the toolbar button is updated and saves the state in the settings.
		"""
		self.dockTransformations.setHidden(not(self.dockTransformations.isHidden()))
		self.actionToggleLeftBar.setChecked(not(self.dockTransformations.isHidden()))
		RegistrationShop.settings.setValue("ui/dock/transformation/hidden", self.dockTransformations.isHidden())
		pass

	def toggleRightSidePanel(self):
		"""
		Toggles the visibility of the visualization parameters panel on the right. Makes sure that
		the state of the toolbar button is updated and saves the state in the settings.
		"""
		self.dockVisualParameters.setHidden(not(self.dockVisualParameters.isHidden()))
		self.actionToggleRightBar.setChecked(not(self.dockVisualParameters.isHidden()))
		RegistrationShop.settings.setValue("ui/dock/visualParameters/hidden", self.dockVisualParameters.isHidden())
		pass

	def toggleBottomPanel(self):
		"""
		Toggles the visibility of the datasets panel on the bottom. Makes sure that
		the state of the toolbar button is updated and saves the state in the settings.
		"""
		self.dockDataSets.setHidden(not(self.dockDataSets.isHidden()))
		self.actionToggleBottomBar.setChecked(not(self.dockDataSets.isHidden()))
		RegistrationShop.settings.setValue("ui/dock/dataSets/hidden", self.dockDataSets.isHidden())
		pass

	def loadFixedDataSetFile(self):
		"""
		Open file dialog to search for data files. If valid data is given, it will
		pass the data file location on to the slicer and the project controller.
		"""
		fileName, other = QFileDialog.getOpenFileName(self, "Open fixed data set", "", "Images (*.mhd)")
		if len(fileName) > 0:
			projectController = ProjectController.Instance()
			projectController.loadFixedDataSet(fileName)
		pass

	def loadMovingDataSetFile(self):
		"""
		Open file dialog to search for data files. If valid data is given, it will
		pass the data file location on to the slicer and the project controller.
		"""
		fileName, other = QFileDialog.getOpenFileName(self, "Open fixed data set", "", "Images (*.mhd)")
		if len(fileName) > 0:
			projectController = ProjectController.Instance()
			projectController.loadMovingDataSet(fileName)
		pass

def main():
	app = QApplication(sys.argv)
	app.setObjectName(APPNAME)
	app.setApplicationName(APPNAME)
	app.setOrganizationName(ORGNAME)
	app.setOrganizationDomain(ORGDOMAIN)

	mainWindow = RegistrationShop(sys.argv)
	sys.exit(app.exec_())

if __name__ == '__main__':
	main()
<|endoftext|>