<commit_before>from __future__ import with_statement
from __future__ import absolute_import
from twisted.internet.protocol import DatagramProtocol, Protocol, Factory

from io import open
import os
from os import makedirs, path
from os.path import isfile

import json, logging, re
import pwd, grp, stat

import socket
import six

from marcopolo.marco_conf import conf, utils
from marcopolo.polo import tokenprovider

def sanitize_path(path_str):
    """
    Prevents unwanted directory traversing and other bash vulnerabilities.

    :param str path_str: The path to be sanitized.

    :returns: The sanitized path.

    :rtype: str
    """
    return path.normpath("/"+path_str).lstrip('/')


class PoloBindingSSLFactory(Factory):
    def __init__(self, secret, offered_services, user_services, multicast_addrs):
        
        self.secret = secret
        self.offered_services = offered_services
        self.user_services = user_services
        self.multicast_addrs = multicast_addrs

    def buildProtocol(self, addr):
        p =  self.protocol(self.secret, self.offered_services, self.user_services, self.multicast_addrs)
        p.factory = self
        return p

class PoloBindingSSL(Protocol):

    def __init__(self, secret, offered_services, user_services, multicast_groups=conf.MULTICAST_ADDRS, verify_regexp=conf.VERIFY_REGEXP):
        """
        Creates the ``PoloBinding`` instance with the data structures to work with.
        If defined, the ``offered_services`` and ``user_services`` variables will be treated 
        as references to a dictionaries (i.e. the values will be modified, but the object reference 
        will never be altered).
        
        :param dict offered_services: A dictionary which comprises all the dictionaries \
        passed to the ``offered_services`` param in the Polo instances. That way the services \
        can be altered by both parties
        
        :param dict user_services: A dictionary of all the user services dictionaries (the key is multicast
            group and the value is the list of user dictionaries passed to the param ``user_services``.
        
        :param str multicast_group: The IPv4 address of the multicast group to join to. **Important**: The multicast_addr is not validated until the reactor is started.
        
        :param str verify_regexp: Regular expression used to verify an user service.
        """

        self.secret = secret
        self.offered_services = offered_services
        self.user_services = user_services
        self.verify = re.compile(verify_regexp)#re.compile('^([\d\w]+):([\d\w]+)$')
        self.multicast_groups = multicast_groups
        
        self.router = {}
        self.router["Register"] = self.publish_service_wrapper
        self.router["Publish"] = self.publish_service_wrapper
        self.router["Unpublish"] = self.unpublish_service_wrapper
        self.router["Request-token"] = self.request_token_service_wrapper

    def startProtocol(self):
        """
        Starts the binding and adds an entry in the log file
        """
        logging.info("Starting binding")

    def connectionMade(self):
        print("A connection was made!")

    def dataReceived(self, datagram):
        """
        Receives datagrams from bindings, and verifies the `Command` field.
        It emits a response based on the value (if necessary)

        :param bytes datagram: The byte stream with the message
        """
        
             
        datos = datagram.decode('utf-8')
        logging.debug("Datagram received: %s" % datos)
    
        try:
            datos_dict = json.loads(datos)
        except ValueError:
            self.write_error("Malformed JSON")
            logging.debug("Malformed JSON")
            return
        
        if datos_dict.get("Command", None) is None:
            self.write_error("Missing command")
            logging.debug("Missing command")
            return
        
        command = datos_dict["Command"]
        
        method = self.router.get(command, self.unknown_command_handler)

        method(command, datos_dict.get("Args", {}))
 
    def request_token(self, uid):
        pw_user = pwd.getpwuid(uid)
        if pw_user == None:
            self.write_error("User not found")
            return

        polo_dir = os.path.join(pw_user.pw_dir, ".polo")
        
        if not os.path.exists(polo_dir):
            os.mkdir(polo_dir)
            os.chown(polo_dir, pw_user.pw_uid, pw_user.pw_gid)

        if not os.path.isfile(os.path.join(polo_dir, "token")):
            try:
                f = open(os.path.join(polo_dir, "token"), 'w')
                os.fchmod(f.fileno(), stat.S_IRUSR | stat.S_IWUSR | stat.S_IRUSR)
                os.fchown(f.fileno(), pw_user.pw_uid, pw_user.pw_gid)
                f.write(tokenprovider.create_token(uid, self.secret))
                f.close()
            except Exception as e:
                self.write_error(str(e))
                return
            self.write_ok(0)
        else:
            self.write_ok(1)

    def write_ok(self, status):
        """
        Creates and sends an OK message
<commit_msg>bytes<commit_after>from __future__ import with_statement
from __future__ import absolute_import
from twisted.internet.protocol import DatagramProtocol, Protocol, Factory

from io import open
import os
from os import makedirs, path
from os.path import isfile

import json, logging, re
import pwd, grp, stat

import socket
import six

from marcopolo.marco_conf import conf, utils
from marcopolo.polo import tokenprovider

def sanitize_path(path_str):
    """
    Prevents unwanted directory traversing and other bash vulnerabilities.

    :param str path_str: The path to be sanitized.

    :returns: The sanitized path.

    :rtype: str
    """
    return path.normpath("/"+path_str).lstrip('/')


class PoloBindingSSLFactory(Factory):
    def __init__(self, secret, offered_services, user_services, multicast_addrs):
        
        self.secret = secret
        self.offered_services = offered_services
        self.user_services = user_services
        self.multicast_addrs = multicast_addrs

    def buildProtocol(self, addr):
        p =  self.protocol(self.secret, self.offered_services, self.user_services, self.multicast_addrs)
        p.factory = self
        return p

class PoloBindingSSL(Protocol):

    def __init__(self, secret, offered_services, user_services, multicast_groups=conf.MULTICAST_ADDRS, verify_regexp=conf.VERIFY_REGEXP):
        """
        Creates the ``PoloBinding`` instance with the data structures to work with.
        If defined, the ``offered_services`` and ``user_services`` variables will be treated 
        as references to a dictionaries (i.e. the values will be modified, but the object reference 
        will never be altered).
        
        :param dict offered_services: A dictionary which comprises all the dictionaries \
        passed to the ``offered_services`` param in the Polo instances. That way the services \
        can be altered by both parties
        
        :param dict user_services: A dictionary of all the user services dictionaries (the key is multicast
            group and the value is the list of user dictionaries passed to the param ``user_services``.
        
        :param str multicast_group: The IPv4 address of the multicast group to join to. **Important**: The multicast_addr is not validated until the reactor is started.
        
        :param str verify_regexp: Regular expression used to verify an user service.
        """

        self.secret = secret
        self.offered_services = offered_services
        self.user_services = user_services
        self.verify = re.compile(verify_regexp)#re.compile('^([\d\w]+):([\d\w]+)$')
        self.multicast_groups = multicast_groups
        
        self.router = {}
        self.router["Register"] = self.publish_service_wrapper
        self.router["Publish"] = self.publish_service_wrapper
        self.router["Unpublish"] = self.unpublish_service_wrapper
        self.router["Request-token"] = self.request_token_service_wrapper

    def startProtocol(self):
        """
        Starts the binding and adds an entry in the log file
        """
        logging.info("Starting binding")

    def connectionMade(self):
        print("A connection was made!")

    def dataReceived(self, datagram):
        """
        Receives datagrams from bindings, and verifies the `Command` field.
        It emits a response based on the value (if necessary)

        :param bytes datagram: The byte stream with the message
        """
        
             
        datos = datagram.decode('utf-8')
        logging.debug("Datagram received: %s" % datos)
    
        try:
            datos_dict = json.loads(datos)
        except ValueError:
            self.write_error("Malformed JSON")
            logging.debug("Malformed JSON")
            return
        
        if datos_dict.get("Command", None) is None:
            self.write_error("Missing command")
            logging.debug("Missing command")
            return
        
        command = datos_dict["Command"]
        
        method = self.router.get(command, self.unknown_command_handler)

        method(command, datos_dict.get("Args", {}))
 
    def request_token(self, uid):
        pw_user = pwd.getpwuid(uid)
        if pw_user == None:
            self.write_error("User not found")
            return

        polo_dir = os.path.join(pw_user.pw_dir, ".polo")
        
        if not os.path.exists(polo_dir):
            os.mkdir(polo_dir)
            os.chown(polo_dir, pw_user.pw_uid, pw_user.pw_gid)

        if not os.path.isfile(os.path.join(polo_dir, "token")):
            try:
                f = open(os.path.join(polo_dir, "token"), 'wb')
                os.fchmod(f.fileno(), stat.S_IRUSR | stat.S_IWUSR | stat.S_IRUSR)
                os.fchown(f.fileno(), pw_user.pw_uid, pw_user.pw_gid)
                f.write(tokenprovider.create_token(uid, self.secret))
                f.close()
            except Exception as e:
                self.write_error(str(e))
                return
            self.write_ok(0)
        else:
            self.write_ok(1)

    def write_ok(self, status):
        """
        Creates and sends an OK message

{'fraction_non_alphanumeric': 0.08772440562833576, 'fraction_numerical': 0.0007763221737020863, 'mean_word_length': 2.4250581588567632, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3213903', 'n_tokens_mistral': 2997, 'n_tokens_neox': 2894, 'n_words': 820}