Ejemplo n.º 1
0
class OFXHeaderV2(OFXHeaderBase):
    """Header for OFX version 2"""

    ofxheader = Types.OneOf(200)
    version = Types.OneOf(200, 201, 202, 203, 210, 211, 220)
    security = Types.OneOf("NONE", "TYPE1")
    oldfileuid = Types.String(36)
    newfileuid = Types.String(36)

    regex = re.compile(
        r"""<\?OFX\s+
                       OFXHEADER=\"(?P<ofxheader>\d+)\"\s+
                       VERSION=\"(?P<version>\d+)\"\s+
                       SECURITY=\"(?P<security>[\w]+)\"\s+
                       OLDFILEUID=\"(?P<oldfileuid>[\w-]+)\"\s+
                       NEWFILEUID=\"(?P<newfileuid>[\w-]+)\"\s*
                       \?>\s*""",
        re.VERBOSE,
    )
    # UTF-8 encoding required by OFXv2 spec; explicitly listed here to
    # conform to v1 class interface above.
    codec = "utf_8"

    def __init__(
        self,
        version: Union[int, str],
        ofxheader: Optional[int] = None,
        security: Optional[str] = None,
        oldfileuid: Optional[str] = None,
        newfileuid: Optional[str] = None,
    ):
        try:
            self.version = int(version)
            self.ofxheader = int(ofxheader or 200)
            self.security = security or "NONE"
            self.oldfileuid = oldfileuid or "NONE"
            self.newfileuid = newfileuid or "NONE"
        except ValueError as err:
            raise OFXHeaderError(f"Invalid OFX header - {err.args[0]}")

    def __str__(self) -> str:
        # XML header
        xml_decl = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
        fields = (
            ("OFXHEADER", str(self.ofxheader)),
            ("VERSION", str(self.version)),
            ("SECURITY", self.security),
            ("OLDFILEUID", self.oldfileuid),
            ("NEWFILEUID", self.newfileuid),
        )
        attrs = ["=".join((attr, '"{}"'.format(val))) for attr, val in fields]
        ofx_decl = "<?OFX {}?>".format(" ".join(attrs))
        return "\r\n".join((xml_decl, ofx_decl, ""))
Ejemplo n.º 2
0
    class v2(object):
        ofxheader = Types.OneOf(200, )
        version = Types.OneOf(200, 201, 202, 203, 210, 211, 220)
        security = Types.OneOf('NONE', 'TYPE1')
        oldfileuid = Types.String(36)
        newfileuid = Types.String(36)

        regex = re.compile(
            r"""<\?OFX\s+
                           OFXHEADER=\"(?P<ofxheader>\d+)\"\s+
                           VERSION=\"(?P<version>\d+)\"\s+
                           SECURITY=\"(?P<security>[\w]+)\"\s+
                           OLDFILEUID=\"(?P<oldfileuid>[\w-]+)\"\s+
                           NEWFILEUID=\"(?P<newfileuid>[\w-]+)\"\s*
                           \?>\s*""", re.VERBOSE)

        codec = 'utf8'

        def __init__(self,
                     version,
                     xmlversion=None,
                     encoding=None,
                     standalone=None,
                     ofxheader=None,
                     security=None,
                     oldfileuid=None,
                     newfileuid=None):
            try:
                self.version = int(version)
                self.ofxheader = int(ofxheader or 200)
                self.security = security or 'NONE'
                self.oldfileuid = oldfileuid or 'NONE'
                self.newfileuid = newfileuid or 'NONE'
            except ValueError as e:
                raise OFXHeaderError('Invalid OFX header - %s' % e.args[0])

        def __str__(self):
            # XML header
            xml_decl = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
            fields = (
                ('OFXHEADER', str(self.ofxheader)),
                ('VERSION', str(self.version)),
                ('SECURITY', self.security),
                ('OLDFILEUID', self.oldfileuid),
                ('NEWFILEUID', self.newfileuid),
            )
            attrs = ['='.join((attr, '"%s"' % val)) for attr, val in fields]
            ofx_decl = '<?OFX %s?>' % ' '.join(attrs)
            return '\r\n'.join((xml_decl, ofx_decl))
