Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
adenjonah committed May 15, 2024
2 parents c48305c + fe4edd1 commit b56dac8
Show file tree
Hide file tree
Showing 20 changed files with 2,313 additions and 70 deletions.
Binary file modified __pycache__/server.cpython-312.pyc
Binary file not shown.
16 changes: 16 additions & 0 deletions myenv/lib/python3.12/site-packages/multipart/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This is the canonical package information.
__author__ = "Andrew Dunham"
__license__ = "Apache"
__copyright__ = "Copyright (c) 2012-2013, Andrew Dunham"
__version__ = "0.0.9"

from .multipart import FormParser, MultipartParser, OctetStreamParser, QuerystringParser, create_form_parser, parse_form

__all__ = (
"FormParser",
"MultipartParser",
"OctetStreamParser",
"QuerystringParser",
"create_form_parser",
"parse_form",
)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
171 changes: 171 additions & 0 deletions myenv/lib/python3.12/site-packages/multipart/decoders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import base64
import binascii

from .exceptions import DecodeError


class Base64Decoder:
"""This object provides an interface to decode a stream of Base64 data. It
is instantiated with an "underlying object", and whenever a write()
operation is performed, it will decode the incoming data as Base64, and
call write() on the underlying object. This is primarily used for decoding
form data encoded as Base64, but can be used for other purposes::
from multipart.decoders import Base64Decoder
fd = open("notb64.txt", "wb")
decoder = Base64Decoder(fd)
try:
decoder.write("Zm9vYmFy") # "foobar" in Base64
decoder.finalize()
finally:
decoder.close()
# The contents of "notb64.txt" should be "foobar".
This object will also pass all finalize() and close() calls to the
underlying object, if the underlying object supports them.
Note that this class maintains a cache of base64 chunks, so that a write of
arbitrary size can be performed. You must call :meth:`finalize` on this
object after all writes are completed to ensure that all data is flushed
to the underlying object.
:param underlying: the underlying object to pass writes to
"""

def __init__(self, underlying):
self.cache = bytearray()
self.underlying = underlying

def write(self, data):
"""Takes any input data provided, decodes it as base64, and passes it
on to the underlying object. If the data provided is invalid base64
data, then this method will raise
a :class:`multipart.exceptions.DecodeError`
:param data: base64 data to decode
"""

# Prepend any cache info to our data.
if len(self.cache) > 0:
data = self.cache + data

# Slice off a string that's a multiple of 4.
decode_len = (len(data) // 4) * 4
val = data[:decode_len]

# Decode and write, if we have any.
if len(val) > 0:
try:
decoded = base64.b64decode(val)
except binascii.Error:
raise DecodeError("There was an error raised while decoding base64-encoded data.")

self.underlying.write(decoded)

# Get the remaining bytes and save in our cache.
remaining_len = len(data) % 4
if remaining_len > 0:
self.cache = data[-remaining_len:]
else:
self.cache = b""

# Return the length of the data to indicate no error.
return len(data)

def close(self):
"""Close this decoder. If the underlying object has a `close()`
method, this function will call it.
"""
if hasattr(self.underlying, "close"):
self.underlying.close()

def finalize(self):
"""Finalize this object. This should be called when no more data
should be written to the stream. This function can raise a
:class:`multipart.exceptions.DecodeError` if there is some remaining
data in the cache.
If the underlying object has a `finalize()` method, this function will
call it.
"""
if len(self.cache) > 0:
raise DecodeError(
"There are %d bytes remaining in the Base64Decoder cache when finalize() is called" % len(self.cache)
)

if hasattr(self.underlying, "finalize"):
self.underlying.finalize()

def __repr__(self):
return f"{self.__class__.__name__}(underlying={self.underlying!r})"


class QuotedPrintableDecoder:
"""This object provides an interface to decode a stream of quoted-printable
data. It is instantiated with an "underlying object", in the same manner
as the :class:`multipart.decoders.Base64Decoder` class. This class behaves
in exactly the same way, including maintaining a cache of quoted-printable
chunks.
:param underlying: the underlying object to pass writes to
"""

def __init__(self, underlying):
self.cache = b""
self.underlying = underlying

def write(self, data):
"""Takes any input data provided, decodes it as quoted-printable, and
passes it on to the underlying object.
:param data: quoted-printable data to decode
"""
# Prepend any cache info to our data.
if len(self.cache) > 0:
data = self.cache + data

# If the last 2 characters have an '=' sign in it, then we won't be
# able to decode the encoded value and we'll need to save it for the
# next decoding step.
if data[-2:].find(b"=") != -1:
enc, rest = data[:-2], data[-2:]
else:
enc = data
rest = b""

# Encode and write, if we have data.
if len(enc) > 0:
self.underlying.write(binascii.a2b_qp(enc))

# Save remaining in cache.
self.cache = rest
return len(data)

def close(self):
"""Close this decoder. If the underlying object has a `close()`
method, this function will call it.
"""
if hasattr(self.underlying, "close"):
self.underlying.close()

def finalize(self):
"""Finalize this object. This should be called when no more data
should be written to the stream. This function will not raise any
exceptions, but it may write more data to the underlying object if
there is data remaining in the cache.
If the underlying object has a `finalize()` method, this function will
call it.
"""
# If we have a cache, write and then remove it.
if len(self.cache) > 0:
self.underlying.write(binascii.a2b_qp(self.cache))
self.cache = b""

# Finalize our underlying stream.
if hasattr(self.underlying, "finalize"):
self.underlying.finalize()

def __repr__(self):
return f"{self.__class__.__name__}(underlying={self.underlying!r})"
34 changes: 34 additions & 0 deletions myenv/lib/python3.12/site-packages/multipart/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class FormParserError(ValueError):
"""Base error class for our form parser."""


class ParseError(FormParserError):
"""This exception (or a subclass) is raised when there is an error while
parsing something.
"""

#: This is the offset in the input data chunk (*NOT* the overall stream) in
#: which the parse error occurred. It will be -1 if not specified.
offset = -1


class MultipartParseError(ParseError):
"""This is a specific error that is raised when the MultipartParser detects
an error while parsing.
"""


class QuerystringParseError(ParseError):
"""This is a specific error that is raised when the QuerystringParser
detects an error while parsing.
"""


class DecodeError(ParseError):
"""This exception is raised when there is a decoding error - for example
with the Base64Decoder or QuotedPrintableDecoder.
"""


class FileError(FormParserError, OSError):
"""Exception class for problems with the File class."""
Loading

0 comments on commit b56dac8

Please sign in to comment.