<commit_before># -*- encoding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2014-2016 Compassion CH (http://www.compassion.ch)
#    Releasing children from poverty in Jesus' name
#    @author: Cyril Sester, Emanuel Cino
#
#    The licence is in the file __openerp__.py
#
##############################################################################
from openerp import api, fields, models, _
from functools import reduce

class ResPartner(models.Model):
    _inherit = 'res.partner'

    ##########################################################################
    #                                 FIELDS                                 #
    ##########################################################################
    ref = fields.Char(
        required=True,
        default=lambda self: self.env['ir.sequence'].get('partner.ref'))
    global_id = fields.Char()
    contracts_fully_managed = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Fully managed sponsorships',
        order="state asc")
    contracts_paid = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Sponsorships as payer only')
    contracts_correspondant = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Sponsorships as correspondant only')
    mandatory_review = fields.Boolean(
        help='Indicates that we should review the letters of this sponsor '
             'before sending them to GMC.')
    other_contract_ids = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Other contracts')
    unrec_items = fields.Integer(compute='_set_count_items')
    receivable_items = fields.Integer(compute='_set_count_items')
    has_sponsorships = fields.Boolean(
        compute='_compute_has_sponsorships', store=True)
    send_original = fields.Boolean(
        help='Indicates that we request the original letters for this sponsor'
    )
    preferred_name = fields.Char(
        compute='_compute_preferred_name',
        inverse='_inverse_preferred_name', store=True)

    ##########################################################################
    #                             FIELDS METHODS                             #
    ##########################################################################
    @api.multi
    @api.depends('category_id')
    def _compute_has_sponsorships(self):
        """
        A partner is sponsor if he is correspondent of at least one
        sponsorship.
        """
        for partner in self:
            partner.has_sponsorships = self.env[
                'recurring.contract'].search_count([
                    '|', ('partner_id', '=', partner.id),
                    ('correspondant_id', '=', partner.id),
                    ('type', 'like', 'S')
                ])

    @api.multi
    def _get_related_contracts(self):
        """ Returns the contracts of the sponsor of given type
        ('fully_managed', 'correspondant' or 'payer')
        """
        contract_obj = self.env['recurring.contract']
        for partner in self:
            partner.contracts_correspondant = contract_obj.search(
                [('correspondant_id', '=', partner.id),
                 ('type', 'in', ['S', 'SC']),
                 ('fully_managed', '=', False)],
                order='start_date desc').ids
            partner.contracts_paid = contract_obj.search(
                [('partner_id', '=', partner.id),
                 ('type', 'in', ['S', 'SC']),
                 ('fully_managed', '=', False)],
                order='start_date desc').ids
            partner.contracts_fully_managed = contract_obj.search(
                [('partner_id', '=', partner.id),
                 ('type', 'in', ['S', 'SC']),
                 ('fully_managed', '=', True)],
                order='start_date desc').ids
            partner.other_contract_ids = contract_obj.search(
                [('partner_id', '=', partner.id),
                 ('type', 'not in', ['S', 'SC'])],
                order='start_date desc').ids

    def _set_count_items(self):
        move_line_obj = self.env['account.move.line']
        for partner in self:
            partner.unrec_items = move_line_obj.search_count([
                ('partner_id', '=', partner.id),
                ('reconcile_id', '=', False),
                ('account_id.reconcile', '=', True)])
            partner.receivable_items = move_line_obj.search_count([
                ('partner_id', '=', partner.id),
                ('account_id.code', '=', '1050')])

    def _compute_preferred_name(self):
        for partner in self:
            partner.preferred_name = partner.firstname or partner.name

    def _inverse_preferred_name(self):
        return True

    ##########################################################################
    #                              ORM METHODS                               #
    ##########################################################################
    @api.multi
    def write(self, vals):
        res = super(ResPartner, self).write(vals)
        notify_vals = ['firstname', 'lastname', 'name', 'preferred_name',
                       'mandatory_review', 'send_original']
        notify = reduce(lambda prev, val: prev or val in vals, notify_vals,
                        False)
        if notify and not self.env.context.get('no_upsert'):
            self.upsert_constituent()

        return res

    ##########################################################################
    #                             VIEW CALLBACKS                             #
    ##########################################################################
    @api.multi
    def show_lines(self):
        try:
            ir_model_data = self.env['ir.model.data']
            view_id = ir_model_data.get_object_reference(
                'sponsorship_compassion',
                'view_invoice_line_partner_tree')[1]
        except ValueError:
            view_id = False
        action = {
            'name': _('Related invoice lines'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'tree,form',
            'res_model': 'account.invoice.line',
            'view_id': view_id,
            'views': [(view_id, 'tree'), (False, 'form')],
            'target': 'current',
            'context': self.with_context(
                search_default_partner_id=self.ids).env.context,
        }

        return action

    @api.multi
    def show_move_lines(self):
        try:
            ir_model_data = self.env['ir.model.data']
            move_line_id = ir_model_data.get_object_reference(
                'account',
                'view_move_line_tree')[1]
        except ValueError:
            move_line_id = False
        action = {
            'name': _('1050 move lines'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'tree',
            'res_model': 'account.move.line',
            'view_id': move_line_id,
            'views': [(move_line_id, 'tree')],
            'target': 'current',
            'context': self.with_context(
                search_default_partner_id=self.ids).env.context,
        }
        return action

    @api.multi
    def create_contract(self):
        self.ensure_one()
        context = self.with_context({
            'default_partner_id': self.id,
            'default_type': 'S',
            'type': 'S',
        }).env.context
        return {
            'type': 'ir.actions.act_window',
            'name': _('New Sponsorship'),
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'recurring.contract',
            'target': 'current',
            'context': context
        }

    @api.multi
    def unreconciled_transaction_items(self):
        return self.with_context(
            search_default_unreconciled=1).show_move_lines()

    @api.multi
    def receivable_transaction_items(self):
        account_ids = self.env['account.account'].search(
            [('code', '=', '1050')]).ids
        return self.with_context(
            search_default_account_id=account_ids[0]).show_move_lines()

    @api.multi
    def open_contracts(self):
        """ Used to bypass opening a contract in popup mode from
        res_partner view. """
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': 'Contracts',
            'res_model': 'recurring.contract',
            'views': [[False, "tree"], [False, "form"]],
            'domain': ['|', ('correspondant_id', '=', self.id),
                       ('partner_id', '=', self.id)],
            'context': self.with_context({
                'default_type': 'S'}).env.context,
        }

    ##########################################################################
    #                             PUBLIC METHODS                             #
    ##########################################################################
    def upsert_constituent(self):
        """If partner has active contracts, UPSERT Constituent in GMC."""
        for partner in self:
            contract_count = self.env['recurring.contract'].search_count([
                ('correspondant_id', '=', partner.id),
                ('state', 'not in', ('terminated', 'cancelled'))])
            if contract_count:
                # UpsertConstituent Message if not one already pending
                message_obj = self.env['gmc.message.pool']
                action_id = self.env.ref(
                    'sponsorship_compassion.upsert_partner').id

                message_vals = {
                    'action_id': action_id,
                    'object_id': partner.id,
                    'partner_id': partner.id,
                }
                message_obj.create(message_vals)
<commit_msg>Add sponsorship_ids field in res_partner<commit_after># -*- encoding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2014-2016 Compassion CH (http://www.compassion.ch)
#    Releasing children from poverty in Jesus' name
#    @author: Cyril Sester, Emanuel Cino
#
#    The licence is in the file __openerp__.py
#
##############################################################################
from openerp import api, fields, models, _
from functools import reduce

class ResPartner(models.Model):
    _inherit = 'res.partner'

    ##########################################################################
    #                                 FIELDS                                 #
    ##########################################################################
    ref = fields.Char(
        required=True,
        default=lambda self: self.env['ir.sequence'].get('partner.ref'))
    global_id = fields.Char()
    contracts_fully_managed = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Fully managed sponsorships',
        order="state asc")
    contracts_paid = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Sponsorships as payer only')
    contracts_correspondant = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Sponsorships as correspondant only')
    sponsorship_ids = fields.One2many(
        "recurring.contract", compute='_get_related_contracts')
    mandatory_review = fields.Boolean(
        help='Indicates that we should review the letters of this sponsor '
             'before sending them to GMC.')
    other_contract_ids = fields.One2many(
        "recurring.contract", compute='_get_related_contracts',
        string='Other contracts')
    unrec_items = fields.Integer(compute='_set_count_items')
    receivable_items = fields.Integer(compute='_set_count_items')
    has_sponsorships = fields.Boolean(
        compute='_compute_has_sponsorships', store=True)
    send_original = fields.Boolean(
        help='Indicates that we request the original letters for this sponsor'
    )
    preferred_name = fields.Char(
        compute='_compute_preferred_name',
        inverse='_inverse_preferred_name', store=True)

    ##########################################################################
    #                             FIELDS METHODS                             #
    ##########################################################################
    @api.multi
    @api.depends('category_id')
    def _compute_has_sponsorships(self):
        """
        A partner is sponsor if he is correspondent of at least one
        sponsorship.
        """
        for partner in self:
            partner.has_sponsorships = self.env[
                'recurring.contract'].search_count([
                    '|', ('partner_id', '=', partner.id),
                    ('correspondant_id', '=', partner.id),
                    ('type', 'like', 'S')
                ])

    @api.multi
    def _get_related_contracts(self):
        """ Returns the contracts of the sponsor of given type
        ('fully_managed', 'correspondant' or 'payer')
        """
        contract_obj = self.env['recurring.contract']
        for partner in self:
            partner.contracts_correspondant = contract_obj.search(
                [('correspondant_id', '=', partner.id),
                 ('type', 'in', ['S', 'SC']),
                 ('fully_managed', '=', False)],
                order='start_date desc').ids
            partner.contracts_paid = contract_obj.search(
                [('partner_id', '=', partner.id),
                 ('type', 'in', ['S', 'SC']),
                 ('fully_managed', '=', False)],
                order='start_date desc').ids
            partner.contracts_fully_managed = contract_obj.search(
                [('partner_id', '=', partner.id),
                 ('type', 'in', ['S', 'SC']),
                 ('fully_managed', '=', True)],
                order='start_date desc').ids
            partner.sponsorship_ids = partner.contracts_correspondant + \
                partner.contracts_paid + \
                partner.contracts_fully_managed
            partner.other_contract_ids = contract_obj.search(
                [('partner_id', '=', partner.id),
                 ('type', 'not in', ['S', 'SC'])],
                order='start_date desc').ids

    def _set_count_items(self):
        move_line_obj = self.env['account.move.line']
        for partner in self:
            partner.unrec_items = move_line_obj.search_count([
                ('partner_id', '=', partner.id),
                ('reconcile_id', '=', False),
                ('account_id.reconcile', '=', True)])
            partner.receivable_items = move_line_obj.search_count([
                ('partner_id', '=', partner.id),
                ('account_id.code', '=', '1050')])

    def _compute_preferred_name(self):
        for partner in self:
            partner.preferred_name = partner.firstname or partner.name

    def _inverse_preferred_name(self):
        return True

    ##########################################################################
    #                              ORM METHODS                               #
    ##########################################################################
    @api.multi
    def write(self, vals):
        res = super(ResPartner, self).write(vals)
        notify_vals = ['firstname', 'lastname', 'name', 'preferred_name',
                       'mandatory_review', 'send_original']
        notify = reduce(lambda prev, val: prev or val in vals, notify_vals,
                        False)
        if notify and not self.env.context.get('no_upsert'):
            self.upsert_constituent()

        return res

    ##########################################################################
    #                             VIEW CALLBACKS                             #
    ##########################################################################
    @api.multi
    def show_lines(self):
        try:
            ir_model_data = self.env['ir.model.data']
            view_id = ir_model_data.get_object_reference(
                'sponsorship_compassion',
                'view_invoice_line_partner_tree')[1]
        except ValueError:
            view_id = False
        action = {
            'name': _('Related invoice lines'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'tree,form',
            'res_model': 'account.invoice.line',
            'view_id': view_id,
            'views': [(view_id, 'tree'), (False, 'form')],
            'target': 'current',
            'context': self.with_context(
                search_default_partner_id=self.ids).env.context,
        }

        return action

    @api.multi
    def show_move_lines(self):
        try:
            ir_model_data = self.env['ir.model.data']
            move_line_id = ir_model_data.get_object_reference(
                'account',
                'view_move_line_tree')[1]
        except ValueError:
            move_line_id = False
        action = {
            'name': _('1050 move lines'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'tree',
            'res_model': 'account.move.line',
            'view_id': move_line_id,
            'views': [(move_line_id, 'tree')],
            'target': 'current',
            'context': self.with_context(
                search_default_partner_id=self.ids).env.context,
        }
        return action

    @api.multi
    def create_contract(self):
        self.ensure_one()
        context = self.with_context({
            'default_partner_id': self.id,
            'default_type': 'S',
            'type': 'S',
        }).env.context
        return {
            'type': 'ir.actions.act_window',
            'name': _('New Sponsorship'),
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'recurring.contract',
            'target': 'current',
            'context': context
        }

    @api.multi
    def unreconciled_transaction_items(self):
        return self.with_context(
            search_default_unreconciled=1).show_move_lines()

    @api.multi
    def receivable_transaction_items(self):
        account_ids = self.env['account.account'].search(
            [('code', '=', '1050')]).ids
        return self.with_context(
            search_default_account_id=account_ids[0]).show_move_lines()

    @api.multi
    def open_contracts(self):
        """ Used to bypass opening a contract in popup mode from
        res_partner view. """
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': 'Contracts',
            'res_model': 'recurring.contract',
            'views': [[False, "tree"], [False, "form"]],
            'domain': ['|', ('correspondant_id', '=', self.id),
                       ('partner_id', '=', self.id)],
            'context': self.with_context({
                'default_type': 'S'}).env.context,
        }

    ##########################################################################
    #                             PUBLIC METHODS                             #
    ##########################################################################
    def upsert_constituent(self):
        """If partner has active contracts, UPSERT Constituent in GMC."""
        for partner in self:
            contract_count = self.env['recurring.contract'].search_count([
                ('correspondant_id', '=', partner.id),
                ('state', 'not in', ('terminated', 'cancelled'))])
            if contract_count:
                # UpsertConstituent Message if not one already pending
                message_obj = self.env['gmc.message.pool']
                action_id = self.env.ref(
                    'sponsorship_compassion.upsert_partner').id

                message_vals = {
                    'action_id': action_id,
                    'object_id': partner.id,
                    'partner_id': partner.id,
                }
                message_obj.create(message_vals)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#    Copyright (C) 2017-2018 CIRCL Computer Incident Response Center Luxembourg (smile gie)
#    Copyright (C) 2017-2018 Christian Studer
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys, json, os, time
import stix2
import pymisp
from stix2misp_mapping import *

class StixParser():
    def __init__(self):
        self.misp_event = pymisp.MISPEvent()
        self.event = []
        self.misp_event['Galaxy'] = []

    def loadEvent(self, args, pathname):
        # try:
        filename = os.path.join(pathname, args[1])
        tempFile = open(filename, 'r')
        self.filename = filename
        event = stix2.get_dict(tempFile)
        for o in event.get('objects'):
            try:
                self.event.append(stix2.parse(o))
            except:
                self.parse_custom(o)
        # except:
        #     print(json.dumps({'success': 0, 'message': 'The temporary STIX export file could not be read'}))
        #     sys.exit(1)

    def parse_custom(self, obj):
        custom_object_type = obj.pop('type')
        labels = obj['labels']
        try:
            @stix2.CustomObject(custom_object_type,[('id', stix2.properties.StringProperty(required=True)),
            ('x_misp_timestamp', stix2.properties.StringProperty(required=True)),
            ('labels', stix2.properties.ListProperty(labels, required=True)),
            ('x_misp_value', stix2.properties.StringProperty(required=True)),
            ('created_by_ref', stix2.properties.StringProperty(required=True)),
            ('x_misp_comment', stix2.properties.StringProperty()),
            ('x_misp_category', stix2.properties.StringProperty())
            ])
            class Custom(object):
                def __init__(self, **kwargs):
                    return
        except:
            @stix2.CustomObject(custom_object_type,[('id', stix2.properties.StringProperty(required=True)),
            ('x_misp_timestamp', stix2.properties.StringProperty(required=True)),
            ('labels', stix2.properties.ListProperty(labels, required=True)),
            ('x_misp_values', stix2.properties.DictionaryProperty(required=True)),
            ('created_by_ref', stix2.properties.StringProperty(required=True)),
            ('x_misp_comment', stix2.properties.StringProperty()),
            ('x_misp_category', stix2.properties.StringProperty())
            ])
            class Custom(object):
                def __init__(self, **kwargs):
                    return
        custom = Custom(**obj)
        self.event.append(stix2.parse(custom))

    def handler(self):
        self.outputname = '{}.stix2'.format(self.filename)
        if self.from_misp():
            self.buildMispDict()
        else:
            self.buildExternalDict()

    def from_misp(self):
        for o in self.event:
            if o._type == 'report' and 'misp:tool="misp2stix2"' in o.get('labels'):
                index = self.event.index(o)
                self.report = self.event.pop(index)
                return True
        return False

    def buildMispDict(self):
        self.parse_identity()
        self.parse_report()
        for o in self.event:
            object_type = o._type
            labels = o.get('labels')
            if object_type in ('attack-pattern', 'course-of-action', 'intrusion-set', 'malware', 'threat-actor', 'tool'):
                self.parse_galaxy(o, labels)
            elif 'x-misp-object' in object_type:
                if 'from_object' in labels:
                    self.parse_custom_object(o, labels)
                else:
                    self.parse_custom_attribute(o, labels)
            else:
                if 'from_object' in labels:
                    self.parse_object(o, labels)
                else:
                    self.parse_attribute(o, labels)

    def parse_identity(self):
        identity = self.event.pop(0)
        org = {'name': identity.get('name')}
        self.misp_event['Org'] = org

    def parse_report(self):
        report = self.report
        self.misp_event.info = report.get('name')
        if report.get('published'):
            self.misp_event.publish_timestamp = self.getTimestampfromDate(report.get('published'))
        if hasattr(report, 'labels'):
            labels = report['labels']
            for l in labels:
                self.misp_event.add_tag(l)
        if hasattr(report, 'external_references'):
            ext_refs = report['external_references']
            for e in ext_refs:
                link = {"type": "link"}
                comment = e.get('source_name').split('url - ')[1]
                if comment:
                    link['comment'] = comment
                link['value'] = e.get('url')
                self.misp_event.add_attribute(**link)

    def parse_galaxy(self, o, labels):
        galaxy_type = self.get_misp_type(labels)
        tag = labels[1]
        value = tag.split(':')[1].split('=')[1]
        galaxy_description, cluster_description = o.get('description').split('|')
        galaxy = {'type': galaxy_type, 'name': o.get('name'), 'description': galaxy_description,
                  'GalaxyCluster': [{'type': galaxy_type, 'value':value, 'tag_name': tag,
                                     'description': cluster_description}]}
        self.misp_event['Galaxy'].append(galaxy)

    def parse_custom_object(self, o):
        name = o.get('type').split('x-misp-object-')[1]
        timestamp = self.getTimestampfromDate(o.get('x_misp_timestamp'))
        category = o.get('category')
        attributes = []
        values = o.get('x_misp_values')
        for v in values:
            attribute_type, object_relation = v.split('_')
            attribute = {'type': attribute_type, 'value': value.get(v),
                         'object_relation': object_relation}
            attributes.append(attribute)
        misp_object = {'name': name, 'timestamp': timestamp, 'meta-category': category,
                       'Attribute': attributes}
        self.misp_event.add_object(**misp_object)

    def parse_custom_attribute(self, o, labels):
        attribute_type = o.get('type').split('x-misp-object-')[1]
        timestamp = self.getTimestampfromDate(o.get('x_misp_timestamp'))
        to_ids = bool(labels[1].split('=')[1])
        value = o.get('x_misp_value')
        category = self.get_misp_category(labels)
        attribute = {'type': attribute_type, 'timestamp': timestamp, 'to_ids': to_ids,
                     'value': value, 'category': category}
        self.misp_event.add_attribute(**attribute)

    def parse_object(self, o, labels):
        object_type = self.get_misp_type(labels)
        object_category = self.get_misp_category(labels)
        stix_type = o._type
        if stix_type == 'indicator':
            misp_object = {'name': object_type, 'meta-category': object_category}
            pattern = o.get('pattern').split('AND')
            pattern[0] = pattern[0][2:]
            pattern[-1] = pattern[-1][:-2]
            attributes = self.parse_pattern_from_object(pattern)
        if stix_type == 'observed-data':
            misp_object = {'name': object_type, 'meta-category': object_category}
            observable = o.get('objects')
            attributes = self.parse_observable_from_object(observable)
        misp_object['to_ids'] = bool(labels[1].split('=')[1])
        self.misp_event.add_object(**misp_object)

    def parse_attribute(self, o, labels):
        attribute_type = self.get_misp_type(labels)
        attribute_category = self.get_misp_category(labels)
        attribute = {'type': attribute_type, 'category': attribute_category}
        stix_type = o._type
        if stix_type == 'vulnerability':
            value = o.get('name')
        else:
            if stix_type == 'indicator':
                o_date = o.get('valid_from')
                pattern = o.get('pattern')
                value = self.parse_pattern(pattern)
            else:
                o_date = o.get('first_observed')
                observable = o.get('objects')
                try:
                    value = self.parse_observable(observable, attribute_type)
                except:
                    print('{}: {}'.format(attribute_type, observable))
            attribute['timestamp'] = self.getTimestampfromDate(o_date)
        try:
            attribute['value'] = value
            self.misp_event.add_attribute(**attribute)
        except:
            pass

    def buildExternalDict(self):
        sys.exit(1)
        for o in self.event:
            print(o)

    def saveFile(self):
        eventDict = self.misp_event.to_json()
        outputfile = '{}.stix2'.format(self.filename)
        with open(outputfile, 'w') as f:
            f.write(eventDict)

    @staticmethod
    def getTimestampfromDate(stix_date):
        try:
            return int(stix_date.timestamp())
        except:
            return int(time.mktime(time.strptime(stix_date.split('+')[0], "%Y-%m-%d %H:%M:%S")))

    @staticmethod
    def get_misp_type(labels):
        return labels[0].split('=')[1][1:-1]

    @staticmethod
    def get_misp_category(labels):
        return labels[1].split('=')[1][1:-1]

    @staticmethod
    def parse_observable(observable, attribute_type):
        return misp_types_mapping[attribute_type](observable, attribute_type)

    @staticmethod
    def parse_pattern(pattern):
        if ' AND ' in pattern:
            pattern_parts = pattern.split(' AND ')
            if len(pattern_parts) == 3:
                _, value1 = pattern_parts[2].split(' = ')
                _, value2 = pattern_parts[0].split(' = ')
            else:
                _, value1 = pattern_parts[0].split(' = ')
                _, value2 = pattern_parts[1].split(' = ')
            return '{}|{}'.split(value1[1:-1], value2[1:-1])
        else:
            return pattern.split(' = ')[1][1:-1]

    @staticmethod
    def parse_observable_from_object(observable):
        return

    @staticmethod
    def parse_pattern_from_object(pattern):
        if 'malware-sample' in labels:
            self.parse_malware_sample()
        return

def main(args):
    pathname = os.path.dirname(args[0])
    stix_parser = StixParser()
    stix_parser.loadEvent(args, pathname)
    stix_parser.handler()
    stix_parser.saveFile()
    print(1)

if __name__ == "__main__":
    main(sys.argv)
<commit_msg>fix: Fixed patterns parsing to avoid useless special caracters import<commit_after># -*- coding: utf-8 -*-
#    Copyright (C) 2017-2018 CIRCL Computer Incident Response Center Luxembourg (smile gie)
#    Copyright (C) 2017-2018 Christian Studer
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys, json, os, time
import stix2
import pymisp
from stix2misp_mapping import *

class StixParser():
    def __init__(self):
        self.misp_event = pymisp.MISPEvent()
        self.event = []
        self.misp_event['Galaxy'] = []

    def loadEvent(self, args, pathname):
        # try:
        filename = os.path.join(pathname, args[1])
        tempFile = open(filename, 'r')
        self.filename = filename
        event = stix2.get_dict(tempFile)
        for o in event.get('objects'):
            try:
                self.event.append(stix2.parse(o))
            except:
                self.parse_custom(o)
        # except:
        #     print(json.dumps({'success': 0, 'message': 'The temporary STIX export file could not be read'}))
        #     sys.exit(1)

    def parse_custom(self, obj):
        custom_object_type = obj.pop('type')
        labels = obj['labels']
        try:
            @stix2.CustomObject(custom_object_type,[('id', stix2.properties.StringProperty(required=True)),
            ('x_misp_timestamp', stix2.properties.StringProperty(required=True)),
            ('labels', stix2.properties.ListProperty(labels, required=True)),
            ('x_misp_value', stix2.properties.StringProperty(required=True)),
            ('created_by_ref', stix2.properties.StringProperty(required=True)),
            ('x_misp_comment', stix2.properties.StringProperty()),
            ('x_misp_category', stix2.properties.StringProperty())
            ])
            class Custom(object):
                def __init__(self, **kwargs):
                    return
        except:
            @stix2.CustomObject(custom_object_type,[('id', stix2.properties.StringProperty(required=True)),
            ('x_misp_timestamp', stix2.properties.StringProperty(required=True)),
            ('labels', stix2.properties.ListProperty(labels, required=True)),
            ('x_misp_values', stix2.properties.DictionaryProperty(required=True)),
            ('created_by_ref', stix2.properties.StringProperty(required=True)),
            ('x_misp_comment', stix2.properties.StringProperty()),
            ('x_misp_category', stix2.properties.StringProperty())
            ])
            class Custom(object):
                def __init__(self, **kwargs):
                    return
        custom = Custom(**obj)
        self.event.append(stix2.parse(custom))

    def handler(self):
        self.outputname = '{}.stix2'.format(self.filename)
        if self.from_misp():
            self.buildMispDict()
        else:
            self.buildExternalDict()

    def from_misp(self):
        for o in self.event:
            if o._type == 'report' and 'misp:tool="misp2stix2"' in o.get('labels'):
                index = self.event.index(o)
                self.report = self.event.pop(index)
                return True
        return False

    def buildMispDict(self):
        self.parse_identity()
        self.parse_report()
        for o in self.event:
            object_type = o._type
            labels = o.get('labels')
            if object_type in ('attack-pattern', 'course-of-action', 'intrusion-set', 'malware', 'threat-actor', 'tool'):
                self.parse_galaxy(o, labels)
            elif 'x-misp-object' in object_type:
                if 'from_object' in labels:
                    self.parse_custom_object(o, labels)
                else:
                    self.parse_custom_attribute(o, labels)
            else:
                if 'from_object' in labels:
                    self.parse_object(o, labels)
                else:
                    self.parse_attribute(o, labels)

    def parse_identity(self):
        identity = self.event.pop(0)
        org = {'name': identity.get('name')}
        self.misp_event['Org'] = org

    def parse_report(self):
        report = self.report
        self.misp_event.info = report.get('name')
        if report.get('published'):
            self.misp_event.publish_timestamp = self.getTimestampfromDate(report.get('published'))
        if hasattr(report, 'labels'):
            labels = report['labels']
            for l in labels:
                self.misp_event.add_tag(l)
        if hasattr(report, 'external_references'):
            ext_refs = report['external_references']
            for e in ext_refs:
                link = {"type": "link"}
                comment = e.get('source_name').split('url - ')[1]
                if comment:
                    link['comment'] = comment
                link['value'] = e.get('url')
                self.misp_event.add_attribute(**link)

    def parse_galaxy(self, o, labels):
        galaxy_type = self.get_misp_type(labels)
        tag = labels[1]
        value = tag.split(':')[1].split('=')[1]
        galaxy_description, cluster_description = o.get('description').split('|')
        galaxy = {'type': galaxy_type, 'name': o.get('name'), 'description': galaxy_description,
                  'GalaxyCluster': [{'type': galaxy_type, 'value':value, 'tag_name': tag,
                                     'description': cluster_description}]}
        self.misp_event['Galaxy'].append(galaxy)

    def parse_custom_object(self, o):
        name = o.get('type').split('x-misp-object-')[1]
        timestamp = self.getTimestampfromDate(o.get('x_misp_timestamp'))
        category = o.get('category')
        attributes = []
        values = o.get('x_misp_values')
        for v in values:
            attribute_type, object_relation = v.split('_')
            attribute = {'type': attribute_type, 'value': value.get(v),
                         'object_relation': object_relation}
            attributes.append(attribute)
        misp_object = {'name': name, 'timestamp': timestamp, 'meta-category': category,
                       'Attribute': attributes}
        self.misp_event.add_object(**misp_object)

    def parse_custom_attribute(self, o, labels):
        attribute_type = o.get('type').split('x-misp-object-')[1]
        timestamp = self.getTimestampfromDate(o.get('x_misp_timestamp'))
        to_ids = bool(labels[1].split('=')[1])
        value = o.get('x_misp_value')
        category = self.get_misp_category(labels)
        attribute = {'type': attribute_type, 'timestamp': timestamp, 'to_ids': to_ids,
                     'value': value, 'category': category}
        self.misp_event.add_attribute(**attribute)

    def parse_object(self, o, labels):
        object_type = self.get_misp_type(labels)
        object_category = self.get_misp_category(labels)
        stix_type = o._type
        if stix_type == 'indicator':
            misp_object = {'name': object_type, 'meta-category': object_category}
            pattern = o.get('pattern').replace('\\\\', '\\').split('AND')
            pattern[0] = pattern[0][2:]
            pattern[-1] = pattern[-1][:-2]
            attributes = self.parse_pattern_from_object(pattern)
        if stix_type == 'observed-data':
            misp_object = {'name': object_type, 'meta-category': object_category}
            observable = o.get('objects')
            attributes = self.parse_observable_from_object(observable)
        misp_object['to_ids'] = bool(labels[1].split('=')[1])
        self.misp_event.add_object(**misp_object)

    def parse_attribute(self, o, labels):
        attribute_type = self.get_misp_type(labels)
        attribute_category = self.get_misp_category(labels)
        attribute = {'type': attribute_type, 'category': attribute_category}
        stix_type = o._type
        if stix_type == 'vulnerability':
            value = o.get('name')
        else:
            if stix_type == 'indicator':
                o_date = o.get('valid_from')
                pattern = o.get('pattern').replace('\\\\', '\\')
                value = self.parse_pattern(pattern)
            else:
                o_date = o.get('first_observed')
                observable = o.get('objects')
                try:
                    value = self.parse_observable(observable, attribute_type)
                except:
                    print('{}: {}'.format(attribute_type, observable))
            attribute['timestamp'] = self.getTimestampfromDate(o_date)
        try:
            attribute['value'] = value
            self.misp_event.add_attribute(**attribute)
        except:
            pass

    def buildExternalDict(self):
        sys.exit(1)
        for o in self.event:
            print(o)

    def saveFile(self):
        eventDict = self.misp_event.to_json()
        outputfile = '{}.stix2'.format(self.filename)
        with open(outputfile, 'w') as f:
            f.write(eventDict)

    @staticmethod
    def getTimestampfromDate(stix_date):
        try:
            return int(stix_date.timestamp())
        except:
            return int(time.mktime(time.strptime(stix_date.split('+')[0], "%Y-%m-%d %H:%M:%S")))

    @staticmethod
    def get_misp_type(labels):
        return labels[0].split('=')[1][1:-1]

    @staticmethod
    def get_misp_category(labels):
        return labels[1].split('=')[1][1:-1]

    @staticmethod
    def parse_observable(observable, attribute_type):
        return misp_types_mapping[attribute_type](observable, attribute_type)

    @staticmethod
    def parse_pattern(pattern):
        if ' AND ' in pattern:
            pattern_parts = pattern.split(' AND ')
            if len(pattern_parts) == 3:
                _, value1 = pattern_parts[2].split(' = ')
                _, value2 = pattern_parts[0].split(' = ')
                return '{}|{}'.format(value1[1:-3], value2[1:-1])
            else:
                _, value1 = pattern_parts[0].split(' = ')
                _, value2 = pattern_parts[1].split(' = ')
                if value1 in ("'ipv4-addr'", "'ipv6-addr'"):
                    return value2[1:-3]
                return '{}|{}'.format(value1[1:-1], value2[1:-3])
        else:
            return pattern.split(' = ')[1][1:-3]

    @staticmethod
    def parse_observable_from_object(observable):
        return

    @staticmethod
    def parse_pattern_from_object(pattern):
        return

def main(args):
    pathname = os.path.dirname(args[0])
    stix_parser = StixParser()
    stix_parser.loadEvent(args, pathname)
    stix_parser.handler()
    stix_parser.saveFile()
    print(1)

if __name__ == "__main__":
    main(sys.argv)
<|endoftext|>


<commit_before>import argparse
import sys
import re

from rest_client_generator import RestClientGenerator

class JavaClientGenerator(RestClientGenerator):

    def __init__(self, server_url, output_dir):
        super().__init__(server_url, output_dir)

        self.java_types = set()
        self.type_imports = {
            'ObjectMap': 'org.opencb.commons.datastore.core.ObjectMap;'
        }
        self.ignore_types = [
            'Integer', 'String', 'boolean', 'int', 'Boolean'
        ]
        self.categories = {
            'Users': 'User',
            'Projects': 'Project',
            'Studies': 'Study',
            'Files': 'File',
            'Jobs': 'Job',
            'Samples': 'Sample',
            'Individuals': 'Individual',
            'Families': 'Family',
            'Cohorts': 'Cohort',
            'Disease Panels': 'Panel',
            'Analysis - Alignment': 'Alignment',
            'Analysis - Variant': 'Variant',
            'Analysis - Clinical Interpretation': 'Clinical',
            'Operations - Variant Storage': 'Operation',
            'Meta': 'Meta',
            'GA4GH': 'GA4GH',
            'Admin': 'Admin'
        }
        self.param_types = {
            'string': 'String',
            'integer': 'int',
            'int': 'int',
            'map': 'ObjectMap',
            'boolean': 'boolean',
            'enum': 'String'
        }

    def get_imports(self):
        headers = []
        headers.append('/*')
        headers.append('* Copyright 2015-2020 OpenCB')
        headers.append('*')
        headers.append('* Licensed under the Apache License, Version 2.0 (the "License");')
        headers.append('* you may not use this file except in compliance with the License.')
        headers.append('* You may obtain a copy of the License at')
        headers.append('*')
        headers.append('*     http://www.apache.org/licenses/LICENSE-2.0')
        headers.append('*')
        headers.append('* Unless required by applicable law or agreed to in writing, software')
        headers.append('* distributed under the License is distributed on an "AS IS" BASIS,')
        headers.append('* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.')
        headers.append('* See the License for the specific language governing permissions and')
        headers.append('* limitations under the License.')
        headers.append('*/')
        headers.append('')
        headers.append('package org.opencb.opencga.client.rest;')
        headers.append('')

        imports = set()
        imports.add('org.opencb.opencga.client.exceptions.ClientException;')
        imports.add('org.opencb.opencga.client.config.ClientConfiguration;')
        # imports.append('import org.opencb.opencga.client.rest.AbstractParentClient;')
        imports.add('org.opencb.opencga.core.response.RestResponse;')

        for java_type in self.java_types:
            if java_type in self.type_imports and java_type not in self.ignore_types:
                imports.add(self.type_imports[java_type])
            elif java_type not in self.ignore_types:
                raise Exception(java_type + ' not found')

        imports = remove_redundant_imports(list(imports))
        imports.sort()

        return '\n'.join(headers) + '\n' + '\n'.join(['import ' + i for i in imports])

    def get_class_definition(self, category):
        self.java_types = set()

        text = []
        text.append('')
        text.append('')
        text.append('/**')
        text.append(' * This class contains methods for the {} webservices.'.format(
            self.categories[self.get_category_name(category)]))
        text.append(' *{}Client version: {}'.format(' ' * 4, self.version))
        text.append(' *{}PATH: {}'.format(' ' * 4, self.get_category_path(category)))
        text.append(' */')
        text.append('public class {}Client extends AbstractParentClient {{'.format(self.categories[self.get_category_name(category)]))
        text.append('')
        text.append('{}public {}Client(String userId, String token, ClientConfiguration configuration) {{'.format(' ' * 4, self.categories[self.get_category_name(category)]))
        text.append('{}super(userId, token, configuration);'.format(' ' * 8))
        text.append('{}}}'.format(' ' * 4))
        return '\n'.join(text)

    def get_class_end(self):
        return '}\n'

    def get_method_definition(self, category, endpoint):
        parameters = self.get_method_parameters(endpoint)
        typed_parameters = []
        print("Processing " + self.get_endpoint_path(endpoint))
        for parameter in parameters:
            typed_parameters.append(self.get_parameter_type(parameter) + ' ' + parameter)

        response_type = self.get_valid_parameter_type(self.get_endpoint_response(endpoint), self.get_endpoint_response_class(endpoint))

        text = []
        append_comment_text(text, '', 4)
        append_comment_text(text, '{}/**'.format(' ' * 4), 4)
        append_comment_text(text, '{}* {}'.format(' ' * 5, self.get_endpoint_description(endpoint)), 5)
        for parameter in parameters:
            append_comment_text(text, '{}* @param {} {}'.format(' ' * 5, parameter, self.get_parameter_description(parameter)), 5)
        append_comment_text(text, '{}* @return a RestResponse object.'.format(' ' * 5), 5)
        append_comment_text(text, '{}* @throws ClientException ClientException if there is any server error.'.format(' ' * 5), 5)
        append_comment_text(text, '{}*/'.format(' ' * 5), 5)

        append_text(text, '{}public RestResponse<{}> {}({}) throws ClientException {{'.format(
            ' ' * 4, response_type, self.get_method_name(endpoint, category),
            ', '.join(typed_parameters)), 4)

        if 'params' in parameters:
            append_text(text, '{}params = params != null ? params : new ObjectMap();'.format(' ' * 8), 8)
        else:
            append_text(text, '{}ObjectMap params = new ObjectMap();'.format(' ' * 8), 8)

        for parameter in parameters:
            if parameter not in ['params', 'data'] and not self.is_path_param(parameter):
                append_text(text, '{}params.putIfNotNull("{}", {});'.format(' ' * 8, parameter, parameter), 8)

        if 'data' in parameters:
            append_text(text, '{}params.put("body", data);'.format(' ' * 8), 8)

        append_text(text, '{}return execute("{}", {}, {}, {}, "{}", params, {}, {}.class);'.format((' ' * 8),
            self.get_category_path(category),
            self.get_endpoint_id1() if self.get_endpoint_id1() else 'null',
            '"' + self.get_endpoint_subcategory() + '"' if self.get_endpoint_subcategory() else 'null',
            self.get_endpoint_id2() if self.get_endpoint_id2() else 'null',
            self.get_endpoint_action() if self.get_endpoint_action() else 'null',
            self.get_endpoint_method(endpoint),
            response_type), 8)

        text.append('{}}}'.format(' ' * 4))
        return '\n'.join(text)

    def get_file_name(self, category):
        return self.categories[self.get_category_name(category)] + "Client.java"

    def get_method_name(self, endpoint, category):
        method_name = super().get_method_name(endpoint, category)
        # Convert to cammel case
        method_name = method_name.replace('_', ' ').title().replace(' ', '')
        return method_name[0].lower() + method_name[1:]

    def get_method_parameters(self, endpoint):
        parameters = []
        parameters.extend(self.get_path_params(endpoint))
        parameters.extend(self.get_mandatory_query_params(endpoint))

        if 'data' in self.parameters:
            parameters.append('data')

        if self.has_optional_params(endpoint):
            parameters.append('params')

        return parameters

    def get_parameter_description(self, parameter):
        if parameter != 'params':
            return super().get_parameter_description(parameter)
        else:
            return 'Map containing any additional optional parameters.'

    def get_parameter_type(self, parameter):
        my_type = ''
        my_import = ''
        if parameter != 'params':
            param_type = super().get_parameter_type(parameter)
            if param_type in self.param_types:
                my_type = self.param_types[param_type]
                my_import = self.get_parameter_type_class(parameter)
            elif param_type == 'object':
                my_import = self.get_parameter_type_class(parameter)
                my_type = my_import.split('.')[-1]
            else:
                raise Exception('Param ' + param_type + ' not found')
        return self.get_valid_parameter_type(my_type, my_import)

    def get_valid_parameter_type(self, my_type, my_import):
        if my_type.endswith(';'):
            my_type = my_type[:-1]

        if '$' in my_type:
            my_type = my_type.replace('$', '.')
        if '$' in my_import:
            my_import = my_import.replace('$', '.')

        if my_type == '' or my_type == 'Map':
            my_type = 'ObjectMap'
        else:
            self.type_imports[my_type] = my_import
        self.java_types.add(my_type)

        return my_type

def remove_redundant_imports(imports):
    to_remove = []
    for i in range(len(imports) - 1):
        for j in range(i + 1, len(imports)):
            if imports[i][:-1] + "." in imports[j][:-1]:
                to_remove.append(imports[j])
            elif imports[j][:-1] + "." in imports[i][:-1]:
                to_remove.append(imports[i])

    for my_import in to_remove:
        imports.remove(my_import)

    return imports

def append_text(array, string, sep):
    _append_text(array, string, sep, False)

def append_comment_text(array, string, sep):
    _append_text(array, string, sep, True)

def _append_text(array, string, sep, comment):
    if len(string) <= 140:
        array.append(string)
    else:
        my_string = string
        throw_string = None

        if 'throws' in my_string:
            pos = my_string.find('throws')
            throw_string = my_string[pos:]
            my_string = my_string[:pos - 1]

        while len(my_string) > 140:
            max = 0
            for it in re.finditer(' ', my_string):
                pos = it.start()
                if len(string[:pos]) < 140:
                    max = pos
            array.append(my_string[:max])
            text = ' ' * sep
            if comment:
                text += '*'
            text += ' ' * sep + my_string[max + 1:]
            my_string = text

        if throw_string:
            if len(my_string + ' ' + throw_string) <= 140:
                array.append(my_string + ' ' + throw_string)
            else:
                array.append(my_string)
                array.append(' ' * sep * 3 + throw_string)
        else:
            array.append(my_string)

def _setup_argparse():
    desc = 'This script creates automatically all RestClients files'
    parser = argparse.ArgumentParser(description=desc, formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument('server_url', help='server URL')
    parser.add_argument('output_dir', help='output directory')
    args = parser.parse_args()
    return args

def main():
    # Getting arg parameters
    args = _setup_argparse()

    client_generator = JavaClientGenerator(args.server_url, args.output_dir)
    client_generator.create_rest_clients()

if __name__ == '__main__':
    sys.exit(main())
<commit_msg>app: remove user from java client constructor, #1464<commit_after>import argparse
import sys
import re

from rest_client_generator import RestClientGenerator

class JavaClientGenerator(RestClientGenerator):

    def __init__(self, server_url, output_dir):
        super().__init__(server_url, output_dir)

        self.java_types = set()
        self.type_imports = {
            'ObjectMap': 'org.opencb.commons.datastore.core.ObjectMap;'
        }
        self.ignore_types = [
            'Integer', 'String', 'boolean', 'int', 'Boolean'
        ]
        self.categories = {
            'Users': 'User',
            'Projects': 'Project',
            'Studies': 'Study',
            'Files': 'File',
            'Jobs': 'Job',
            'Samples': 'Sample',
            'Individuals': 'Individual',
            'Families': 'Family',
            'Cohorts': 'Cohort',
            'Disease Panels': 'Panel',
            'Analysis - Alignment': 'Alignment',
            'Analysis - Variant': 'Variant',
            'Analysis - Clinical Interpretation': 'Clinical',
            'Operations - Variant Storage': 'Operation',
            'Meta': 'Meta',
            'GA4GH': 'GA4GH',
            'Admin': 'Admin'
        }
        self.param_types = {
            'string': 'String',
            'integer': 'int',
            'int': 'int',
            'map': 'ObjectMap',
            'boolean': 'boolean',
            'enum': 'String'
        }

    def get_imports(self):
        headers = []
        headers.append('/*')
        headers.append('* Copyright 2015-2020 OpenCB')
        headers.append('*')
        headers.append('* Licensed under the Apache License, Version 2.0 (the "License");')
        headers.append('* you may not use this file except in compliance with the License.')
        headers.append('* You may obtain a copy of the License at')
        headers.append('*')
        headers.append('*     http://www.apache.org/licenses/LICENSE-2.0')
        headers.append('*')
        headers.append('* Unless required by applicable law or agreed to in writing, software')
        headers.append('* distributed under the License is distributed on an "AS IS" BASIS,')
        headers.append('* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.')
        headers.append('* See the License for the specific language governing permissions and')
        headers.append('* limitations under the License.')
        headers.append('*/')
        headers.append('')
        headers.append('package org.opencb.opencga.client.rest;')
        headers.append('')

        imports = set()
        imports.add('org.opencb.opencga.client.exceptions.ClientException;')
        imports.add('org.opencb.opencga.client.config.ClientConfiguration;')
        # imports.append('import org.opencb.opencga.client.rest.AbstractParentClient;')
        imports.add('org.opencb.opencga.core.response.RestResponse;')

        for java_type in self.java_types:
            if java_type in self.type_imports and java_type not in self.ignore_types:
                imports.add(self.type_imports[java_type])
            elif java_type not in self.ignore_types:
                raise Exception(java_type + ' not found')

        imports = remove_redundant_imports(list(imports))
        imports.sort()

        return '\n'.join(headers) + '\n' + '\n'.join(['import ' + i for i in imports])

    def get_class_definition(self, category):
        self.java_types = set()

        text = []
        text.append('')
        text.append('')
        text.append('/**')
        text.append(' * This class contains methods for the {} webservices.'.format(
            self.categories[self.get_category_name(category)]))
        text.append(' *{}Client version: {}'.format(' ' * 4, self.version))
        text.append(' *{}PATH: {}'.format(' ' * 4, self.get_category_path(category)))
        text.append(' */')
        text.append('public class {}Client extends AbstractParentClient {{'.format(self.categories[self.get_category_name(category)]))
        text.append('')
        text.append('{}public {}Client(String token, ClientConfiguration configuration) {{'.format(' ' * 4, self.categories[self.get_category_name(category)]))
        text.append('{}super(token, configuration);'.format(' ' * 8))
        text.append('{}}}'.format(' ' * 4))
        return '\n'.join(text)

    def get_class_end(self):
        return '}\n'

    def get_method_definition(self, category, endpoint):
        parameters = self.get_method_parameters(endpoint)
        typed_parameters = []
        print("Processing " + self.get_endpoint_path(endpoint))
        for parameter in parameters:
            typed_parameters.append(self.get_parameter_type(parameter) + ' ' + parameter)

        response_type = self.get_valid_parameter_type(self.get_endpoint_response(endpoint), self.get_endpoint_response_class(endpoint))

        text = []
        append_comment_text(text, '', 4)
        append_comment_text(text, '{}/**'.format(' ' * 4), 4)
        append_comment_text(text, '{}* {}'.format(' ' * 5, self.get_endpoint_description(endpoint)), 5)
        for parameter in parameters:
            append_comment_text(text, '{}* @param {} {}'.format(' ' * 5, parameter, self.get_parameter_description(parameter)), 5)
        append_comment_text(text, '{}* @return a RestResponse object.'.format(' ' * 5), 5)
        append_comment_text(text, '{}* @throws ClientException ClientException if there is any server error.'.format(' ' * 5), 5)
        append_comment_text(text, '{}*/'.format(' ' * 5), 5)

        append_text(text, '{}public RestResponse<{}> {}({}) throws ClientException {{'.format(
            ' ' * 4, response_type, self.get_method_name(endpoint, category),
            ', '.join(typed_parameters)), 4)

        if 'params' in parameters:
            append_text(text, '{}params = params != null ? params : new ObjectMap();'.format(' ' * 8), 8)
        else:
            append_text(text, '{}ObjectMap params = new ObjectMap();'.format(' ' * 8), 8)

        for parameter in parameters:
            if parameter not in ['params', 'data'] and not self.is_path_param(parameter):
                append_text(text, '{}params.putIfNotNull("{}", {});'.format(' ' * 8, parameter, parameter), 8)

        if 'data' in parameters:
            append_text(text, '{}params.put("body", data);'.format(' ' * 8), 8)

        append_text(text, '{}return execute("{}", {}, {}, {}, "{}", params, {}, {}.class);'.format((' ' * 8),
            self.get_category_path(category),
            self.get_endpoint_id1() if self.get_endpoint_id1() else 'null',
            '"' + self.get_endpoint_subcategory() + '"' if self.get_endpoint_subcategory() else 'null',
            self.get_endpoint_id2() if self.get_endpoint_id2() else 'null',
            self.get_endpoint_action() if self.get_endpoint_action() else 'null',
            self.get_endpoint_method(endpoint),
            response_type), 8)

        text.append('{}}}'.format(' ' * 4))
        return '\n'.join(text)

    def get_file_name(self, category):
        return self.categories[self.get_category_name(category)] + "Client.java"

    def get_method_name(self, endpoint, category):
        method_name = super().get_method_name(endpoint, category)
        # Convert to cammel case
        method_name = method_name.replace('_', ' ').title().replace(' ', '')
        return method_name[0].lower() + method_name[1:]

    def get_method_parameters(self, endpoint):
        parameters = []
        parameters.extend(self.get_path_params(endpoint))
        parameters.extend(self.get_mandatory_query_params(endpoint))

        if 'data' in self.parameters:
            parameters.append('data')

        if self.has_optional_params(endpoint):
            parameters.append('params')

        return parameters

    def get_parameter_description(self, parameter):
        if parameter != 'params':
            return super().get_parameter_description(parameter)
        else:
            return 'Map containing any additional optional parameters.'

    def get_parameter_type(self, parameter):
        my_type = ''
        my_import = ''
        if parameter != 'params':
            param_type = super().get_parameter_type(parameter)
            if param_type in self.param_types:
                my_type = self.param_types[param_type]
                my_import = self.get_parameter_type_class(parameter)
            elif param_type == 'object':
                my_import = self.get_parameter_type_class(parameter)
                my_type = my_import.split('.')[-1]
            else:
                raise Exception('Param ' + param_type + ' not found')
        return self.get_valid_parameter_type(my_type, my_import)

    def get_valid_parameter_type(self, my_type, my_import):
        if my_type.endswith(';'):
            my_type = my_type[:-1]

        if '$' in my_type:
            my_type = my_type.replace('$', '.')
        if '$' in my_import:
            my_import = my_import.replace('$', '.')

        if my_type == '' or my_type == 'Map':
            my_type = 'ObjectMap'
        else:
            self.type_imports[my_type] = my_import
        self.java_types.add(my_type)

        return my_type

def remove_redundant_imports(imports):
    to_remove = []
    for i in range(len(imports) - 1):
        for j in range(i + 1, len(imports)):
            if imports[i][:-1] + "." in imports[j][:-1]:
                to_remove.append(imports[j])
            elif imports[j][:-1] + "." in imports[i][:-1]:
                to_remove.append(imports[i])

    for my_import in to_remove:
        imports.remove(my_import)

    return imports

def append_text(array, string, sep):
    _append_text(array, string, sep, False)

def append_comment_text(array, string, sep):
    _append_text(array, string, sep, True)

def _append_text(array, string, sep, comment):
    if len(string) <= 140:
        array.append(string)
    else:
        my_string = string
        throw_string = None

        if 'throws' in my_string:
            pos = my_string.find('throws')
            throw_string = my_string[pos:]
            my_string = my_string[:pos - 1]

        while len(my_string) > 140:
            max = 0
            for it in re.finditer(' ', my_string):
                pos = it.start()
                if len(string[:pos]) < 140:
                    max = pos
            array.append(my_string[:max])
            text = ' ' * sep
            if comment:
                text += '*'
            text += ' ' * sep + my_string[max + 1:]
            my_string = text

        if throw_string:
            if len(my_string + ' ' + throw_string) <= 140:
                array.append(my_string + ' ' + throw_string)
            else:
                array.append(my_string)
                array.append(' ' * sep * 3 + throw_string)
        else:
            array.append(my_string)

def _setup_argparse():
    desc = 'This script creates automatically all RestClients files'
    parser = argparse.ArgumentParser(description=desc, formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument('server_url', help='server URL')
    parser.add_argument('output_dir', help='output directory')
    args = parser.parse_args()
    return args

def main():
    # Getting arg parameters
    args = _setup_argparse()

    client_generator = JavaClientGenerator(args.server_url, args.output_dir)
    client_generator.create_rest_clients()

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


<commit_before># -*- encoding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
#    Releasing children from poverty in Jesus' name
#    @author: Emanuel Cino <ecino@compassion.ch>
#
#    The licence is in the file __openerp__.py
#
##############################################################################

from openerp.osv import orm, fields
from openerp.tools.translate import _

from . import gp_connector

class account_invoice(orm.Model):
    _inherit = 'account.invoice'

    # Add a field to know if we sent the receipt for a paid invoice
    _columns = {
        'receipt_id': fields.many2one('mail.message', _('Receipt'))
    }

    def action_cancel(self, cr, uid, ids, context=None):
        """ If an invoice was cancelled, update the situation in GP. """
        for invoice in self.browse(cr, uid, ids, {'lang': 'en_US'}):
            # Customer invoice going from 'open' to 'cancel' state
            if invoice.type == 'out_invoice' and invoice.state == 'open':
                contract_ids = set()
                gp_connect = gp_connector.GPConnect()
                for line in invoice.invoice_line:
                    contract = line.contract_id
                    if contract and contract.id not in contract_ids \
                            and line.product_id.categ_name == 'Sponsorship':
                        contract_ids.add(contract.id)
                        # Removes one month due in GP.
                        if not gp_connect.register_payment(
                                contract.id, contract.months_paid+1):
                            raise orm.except_orm(
                                _("GP Sync Error"),
                                _("The cancellation could not be registered "
                                  "into GP. Please contact an IT person."))
        return super(account_invoice, self).action_cancel(cr, uid, ids,
                                                          context)

    def action_move_create(self, cr, uid, ids, context=None):
        """ If an invoice was cancelled,
            and validated again, update the situation in GP.
        """
        res = super(account_invoice, self).action_move_create(cr, uid, ids,
                                                              context)
        for invoice in self.browse(cr, uid, ids, {'lang': 'en_US'}):
            if invoice.type == 'out_invoice' and invoice.internal_number:
                contract_ids = set()
                gp_connect = gp_connector.GPConnect()
                for line in invoice.invoice_line:
                    contract = line.contract_id
                    if contract and contract.id not in contract_ids \
                            and line.product_id.categ_name == 'Sponsorship':
                        contract_ids.add(contract.id)
                        if not gp_connect.undo_payment(contract.id):
                            raise orm.except_orm(
                                _("GP Sync Error"),
                                _("Please contact an IT person."))
        return res

    def get_funds_paid(self, cr, uid, from_date, to_date, context=None):
        """ Search invoices paid in the given period which are not
            sponsorships and return the ids. """
        invl_obj = self.pool.get('account.invoice.line')
        invl_ids = invl_obj.search(
            cr, uid, [
                ('state', '=', 'paid'),
                ('last_payment', '>=', from_date),
                ('last_payment', '<=', to_date),
                ('contract_id', '=', False),
                ('price_subtotal', '>', 8),
                ('product_id.name', '!=', 'The 4th Musketeer Fund')],
            context=context)

        return list(set([invl.invoice_id.id for invl in
                         invl_obj.browse(cr, uid, invl_ids, context)]))
<commit_msg>Exclude child gift product from thanks<commit_after># -*- encoding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
#    Releasing children from poverty in Jesus' name
#    @author: Emanuel Cino <ecino@compassion.ch>
#
#    The licence is in the file __openerp__.py
#
##############################################################################

from openerp.osv import orm, fields
from openerp.tools.translate import _

from . import gp_connector

class account_invoice(orm.Model):
    _inherit = 'account.invoice'

    # Add a field to know if we sent the receipt for a paid invoice
    _columns = {
        'receipt_id': fields.many2one('mail.message', _('Receipt'))
    }

    def action_cancel(self, cr, uid, ids, context=None):
        """ If an invoice was cancelled, update the situation in GP. """
        for invoice in self.browse(cr, uid, ids, {'lang': 'en_US'}):
            # Customer invoice going from 'open' to 'cancel' state
            if invoice.type == 'out_invoice' and invoice.state == 'open':
                contract_ids = set()
                gp_connect = gp_connector.GPConnect()
                for line in invoice.invoice_line:
                    contract = line.contract_id
                    if contract and contract.id not in contract_ids \
                            and line.product_id.categ_name == 'Sponsorship':
                        contract_ids.add(contract.id)
                        # Removes one month due in GP.
                        if not gp_connect.register_payment(
                                contract.id, contract.months_paid+1):
                            raise orm.except_orm(
                                _("GP Sync Error"),
                                _("The cancellation could not be registered "
                                  "into GP. Please contact an IT person."))
        return super(account_invoice, self).action_cancel(cr, uid, ids,
                                                          context)

    def action_move_create(self, cr, uid, ids, context=None):
        """ If an invoice was cancelled,
            and validated again, update the situation in GP.
        """
        res = super(account_invoice, self).action_move_create(cr, uid, ids,
                                                              context)
        for invoice in self.browse(cr, uid, ids, {'lang': 'en_US'}):
            if invoice.type == 'out_invoice' and invoice.internal_number:
                contract_ids = set()
                gp_connect = gp_connector.GPConnect()
                for line in invoice.invoice_line:
                    contract = line.contract_id
                    if contract and contract.id not in contract_ids \
                            and line.product_id.categ_name == 'Sponsorship':
                        contract_ids.add(contract.id)
                        if not gp_connect.undo_payment(contract.id):
                            raise orm.except_orm(
                                _("GP Sync Error"),
                                _("Please contact an IT person."))
        return res

    def get_funds_paid(self, cr, uid, from_date, to_date, context=None):
        """ Search invoices paid in the given period which are not
            sponsorships and return the ids. """
        invl_obj = self.pool.get('account.invoice.line')
        invl_ids = invl_obj.search(
            cr, uid, [
                ('state', '=', 'paid'),
                ('last_payment', '>=', from_date),
                ('last_payment', '<=', to_date),
                ('contract_id', '=', False),
                ('price_subtotal', '>', 8),
                ('product_id.name', 'not in', ('The 4th Musketeer Fund',
                                               'Child gift'))],
            context=context)

        return list(set([invl.invoice_id.id for invl in
                         invl_obj.browse(cr, uid, invl_ids, context)]))
<|endoftext|>


<commit_before>"""
This file contains Django middleware related to the site_configuration app.
"""

from django.conf import settings
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from django.contrib.auth.decorators import login_required
from django.conf import settings
from re import compile

class SessionCookieDomainOverrideMiddleware(object):
    """
    Special case middleware which should be at the very end of the MIDDLEWARE list (so that it runs first
    on the process_response chain). This middleware will define a wrapper function for the set_cookie() function
    on the HttpResponse object, if the request is running in a middleware.

    This wrapped set_cookie will change the SESSION_COOKIE_DOMAIN setting so that the cookie can be bound to a
    fully customized URL.
    """

    def process_response(self, __, response):
        """
        Django middleware hook for process responses
        """

        # Check for SESSION_COOKIE_DOMAIN setting override
        session_cookie_domain = configuration_helpers.get_value('SESSION_COOKIE_DOMAIN')
        if session_cookie_domain:
            def _set_cookie_wrapper(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None,
                                    httponly=False):
                """
                Wrapper function for set_cookie() which applies SESSION_COOKIE_DOMAIN override
                """

                # only override if we are setting the cookie name to be the one the Django Session Middleware uses
                # as defined in settings.SESSION_COOKIE_NAME
                if key == configuration_helpers.get_value('SESSION_COOKIE_NAME', settings.SESSION_COOKIE_NAME):
                    domain = session_cookie_domain

                # then call down into the normal Django set_cookie method
                return response.set_cookie_wrapped_func(
                    key,
                    value,
                    max_age=max_age,
                    expires=expires,
                    path=path,
                    domain=domain,
                    secure=secure,
                    httponly=httponly
                )

            # then point the HttpResponse.set_cookie to point to the wrapper and keep
            # the original around
            response.set_cookie_wrapped_func = response.set_cookie
            response.set_cookie = _set_cookie_wrapper

        return response

class LoginRequiredMiddleware:
    """
    Middleware that requires a user to be authenticated to view any page other
    than LOGIN_URL. Exemptions to this requirement can optionally be specified
    in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
    you can copy from any urls.py).
    """

    def __init__(self):
        self.LOGIN_URL = settings.LOGIN_URL or '/login/'
        self.LOGIN_EXEMPT_URLS = list()
        self.RESTRICT_SITE_TO_LOGGED_IN_USERS = None
        self.EXEMPT_URLS = [compile(self.LOGIN_URL.lstrip('/')), compile(r'^user_api/v1/account/.*$')]

    def process_view(self, request, view_func, view_args, view_kwargs):

        '''
        If the site is configured to restrict not logged in users to the LOGIN_EXEMPT_URLS
        from accessing pages, wrap the next view with the django login_required middleware
        '''

        if request.user.is_authenticated():
            return None

        self.RESTRICT_SITE_TO_LOGGED_IN_USERS = self.RESTRICT_SITE_TO_LOGGED_IN_USERS or configuration_helpers.get_value(
            'RESTRICT_SITE_TO_LOGGED_IN_USERS',
            settings.FEATURES.get('RESTRICT_SITE_TO_LOGGED_IN_USERS', False)
        )

        if self.RESTRICT_SITE_TO_LOGGED_IN_USERS:
            self.LOGIN_EXEMPT_URLS = self.LOGIN_EXEMPT_URLS or configuration_helpers.get_value(
                'LOGIN_EXEMPT_URLS',
                getattr(settings, 'LOGIN_EXEMPT_URLS', None)
            )

            if self.LOGIN_EXEMPT_URLS:
                if type(self.LOGIN_EXEMPT_URLS) is str or type(self.LOGIN_EXEMPT_URLS) is unicode:
                    self.LOGIN_EXEMPT_URLS = [self.LOGIN_EXEMPT_URLS]
                self.EXEMPT_URLS += [compile(expr) for expr in self.LOGIN_EXEMPT_URLS]
            path = request.path_info.lstrip('/')
            if not any(m.match(path) for m in self.EXEMPT_URLS):
                return login_required(view_func)(request, view_args, view_kwargs)

        return None
<commit_msg>Small fixes to LoginRequiredMiddleware needed on courses.ms<commit_after>"""
This file contains Django middleware related to the site_configuration app.
"""

from django.conf import settings
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from django.contrib.auth.decorators import login_required
from django.conf import settings
from re import compile

class SessionCookieDomainOverrideMiddleware(object):
    """
    Special case middleware which should be at the very end of the MIDDLEWARE list (so that it runs first
    on the process_response chain). This middleware will define a wrapper function for the set_cookie() function
    on the HttpResponse object, if the request is running in a middleware.

    This wrapped set_cookie will change the SESSION_COOKIE_DOMAIN setting so that the cookie can be bound to a
    fully customized URL.
    """

    def process_response(self, __, response):
        """
        Django middleware hook for process responses
        """

        # Check for SESSION_COOKIE_DOMAIN setting override
        session_cookie_domain = configuration_helpers.get_value('SESSION_COOKIE_DOMAIN')
        if session_cookie_domain:
            def _set_cookie_wrapper(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None,
                                    httponly=False):
                """
                Wrapper function for set_cookie() which applies SESSION_COOKIE_DOMAIN override
                """

                # only override if we are setting the cookie name to be the one the Django Session Middleware uses
                # as defined in settings.SESSION_COOKIE_NAME
                if key == configuration_helpers.get_value('SESSION_COOKIE_NAME', settings.SESSION_COOKIE_NAME):
                    domain = session_cookie_domain

                # then call down into the normal Django set_cookie method
                return response.set_cookie_wrapped_func(
                    key,
                    value,
                    max_age=max_age,
                    expires=expires,
                    path=path,
                    domain=domain,
                    secure=secure,
                    httponly=httponly
                )

            # then point the HttpResponse.set_cookie to point to the wrapper and keep
            # the original around
            response.set_cookie_wrapped_func = response.set_cookie
            response.set_cookie = _set_cookie_wrapper

        return response

class LoginRequiredMiddleware:
    """
    Middleware that requires a user to be authenticated to view any page other
    than LOGIN_URL. Exemptions to this requirement can optionally be specified
    in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
    you can copy from any urls.py).
    """

    def __init__(self):
        self.LOGIN_URL = settings.LOGIN_URL or '/login/'
        self.LOGIN_EXEMPT_URLS = list()

        # Needed for user to be able to login at all
        self.DEFAULT_LOGIN_EXEMPT_URLS = [
            r'^user_api/v1/account/.*$',
            r'^auth/.*$',
            r'^register.*$',
            r'^create_account.*$',
            r'^admin.*$'
        ]
        self.RESTRICT_SITE_TO_LOGGED_IN_USERS = None
        self.EXEMPT_URLS = [compile(self.LOGIN_URL.lstrip('/'))]

    def process_view(self, request, view_func, view_args, view_kwargs):

        '''
        If the site is configured to restrict not logged in users to the LOGIN_EXEMPT_URLS
        from accessing pages, wrap the next view with the django login_required middleware
        '''

        if request.user.is_authenticated():
            return None

        self.RESTRICT_SITE_TO_LOGGED_IN_USERS = self.RESTRICT_SITE_TO_LOGGED_IN_USERS or configuration_helpers.get_value(
            'RESTRICT_SITE_TO_LOGGED_IN_USERS',
            settings.FEATURES.get('RESTRICT_SITE_TO_LOGGED_IN_USERS', False)
        )

        if self.RESTRICT_SITE_TO_LOGGED_IN_USERS:
            self.LOGIN_EXEMPT_URLS = self.LOGIN_EXEMPT_URLS or configuration_helpers.get_value(
                'LOGIN_EXEMPT_URLS',
                settings.FEATURES.get('LOGIN_EXEMPT_URLS', None)
            )

            if self.LOGIN_EXEMPT_URLS:
                if type(self.LOGIN_EXEMPT_URLS) is str or type(self.LOGIN_EXEMPT_URLS) is unicode:
                    self.LOGIN_EXEMPT_URLS = [self.LOGIN_EXEMPT_URLS]
                self.EXEMPT_URLS += [compile(expr) for expr in self.LOGIN_EXEMPT_URLS + self.DEFAULT_LOGIN_EXEMPT_URLS]
            path = request.path_info.lstrip('/')
            if not any(m.match(path) for m in self.EXEMPT_URLS):
                return login_required(view_func)(request, view_args, view_kwargs)

        return None
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# This file is part of BridgeDB, a Tor bridge distribution system.
#
# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@torproject.org>
#           please also see AUTHORS file
# :copyright: (c) 2007-2013, The Tor Project, Inc.
#             (c) 2007-2013, all entities within the AUTHORS file
# :license: 3-clause BSD, see included LICENSE for information

from __future__ import absolute_import
from __future__ import unicode_literals

import logging

import os

import OpenSSL.rand

def getKey(filename):
    """Load the key stored in ``filename``, or create a new key.

    If ``filename`` does not exist, create a new 32-byte key and store it in
    ``filename``.

    >>> import os
    >>> from bridgedb import crypto
    >>> name = 'doctest_getKey'
    >>> os.path.exists(name)
    False
    >>> k1 = crypto.getKey(name)
    >>> os.path.exists(name)
    True
    >>> open(name).read() == k1
    True
    >>> k2 = crypto.getKey(name)
    >>> k1 == k2
    True

    :param string filename: The filename to store the secret key in.
    :rtype: bytes
    :returns: A byte string containing the secret key.
    """
    try:
        fh = open(filename, 'rb')
    except IOError:
        logging.debug("getKey(): Creating new secret key.")
        key = OpenSSL.rand.bytes(32)
        flags = os.O_WRONLY | os.O_TRUNC | os.O_CREAT | getattr(os, "O_BIN", 0)
        fd = os.open(filename, flags, 0400)
        os.write(fd, key)
        os.fsync(fd)
        os.close(fd)
    else:
        logging.debug("getKey(): Secret key file found. Loading...")
        key = fh.read()
        fh.close()
    return key
<commit_msg>Add a module docstring to bridgedb.crypto.<commit_after># -*- coding: utf-8 -*-
#
# This file is part of BridgeDB, a Tor bridge distribution system.
#
# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@torproject.org>
# :copyright: (c) 2007-2014, The Tor Project, Inc.
#             (c) 2013-2014, Isis Lovecruft
#             (c) 2007-2014, all entities within the AUTHORS file
# :license: 3-clause BSD, see included LICENSE for information

"""crypto - BridgeDB general cryptographic utilities.

**Module Overview:**

..
  crypto
   |_getKey() - Load the master key from a file, or create a new one.
   |
   \_SSLVerifyingContextFactory - OpenSSL.SSL.Context factory which verifies
      |                           certificate chains and matches hostnames.
      |_getContext() - Retrieve an SSL context configured for certificate
      |                verification.
      |_getHostnameFromURL() - Parses the hostname from the request URL.
      \_verifyHostname() - Check that the cert CN matches the request
                           hostname.

"""

from __future__ import absolute_import
from __future__ import unicode_literals

import logging
import os

import OpenSSL.rand

def getKey(filename):
    """Load the key stored in ``filename``, or create a new key.

    If ``filename`` does not exist, create a new 32-byte key and store it in
    ``filename``.

    >>> import os
    >>> from bridgedb import crypto
    >>> name = 'doctest_getKey'
    >>> os.path.exists(name)
    False
    >>> k1 = crypto.getKey(name)
    >>> os.path.exists(name)
    True
    >>> open(name).read() == k1
    True
    >>> k2 = crypto.getKey(name)
    >>> k1 == k2
    True

    :param string filename: The filename to store the secret key in.
    :rtype: bytes
    :returns: A byte string containing the secret key.
    """
    try:
        fh = open(filename, 'rb')
    except IOError:
        logging.debug("getKey(): Creating new secret key.")
        key = OpenSSL.rand.bytes(32)
        flags = os.O_WRONLY | os.O_TRUNC | os.O_CREAT | getattr(os, "O_BIN", 0)
        fd = os.open(filename, flags, 0400)
        os.write(fd, key)
        os.fsync(fd)
        os.close(fd)
    else:
        logging.debug("getKey(): Secret key file found. Loading...")
        key = fh.read()
        fh.close()
    return key
<|endoftext|>


<commit_before>import os

import sublime
from sublime_plugin import WindowCommand

from ..git_command import GitCommand
from ...common import util

NO_REPO_MESSAGE = ("It looks like you haven't initialized Git in this directory.  "
                   "Would you like to?")
REPO_PATH_PROMPT = "Enter root path of new git repo:"
CONFIRM_REINITIALIZE = ("It looks like Git is already initialized here.  "
                        "Would you like to re-initialize?")
NAME_MESSAGE = "Enter your first and last name:"
EMAIL_MESSAGE = "Enter your email address:"
NO_CONFIG_MESSAGE = ("It looks like you haven't configured Git yet.  Would you "
                     "like to enter your name and email for Git to use?")
RECLONE_CANT_BE_DONE = ("It looks like Git is already initialized here.  "
                        "You can not re-clone")
GIT_URL = "Enter git url:"

views_with_offer_made = set()

class GsOfferInit(WindowCommand, GitCommand):

    """
    If a git command fails indicating no git repo was found, this
    command will ask the user whether they'd like to init a new repo.

    Offer only once per session for a given view.
    """

    def run(self):
        if self.savvy_settings.get("disable_git_init_prompt"):
            return

        active_view_id = self.window.active_view().id()
        if active_view_id not in views_with_offer_made and sublime.ok_cancel_dialog(NO_REPO_MESSAGE):
            self.window.run_command("gs_init")
        else:
            views_with_offer_made.add(active_view_id)

class GsInit(WindowCommand, GitCommand):

    """
    If the active Sublime window has folders added to the project (or if Sublime was
    opened from the terminal with something like `subl .`), initialize a new Git repo
    at that location.  If that directory cannot be determined, use the open file's
    directory.  If there is no open file, prompt the user for the directory to use.

    If the selected directory has previosly been initialized with Git, prompt the user
    to confirm a re-initialize before proceeding.
    """

    def run(self):
        sublime.set_timeout_async(self.run_async, 0)

    def run_async(self):
        git_root = self.find_working_dir()

        if git_root and os.path.exists(os.path.join(git_root, ".git")):
            if sublime.ok_cancel_dialog(CONFIRM_REINITIALIZE):
                self.on_done(git_root, re_init=True)
            return

        self.window.show_input_panel(REPO_PATH_PROMPT, git_root, self.on_done, None, None)

    def on_done(self, path, re_init=False):
        self.git("init", working_dir=path)
        self.window.status_message("{word_start}nitialized repo successfully.".format(
            word_start="Re-i" if re_init else "I"))
        util.view.refresh_gitsavvy(self.window.active_view())

class GsClone(WindowCommand, GitCommand):

    """
    If the active Sublime window has folders added to the project (or if Sublime was
    opened from the terminal with something like `subl .`), initialize a new Git repo
    at that location.  If that directory cannot be determined, use the open file's
    directory.  If there is no open file, prompt the user for the directory to use.

    If the selected directory has previously been initialized with Git, prompt the user
    to confirm a re-initialize before proceeding.
    """

    def run(self):
        self.window.show_input_panel(GIT_URL, '', self.on_enter_url, None, None)

    def on_enter_url(self, url):
        self.git_url = url
        self.suggested_git_root = self.find_suggested_git_root()
        self.window.show_input_panel(REPO_PATH_PROMPT, self.suggested_git_root, self.on_enter_directory, None, None)

    def find_suggested_git_root(self):
        folder = self.find_working_dir()
        project = self.project_name_from_url(self.git_url)
        if folder:
            if not os.path.exists(os.path.join(folder, project, ".git")):
                return os.path.join(folder, project)
            else:
                parent = os.path.realpath(os.path.join(folder, ".."))
                return os.path.join(parent, project)
        return ""

    def on_enter_directory(self, path):
        self.suggested_git_root = path
        if self.suggested_git_root and os.path.exists(os.path.join(self.suggested_git_root, ".git")):
            sublime.ok_cancel_dialog(RECLONE_CANT_BE_DONE)
            return

        sublime.set_timeout_async(self.do_clone, 0)

    def do_clone(self):
        self.window.status_message("Start cloning {}".format(self.git_url))
        self.git("clone", self.git_url, self.suggested_git_root, working_dir='.')
        self.window.status_message("Cloned repo successfully.")
        self.open_folder()
        util.view.refresh_gitsavvy(self.window.active_view())

    def open_folder(self):
        # taken from
        # https://github.com/rosshemsley/iOpener/blob/a35117a201290b63b53ba6372dbf8bbfc68f28b9/i_opener.py#L203-L205
        sublime.run_command("new_window")
        project_data = dict(folders=[dict(follow_symlinks=True, path=self.suggested_git_root)])
        sublime.active_window().set_project_data(project_data)

class GsSetupUserCommand(WindowCommand, GitCommand):

    """
    Set user's name and email address in global Git config.
    """

    def run(self):
        sublime.set_timeout_async(self.run_async, 0)

    def run_async(self):
        if sublime.ok_cancel_dialog(NO_CONFIG_MESSAGE, "OK"):
            self.get_name()

    def get_name(self):
        self.window.show_input_panel(NAME_MESSAGE, "", self.on_done_name, None, None)

    def on_done_name(self, name):
        self.git("config", "--global", "user.name", "\"{}\"".format(name))
        self.get_email()

    def get_email(self):
        self.window.show_input_panel(EMAIL_MESSAGE, "", self.on_done_email, None, None)

    def on_done_email(self, email):
        self.git("config", "--global", "user.email", "\"{}\"".format(email))
<commit_msg>feat: expand home dir when cloning a project<commit_after>import os

import sublime
from sublime_plugin import WindowCommand

from ..git_command import GitCommand
from ...common import util

NO_REPO_MESSAGE = ("It looks like you haven't initialized Git in this directory.  "
                   "Would you like to?")
REPO_PATH_PROMPT = "Enter root path of new git repo:"
CONFIRM_REINITIALIZE = ("It looks like Git is already initialized here.  "
                        "Would you like to re-initialize?")
NAME_MESSAGE = "Enter your first and last name:"
EMAIL_MESSAGE = "Enter your email address:"
NO_CONFIG_MESSAGE = ("It looks like you haven't configured Git yet.  Would you "
                     "like to enter your name and email for Git to use?")
RECLONE_CANT_BE_DONE = ("It looks like Git is already initialized here.  "
                        "You can not re-clone")
GIT_URL = "Enter git url:"

views_with_offer_made = set()

class GsOfferInit(WindowCommand, GitCommand):

    """
    If a git command fails indicating no git repo was found, this
    command will ask the user whether they'd like to init a new repo.

    Offer only once per session for a given view.
    """

    def run(self):
        if self.savvy_settings.get("disable_git_init_prompt"):
            return

        active_view_id = self.window.active_view().id()
        if active_view_id not in views_with_offer_made and sublime.ok_cancel_dialog(NO_REPO_MESSAGE):
            self.window.run_command("gs_init")
        else:
            views_with_offer_made.add(active_view_id)

class GsInit(WindowCommand, GitCommand):

    """
    If the active Sublime window has folders added to the project (or if Sublime was
    opened from the terminal with something like `subl .`), initialize a new Git repo
    at that location.  If that directory cannot be determined, use the open file's
    directory.  If there is no open file, prompt the user for the directory to use.

    If the selected directory has previosly been initialized with Git, prompt the user
    to confirm a re-initialize before proceeding.
    """

    def run(self):
        sublime.set_timeout_async(self.run_async, 0)

    def run_async(self):
        git_root = self.find_working_dir()

        if git_root and os.path.exists(os.path.join(git_root, ".git")):
            if sublime.ok_cancel_dialog(CONFIRM_REINITIALIZE):
                self.on_done(git_root, re_init=True)
            return

        self.window.show_input_panel(REPO_PATH_PROMPT, git_root, self.on_done, None, None)

    def on_done(self, path, re_init=False):
        self.git("init", working_dir=path)
        self.window.status_message("{word_start}nitialized repo successfully.".format(
            word_start="Re-i" if re_init else "I"))
        util.view.refresh_gitsavvy(self.window.active_view())

class GsClone(WindowCommand, GitCommand):

    """
    If the active Sublime window has folders added to the project (or if Sublime was
    opened from the terminal with something like `subl .`), initialize a new Git repo
    at that location.  If that directory cannot be determined, use the open file's
    directory.  If there is no open file, prompt the user for the directory to use.

    If the selected directory has previously been initialized with Git, prompt the user
    to confirm a re-initialize before proceeding.
    """

    def run(self):
        self.window.show_input_panel(GIT_URL, '', self.on_enter_url, None, None)

    def on_enter_url(self, url):
        self.git_url = url
        self.suggested_git_root = self.find_suggested_git_root()
        self.window.show_input_panel(REPO_PATH_PROMPT, self.suggested_git_root, self.on_enter_directory, None, None)

    def find_suggested_git_root(self):
        folder = self.find_working_dir()
        project = self.project_name_from_url(self.git_url)
        if folder:
            if not os.path.exists(os.path.join(folder, project, ".git")):
                return os.path.join(folder, project)
            else:
                parent = os.path.realpath(os.path.join(folder, ".."))
                return os.path.join(parent, project)
        return ""

    def on_enter_directory(self, path):
        self.suggested_git_root = os.path.expanduser(path)  # handle ~/%HOME%
        if self.suggested_git_root and os.path.exists(os.path.join(self.suggested_git_root, ".git")):
            sublime.ok_cancel_dialog(RECLONE_CANT_BE_DONE)
            return

        sublime.set_timeout_async(self.do_clone, 0)

    def do_clone(self):
        self.window.status_message("Start cloning {}".format(self.git_url))
        self.git("clone", self.git_url, self.suggested_git_root, working_dir='.')
        self.window.status_message("Cloned repo successfully.")
        self.open_folder()
        util.view.refresh_gitsavvy(self.window.active_view())

    def open_folder(self):
        # taken from
        # https://github.com/rosshemsley/iOpener/blob/a35117a201290b63b53ba6372dbf8bbfc68f28b9/i_opener.py#L203-L205
        sublime.run_command("new_window")
        project_data = dict(folders=[dict(follow_symlinks=True, path=self.suggested_git_root)])
        sublime.active_window().set_project_data(project_data)

class GsSetupUserCommand(WindowCommand, GitCommand):

    """
    Set user's name and email address in global Git config.
    """

    def run(self):
        sublime.set_timeout_async(self.run_async, 0)

    def run_async(self):
        if sublime.ok_cancel_dialog(NO_CONFIG_MESSAGE, "OK"):
            self.get_name()

    def get_name(self):
        self.window.show_input_panel(NAME_MESSAGE, "", self.on_done_name, None, None)

    def on_done_name(self, name):
        self.git("config", "--global", "user.name", "\"{}\"".format(name))
        self.get_email()

    def get_email(self):
        self.window.show_input_panel(EMAIL_MESSAGE, "", self.on_done_email, None, None)

    def on_done_email(self, email):
        self.git("config", "--global", "user.email", "\"{}\"".format(email))
<|endoftext|>