Ejemplo n.º 3
0
    class v1(object):
        ofxheader = Types.OneOf(100,)
        data = Types.OneOf('OFXSGML',)
        version = Types.OneOf(102, 103, 151, 160)
        security = Types.OneOf('NONE', 'TYPE1')
        encoding = Types.OneOf('USASCII','UNICODE', 'UTF-8')
        charset = Types.OneOf('ISO-8859-1', '1252', 'NONE')
        compression = Types.OneOf('NONE',)
        oldfileuid = Types.String(36)
        newfileuid = Types.String(36)

        regex = re.compile(r"""\s*
                                OFXHEADER:(?P<OFXHEADER>\d+)\s+
                                DATA:(?P<DATA>[A-Z]+)\s+
                                VERSION:(?P<VERSION>\d+)\s+
                                SECURITY:(?P<SECURITY>[\w]+)\s+
                                ENCODING:(?P<ENCODING>[A-Z]+)\s+
                                CHARSET:(?P<CHARSET>\w+)\s+
                                COMPRESSION:(?P<COMPRESSION>[A-Z]+)\s+
                                OLDFILEUID:(?P<OLDFILEUID>[\w-]+)\s+
                                NEWFILEUID:(?P<NEWFILEUID>[\w-]+)\s+
                                """, re.VERBOSE)

        def __init__(self, version, ofxheader=None, data=None, security=None,
                     encoding=None, charset=None, compression=None,
                     oldfileuid=None, newfileuid=None):
            try:
                self.ofxheader = int(ofxheader or 100)
                self.data = data or 'OFXSGML'
                self.version = int(version)
                self.security = security or 'NONE'
                self.encoding = encoding or 'USASCII'
                self.charset = charset or 'NONE'
                self.compression = compression or 'NONE'
                self.oldfileuid = oldfileuid or 'NONE'
                self.newfileuid = newfileuid or 'NONE'
            except ValueError as e:
                raise OFXHeaderError('Invalid OFX header - %s' % e.args[0])

        def __str__(self):
            # Flat text header
            fields = (  ('OFXHEADER', str(self.ofxheader)),
                      ('DATA', self.data),
                      ('VERSION', str(self.version)),
                      ('SECURITY', self.security),
                      ('ENCODING', self.encoding),
                      ('CHARSET', self.charset),
                      ('COMPRESSION', self.compression),
                      ('OLDFILEUID', self.oldfileuid),
                      ('NEWFILEUID', self.newfileuid),
                     )
            lines = [':'.join(field) for field in fields]
            lines = '\r\n'.join(lines)
            lines += '\r\n'*2
            return lines
Ejemplo n.º 4
0
    class v2(object):
        xmlversion = Types.OneOf('1.0',)
        encoding = Types.OneOf('UTF-8',)
        standalone = Types.OneOf('no',)
        ofxheader = Types.OneOf(200,)
        version = Types.OneOf(200, 201, 202, 203, 210, 211, 220)
        security = Types.OneOf('NONE', 'TYPE1')
        oldfileuid = Types.String(36)
        newfileuid = Types.String(36)

        regex = re.compile(r"""(<\?xml\s+
                           (version=\"(?P<XMLVERSION>[\d.]+)\")?\s*
                           (encoding=\"(?P<ENCODING>[\w-]+)\")?\s*
                           (standalone=\"(?P<STANDALONE>[\w]+)\")?\s*
                           \?>)\s*
                           <\?OFX\s+
                           OFXHEADER=\"(?P<OFXHEADER>\d+)\"\s+
                           VERSION=\"(?P<VERSION>\d+)\"\s+
                           SECURITY=\"(?P<SECURITY>[\w]+)\"\s+
                           OLDFILEUID=\"(?P<OLDFILEUID>[\w-]+)\"\s+
                           NEWFILEUID=\"(?P<NEWFILEUID>[\w-]+)\"\s*
                           \?>\s*""", re.VERBOSE)

        def __init__(self, version, xmlversion=None, encoding=None,
                     standalone=None, ofxheader=None, security=None,
                     oldfileuid=None, newfileuid=None):
            try:
                self.version = int(version)
                self.xmlversion = xmlversion or '1.0'
                self.encoding = encoding or 'UTF-8'
                self.standalone = standalone or 'no'
                self.ofxheader = int(ofxheader or 200)
                self.security = security or 'NONE'
                self.oldfileuid = oldfileuid or 'NONE'
                self.newfileuid = newfileuid or 'NONE'
            except ValueError as e:
                raise OFXHeaderError('Invalid OFX header - %s' % e.args[0])

        def __str__(self):
            # XML header
            xmlfields = (('version', self.xmlversion),
                         ('encoding', self.encoding),
                         ('standalone', self.standalone),
                        )
            xmlattrs = ['='.join((attr, '"%s"' %val)) for attr,val in xmlfields]
            xml_decl = '<?xml %s?>' % ' '.join(xmlattrs)
            fields = (('OFXHEADER', str(self.ofxheader)),
                      ('VERSION', str(self.version)),
                      ('SECURITY', self.security),
                      ('OLDFILEUID', self.oldfileuid),
                      ('NEWFILEUID', self.newfileuid),
                     )
            attrs = ['='.join((attr, '"%s"' %val)) for attr,val in fields]
            ofx_decl = '<?OFX %s?>' % ' '.join(attrs)
            return '\r\n'.join((xml_decl, ofx_decl))
