Пример #1
0
    def validate(self):
        """Validate arguments, raises UrlArgsValidationError if something is wrong"""

        args = self.request.args

        if len(args) == 0:
            raise UrlArgsValidationError(
                'Mandatory arguments not found, please refer to the HTTPAPI specifications.')

        for arg in args:
            # Check for unknown args
            if arg not in self.fields:
                raise UrlArgsValidationError("Argument [%s] is unknown." % arg)

            # Validate known args and check for mandatory fields
            for field in self.fields:
                fieldData = self.fields[field]

                if field in args:
                    if isinstance(args[field][0], dict) or isinstance(args[field][0], list):
                        continue  # Todo check structure of dict/list
                    elif isinstance(args[field][0], int) or isinstance(args[field][0], float):
                        value = str(args[field][0])
                    else:
                        value = args[field][0]

                    # Validate known args
                    if ('pattern' in self.fields[field]
                        and self.fields[field]['pattern'].match(value) is None):
                        raise UrlArgsValidationError("Argument [%s] has an invalid value: [%s]." % (
                            field, value))
                elif not fieldData['optional']:
                    raise UrlArgsValidationError("Mandatory argument [%s] is not found." % field)

        return True
Пример #2
0
    def validate(self):
        """Validate arguments, raises UrlArgsValidationError if something is wrong"""

        args = self.request.args

        if len(args) == 0:
            raise UrlArgsValidationError(
                'Mandatory arguments not found, please refer to the HTTPAPI specifications.'
            )

        for arg in args:
            # Check for unknown args
            if arg not in self.fields:
                # we probably just should drop extraneous args rather than throwing an error...
                raise UrlArgsValidationError(b"Argument [%s] is unknown." %
                                             arg)

            # Validate known args and check for mandatory fields
            for field in self.fields:
                fieldData = self.fields[field]

                if field in args:
                    if isinstance(args[field][0], dict) or isinstance(
                            args[field][0], list):
                        continue  # Todo check structure of dict/list
                    elif isinstance(args[field][0], int) or isinstance(
                            args[field][0], float):
                        value = str(args[field][0]).encode()
                    elif isinstance(args[field][0], str):
                        value = args[field][0].encode()
                    else:
                        value = args[field][0]

                    # Validate known args
                    # print(f'Validating field {field} of value {value}')
                    if ('pattern' in self.fields[field]
                            and self.fields[field]['pattern'].match(value) is
                            None):
                        raise UrlArgsValidationError(
                            b"Argument [%s] has an invalid value: [%s]." %
                            (field, value))
                elif not fieldData['optional']:
                    raise UrlArgsValidationError(
                        b"Mandatory argument [%s] is not found." % field)

        return True
Пример #3
0
def hex2bin(hex_content):
    """Convert hex-content back to binary data, raise a UrlArgsValidationError on failure"""

    try:
        return binascii.unhexlify(hex_content)
    except Exception as e:
        raise UrlArgsValidationError("Invalid hex-content data: '%s'" %
                                     hex_content)
Пример #4
0
    def render(self, request):
        """
        /rate request processing

        Note: This method will indicate the rate of the message once sent
        """

        self.log.debug("Rendering /rate response with args: %s from %s",
                       request.args, request.getClientIP())
        request.responseHeaders.addRawHeader(b"content-type",
                                             b"application/json")
        response = {'return': None, 'status': 200}

        self.stats.inc('request_count')
        self.stats.set('last_request_at', datetime.now())

        try:
            # Validation (must be almost the same params as /send service)
            fields = {
                'to': {
                    'optional': False,
                    'pattern': re.compile(r'^\+{0,1}\d+$')
                },
                'from': {
                    'optional': True
                },
                'coding': {
                    'optional': True,
                    'pattern':
                    re.compile(r'^(0|1|2|3|4|5|6|7|8|9|10|13|14){1}$')
                },
                'username': {
                    'optional': False,
                    'pattern': re.compile(r'^.{1,15}$')
                },
                'password': {
                    'optional': False,
                    'pattern': re.compile(r'^.{1,8}$')
                },
                # Priority validation pattern can be validated/filtered further more
                # through HttpAPICredentialValidator
                'priority': {
                    'optional': True,
                    'pattern': re.compile(r'^[0-3]$')
                },
                # Validity period validation pattern can be validated/filtered further more
                # through HttpAPICredentialValidator
                'validity-period': {
                    'optional': True,
                    'pattern': re.compile(r'^\d+$')
                },
                'tags': {
                    'optional': True,
                    'pattern': re.compile(r'^([-a-zA-Z0-9,])*$')
                },
                'content': {
                    'optional': True
                },
                'hex-content': {
                    'optional': True
                },
            }

            # Default coding is 0 when not provided
            if 'coding' not in request.args:
                request.args['coding'] = ['0']

            # Content is optional, defaults to empty content string
            if 'hex-content' not in request.args and 'content' not in request.args:
                request.args['content'] = ['']

            # Make validation
            v = UrlArgsValidator(request, fields)
            v.validate()

            # Check if have content --OR-- hex-content
            # @TODO: make this inside UrlArgsValidator !
            if 'content' in request.args and 'hex-content' in request.args:
                raise UrlArgsValidationError(
                    "content and hex-content cannot be used both in same request."
                )

            # Continue routing in a separate thread
            reactor.callFromThread(self.route_routable, request=request)
        except Exception as e:
            self.log.error("Error: %s", e)

            if hasattr(e, 'code'):
                response = {'return': e.message, 'status': e.code}
            else:
                response = {'return': "Unknown error: %s" % e, 'status': 500}

            self.log.debug("Returning %s to %s.", response,
                           request.getClientIP())

            # Return message
            if response['return'] is None:
                response['return'] = 'System error'
                request.setResponseCode(500)
            else:
                request.setResponseCode(response['status'])
            return json.dumps(response['return'])
        else:
            return NOT_DONE_YET
