def __init__(self, config): if not 'host' in config: raise MailConfigurationException('No server configured for SMTP') self.host = native(config.get('host')) self.tls = config.get('tls', 'optional') self.certfile = config.get('certfile', None) self.keyfile = config.get('keyfile', None) self.port = int(config.get('port', 465 if self.tls == 'ssl' else 25)) self.local_hostname = native(config.get('local_hostname', '')) or None self.username = native(config.get('username', '')) or None self.password = native(config.get('password', '')) or None self.timeout = config.get('timeout', None) if self.timeout: self.timeout = int(self.timeout) self.debug = boolean(config.get('debug', False)) self.pipeline = config.get('pipeline', None) if self.pipeline is not None: self.pipeline = int(self.pipeline) self.connection = None self.sent = 0
def __set__(self, obj, value): value = native(value) if value is not None else '' if ';' not in value: original = native(super(ContentType, self).__get__(obj, None), 'ascii') if ';' in original: value += ';' + original.split(';', 1)[1] super(ContentType, self).__set__(obj, bytestring(value, 'ascii'))
def _build_date_header_string(self, date_value): """Gets the date_value (may be None, basestring, float or datetime.datetime instance) and returns a valid date string as per RFC 2822.""" if isinstance(date_value, datetime): date_value = time.mktime(date_value.timetuple()) if not isinstance(date_value, basestring): date_value = formatdate(date_value, localtime=True) # Encode it here to avoid this: # Date: =?utf-8?q?Sat=2C_01_Sep_2012_13=3A08=3A29_-0300?= return native(date_value)
def __get__(self, obj, cls): content_type = super(Charset, self).__get__(obj, cls) if not content_type: return None charset_match = CHARSET_RE.search(native(content_type, 'ascii')) if charset_match: result = charset_match.group(1).strip('"').strip() return result return None
def __init__(self, config): self.host = native(config.get('host', '127.0.0.1')) self.tls = config.get('tls', 'optional') self.certfile = config.get('certfile', None) self.keyfile = config.get('keyfile', None) self.port = int(config.get('port', 465 if self.tls == 'ssl' else 25)) self.local_hostname = native(config.get('local_hostname', '')) or None self.username = native(config.get('username', '')) or None self.password = native(config.get('password', '')) or None self.timeout = config.get('timeout', None) if self.timeout: self.timeout = int(self.timeout) self.debug = boolean(config.get('debug', False)) self.pipeline = config.get('pipeline', None) if self.pipeline not in (None, True, False): self.pipeline = int(self.pipeline) self.connection = None self.sent = 0
def __init__(self, config): self.host = native(config.get("host", "127.0.0.1")) self.tls = config.get("tls", "optional") self.certfile = config.get("certfile", None) self.keyfile = config.get("keyfile", None) self.port = int(config.get("port", 465 if self.tls == "ssl" else 25)) self.local_hostname = native(config.get("local_hostname", "")) or None self.username = native(config.get("username", "")) or None self.password = native(config.get("password", "")) or None self.timeout = config.get("timeout", None) if self.timeout: self.timeout = int(self.timeout) self.debug = boolean(config.get("debug", False)) self.pipeline = config.get("pipeline", None) if self.pipeline not in (None, True, False): self.pipeline = int(self.pipeline) self.connection = None self.sent = 0
def __set__(self, obj, value): if not value: self.__delete__(obj) return value = native(value) content_type = native(super(Charset, self).__get__(obj, None), 'ascii') charset_match = CHARSET_RE.search(content_type) if content_type else None if charset_match: content_type = content_type[:charset_match.start(1)] + value + content_type[charset_match.end(1):] # TODO: Examine what action browsers take. # elif ';' in content_type: # content_type += ', charset="%s"' % charset elif content_type: content_type += '; charset="' + value + '"' else: content_type = '; charset="' + value + '"' super(Charset, self).__set__(obj, bytestring(content_type, 'ascii'))
def __str__(self): try: return '%d %s' % (self.value, _reasons[self.value]) except KeyError: return native(self.value, 'ascii')
def __set__(self, obj, value): if isinstance(value, int): self.value = value return self.value = _codes.get(value, native(value, 'ascii'))
def __init__(self, attr, cls, can=True): self.cls = cls self.can = can self.attr = native(attr)
def __repr__(self): return native(self.render(True))
def headers(self, data): """Process HTTP headers, and pull in the body as needed.""" # THREADING TODO: Experiment with threading this callback. # log.debug("Received: %r", data) self.environ = environ = dict(self.environ_template) line = data[:data.index(CRLF)].split() environ['REQUEST_URI'] = line[1] remainder, _, fragment = line[1].partition(b'#') remainder, _, query = remainder.partition(b'?') path, _, param = remainder.partition(b';') if b"://" in path: scheme, _, path = path.partition(b'://') host, _, path = path.partition(b'/') path = b'/' + path environ['wsgi.url_scheme'] = native(scheme) environ['HTTP_HOST'] = host environ['REQUEST_METHOD'] = native(line[0]) environ['CONTENT_TYPE'] = None environ['FRAGMENT'] = fragment environ['SERVER_PROTOCOL'] = native(line[2]) environ['CONTENT_LENGTH'] = None environ['PATH_INFO'] = unquote(path) environ['PARAMETERS'] = param environ['QUERY_STRING'] = query if environ['REQUEST_METHOD'] == 'HEAD': environ['marrow.head'] = True environ['REQUEST_METHOD'] = 'GET' _ = ('PATH_INFO', 'PARAMETERS', 'QUERY_STRING', 'FRAGMENT') environ['wsgi.uri_encoding'], __ = uvalues([environ[i] for i in _], self.protocol.encoding) environ.update(zip(_, __)) del _, __ current, header = None, None noprefix = dict(CONTENT_TYPE=True, CONTENT_LENGTH=True) # All keys and values are native strings. data = native(data) if str is unicode else data for line in data.split(nCRLF)[1:]: if not line: break assert current is not None or line[0] != ' ' # TODO: Do better than dying abruptly. if line[0] == ' ': _ = line.lstrip() environ[current] += _ continue header, _, value = line.partition(': ') current = header.replace('-', '_').upper() if current not in noprefix: current = 'HTTP_' + current environ[current] = value # TODO: Proxy support. # for h in ("X-Real-Ip", "X-Real-IP", "X-Forwarded-For"): # self.remote_ip = self.engiron.get(h, None) # if self.remote_ip is not None: # break if environ.get("HTTP_EXPECT", None) == "100-continue": self.client.write(b"HTTP/1.1 100 (Continue)\r\n\r\n") if environ['CONTENT_LENGTH'] is None: if environ.get('HTTP_TRANSFER_ENCODING', '').lower() == 'chunked': self.client.read_until(CRLF, self.body_chunked) return self.body_finished() return length = int(environ['CONTENT_LENGTH']) if length > self.client.max_buffer_size: # TODO: Return appropriate HTTP response in addition to logging the error. raise Exception("Content-Length too long.") self.client.read_bytes(length, self.body)
def __str__(self): return native(self.render())
def __get__(self, obj, cls, strip=True): value = native(super(ContentType, self).__get__(obj, cls)) if not value: return None return bytestring(value.split(';', 1)[0] if strip else value)
from marrow.util.object import LoggingFile from marrow.util.compat import binary, unicode, native, bytestring, uvalues, IO, unquote from marrow.server.http import release __all__ = ['HTTPProtocol'] log = logging.getLogger(__name__) CRLF = b"\r\n" dCRLF = b"\r\n\r\n" HTTP_INTERNAL_ERROR = b" 500 Internal Server Error\r\nContent-Type: text/plain\r\nContent-Length: 48\r\n\r\nThe server encountered an unrecoverable error.\r\n" VERSION_STRING = b'marrow.httpd/' + release.release.encode('iso-8859-1') nCRLF = native(CRLF) errorlog = LoggingFile(logging.getLogger('wsgi.errors')) class HTTPProtocol(Protocol): def __init__(self, server, testing, application, ingress=None, egress=None, encoding="utf8", **options): super(HTTPProtocol, self).__init__(server, testing, **options) self.application = application self.ingress = ingress if ingress else [] self.egress = egress if egress else [] self.encoding = encoding self._name = server.name self._addr = server.address[0] if isinstance(server.address, tuple) else ''