Ejemplo n.º 5
0
class OFXHeaderV1(OFXHeaderBase):
    """Header for OFX version 1"""

    ofxheader = Types.OneOf(100)
    data = Types.OneOf("OFXSGML")
    version = Types.OneOf(102, 103, 151, 160)
    security = Types.OneOf("NONE", "TYPE1")
    encoding = Types.OneOf("USASCII", "UNICODE", "UTF-8")
    # DRY - mapping of CHARSET: codec used below in codec()
    #  https://docs.python.org/3/library/codecs.html#standard-encodings
    codecs = {"ISO-8859-1": "latin_1", "1252": "cp1252", "NONE": "utf_8"}
    charset = Types.OneOf(*codecs.keys())
    compression = Types.OneOf("NONE")
    oldfileuid = Types.String(36)
    newfileuid = Types.String(36)

    # 1) Although the OFX spec requires formatting OFX headers as
    # "HEADER:VALUE", apparently some FIs are inserting whitespace between
    # the colon and the header value.  We'll allow this noncompliant
    # format, because it's pretty harmless.
    #
    # 2) The OFXv1 spec doesn't require line breaks between header fields,
    # and # apparently some FIs are sending OFX files (including header)
    # all as one line.
    #
    # 3) The OFXv1 spec requires a line break between the OFX header and
    # the SGML data, but some FIs disregard this requirement.  We allow it.
    # Therefore the regex doesn't capture whitespace at the end of the header;
    # instead ``parse_header()`` strips whitespace from the start of the data.
    regex = re.compile(
        r"""\s*
            OFXHEADER:\s*(?P<OFXHEADER>\d+)\s*
            DATA:\s*(?P<DATA>[A-Z]+)\s*
            VERSION:\s*(?P<VERSION>\d+)\s*
            SECURITY:\s*(?P<SECURITY>[\w]+)\s*
            ENCODING:\s*(?P<ENCODING>[A-Z0-9-]+)\s*
            CHARSET:\s*(?P<CHARSET>[\w-]+)\s*
            COMPRESSION:\s*(?P<COMPRESSION>[A-Z]+)\s*
            OLDFILEUID:\s*(?P<OLDFILEUID>[\w-]+)\s*
            NEWFILEUID:\s*(?P<NEWFILEUID>[\w-]+)
        """,
        re.VERBOSE,
    )

    @property
    def codec(self) -> str:
        """
        String codec used to decode OFX message body.

        Maps from OFX character set name to Python codec name.
        """
        return self.codecs[self.charset]

    def __init__(
        self,
        version: Union[int, str],
        ofxheader: Optional[int] = None,
        data: Optional[str] = None,
        security: Optional[str] = None,
        encoding: Optional[str] = None,
        charset: Optional[str] = None,
        compression: Optional[str] = None,
        oldfileuid: Optional[str] = None,
        newfileuid: Optional[str] = None,
    ):
        try:
            self.ofxheader = int(ofxheader or 100)
            self.data = data or "OFXSGML"
            self.version = int(version)
            self.security = security or "NONE"
            self.encoding = encoding or "USASCII"
            self.charset = charset or "NONE"
            self.compression = compression or "NONE"
            self.oldfileuid = oldfileuid or "NONE"
            self.newfileuid = newfileuid or "NONE"
        except ValueError as err:
            raise OFXHeaderError(f"Invalid OFX header - {err.args[0]}")

    def __str__(self) -> str:
        # Flat text header
        fields = (
            ("OFXHEADER", str(self.ofxheader)),
            ("DATA", self.data),
            ("VERSION", str(self.version)),
            ("SECURITY", self.security),
            ("ENCODING", self.encoding),
            ("CHARSET", self.charset),
            ("COMPRESSION", self.compression),
            ("OLDFILEUID", self.oldfileuid),
            ("NEWFILEUID", self.newfileuid),
        )
        lines = "\r\n".join([":".join(field) for field in fields])
        # More recent versions of the OFXv1 spec require newlines to demarcate
        # the message header from the message body
        lines += "\r\n" * 2
        return lines