Пример #5
0
    def render(self, request):
        """
        /send request processing

        Note: This method MUST behave exactly like jasmin.protocols.smpp.factory.SMPPServerFactory.submit_sm_event
        """

        self.log.debug("Rendering /send response with args: %s from %s",
                       request.args, request.getClientIP())
        request.responseHeaders.addRawHeader(b"content-type", b"text/plain")
        response = {'return': None, 'status': 200}

        self.stats.inc('request_count')
        self.stats.set('last_request_at', datetime.now())

        # updated_request will be filled with default values where request will never get modified
        # updated_request is used for sending the SMS, request is just kept as an original request object
        updated_request = request

        try:
            # Validation (must have almost the same params as /rate service)
            fields = {
                'to': {
                    'optional': False,
                    'pattern': re.compile(r'^\+{0,1}\d+$')
                },
                'from': {
                    'optional': True
                },
                'coding': {
                    'optional': True,
                    'pattern':
                    re.compile(r'^(0|1|2|3|4|5|6|7|8|9|10|13|14){1}$')
                },
                'username': {
                    'optional': False,
                    'pattern': re.compile(r'^.{1,15}$')
                },
                'password': {
                    'optional': False,
                    'pattern': re.compile(r'^.{1,8}$')
                },
                # Priority validation pattern can be validated/filtered further more
                # through HttpAPICredentialValidator
                'priority': {
                    'optional': True,
                    'pattern': re.compile(r'^[0-3]$')
                },
                'sdt': {
                    'optional':
                    True,
                    'pattern':
                    re.compile(
                        r'^\d{2}\d{2}\d{2}\d{2}\d{2}\d{2}\d{1}\d{2}(\+|-|R)$')
                },
                # Validity period validation pattern can be validated/filtered further more
                # through HttpAPICredentialValidator
                'validity-period': {
                    'optional': True,
                    'pattern': re.compile(r'^\d+$')
                },
                'dlr': {
                    'optional': False,
                    'pattern': re.compile(r'^(yes|no)$')
                },
                'dlr-url': {
                    'optional': True,
                    'pattern': re.compile(r'^(http|https)\://.*$')
                },
                # DLR Level validation pattern can be validated/filtered further more
                # through HttpAPICredentialValidator
                'dlr-level': {
                    'optional': True,
                    'pattern': re.compile(r'^[1-3]$')
                },
                'dlr-method': {
                    'optional': True,
                    'pattern': re.compile(r'^(get|post)$', re.IGNORECASE)
                },
                'tags': {
                    'optional': True,
                    'pattern': re.compile(r'^([-a-zA-Z0-9,])*$')
                },
                'content': {
                    'optional': True
                },
                'hex-content': {
                    'optional': True
                },
                'custom_tlvs': {
                    'optional': True
                }
            }

            if updated_request.getHeader('content-type') == 'application/json':
                json_body = updated_request.content.read()
                json_data = json.loads(json_body)
                for key, value in json_data.items():
                    # Make the values look like they came from form encoding all surrounded by [ ]
                    if isinstance(value, unicode):
                        value = value.encode()

                    updated_request.args[key.encode()] = [value]

            # If no custom TLVs present, defaujlt to an [] which will be passed down to SubmitSM
            if 'custom_tlvs' not in updated_request.args:
                updated_request.args['custom_tlvs'] = [[]]

            # Default coding is 0 when not provided
            if 'coding' not in updated_request.args:
                updated_request.args['coding'] = ['0']

            # Set default for undefined updated_request.arguments
            if 'dlr-url' in updated_request.args or 'dlr-level' in updated_request.args:
                updated_request.args['dlr'] = ['yes']
            if 'dlr' not in updated_request.args:
                # Setting DLR updated_request to 'no'
                updated_request.args['dlr'] = ['no']

            # Set default values
            if updated_request.args['dlr'][0] == 'yes':
                if 'dlr-level' not in updated_request.args:
                    # If DLR is requested and no dlr-level were provided, assume minimum level (1)
                    updated_request.args['dlr-level'] = [1]
                if 'dlr-method' not in updated_request.args:
                    # If DLR is requested and no dlr-method were provided, assume default (POST)
                    updated_request.args['dlr-method'] = ['POST']

            # DLR method must be uppercase
            if 'dlr-method' in updated_request.args:
                updated_request.args['dlr-method'][0] = updated_request.args[
                    'dlr-method'][0].upper()

            # Make validation
            v = UrlArgsValidator(updated_request, fields)
            v.validate()

            # Check if have content --OR-- hex-content
            # @TODO: make this inside UrlArgsValidator !
            if 'content' not in request.args and 'hex-content' not in request.args:
                raise UrlArgsValidationError(
                    "content or hex-content not present.")
            elif 'content' in request.args and 'hex-content' in request.args:
                raise UrlArgsValidationError(
                    "content and hex-content cannot be used both in same request."
                )

            # Continue routing in a separate thread
            reactor.callFromThread(self.route_routable,
                                   updated_request=updated_request)
        except Exception as e:
            self.log.error("Error: %s", e)

            if hasattr(e, 'code'):
                response = {'return': e.message, 'status': e.code}
            else:
                response = {'return': "Unknown error: %s" % e, 'status': 500}

            self.log.debug("Returning %s to %s.", response,
                           updated_request.getClientIP())
            updated_request.setResponseCode(response['status'])

            return 'Error "%s"' % response['return']
        else:
            return NOT_DONE_YET