Ejemplo n.º 6
0
class OFXHeaderV1(OFXHeaderBase):
    """ Header for OFX version 1 """

    ofxheader = Types.OneOf(100)
    data = Types.OneOf("OFXSGML")
    version = Types.OneOf(102, 103, 151, 160)
    security = Types.OneOf("NONE", "TYPE1")
    encoding = Types.OneOf("USASCII", "UNICODE", "UTF-8")
    # DRY - mapping of CHARSET: codec used below in codec()
    #  https://docs.python.org/3/library/codecs.html#standard-encodings
    codecs = {"ISO-8859-1": "latin_1", "1252": "cp1252", "NONE": "utf_8"}
    charset = Types.OneOf(*codecs.keys())
    compression = Types.OneOf("NONE")
    oldfileuid = Types.String(36)
    newfileuid = Types.String(36)

    regex = re.compile(
        r"""\s*
            OFXHEADER:(?P<OFXHEADER>\d+)\s+
            DATA:(?P<DATA>[A-Z]+)\s+
            VERSION:(?P<VERSION>\d+)\s+
            SECURITY:(?P<SECURITY>[\w]+)\s+
            ENCODING:(?P<ENCODING>[A-Z0-9-]+)\s+
            CHARSET:(?P<CHARSET>[\w-]+)\s+
            COMPRESSION:(?P<COMPRESSION>[A-Z]+)\s+
            OLDFILEUID:(?P<OLDFILEUID>[\w-]+)\s+
            NEWFILEUID:(?P<NEWFILEUID>[\w-]+)\s+
        """,
        re.VERBOSE,
    )

    @property
    def codec(self):
        """
        String codec used to decode OFX message body.

        Maps from OFX character set name to Python codec name.
        """
        return self.codecs[self.charset]

    def __init__(
        self,
        version,
        ofxheader=None,
        data=None,
        security=None,
        encoding=None,
        charset=None,
        compression=None,
        oldfileuid=None,
        newfileuid=None,
    ):
        try:
            self.ofxheader = int(ofxheader or 100)
            self.data = data or "OFXSGML"
            self.version = int(version)
            self.security = security or "NONE"
            self.encoding = encoding or "USASCII"
            self.charset = charset or "NONE"
            self.compression = compression or "NONE"
            self.oldfileuid = oldfileuid or "NONE"
            self.newfileuid = newfileuid or "NONE"
        except ValueError as err:
            raise OFXHeaderError("Invalid OFX header - %s" % err.args[0])

    def __str__(self):
        # Flat text header
        fields = (
            ("OFXHEADER", str(self.ofxheader)),
            ("DATA", self.data),
            ("VERSION", str(self.version)),
            ("SECURITY", self.security),
            ("ENCODING", self.encoding),
            ("CHARSET", self.charset),
            ("COMPRESSION", self.compression),
            ("OLDFILEUID", self.oldfileuid),
            ("NEWFILEUID", self.newfileuid),
        )
        lines = [":".join(field) for field in fields]
        lines = "\r\n".join(lines)
        # More recent versions of the OFXv1 spec require newlines to demarcate
        # the message header from the message body
        lines += "\r\n" * 2
        return lines