commit 9372e413939dd542f336994b6adc6ac7e1b3744e Author: Stefan Bühler Date: Tue Jun 24 21:19:20 2008 +0200 Initial commit diff --git a/.bzrignore b/.bzrignore new file mode 100644 index 0000000..1fe27cb --- /dev/null +++ b/.bzrignore @@ -0,0 +1,3 @@ +build +.lock-wscript +.waf-* diff --git a/src/base.h b/src/base.h new file mode 100644 index 0000000..8c5fcbf --- /dev/null +++ b/src/base.h @@ -0,0 +1,14 @@ +#ifndef _LIGHTTPD_BASE_H_ +#define _LIGHTTPD_BASE_H_ + +#include "settings.h" + +#define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0 + +struct server; +typedef struct server server; + +struct connection; +typedef struct connection connection; + +#endif diff --git a/src/chunks.c b/src/chunks.c new file mode 100644 index 0000000..1339c12 --- /dev/null +++ b/src/chunks.c @@ -0,0 +1,436 @@ + +#include "base.h" +#include "chunks.h" +#include "log.h" + +/****************** + * chunkfile * + ******************/ + +static chunkfile *chunkfile_new(GString *name, int fd, gboolean is_temp) { + chunkfile *cf = g_slice_new(chunkfile); + cf->refcount = 1; + cf->name = name; + cf->fd = fd; + cf->is_temp = is_temp; + return cf; +} + +static void chunkfile_acquire(chunkfile *cf) { +// assert(cf->refcount > 0) + cf->refcount++; +} + +static void chunkfile_release(chunkfile *cf) { +// assert(cf->refcount > 0) + if (!(--cf->refcount)) { + if (-1 != cf->fd) close(cf->fd); + cf->fd = -1; + if (cf->is_temp) unlink(cf->name->str); + cf->is_temp = FALSE; + g_string_free(cf->name, TRUE); + cf->name = NULL; + g_slice_free(chunkfile, cf); + } +} + +/* open the file cf->name if it is not already opened for reading + * may return HANDLER_GO_ON, HANDLER_ERROR, HANDLER_WAIT_FOR_FD + */ +handler_t chunkfile_open(server *srv, connection *con, chunkfile *cf) { + if (!cf) return HANDLER_ERROR; + if (-1 != cf->fd) return HANDLER_GO_ON; + if (!cf->name) { + CON_ERROR(srv, con, "%s", "Missing filename for FILE_CHUNK"); + return HANDLER_ERROR; + } + if (-1 == (cf->fd = open(cf->name->str, O_RDONLY))) { + if (EMFILE == errno) return HANDLER_WAIT_FOR_FD; + CON_ERROR(srv, con, "Couldn't open file '%s': %s (%i)", cf->name->str, strerror(errno), errno); + return HANDLER_ERROR; + } +#ifdef FD_CLOEXEC + fcntl(cf->fd, F_SETFD, FD_CLOEXEC); +#endif + return HANDLER_GO_ON; +} + +/****************** + * chunk iterator * + ******************/ + +/* must be powers of 2 */ +#define MAX_MMAP_CHUNK (2*1024*1024) +#define MMAP_CHUNK_ALIGN (4*1024) + +/* get the data from a chunk; easy in case of a MEM_CHUNK, + * but needs to do io in case of FILE_CHUNK; it tries mmap and + * falls back to read(...) + * the data is _not_ marked as "done" + * may return HANDLER_GO_ON, HANDLER_ERROR, HANDLER_WAIT_FOR_FD + */ +handler_t chunkiter_read(server *srv, connection *con, chunkiter iter, off_t start, off_t length, char **data_start, off_t *data_len) { + chunk *c = chunkiter_chunk(iter); + off_t we_want, we_have, our_start, our_offset; + handler_t res = HANDLER_GO_ON; + int mmap_errno = 0; + + if (!c) return HANDLER_ERROR; + if (!data_start || !data_len) return HANDLER_ERROR; + + if (HANDLER_GO_ON != (res = chunkfile_open(srv, con, c->file.file))) return res; + + we_have = chunk_length(c) - start; + if (length > we_have) length = we_have; + if (length <= 0) return HANDLER_ERROR; + + switch (c->type) { + case UNUSED_CHUNK: return HANDLER_ERROR; + case MEM_CHUNK: + *data_start = c->mem->str + c->offset + start; + *data_len = length; + break; + case FILE_CHUNK: + if ( !(c->file.mmap.data != MAP_FAILED || c->mem) /* no data present */ + || !( /* or in the wrong range */ + (start + c->offset >= c->file.mmap.offset) + && (start + c->offset + length <= c->file.mmap.offset + c->file.mmap.length)) ) { + /* then find new range */ + our_offset = start % MMAP_CHUNK_ALIGN; + our_start = start - our_offset; + + if (length > MAX_MMAP_CHUNK) length = MAX_MMAP_CHUNK; + we_want = length + MAX_MMAP_CHUNK; + if (we_want > we_have) we_want = we_have; + we_want += our_offset; + + if (MAP_FAILED != c->file.mmap.data) { + munmap(c->file.mmap.data, c->file.mmap.length); + c->file.mmap.data = MAP_FAILED; + } + c->file.mmap.offset = our_offset; + c->file.mmap.length = we_want; + if (!c->mem) { /* mmap did not fail till now */ + c->file.mmap.data = mmap(0, we_want, PROT_READ, MAP_SHARED, c->file.file->fd, our_offset); + mmap_errno = errno; + } + if (MAP_FAILED == c->file.mmap.data) { + /* fallback to read(...) */ + if (!c->mem) { + c->mem = g_string_sized_new(we_want); + } else { + g_string_set_size(c->mem, we_want); + } + if (-1 == lseek(c->file.file->fd, our_offset, SEEK_SET)) { + /* prefer the error of the first syscall */ + if (0 != mmap_errno) { + CON_ERROR(srv, con, "mmap failed for '%s' (fd = %i): %s (%i)", + c->file.file->name->str, c->file.file->fd, + strerror(mmap_errno), mmap_errno); + } else { + CON_ERROR(srv, con, "lseek failed for '%s' (fd = %i): %s (%i)", + c->file.file->name->str, c->file.file->fd, + strerror(errno), errno); + } + g_string_free(c->mem, TRUE); + c->mem = NULL; + return HANDLER_ERROR; + } +read_chunk: + if (-1 == (we_have = read(c->file.file->fd, c->mem->str, we_want))) { + if (EINTR == errno) goto read_chunk; + /* prefer the error of the first syscall */ + if (0 != mmap_errno) { + CON_ERROR(srv, con, "mmap failed for '%s' (fd = %i): %s (%i)", + c->file.file->name->str, c->file.file->fd, + strerror(mmap_errno), mmap_errno); + } else { + CON_ERROR(srv, con, "read failed for '%s' (fd = %i): %s (%i)", + c->file.file->name->str, c->file.file->fd, + strerror(errno), errno); + } + g_string_free(c->mem, TRUE); + c->mem = NULL; + return HANDLER_ERROR; + } else if (we_have != we_want) { + /* may return less than requested bytes due to signals */ + /* CON_TRACE(srv, con, "read return unexpected number of bytes"); */ + we_want = we_have; + if (length > we_have) length = we_have; + c->file.mmap.length = we_want; + g_string_set_size(c->mem, we_want); + } + } else { +#ifdef HAVE_MADVISE + /* don't advise files < 64Kb */ + if (c->file.mmap.length > (64*1024) && + 0 != madvise(c->file.mmap.data, c->file.mmap.length, MADV_WILLNEED)) { + CON_ERROR(srv, con, "madvise failed for '%s' (fd = %i): %s (%i)", + c->file.file->name->str, c->file.file->fd, + strerror(errno), errno); + } +#endif + } + } + *data_start = (c->mem ? c->mem->str : c->file.mmap.data) + start + c->offset - c->file.mmap.offset; + *data_len = length; + break; + } + return HANDLER_GO_ON; +} + +/****************** + * chunk * + ******************/ + +static chunk* chunk_new() { + chunk *c = g_slice_new0(chunk); + c->file.mmap.data = MAP_FAILED; + return c; +} + +/* +static void chunk_reset(chunk *c) { + if (!c) return; + c->type = UNUSED_CHUNK; + c->offset = 0; + if (c->mem) g_string_free(c->mem, TRUE); + c->mem = NULL; + if (c->file.file) chunkfile_release(c->file.file); + c->file.file = NULL; + c->file.start = 0; + c->file.length = 0; + if (MAP_FAILED != c->file.mmap.data) munmap(c->file.mmap.data, c->file.mmap.length); + c->file.mmap.data = MAP_FAILED; + c->file.mmap.length = 0; + c->file.mmap.offset = 0; +} +*/ + +static void chunk_free(chunk *c) { + if (!c) return; + c->type = UNUSED_CHUNK; + if (c->mem) g_string_free(c->mem, TRUE); + c->mem = NULL; + if (c->file.file) chunkfile_release(c->file.file); + c->file.file = NULL; + if (c->file.mmap.data) munmap(c->file.mmap.data, c->file.mmap.length); + c->file.mmap.data = NULL; + g_slice_free(chunk, c); +} + +/****************** + * chunkqueue * + ******************/ + +chunkqueue* chunkqueue_new() { + chunkqueue *cq = g_slice_new0(chunkqueue); + cq->queue = g_queue_new(); + return cq; +} + +static void __chunk_free(gpointer c, gpointer UNUSED_PARAM(userdata)) { + chunk_free((chunk*) c); +} + +void chunkqueue_reset(chunkqueue *cq) { + if (!cq) return; + cq->is_closed = FALSE; + cq->bytes_in = cq->bytes_out = cq->length = 0; + g_queue_foreach(cq->queue, __chunk_free, NULL); + g_queue_clear(cq->queue); +} + +void chunkqueue_free(chunkqueue *cq) { + if (!cq) return; + g_queue_foreach(cq->queue, __chunk_free, NULL); + g_queue_free(cq->queue); + cq->queue = NULL; + g_slice_free(chunkqueue, cq); +} + + /* pass ownership of str to chunkqueue, do not free/modify it afterwards + * you may modify the data (not the length) if you are sure it isn't sent before. + */ +void chunkqueue_append_string(chunkqueue *cq, GString *str) { + chunk *c = chunk_new(); + c->type = MEM_CHUNK; + c->mem = str; + g_queue_push_tail(cq->queue, c); + cq->length += str->len; + cq->bytes_in += str->len; +} + +/* memory gets copied */ +void chunkqueue_append_mem(chunkqueue *cq, void *mem, gssize len) { + chunk *c = chunk_new(); + c->type = MEM_CHUNK; + c->mem = g_string_new_len(mem, len); + g_queue_push_tail(cq->queue, c); + cq->length += c->mem->len; + cq->bytes_in += c->mem->len; +} + +static void __chunkqueue_append_file(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd, gboolean is_temp) { + chunk *c = chunk_new(); + c->file.file = chunkfile_new(filename, fd, is_temp); + c->file.start = start; + c->file.length = length; + + g_queue_push_tail(cq->queue, c); + cq->length += length; + cq->bytes_in += length; +} +/* pass ownership of filename, do not free it */ +void chunkqueue_append_file(chunkqueue *cq, GString *filename, off_t start, off_t length) { + __chunkqueue_append_file(cq, filename, start, length, -1, FALSE); +} + +/* if you already opened the file, you can pass the fd here - do not close it */ +void chunkqueue_append_file_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd) { + __chunkqueue_append_file(cq, filename, start, length, fd, FALSE); +} + +/* temp files get deleted after usage */ +/* pass ownership of filename, do not free it */ +void chunkqueue_append_tempfile(chunkqueue *cq, GString *filename, off_t start, off_t length) { + __chunkqueue_append_file(cq, filename, start, length, -1, TRUE); +} + +/* if you already opened the file, you can pass the fd here - do not close it */ +void chunkqueue_append_tempfile_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd) { + __chunkqueue_append_file(cq, filename, start, length, fd, TRUE); +} + +/* steal up to length bytes from in and put them into out, return number of bytes stolen */ +goffset chunkqueue_steal_len(chunkqueue *out, chunkqueue *in, goffset length) { + chunk *c, *cnew; + GList* l; + goffset bytes = 0; + goffset we_have; + + while ( (NULL != (c = chunkqueue_first_chunk(in))) && length > 0 ) { + we_have = chunk_length(c); + if (!we_have) { /* remove empty chunks */ + chunk_free(c); + g_queue_pop_head(in->queue); + continue; + } + if (we_have <= length) { /* move complete chunk */ + l = g_queue_pop_head_link(in->queue); + g_queue_push_tail_link(out->queue, l); + bytes += we_have; + length -= we_have; + } else { /* copy first part of a chunk */ + cnew = chunk_new(); + switch (c->type) { + case UNUSED_CHUNK: /* impossible, has length 0 */ + /* remove "empty" chunks */ + chunk_free(c); + chunk_free(cnew); + g_queue_pop_head(in->queue); + continue; + case MEM_CHUNK: + cnew->type = MEM_CHUNK; + cnew->mem = g_string_new_len(c->mem->str + c->offset, length); + break; + case FILE_CHUNK: + cnew->type = FILE_CHUNK; + chunkfile_acquire(c->file.file); + cnew->file.file = c->file.file; + cnew->file.start = c->file.start + c->offset; + cnew->file.length = length; + break; + } + c->offset += length; + bytes += length; + length = 0; + g_queue_push_tail(out->queue, cnew); + } + } + + in->bytes_out += bytes; + in->length -= bytes; + out->bytes_in += bytes; + out->length += bytes; + return bytes; +} + +/* steal all chunks from in and put them into out, return number of bytes stolen */ +goffset chunkqueue_steal_all(chunkqueue *out, chunkqueue *in) { + /* if in->queue is empty, do nothing */ + if (!in->length) return 0; + /* if out->queue is empty, just swap in->queue/out->queue */ + if (g_queue_is_empty(out->queue)) { + GQueue *tmp = in->queue; in->queue = out->queue; out->queue = tmp; + } else { + /* link the two "lists", neither of them is empty */ + out->queue->tail->next = in->queue->head; + in->queue->head->prev = out->queue->tail; + /* update the queue tail and length */ + out->queue->tail = in->queue->tail; + out->queue->length += in->queue->length; + /* reset in->queue) */ + g_queue_init(in->queue); + } + /* count bytes in chunkqueues */ + goffset len = in->length; + in->bytes_out += len; + in->length = 0; + out->bytes_in += len; + out->length += len; + return len; +} + +/* steal the first chunk from in and append it to out, return number of bytes stolen */ +goffset chunkqueue_steal_chunk(chunkqueue *out, chunkqueue *in) { + goffset length; + GList *l = g_queue_pop_head_link(in->queue); + if (!l) return 0; + g_queue_push_tail_link(out->queue, l); + + length = chunk_length((chunk*) l->data); + in->bytes_out += length; + in->length -= length; + out->bytes_in += length; + out->length += length; + return length; +} + +/* skip up to length bytes in a chunkqueue, return number of bytes skipped */ +goffset chunkqueue_skip(chunkqueue *cq, goffset length) { + chunk *c; + goffset bytes = 0; + goffset we_have; + + while ( (NULL != (c = chunkqueue_first_chunk(cq))) && length > 0 ) { + we_have = chunk_length(c); + if (we_have <= length) { + /* skip (delete) complete chunk */ + chunk_free(c); + g_queue_pop_head(cq->queue); + bytes += we_have; + length -= we_have; + } else { /* skip first part of a chunk */ + c->offset += length; + bytes += length; + length = 0; + } + } + + cq->bytes_out += bytes; + cq->length -= bytes; + return bytes; +} + +goffset chunkqueue_skip_all(chunkqueue *cq) { + goffset bytes = cq->length; + + g_queue_foreach(cq->queue, __chunk_free, NULL); + g_queue_clear(cq->queue); + + cq->bytes_out += bytes; + cq->length = 0; + + return bytes; +} diff --git a/src/chunks.h b/src/chunks.h new file mode 100644 index 0000000..8ad4806 --- /dev/null +++ b/src/chunks.h @@ -0,0 +1,191 @@ +#ifndef _LIGHTTPD_CHUNK_H_ +#define _LIGHTTPD_CHUNK_H_ + +#include + +struct chunkfile; +typedef struct chunkfile chunkfile; + +struct chunk; +typedef struct chunk chunk; + +struct chunkqueue; +typedef struct chunkqueue chunkqueue; + +struct chunkiter; +typedef struct chunkiter chunkiter; + +#include "base.h" + +/* Open a file only once, so it shouldn't get lost; + * as a file may get split into many chunks, we + * use this struct to keep track of the usage + */ +struct chunkfile { + gint refcount; + + GString *name; /* name of the file */ + int fd; + gboolean is_temp; /* file is temporary and will be deleted on cleanup */ +}; + +struct chunk { + enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type; + + goffset offset; + /* if type == FILE_CHUNK and mem != NULL, + * mem contains the data [file.mmap.offset .. file.mmap.offset + file.mmap.length) + * from the file, and file.mmap.start is NULL as mmap failed and read(...) was used. + */ + GString *mem; + + struct { + chunkfile *file; + off_t start; /* starting offset in the file */ + off_t length; /* octets to send from the starting offset */ + + struct { + char *data; /* the pointer of the mmap'ed area */ + size_t length; /* size of the mmap'ed area */ + off_t offset; /* start is octets away from the start of the file */ + } mmap; + } file; +}; + +struct chunkqueue { +/* public */ + gboolean is_closed; +/* read only */ + goffset bytes_in, bytes_out, length; +/* private */ + GQueue *queue; +}; + +struct chunkiter { +/* private */ + GList *element; +}; + +/****************** + * chunkfile * + ******************/ + +/* open the file cf->name if it is not already opened for reading + * may return HANDLER_GO_ON, HANDLER_ERROR, HANDLER_WAIT_FOR_FD + */ +handler_t chunkfile_open(server *srv, connection *con, chunkfile *cf); + +/****************** + * chunk iterator * + ******************/ + +INLINE chunk* chunkiter_chunk(chunkiter iter); +INLINE gboolean chunkiter_next(chunkiter *iter); +INLINE goffset chunkiter_length(chunkiter iter); + +/* get the data from a chunk; easy in case of a MEM_CHUNK, + * but needs to do io in case of FILE_CHUNK; it tries mmap and + * falls back to read(...) + * the data is _not_ marked as "done" + * may return HANDLER_GO_ON, HANDLER_ERROR, HANDLER_WAIT_FOR_FD + */ +handler_t chunkiter_read(server *srv, connection *con, chunkiter iter, off_t start, off_t length, char **data_start, off_t *data_len); + +/****************** + * chunk * + ******************/ + +INLINE goffset chunk_length(chunk *c); + +/****************** + * chunkqueue * + ******************/ + +chunkqueue* chunkqueue_new(); +void chunkqueue_reset(chunkqueue *cq); +void chunkqueue_free(chunkqueue *cq); + + /* pass ownership of str to chunkqueue, do not free/modify it afterwards + * you may modify the data (not the length) if you are sure it isn't sent before. + */ +void chunkqueue_append_string(chunkqueue *cq, GString *str); + +/* memory gets copied */ +void chunkqueue_append_mem(chunkqueue *cq, void *mem, gssize len); + +/* pass ownership of filename, do not free it */ +void chunkqueue_append_file(chunkqueue *cq, GString *filename, off_t start, off_t length); +/* if you already opened the file, you can pass the fd here - do not close it */ +void chunkqueue_append_file_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd); + +/* temp files get deleted after usage */ +/* pass ownership of filename, do not free it */ +void chunkqueue_append_tempfile(chunkqueue *cq, GString *filename, off_t start, off_t length); +/* if you already opened the file, you can pass the fd here - do not close it */ +void chunkqueue_append_tempfile_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd); + + +/* steal up to length bytes from in and put them into out, return number of bytes stolen */ +goffset chunkqueue_steal_len(chunkqueue *out, chunkqueue *in, goffset length); + +/* steal all chunks from in and put them into out, return number of bytes stolen */ +goffset chunkqueue_steal_all(chunkqueue *out, chunkqueue *in); + +/* steal the first chunk from in and append it to out, return number of bytes stolen */ +goffset chunkqueue_steal_chunk(chunkqueue *out, chunkqueue *in); + +/* skip up to length bytes in a chunkqueue, return number of bytes skipped */ +goffset chunkqueue_skip(chunkqueue *cq, goffset length); + +/* skip all chunks in a queue (similar to reset, but keeps stats) */ +goffset chunkqueue_skip_all(chunkqueue *cq); + +/* if the chunk an iterator refers gets stolen/skipped/..., + * the iterator isn't valid anymore + */ +INLINE chunkiter chunkqueue_iter(chunkqueue *cq); + +INLINE chunk* chunkqueue_first_chunk(chunkqueue *cq); + +/******************** + * Inline functions * + ********************/ + +INLINE chunk* chunkiter_chunk(chunkiter iter) { + if (!iter.element) return NULL; + return (chunk*) iter.element->data; +} + +INLINE gboolean chunkiter_next(chunkiter *iter) { + if (!iter || !iter->element) return FALSE; + return NULL != (iter->element = g_list_next(iter->element)); +} + +INLINE goffset chunkiter_length(chunkiter iter) { + return chunk_length(chunkiter_chunk(iter)); +} + +INLINE goffset chunk_length(chunk *c) { + if (!c) return 0; + switch (c->type) { + case UNUSED_CHUNK: + return 0; + case MEM_CHUNK: + return c->mem->len - c->offset; + case FILE_CHUNK: + return c->file.length - c->offset; + } + return 0; +} + +INLINE chunkiter chunkqueue_iter(chunkqueue *cq) { + chunkiter i; + i.element = g_queue_peek_head_link(cq->queue); + return i; +} + +INLINE chunk* chunkqueue_first_chunk(chunkqueue *cq) { + return (chunk*) g_queue_peek_head(cq->queue); +} + +#endif diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..dc4ca0f --- /dev/null +++ b/src/log.c @@ -0,0 +1,31 @@ + +#include "log.h" +#include + +#if REMOVE_PATH_FROM_FILE +const char *remove_path(const char *path) { + char *p = strrchr(path, DIR_SEPERATOR); + if (NULL != p && *(p) != '\0') { + return (p + 1); + } + return path; +} +#endif + +int log_write(server* UNUSED_PARAM(srv), connection* UNUSED_PARAM(con), const char *fmt, ...) { + va_list ap; + GString *logline; + + logline = g_string_sized_new(0); + va_start(ap, fmt); + g_string_vprintf(logline, fmt, ap); + va_end(ap); + + + g_string_append_len(logline, CONST_STR_LEN("\r\n")); + write(STDERR_FILENO, logline->str, logline->len); + g_string_free(logline, TRUE); + + return 0; +} + diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..845c70a --- /dev/null +++ b/src/log.h @@ -0,0 +1,48 @@ +#ifndef _LIGHTTPD_LOG_H_ +#define _LIGHTTPD_LOG_H_ + +/* #include "valgrind/valgrind.h" */ +#include "base.h" + +#define REMOVE_PATH_FROM_FILE 1 +#if REMOVE_PATH_FROM_FILE +LI_API const char *remove_path(const char *path); +#define REMOVE_PATH(file) remove_path(file) +#else +#define REMOVE_PATH(file) file +#endif + + +#define ERROR(fmt, ...) \ + log_write(NULL, NULL, "%s.%d: (error) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__) + +#define TRACE(fmt, ...) \ + log_write(NULL, NULL, "%s.%d: (trace) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__) + +#define SEGFAULT(fmt, ...) \ + do { \ + log_write(NULL, NULL, "%s.%d: (crashing) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__); \ + /* VALGRIND_PRINTF_BACKTRACE(fmt, __VA_ARGS__); */\ + abort();\ + } while(0) + +#define CON_ERROR(srv, con, fmt, ...) \ + log_write(srv, con, "%s.%d: (error) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__) + +#define CON_TRACE(srv, con, fmt, ...) \ + log_write(srv, con, "%s.%d: (trace) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__) + +#define CON_SEGFAULT(srv, con, fmt, ...) \ + do { \ + log_write(srv, con, "%s.%d: (crashing) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__); \ + /* VALGRIND_PRINTF_BACKTRACE(fmt, __VA_ARGS__); */ \ + abort();\ + } while(0) + + +/* TODO: perhaps make portable (detect if cc supports) */ +#define __ATTRIBUTE_PRINTF_FORMAT(fmt, arg) __attribute__ ((__format__ (__printf__, fmt, arg))) + +LI_API int log_write(server *srv, connection *con, const char *fmt, ...) __ATTRIBUTE_PRINTF_FORMAT(3, 4); + +#endif diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..92b5085 --- /dev/null +++ b/src/options.h @@ -0,0 +1,31 @@ +#ifndef _LIGHTTPD_OPTIONS_H_ +#define _LIGHTTPD_OPTIONS_H_ + +typedef enum { OPTION_NONE, OPTION_BOOLEAN, OPTION_INT, OPTION_STRING, OPTION_LIST, OPTION_HASH } option_type; + +struct option; +typedef struct option option; + +struct option_mark; +typedef struct option_mark option_mark; + + +struct option { + option_type type; + union { + gboolean opt_bool; + gint opt_int; + GString *opt_string; + /* array of option */ + GArray *opt_list; + /* hash GString => option */ + GHash *opt_hash; + } value; +}; + +struct option_mark { + size_t ndx; + gpointer value; +}; + +#endif diff --git a/src/plugin.h b/src/plugin.h new file mode 100644 index 0000000..b50b2af --- /dev/null +++ b/src/plugin.h @@ -0,0 +1,48 @@ +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + +#include "base.h" +#include "option.h" + +struct plugin; +typedef struct plugin plugin; + +struct module_option; +typedef struct module_option module_option; + +#define INIT_FUNC(x) \ + LI_EXPORT void * x(server *srv, plugin *) + +#define PLUGIN_DATA \ + size_t id; \ + ssize_t option_base_ndx + +struct plugin { + size_t version; + + GString *name; /* name of the plugin */ + + void *(* init) (server *srv, plugin *p); + /* the plugin must free the _content_ of the option */ + option_mark *(* parse_option) (server *src, void *p_d, size_t option_ndx, option *option); + + gpointer data; + + /* dlopen handle */ + void *lib; + + module_option *options; +}; + +struct module_option { + const char *key; + option_type type; +}; + +struct server_option { + plugin *p; + size_t index, module_index; + option_type type; +}; + +#endif diff --git a/src/server.c b/src/server.c new file mode 100644 index 0000000..f6f6080 --- /dev/null +++ b/src/server.c @@ -0,0 +1,7 @@ + +#include "log.h" + +int main() { + TRACE("%s", "Test!"); + return 0; +} diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 0000000..ec9182c --- /dev/null +++ b/src/settings.h @@ -0,0 +1,189 @@ +#ifndef _LIGHTTPD_SETTINGS_H_ +#define _LIGHTTPD_SETTINGS_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_STDINT_H +# include +#endif + +#ifdef HAVE_STDDEF_H +# include +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include + +/** + * if glib supports threads we will use it for async file-io + */ +#ifdef G_THREADS_ENABLED +# ifndef USE_GTHREAD +# define USE_GTHREAD +# endif +#endif + +/* on linux 2.4.x you get either sendfile or LFS */ +#if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILE && (!defined _LARGEFILE_SOURCE || defined HAVE_SENDFILE64) && defined HAVE_WRITEV && defined(__linux__) && !defined HAVE_SENDFILE_BROKEN +# define USE_LINUX_SENDFILE +# include +# include +#endif + +/* all the Async IO backends need GTHREAD support */ +#if defined(USE_GTHREAD) +# if defined(USE_LINUX_SENDFILE) +# if 0 && defined(HAVE_LIBAIO_H) + /** disabled for now as not all FSs are async-io capable */ +# define USE_LINUX_AIO_SENDFILE +# endif +# define USE_GTHREAD_SENDFILE +# endif +# if defined(HAVE_AIO_H) && (!defined(__FreeBSD__)) +/* FreeBSD has no SIGEV_THREAD for us */ +# define USE_POSIX_AIO +# include /* macosx wants it */ +# include +# endif +# ifdef HAVE_MMAP +# define USE_GTHREAD_AIO +# endif +#endif + +#if defined HAVE_SYS_UIO_H && defined HAVE_SENDFILE && defined HAVE_WRITEV && (defined(__FreeBSD__) || defined(__DragonFly__)) +# define USE_FREEBSD_SENDFILE +# include +#endif + +#if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILEV && defined HAVE_WRITEV && defined(__sun) +# define USE_SOLARIS_SENDFILEV +# include +# include +#endif + +#if defined HAVE_SYS_UIO_H && defined HAVE_WRITEV +# define USE_WRITEV +# include +#endif + +#if defined HAVE_SYS_MMAN_H && defined HAVE_MMAP +# define USE_MMAP +# include +/* NetBSD 1.3.x needs it */ +# ifndef MAP_FAILED +# define MAP_FAILED -1 +# endif + +#if defined(MAP_ANON) +#define HAVE_MEM_MMAP_ANON +#else +/* let's try /dev/zero */ +#define HAVE_MEM_MMAP_ZERO +#endif + +#endif + +#if defined HAVE_SYS_UIO_H && defined HAVE_WRITEV && defined HAVE_SEND_FILE && defined(__aix) +# define USE_AIX_SENDFILE +#endif + + +/** +* unix can use read/write or recv/send on sockets +* win32 only recv/send +*/ +#ifdef _WIN32 + +# define WIN32_LEAN_AND_MEAN +# define NOGDI +# define USE_WIN32_SEND +/* wait for async-io support +# define USE_WIN32_TRANSMITFILE +*/ +#else +# define USE_WRITE +#endif + + +typedef enum { HANDLER_UNSET, + HANDLER_GO_ON, + HANDLER_FINISHED, + HANDLER_COMEBACK, + HANDLER_WAIT_FOR_EVENT, + HANDLER_ERROR, + HANDLER_WAIT_FOR_FD +} handler_t; + +/* Shared library support */ +#ifdef _WIN32 + #define LI_IMPORT __declspec(dllimport) + #define LI_EXPORT __declspec(dllexport) + #define LI_DLLLOCAL + #define LI_DLLPUBLIC +#else + #define LI_IMPORT + #ifdef GCC_HASCLASSVISIBILITY + #define LI_EXPORT __attribute__ ((visibility("default"))) + #define LI_DLLLOCAL __attribute__ ((visibility("hidden"))) + #define LI_DLLPUBLIC __attribute__ ((visibility("default"))) + #else + #define LI_EXPORT + #define LI_DLLLOCAL + #define LI_DLLPUBLIC + #endif +#endif + +#ifdef LI_DECLARE_EXPORTS +#define LI_API LI_EXPORT +#else +#define LI_API LI_IMPORT +#endif + +/* Throwable classes must always be visible on GCC in all binaries */ +#ifdef _WIN32 + #define LI_EXCEPTIONAPI(api) api +#elif defined(GCC_HASCLASSVISIBILITY) + #define LI_EXCEPTIONAPI(api) LI_EXPORT +#else + #define LI_EXCEPTIONAPI(api) +#endif + +#ifdef UNUSED_PARAM +#elif defined(__GNUC__) +# define UNUSED_PARAM(x) UNUSED_ ## x __attribute__((unused)) +#elif defined(__LCLINT__) +# define UNUSED_PARAM(x) /*@unused@*/ x +#else +# define UNUSED_PARAM(x) x +#endif + +#if __GNUC__ +#define INLINE static inline +// # define INLINE extern inline +#else +# define INLINE static +#endif + +#include "sys-files.h" +#include "sys-mmap.h" +#include "sys-process.h" +#include "sys-socket.h" +#include "sys-strings.h" + +#endif diff --git a/src/sys-files.c b/src/sys-files.c new file mode 100644 index 0000000..a7e9307 --- /dev/null +++ b/src/sys-files.c @@ -0,0 +1,64 @@ +#include "sys-files.h" + +#ifdef _WIN32 +DIR *opendir(const char *dn) { + DIR *d = g_slice_new0(DIR); + + if (INVALID_HANDLE_VALUE == (d->h = FindFirstFile(dn, &(d->finddata)))) { + return NULL; + } + + return d; +} + +struct dirent *readdir(DIR *d) { + if (!d->dent.d_name) { + /* opendir has set a finddata already, push it out */ + + d->dent.d_name = d->finddata.cFileName; + return &(d->dent); + } + if (FindNextFile(d->h, &(d->finddata))) { + d->dent.d_name = d->finddata.cFileName; + return &(d->dent); + } else { + return NULL; + } +} + +void closedir(DIR *d) { + FindClose(d); + + g_slice_free(DIR, d); +} + +GString *pathname_unix2local(GString *fn) { + size_t i; + + for (i = 0; i < fn->len; i++) { + if (fn->str[i] == '/') { + fn->str[i] = '\\'; + } + } + + return fn; +} + +GString *filename_unix2local(GString *fn) { + size_t i; + + for (i = 0; i < fn->len; i++) { + if (fn->str[i] == '/') { + fn->str[i] = '\\'; + } + } +#if 0 + buffer_prepare_append(fn, 4); + memmove(fn->ptr + 4, fn->ptr, fn->used); + memcpy(fn->ptr, "\\\\?\\", 4); + fn->used += 4; +#endif + return fn; +} +#endif + diff --git a/src/sys-files.h b/src/sys-files.h new file mode 100644 index 0000000..49dfd91 --- /dev/null +++ b/src/sys-files.h @@ -0,0 +1,84 @@ +#ifndef _SYS_FILES_H_ +#define _SYS_FILES_H_ + +#define DIR_SEPERATOR_UNIX '/' +#define DIR_SEPERATOR_UNIX_STR "/" +#define DIR_SEPERATOR_WIN '\\' +#define DIR_SEPERATOR_WIN_STR "\\" + +#include "settings.h" + +#ifdef _WIN32 +#include +#include /* open */ +#include /* chdir */ + +#define DIR_SEPERATOR DIR_SEPERATOR_WIN +#define DIR_SEPERATOR_STR DIR_SEPERATOR_WIN_STR + +#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask)) + +#undef S_ISDIR +#undef S_ISCHR +#undef S_ISBLK +#undef S_ISREG +#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR) +#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR) +#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK) +#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG) +/* we don't support symlinks */ +#define S_ISLNK(mode) 0 + +#define lstat stat +#define mkstemp(x) open(mktemp(x), O_RDWR) +#define mkdir(x, y) mkdir(x) + +/* retrieve the most recent network, or general libc error */ +#define light_sock_errno() (WSAGetLastError()) + +struct dirent { + const char *d_name; +}; + +typedef struct { + HANDLE h; + WIN32_FIND_DATA finddata; + struct dirent dent; +} DIR; + +LI_EXPORT DIR * opendir(const char *dn); +LI_EXPORT struct dirent * readdir(DIR *d); +LI_EXPORT void closedir(DIR *d); + +LI_EXPORT GString * filename_unix2local(GString *b); +LI_EXPORT GString * pathname_unix2local(GString *b); + +#else /* _WIN32 */ +#include +#include + +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX +#define DIR_SEPERATOR_STR DIR_SEPERATOR_UNIX_STR + +#define light_sock_errno() (errno) + +#define filename_unix2local(x) /* (x) */ +#define pathname_unix2local(x) /* (x) */ +#endif /* _WIN32 */ + +#define PATHNAME_APPEND_SLASH(x) \ + if (x->len > 1 && x->ptr[x->len - 1] != DIR_SEPERATOR) { \ + g_string_append_c(DIR_SEPEARATOR); \ + } + +#ifndef O_LARGEFILE +# define O_LARGEFILE 0 +#endif + +#ifndef O_NOATIME +# define O_NOATIME 0 +#endif + +#endif + + diff --git a/src/sys-mmap.h b/src/sys-mmap.h new file mode 100644 index 0000000..560987b --- /dev/null +++ b/src/sys-mmap.h @@ -0,0 +1,26 @@ +#ifndef WIN32_MMAP_H +#define WIN32_MMAP_H + +#include "settings.h" + +#ifdef _WIN32 + +#define MAP_FAILED -1 +#define PROT_SHARED 0 +#define MAP_SHARED 0 +#define PROT_READ 0 + +#define mmap(a, b, c, d, e, f) (-1) +#define munmap(a, b) (-1) + +#include + +#else +#include + +#ifndef MAP_FAILED +#define MAP_FAILED -1 +#endif +#endif + +#endif diff --git a/src/sys-process.h b/src/sys-process.h new file mode 100644 index 0000000..53df76e --- /dev/null +++ b/src/sys-process.h @@ -0,0 +1,17 @@ +#ifndef _SYS_PROCESS_H_ +#define _SYS_PROCESS_H_ + +#ifdef _WIN32 +#include +#define pid_t int +/* win32 has no fork() */ +#define kill(x, y) do { } while (0) +#define getpid() 0 + +#else +#include +#include +#endif + +#endif + diff --git a/src/sys-socket.c b/src/sys-socket.c new file mode 100644 index 0000000..9766411 --- /dev/null +++ b/src/sys-socket.c @@ -0,0 +1,76 @@ +#include "base.h" +#include "sys-socket.h" + +#ifndef HAVE_INET_ATON +/* win32 has inet_addr instead if inet_aton */ +# ifdef HAVE_INET_ADDR +int inet_aton(const char *cp, struct in_addr *inp) { + struct in_addr a; + + a.s_addr = inet_addr(cp); + + if (INADDR_NONE == a.s_addr) { + return 0; + } + + inp->s_addr = a.s_addr; + + return 1; +} +# else +# error no inet_aton emulation found +# endif + +#endif + +#ifdef _WIN32 + +#include + +/* windows doesn't have inet_ntop */ + +/* +I have to look into this more. WSAAddressToString takes a sockaddr structure, which includes +the port number, so I must first test this stuff more carefully. For now, no IPV6 on windows. +You will notice that HAVE_IPV6 is never true for win32. +*/ + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) +{ + /* WSAAddressToString takes a full sockaddr, while inet_ntop only takes the address */ + struct sockaddr_in sock4; + struct sockaddr_in6 sock6; + DWORD addrLen = cnt; + int err = 0; + + /* src is either an in_addr or an in6_addr. */ + const struct in_addr *src4 = (const struct in_addr*) src; + const struct in6_addr *src6 = (const struct in6_addr*) src; + + int ipv6 = af == AF_INET6; + + // DebugBreak(); + + if ( ipv6 ) + { + sock6.sin6_family = AF_INET6; + sock6.sin6_port = 0; + sock6.sin6_addr = *src6; + } + else + { + sock4.sin_family = AF_INET; + sock4.sin_port = 0; + sock4.sin_addr = *src4; + } + + err = WSAAddressToStringA( + ipv6 ? (LPSOCKADDR) &sock6 : (LPSOCKADDR) &sock4, + ipv6 ? sizeof(sock6) : sizeof(sock4), + NULL, + dst, &addrLen ); + return err == 0 ? dst : NULL; +} + + +#endif diff --git a/src/sys-socket.h b/src/sys-socket.h new file mode 100644 index 0000000..c9650ad --- /dev/null +++ b/src/sys-socket.h @@ -0,0 +1,80 @@ +#ifndef SYS_SOCKET_H +#define SYS_SOCKET_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef _WIN32 +#ifndef FD_SETSIZE +/* By default this is 64 */ +#define FD_SETSIZE 4096 +#endif +#include +#include +//#include +//#define HAVE_IPV6 -- not until we've resolved the inet_ntop issue. + +#define ECONNRESET WSAECONNRESET +#define EINPROGRESS WSAEINPROGRESS +#define EALREADY WSAEALREADY +#define ENOTCONN WSAENOTCONN +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ECONNABORTED WSAECONNABORTED +#define ECONNREFUSED WSAECONNREFUSED +#define EHOSTUNREACH WSAEHOSTUNREACH +#define ioctl ioctlsocket +#define hstrerror(x) "" +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#ifndef __MINGW32__ +#define ssize_t int +#endif + +#define sockread( fd, buf, bytes ) recv( fd, buf, bytes, 0 ) + +LI_EXPORT const char * inet_ntop(int af, const void *src, char *dst, socklen_t cnt); +int inet_aton(const char *cp, struct in_addr *inp); +#define HAVE_INET_ADDR +#undef HAVE_INET_ATON + +#else +#include /* required by netinet/tcp.h on FreeBSD */ +#include +#include +#include +#include +#include +#include + +#ifndef SUN_LEN +#define SUN_LEN(su) \ + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) +#endif + +#define sockread( fd, buf, bytes ) read( fd, buf, bytes ) +#define closesocket(x) close(x) + +#include +#endif /* !_WIN32 */ + +#ifdef HAVE_INET_NTOP +/* only define it if it isn't defined yet */ +#ifndef HAVE_IPV6 +#define HAVE_IPV6 +#endif +#endif + +typedef union { +#ifdef HAVE_IPV6 + struct sockaddr_in6 ipv6; +#endif + struct sockaddr_in ipv4; +#ifdef HAVE_SYS_UN_H + struct sockaddr_un un; +#endif + struct sockaddr plain; +} sock_addr; + +#endif diff --git a/src/sys-strings.h b/src/sys-strings.h new file mode 100644 index 0000000..1103a8c --- /dev/null +++ b/src/sys-strings.h @@ -0,0 +1,46 @@ +#ifndef _SYS_STRINGS_H_ +#define _SYS_STRINGS_H_ + +#ifdef _WIN32 +#define strcasecmp stricmp +#define strncasecmp strnicmp +#include +#define str_to_off_t(p, e, b) _strtoi64(p, e, b) +#define STR_OFF_T_MAX LLONG_MAX +#define STR_OFF_T_MIN LLONG_MIN +#define strtoull _strtoui64 +#ifdef __MINGW32__ +/* missing prototype */ +unsigned __int64 _strtoui64( + const char *nptr, + char **endptr, + int base + ); +__int64 _strtoi64( + const char *nptr, + char **endptr, + int base + ); +#endif +#else /** we are a unix */ + +/** + * we use strtoll() for parsing the ranges into a off_t + * + * if off_t is 32bit, we can use strtol() instead + */ + #if SIZEOF_OFF_T == SIZEOF_LONG + #define str_to_off_t(p, e, b) strtol(p, e, b) + #define STR_OFF_T_MAX LONG_MAX + #define STR_OFF_T_MIN LONG_MIN + #elif defined(HAVE_STRTOLL) + #define str_to_off_t(p, e, b) strtoll(p, e, b) + #define STR_OFF_T_MAX LLONG_MAX + #define STR_OFF_T_MIN LLONG_MIN + #else + #error off_t is more than 4 bytes but we can not parse it with strtol() (run autogen.sh again if you build from svn) + #endif +#endif + +#endif + diff --git a/src/wscript b/src/wscript new file mode 100644 index 0000000..1b85ea3 --- /dev/null +++ b/src/wscript @@ -0,0 +1,120 @@ +#! /usr/bin/env python +# encoding: utf-8 + +#import Action, Object, Params, os, sys +import Params + +common_uselib = 'glib ' + +common_source=''' + chunks.c + log.c + sys-files.c +''' +# sys-socket.c + +main_source = ''' + server.c + ''' + +#def node_in_same_dir(node, name): + #p = node.m_parent + #n = p.m_files_lookup.get(name, None) + #if not n: n = p.m_build_lookup.get(name, None) + #if n: return n + + #newnode = Node(name, p) + #p.m_build_lookup[newnode.m_name]=newnode + + #return newnode + +#def lemon_file(self, node): + #lemon_task = self.create_task('lemon', nice=40) + #lemon_task.set_inputs([node, node_in_same_dir(node, 'lempar.c')]) + + #newnodes = [node.change_ext('.c'), node.change_ext('.h')] + #lemon_task.set_outputs(newnodes) + + #task = self.create_task(self.m_type_initials) + #task.set_inputs(lemon_task.m_outputs[0]) + #task.set_outputs(node.change_ext('.o')) + +def lighty_mod(bld, target, src, uselib = '', option = ''): + if option and not getattr(Params.g_options, option): return + mod = bld.new_task_gen('cc', 'plugin') + mod.target = target + mod.source = src + mod.uselib += 'lightymod ' + common_uselib + uselib + +def build(bld): + env = bld.env + + # 1. Build lemon (parser generator) + #lemon = bld.new_task_gen('cc', 'program') + #lemon.install_var = 0 + #lemon.source = 'lemon.c' + #lemon.target = 'lemon' + + #bld.add_group('lemon') + #lem_task = lemon.m_tasks[1] + #lem_node = lem_task.m_outputs[0] + #lemon_exec = lem_node.abspath(lem_task.m_env) + #Action.simple_action('lemon', 'cd ${TGT[0].bld_dir(env)}; ' + lemon_exec + ' ${SRC[0].abspath()} ${SRC[1].abspath()}', color='BLUE') + + # hook .y to lemon + #Object.hook('cc', 'LEMON_EXT', lemon_file) + + main = bld.new_task_gen('cc', 'program') + main.name = 'lighttpd' + main.source = common_source + main_source + main.target='lighttpd' + env['APPEND'] + main.uselib += 'lighty dl openssl pcre ' + common_uselib + + #lighty_mod(bld, 'mod_access', 'mod_access.c') + #lighty_mod(bld, 'mod_alias', 'mod_alias.c') + #lighty_mod(bld, 'mod_dirlisting', 'mod_dirlisting.c', uselib = 'pcre') + #lighty_mod(bld, 'mod_staticfile', 'mod_staticfile.c') + #lighty_mod(bld, 'mod_indexfile', 'mod_indexfile.c') + #lighty_mod(bld, 'mod_setenv', 'mod_setenv.c') + #lighty_mod(bld, 'mod_rrdtool', 'mod_rrdtool.c') + #lighty_mod(bld, 'mod_usertrack', 'mod_usertrack.c') + #lighty_mod(bld, 'mod_proxy_core', ''' + #mod_proxy_core.c mod_proxy_core_pool.c mod_proxy_core_backend.c + #mod_proxy_core_address.c mod_proxy_core_backlog.c mod_proxy_core_protocol.c + #mod_proxy_core_rewrites.c mod_proxy_core_spawn.c + #''', uselib = 'pcre') + #lighty_mod(bld, 'mod_proxy_backend_http', 'mod_proxy_backend_http.c') + #lighty_mod(bld, 'mod_proxy_backend_fastcgi', 'mod_proxy_backend_fastcgi.c') + #lighty_mod(bld, 'mod_proxy_backend_scgi', 'mod_proxy_backend_scgi.c') + #lighty_mod(bld, 'mod_proxy_backend_ajp13', 'mod_proxy_backend_ajp13.c') + #lighty_mod(bld, 'mod_userdir', 'mod_userdir.c') + #lighty_mod(bld, 'mod_secdownload', 'mod_secure_download.c') + #lighty_mod(bld, 'mod_accesslog', 'mod_accesslog.c') + #lighty_mod(bld, 'mod_simple_vhost', 'mod_simple_vhost.c') + #lighty_mod(bld, 'mod_evhost', 'mod_evhost.c') + #lighty_mod(bld, 'mod_expire', 'mod_expire.c') + #lighty_mod(bld, 'mod_status', 'mod_status.c') + #lighty_mod(bld, 'mod_compress', 'mod_compress.c', uselib = 'bzip zlib') + #lighty_mod(bld, 'mod_redirect', 'mod_redirect.c', uselib = 'pcre') + #lighty_mod(bld, 'mod_rewrite', 'mod_rewrite.c', uselib = 'pcre') + #lighty_mod(bld, 'mod_auth', 'mod_auth.c http_auth_digest.c http_auth.c', uselib = 'crypt ldap') ## lber? + #lighty_mod(bld, 'mod_sql_vhost_core', 'mod_sql_vhost_core.c') + #lighty_mod(bld, 'mod_postgresql_vhost', 'mod_postgresql_vhost.c', uselib = 'postgresql', option = 'postgresql') + #lighty_mod(bld, 'mod_mysql_vhost', 'mod_mysql_vhost.c', uselib = 'mysql', option = 'mysql') + #lighty_mod(bld, 'mod_trigger_b4_dl', 'mod_trigger_b4_dl.c', uselib = 'pcre') + #lighty_mod(bld, 'mod_uploadprogress', 'mod_uploadprogress.c') + #lighty_mod(bld, 'mod_evasive', 'mod_evasive.c') + #lighty_mod(bld, 'mod_ssi', 'mod_ssi_exprparser.y mod_ssi_expr.c mod_ssi.c', uselib = 'pcre') + #lighty_mod(bld, 'mod_flv_streaming', 'mod_flv_streaming.c') + #lighty_mod(bld, 'mod_chunked', 'mod_chunked.c') + #lighty_mod(bld, 'mod_magnet', 'mod_magnet.c mod_magnet_cache.c', uselib = 'lua') + #lighty_mod(bld, 'mod_deflate', 'mod_deflate.c', uselib = 'bzip zlib') + #lighty_mod(bld, 'mod_webdav', 'mod_webdav.c', uselib = 'sqlite3 xml uuid') + +def configure(conf): + env = conf.env + #env['LEMON_EXT'] = [ '.y' ] + env['LIBDIR'] = Params.g_options.libdir + env['APPEND'] = Params.g_options.append + env['plugin_INST_VAR'] = 'LIBDIR' + env['plugin_INST_DIR'] = '' diff --git a/waf b/waf new file mode 100755 index 0000000..2b2be97 --- /dev/null +++ b/waf @@ -0,0 +1,145 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2005-2008 + +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys +if sys.hexversion<0x203000f: raise "Waf requires Python >= 2.3" + +if 'PSYCOWAF' in os.environ: + try:import psyco;psyco.full() + except:pass + +VERSION="1.4.2" +REVISION="6fc051971db49c83aab5565673e789bc" +INSTALL=sys.platform=='win32' and 'c:/temp' or '/usr/local' +cwd = os.getcwd() +join = os.path.join + +def decode(s): + p1 = len(s) + s += '!!!!!' + w1 = [256**(3-u) for u in xrange(4)] + w2 = [(u, 85**(4-u)) for u in xrange(5)] + tot = [sum([(ord(s[i+m])-33) * n for (m, n) in w2]) for i in xrange(0, p1, 5)] + return ''.join([chr((y/x) & 255) for y in tot for x in w1]) + +def err(m): + print '\033[91mError: %s\033[0m' % m + sys.exit(1) + +def unpack_wafdir(dir): + f = open(sys.argv[0],'rb') + c = "corrupted waf (%d)" + while 1: + line = f.readline() + if not line: err("run waf-light from a folder containing wafadmin") + if line == '#==>\n': + txt = f.readline() + if not txt: err(c % 1) + if f.readline()!='#<==\n': err(c % 2) + break + if not txt: err(c % 3) + try: txt = decode(txt[1:-1].replace('z', '!!!!!')) + except: err(c % 4) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: os.makedirs(join(dir, 'wafadmin', 'Tools')) + except OSError: err("Cannot unpack waf lib into %s\nMove waf into a writeable directory" % dir) + + os.chdir(dir) + tmp = 't.tbz2' + t = open(tmp,'wb') + t.write(txt) + t.close() + + t = tarfile.open(tmp) + for x in t: t.extract(x) + t.close() + + os.chmod(join('wafadmin','Tools'), 0755) + + os.unlink(tmp) + os.chdir(cwd) + +def test(dir): + try: os.stat(join(dir, 'wafadmin')); return os.path.abspath(dir) + except OSError: pass + +def find_lib(): + name = sys.argv[0] + base = os.path.dirname(os.path.abspath(name)) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + err("waf-light requires wafadmin -> export WAFDIR=/folder") + + dir = "/lib/waf-%s-%s/" % (VERSION, REVISION) + for i in [INSTALL,'/usr','/usr/local','/opt']: + w = test(i+dir) + if w: return w + + #waf-local + s = '.waf-%s-%s' + if sys.platform == 'win32': s = s[1:] + dir = join(base, s % (VERSION, REVISION)) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir) + return dir + +wafdir = find_lib() +if "-vv" in sys.argv: print "wafdir is %s" % wafdir + +w = join(wafdir, 'wafadmin') +t = join(w, 'Tools') +sys.path = [w, t] + sys.path + +import Scripting, Params +Params.g_tooldir = [t] +Params.g_cwd_launch = cwd + +if Params.g_version != VERSION: + err('Version mismatch: waf %s <> wafadmin %s (wafdir %s)' % (VERSION, Params.g_version, wafdir)) +Scripting.prepare() + +#==> +#6<\%_0gSqh;ct1=O)>%tZ2ak(p?^f=s8W-!s8W-!s8W+L:rj=c!%e2,!e:h)!"gVg2Epj&mBE=`zz!!N?&z!!!!P^@b03ZX6pT^"i>J%OF3-G&qY/Cp4'/.n)3n+r$P:='*$pj:,k4H>[ijFgkm>_.DDuQW_&Z.%p=4g"uJ[HbIb>B4$)AY;^W$X*N;7n!*^g*R?C@!f$O@p1ISfJF>tk&0O2TJ8Xc](b)gqfdJU5&U8Gf4e-5/Rj->4(;E%YH8A!:_<<%AI2G56`h_aDP=KeU4Gl;R_hIV4kp'ZBOur^miC?9F4YR#8P'VXm>C%`oP0Fjo0k$DH[D@Ofk,c1Q#2[FbI;i2GQCUBp'hknVq]u,plG`G;PT_jH+n^po6YkX4I!=72un7F!!#1Iq5qHbWU!%ZDiOpDT5gF0Z%D_q]l.32YT)53RV;D_YBOq\_!(NsXg,;LXGp94E419#"Jc?#$Df?d?-B[L6b+9#F4oAr^@-_sC[3;$.bbN5$J)"&YJ!(?_oAm$QX+a;V_*%.II)"G[b^Y'qp+WFuJ-NeaJN(laOF9\o[64]rZD>kM=I.4F8-HlJD+kLA,u]hT@1TH^V&23aK73Be8mpC>S0Q.r^Rm+iYYfp/nHG3I>SkJu)-X\X-9Hd1&aBg$1u@Cb4+Ze_5#pXo5npP\IsGYUHWg$OQf%nBC_]5ZN:Fl'LmeQa+f71E8NpGb5$mqs*3>Ma/E%qf:^!MI`qG4]*R.Re.STWUe)D#mWO6UOcEcL,i0->2,jY4nI<'?:g`*VK!L[iI!UGk[ZHVqg,OY:mSYaGg#m=51DH'u;2pbT_V;GSKiq`-:^%E7[om-!+FK-%A[p*+HIF#*sq2IQ]]L1/3WJ:/I2]BTB>AXU1NQ$)8AiZFJS^n^sB3VsEp3-1J55+F=H%t_SDZOZ,Y3LGKeNQ>d5RKjT@HiA#qq^G1IIDUN%aA)3S3i28FgfZ]ds9S)[pBj("Go*Ume1hq^%XVSg;"8cb%T<0PT,f9Ni6i4bpLqWMn_r%b95b_+pUST+p)?)1i!6p@3k`eDMGpPFjpg(tmoPO1Hf"%s&?bIWbqA*8p;I@(D`:,/A.<)6Wd@_DWgT+E9f.ocC!!!;.G6A9sXD"4Rru+p\HJ,h[d?XpoaW1]/bflicg!d_9>$bX"KXIEiPl(E2p/X#d&SZYftn"#l)AhB+7JHTWEa8JRA7>?D-SDRISG?""H)4N%(JW19.:2[eE.2>o'FsOVaH1mVqoELUeU@Q.r7R.hP7[]Jnb!`37EK.]i:Ui@9sB/nL%E\V'&gX^DX:,SCpr:k=;"dm+'[5W";F!=UqYPQ?r33=$'EYBD3(Si>J0mU]@3U4WeO5*[;Fs.W71t_/1rVm@0hDr,;DAV<,u#)<2%rYT9%??qbZ,5i<)?F`&P3]L"Ur0[9S$//'FbaMeJ1L^$PYuB&lg4\<09!O&OeE/5sZ/A<-#s_<$'Wf4adnj!XPYj7k2&$c/&qQ6qp(u&HomH7*JRs1(_rsck-sg'bN`/$p[5m9goab'iP]%;[eimeJ)"L<=i(t,S7nIZOp%X!(.DR;_Ud?9e8\s91;5_&I]C"9LD*F'[RLN6pQtk&Ks_:7"i_2&5Ynt0apnm6pif*9Lk2FZTU;IRLo>!=#UZO.8gp\XAu_g7P%GmFRL#:B,-#/k7@C0M+c*.s.Ol:8+JrbF$Atg^M2A/S67=%G#UlR=MB\dkTdYMMTTG"D-n#FsA>E[d$9B%ojQe>$>&#=[81:..8>ZZ]BHeX0#pNcV+IO@OAni4iBPC'e$>>6PAg.R[)1j#LKG[BO;KS?^LoHK%RYdu,,g%;SMF_D0$5t1A#`tI3.$A8;UoG9#@O`iSBaKY8.$uDTJ;/l:U*?;(W+^a>Ul%_jM?6=`-&@)%U+.FUM@q2-,%r<[$:8J7BrYVd#q/7mU)B>M-n7cDU0+@'"KDc]VMU+`JsI_i.#8Ll;BQ8O:&gjbnZ@`]&0qo:mU-nA,cj6C:e_SO5g6JgaUj[[;St:^9WSAm'Mq'q5p8lW"][fUbfl7O&etR,`D%%E`.\jU6q!9`V*bARb:#dn6k(S"%#n7Q%$X/Z$kZH<,tt-I/nI.>"F3Wi6X;&AaN[R3FsA+sN2(PaI'$MO96VQmACM,q'+6Ul#LnTSA:GU7).@$7LKE)QFu"(o`@gVM^b8J1+"qJ>OHG!eRBhMJ.[!M?obJ2$"7#0ha8e%4+E]"=1(e":.g;,YJe=6P)[\"B7WQ71rHk5n_R4&l:kn/O;fn_%\UM;+!lPdR9=b;'[o];\53d9T2MA8B""d74Cq_+X%O&1(uu1$qs(=O[)nY8H^`o78Qr\$<81?jM9*+=QL&m,h)tu&/5=6AO8a=#"au08>RV*0an^!#noY%1GHp+'f.esfI0-R-q+g_d*f!m5q7s^!=6Ud<"]0r1_gYMKbT^b0bG!H&60iP;aj6^'Tk+?ooMI>79%4E6kN'l8RHDtnE7pVQuBF=rs[0uJ(&ae]3kB/77&N-[4G__C]6VRMnl;Z:(l]kGlPN;W[@@."FHi`rTqMNXD4>hJ#W58S8E/+2K/U]p`]3o]VXb)kmtCk2)kNh^'loN-=I,Bdh,JoB>=F,/*A-?qn.ErC"$PK`sQOOSIqG,[!CN*=R@miSpfPs]t$ST/4&u#kVT1n=E\ajcu7tDHS`;;VafsH7B#ehsM4-"M.*t7`Q#o%:sW;BifX_Q])C!bc/4+\(Y(N(-k(_AUpT^5#JlX^/!lVu&9]/ljj2$Hr]U&q)IFmG)uO4@KX0b+;=o_bnqC]5t[gMfA.4sr-iA$BM?0Xp].2qAii/`*EQ'+]t!D?e,LCJro6EE8\I;L\XbS6feQ>_S2kWG^]Ud<>6TKZjcS9/VTkCV+h$*lapTQ[Bc3JYYJ_V=!/-"r4CJ,PtpJloNetr]Le_8AF4(2soaJ:c4n1j7U?N:*`D3rgu/hJrm^$$jd^lbVF@2gN$`>K.p4jP+;ZrZej!bGKdd.8&FECPU_95'N52jp9;@&X]\ho;;QE@,R,'SR2mM/bW+sSVa)dd_jpSo;:lE(lhCr0M2Dji59Zm0)b>\a8"$fGI^OYK'agQ3,i[Z2q\W_"HpV)fL1IP*7T2`j5]\+.*0U9Em6lD!7.f/47>hgMPo4:ZKWO^`a"L=BVYP0s8!'OM48I2M$'/DS5%YC"]13oDGcND`=7q,q0`DBqKWb4o3)F9TU1m8%Pm0s$q4d5mo'S&YY2+GKLuN%1GA53oK^4Fa,WXKILt1'U$D*S?[%2Z+dkh5(^AMdD(*)a/9j1>+NDHjRbeoPk@Ho[U`_kG$&a%_pN_:1SamP";l\/1InFS),fnWZ-Xk<#XLc6l&P]1PM7nqcl;WLdYgPqBL7VS#:U!q]RBfBmI:*8gMPKWLPU%fM!38`89jtk1(IHX4OWB+PJ^IH@,K+&b#sKb0+5'H)N%AYjn3dRRlOPcE_\bTL7,5hS[`Z+Zn=,A>G#fHFn>?`0Os`h>n#5`n6Y^fbQn_HVd3UJBpqrlsmgklPI[$1n."J.5:@&GiX%JSs=BrEg5%'5.<)oLQMH;2KtcALIn7u.p2CqSeVCe[>iq`M,G^eqKT[+CsAC'tp+Vd\3Ys'VG;_C/F\<,c'[d>.e/sNIjOec4(MAA8ge&K+aH8;[3CSNlUjbGb\T0FcJ:@dq.pcl<)!PXc=CZ,S]K_TLi*A&@9!WQ)PeA#F8`)$+Wi!1/Kerp\71bCI@BuPiEM56ur+ZkE(CK3mYL>O$3i>8,GF!gmRLNfaA#nUqdm,R8GKrc1dO%7k)2>4/Kd#2npn4T[e<%dh_aQIq2Kdle1%qp75M:r&kjQSLa9n^Hrmf$-51$8[,ksDj7T8AD9d0s,,akN`cBb\\jV?_L6m%Y0q#$_pQoWABl]6^oEl6B.Ob?7[H7Al1pSBH^#6X;@.LJ3U4j5R'2G<0if(NoslAWRemO],2ual6cr_P.^/oR?V1P"/LrKmipVu%Hhbk*e$Kl\$96YYUs)m<1go+V'0'/,_n'TusE2O!1,hR+'T"QUnj(rPu`5P$R:9d*N9@I&5L5pcOc"tqC&pRspQP(-t'8`[ES$GD"?TX!a84%i^-%HB2o@s$2Y3A5<,BMU36=('tg1DDq7Lm1mpsO2!IhAVqV,h]JUO?X9d(@o*.rkR:2SesoR&"Fm9k#A7"?+Jq?0MXgLd$j3iY`rB_^IQ!\TE1;AV)Sbr7oh]_6tPtlnsLZ;"?Zq@AbdOtB`D0ltVihm#^eX2V*h->_4Oa3*,SWDKH:gBnn=.OIK-%;gM/P7oNVhB@>71AT,_je2n-N_-RAXnXW5&]bI*(Oe.;9K-jZTV^.snU":C=-KdO&311tVa:R$An-\h4H+Su=(F^:)]0,u'q-ID.-1J1TK[Z\<"FtQ#7W"Uiqs9IL)Rjesb"=h^=/t$I?]EiK=^jDgY[E\n[=cNIRQYXtuh@-f%S+jmVXE@-?Vk_"6_!KR0iA4M"69jZ&\M:#oRF]74'Fe.cZmkK0nP)#@%ZCM:aFDZ+PP4Y-E_Y2(^nseIW>#WqgSPCq?PKg:?EJ-O;g7KDeoMo#a2ZGD&+EqH5__TpeX://gj[+Cdo$_$)91#7E:X$mcP0@(V?HSINkYg7bCc?;7(P(r`/NMe="+I'b7[@VnTklNhYiUR:d]3qW)!IN.IhZ#?k*Z88VmP!Q_6)]N)tdqQk^j1G"2X:R"'?DqG>P,,]/Tnkk_?P=jH\T*($CAU*QComjN@jA%tg^V^%lsR)@+Qha_q,X*'Gn1XgCBoto(Sp4?109g+U.p-jCIqJ"0W367Y%i)+jF/honN,Mo<1a%Di%opO)i@2InuNh&/4FtO1MG"[e5DgB5E!PA8:'K:-nCa8&>>@,^3TcE>.8LY7hNkHVaahc1RfPm`$d(mGC?<"Ql%$`ej1j_'oJ,K1GiL?[l2a^J[p5#8ODQsY__a593rU:S>;+mQ8?FQEB=kG']QT;X_a:U$4WRsUi,ngofEaX/6d3T)He-B,>deUNP]D'KkQJ:ok]a(<_b9S(6.=&a7X-Fnu/l"eI\IbRU_Sn1G=-4XTkl2as@jOS#W!dJ>iYS;a@__nq%';)AlaZM6+31T!3Y)/(0AXpHM0OWY#+me?A:fq+U+CpAdOA`'8_KmB`\LAf5+%3.ZLirja8/0NAGt)a#`P6+jZm2e0>:Hc:CR*%_cLFmUNH/\?P9i%j)[F;mTqD=S\#RK+Wup&?#A"a%-V$-+7`=Z47QMj8YD1Cn5&A*B[AgO`'c+8r>ROL7S)2k5$8<0AZb1hHXI)0!YsD+s$.L"6'/Kis*4,(8+Y$5,kQ=K7]dTZE'KM;fU#"pO'>ek"68c1Co#--;"pUpV?Rk%3\K7W]ia9Rt#QH!H='cD4#YBq1KnR(C8#mO^_i-RN8aATnVHCXY]`IKN%F*g--=C@]dh+?_\6.(bEiRRr0c?mmc^'Es:'gPPFf^RYmHJRIG7E#frsn)US"]#[G`aLN.+7=7c,"jL62i0Da%T9?eQLY_BB>ul@3Ugr!4S:kl^>)b2"":^B]RS+e*6gD$qkHVK^!hMop(*qm-o]4O])7>u1)SsA5O_%P92N:\IPL*2jY\e+GEr;#SI@2Eo7&lshRg^L8>3Y]C8:`eGWE$b'.CmI\8sBa)/V;KBPG>0.]%VoqPtoX$bI3J8@f^6bH;Y^3^iHR:2dMY^gMp>bWbl,9Eq@lq6O1YJ^arM]81(,pc\FUD*N(^c$-+g]HRO^^>i6"#b"TA.HH*+:5H`C&Fh2%RL4EgJ43`IMs[76u5*Rd#&>j5(fepe?t^o)5\lHeJZXJ\6Fh!fRq-`bPZ_l#OI'^tCj!La^/m[L;97rRoWm[c`&8A?.f=p1mfIrMSUi"8KR'=P<+QbRfAa-:GC7.F'H0)7;8"(EcU*K4m90e^q$_N)WH!3Au#;//NE]ZRNSq`St13HXEH4F[W3(]AAEfJ^_VN+cU[?HmiJrl?h4+K8E&g4%_\m40L^!)UaBMWT,4S>(7hrlXtob6hZ*%lrCZE+WEUEf.`?G4lQs`AdCl"mWZlVMgI;cUJ"9blSrrgSAs-(^M?9TuJT@s3.I$BX1UQ+]UDcrD)a<^sNqBkP$_0bi.I4Kjq9;;sFS6'o9ZKeTs[8;%@/mi:Z'+H]>cMScY;f2OT4Qk2JL\kKXG@nR+A8[:He<&/:j/:f69-+MXL#!:&Q/W5'(^?tM^\D@,472K`_`V+C42^0jQOdA5k.2KH)`QkU*AKqP;\Cf5SqE]!i3<\LAmopNmd#R[15+r`kMm@P/6573<5WAH%7:1*Q$auKp,:Qa8JEm<_]DPha*kVmLu5s[_kgfc]8lL9cf%.sZc%eg/HOE:QLZr'dKN.`n@j>##qR,]g"Ve0Ht>FcYKI)-oO68\#&4TG\"o/2?dA1(?@JF_c"UOW.AnQ\P5\aLKrN;C3:>7O0l;\+*K_SnK!MV,FCP;^Q+[7o"QY$N\/76':(ImIeJ>E?ppGW7=t(Q3D5qZq,s%_*bo3T0MI(HsAfQAcCbU-SaX<<'j,F(TKAuL_pmNMaZW2X+5l8Pg(8DLnbI5Cs\>iG+>_qS7to2qq/hX!@)*\Wad2Y#U;#S@^r;3b/)KHS8]kOA#k=jGW^@]2A\SqKa;!7WfH^*1(&&93\r=U3Fsl?]W@KL>7s\6o]B(+)mmb51)#Fm%6/M-\plan8#?[c^kNID6mb[faN6Z%T:_MGc7nVd16aX!!H7-=cS.ETS[ne0OJ@KC;ESMXS7u;ca"C3!h6/Z1g52]Ot:kRhIf02oS>:/d@R=.]GoD[dBbP0=%525>JcZjl">SO>JZDg8/)pOg@Y':tT]-&%L%`d]cJja?DgW't7W;[rWFnfb6]bPadrB9I4Wh4k]45F@6]_T(W(Rk*m>#4NBDpM-S46PQmfm1,,4aZeXVsXH=1UE2]KgV&W`o.Fib5-Gd+>Q1/r;NhB.cmH<(Z2#H(-[%Mnd[,pLDCF!(IFKGk!+`QqlmYqs1\k(4p?F_b@p^TT32*Jin5f?9R'SZ2+u\ng@[c]crCa-^H/C**i*T!RIS:(kGWiIQk>%Ljp63fk04Ld+3"tBm@Q^WqP5OF]KaS]"LW&^IPgK)N,/VCJkYWF\D8lIKgtPl?MNAp%4lT:@%GZoZ=IKT?meVMYo[]^khVV>I_"(HtB"s3RD]k,Mr2KGP?[NM?^<7i1"]];j6[c,'e.Uo>MPG.)hFl[YGV4fU*R*M_VO^d"hglTMtgRY\.Am'I8*Xr2[G'Orlk]4)f$=i]>IOa)-c"9?^q\L[f?s0pO*DhHrjKf@A69lLfD(Y0P[oD7-Xgb5e->5:C6C;C:*^f_:pq]nYDr8I0$o.8T!5*^ZYjj]#>)Kg!\4b@sFDHOqVd6]]G&prJc@G:f@X(b0Q-[n%ag#7M[tESI*p<\b$quP7KV"YdNb.nEE%h25X2+JXkC%OFgM:Nk9^#`0EaOs80S+,_,Nb=H>LI3+5!?4Hj0(Id;TsW>N`9hH?bN5r>[-\F+F:U-`J5:W#jLpf"fHi4N+W&V[$KeIZMB%#"Cmep.[b/"i^qlF#,SBp`OgR0i)fR1L4:`)Cd2!P#%BS"@3Vk%1EeF'7?l/japrXJAR-lW$nBXIc'7[h,O/];+2'lr%Nbp34%S4![8fiOjl*Wf6Z:X2BTj`)UK4'2PjL(i>_h..rV"r7(kSTc'09ZWP'G]qc2)2q6TL!TV=4,4+&<.Bdo8H<%dZ/od]f2(oZP:i&\DNGRgfnXcnrW[Z,k8tO=+4/hce:?&H2!?Eo#AM=aUW]6*A+LC4O?)!CV!0"A3s(4*SX+$dT:j8tG0ocWKKCd$q$:gu^frG!9.&ceDNuAj[0gJ>B7]jE2)(h8SB:OL3m+CXVh"]m$@qoOO<;\S3Tto;+>-qleB$iujhO;78Nrs\;.uo,@@1*EOA(oQ'XT_kM;QduiAoAtjkmE!k1XTA*NUMA=b-Xc@>LI_>aU5%?Imdg]GlFC6C()-%5>7\9hb,=//&t/0JO!--NiBfj*\JMoZ$askK9HcqINj17hlAWjPLSX@$39Z'I-K>lM=]$Tp8kiJFVM?*8"emu@c!l65-biQ=M2e`8[^UgD`c2=B:C7.mBaa)gi\5b=T+HVo02t_b"0cG(D^*XW77\Uu%S8@9kD4*3O^SA&l`$8UFcc5Fu0.7DVSh#W#e63p2J'*dM#KbRCu(ArgjJo\]T*2_b6$>L[N=%OsIX8jfN1,?m\g^-R!jr49;')[mi62U7f0.<8$fC(*OY9?Z]lLdD:IG'O%m#"IJJ-f6)h6[0W:AM5DVnH]Bo?g7)]YF,Gpt:+mUaAV%)_UOdEU\C)6[[DT7Fog"1lpr$hYG)\htZ/34Tj3I@Df_sYj?Xeae'\=jZ[_a;!6QQ;DJV_;RX3)B]O][m4W1]:(j)F$nd\`JGQi58AmbS,Rr;_%jmFF,nrsqVp4cf>8GjUN!Ge/j.1F)1\"!WOs^Rn9c6agbI5ro;$FH-XaLbL:O"]Z.H"+^*pPX7;kbVUAk5oI[,Z\L-#M^!V3+m:=33t:S7,lc^HotNZh=`m;T5SVRq'bpeAS?Tm1_sC?iJ-W/T9(;Ruo/B+%<8!N:p\?(A1geNP4tjhFfm`P`"qs*Z,7"N<08$fFe3>K$2uT/0BUA>YgL7_@R<4[\b]i\#n^p%`&JL`65!q.&f0BPo1aI)@g>VL37t9u:@5JB1L.F_a>e)ncVJ$H.g[>^=%]Y3HJ_3gu0!@21A,A>"R>[mjM]d@S""LP`"q!j@M2NMI6u+h#d'7-ghS2:`fH85T)#^B?8!euJWb7m.7jpnn]rpS\2k5ic[CfkcPqZ%DOu!KK1]:h[JHL]$-l496&#^"Q*Ycem!/&\jFO^(EO34Dn"Q/@DXqR6I/c5%TShTcYRu#cf=XlBZ#!`B>ZRbp/9c7Cd([h3[k\*74d/f0TO2WQ*=a_W7foT&OS%>"ffi`fZGSD%l:Z3U++;R8Rci6hE%DZn*NCu:rU',2mLaeVA37H`itVLat=nNCXEiem]*j)i87ntcS;g_W5*>oO1A_`)@Pkp,q#0HVs\uGYt\YlLaT8<-/g8C-3:K(1#W(,)6WS[Gn!!.;*BV]OAUX[VFrF<>^k^o8A_:&h6CI"K6a@c;aJd)%tAQ&\56Q1sVi0ppj`^`^Mg7K.r`.j/kaT-+?807Z,`*/b@8sf2W@$Un=%EX](E<%0h$gZ5/`/#!=ZW%>;re+A>h[;*SH*79S4ZK!uH'Om@JN?'`K0G*7@4ruO9>oH=@AKbHc37uUN)g<@?/*i,G;VT@9GbK>-^=Y@Y]FWLMBRe8AaNbdtC3e7XlLLBQI6EikK0ip%n3qfeb;O@e8,9aamD"W8Oe+iIfHLpk-`CIii+8:*2:_B!^,,#l4`O-%6fckX**9g;aQ]I.Ih1dF&(81;C7DjXCK+=_ZlR:U'Bb2;nW3kU9`i8@;+`>TMighK'OOq4X3D`I"1dl1[G3&;/2P]S4=jMH$/IXXr.-B\I_%Cl:cr!RIb-MZ#3ame%>7j`T@l\P<02C.uKqV,8Q&0Z`iT=9Tr6YhVhn5V-+^[K*UFKS@Oq1."2Z-Xe&8\GME)Q7"/,/5e)3O):YhGpu8j^SMI2Lt<.:=\I2P?d7H4^0P"ma@%;NhY#TImD,(??^8npT^'$nO6bC><,4L"sNp!k$qDJ:S43QGoXAD2W%CfPqG'\Su9T6S1jG4*Vs*d#A_jW'0&*s'SM1)$t]_o]L1QtV)2ofumB^tTj3u`O];jk[XAB?0p$S"8QK&S#VVLn6Za%U$W0U9MbKbeEl[@/BF'kOusQoMF>*;@t]EJ-dV]H7JK#od/leG@D-7p6#C"G6YVm]Pps&WoAAiO`o2b'"tB(DPc%+?W^Z-X^=Lg2gN-h'QTa@5Yl].Z[E#c,O0X`udICb@[8h3WolL\U>^g+'q4k!$=&:LBi[i75)h:)!H]a\:C2IS(pDAWT6>\i:.Q%$k8)1&JE\uMFfgeFiq*H`(`++Rr';CV',&`V[(tjH58mr84UpBac;'>:DEmn#<4.-*_,eG](s_SVEIH<)>cIZ[KZ,=0U5jnBnntu/E-EfV%_s@^LliR4RC>('41buiBfGH9&72%&BXmp4LK"j%Yp#?0%-<"6VO)@5[XlEiQeMn2WM4WOKIY#E,,KO<7X_k!HCtG/A'&Ig2a#+6+[/8X[A9j&;*Li=!NecL3+_b>^/b]@5S?H:#CoF>4\#8$:aK42:D:sNCep`X,Q`85G>hjg.dZU2=9lS#j/"=,L'Z2ET%S8kGu+`>7p`r:FgTB1QUPrim'Z.q'(aOZ+*T-A&"a465_`*6aK*g>u9085pGKQ.!*f5MeR9oL1epHh;KPSi@0nreQ80%KP!m>3hEga1jX?@+'b,Ma%,sFqO-j_$H`kY+6Nn2Ld(pTqa]uT+\@eNgMEEG+?EeOmnKq3&Lnm2J8qO5K:3Xi\:Y.KK;[=u",!>1_tPWI569Q<[O]9$SF\uWIf]?DT6*D>.F8CTiq;5';CFIcc!S5JPNbtgPCjD;*,gl]0uL%9/TJ.Wn6)1m7T+GPSmk"Sq>[es@UnYP@48F*$.5.i0He,>'.?dqia^V`F5dq_e5ZqKE^in9QWf0NpA"?2::f_7$,a4`=("Zf"V6B+mRSdCk.@QE68g[shu^_l1TDWJj\bRGS=<4#JaM@F\?BtVHZ3nRQ@(]pL'Ff+?GDX_npmAni#kklkW(g$5TF\7,tjCDo_g:H-[H_bRNa?O5Mho&7d*;n`u8YQD(F6rgo`8:Sc!7#JnI7+/<465VrrReF^%a]q'lgJ*co2gU*TnkJSoQVj+L+A6jZ0T'aiEf6r(t>B-?t]T\I:m.YMcpg[No_Z^Mn0R_gi9kQ0K80424n/N^QY:&nG\G+o?t3-p\/$:CVB:kTL2Q-UWFKXSd`ZkC1]2\DD'MBJ-g?hms8U&O;okV*gf;&"2bL.tZd2T,U(#(DHQ^/H/[7F,Pg-gFr'1>@!fuk8F&>9H+9,R&R8+lkQ\'A]cYu(GQo@2+Rr_5'eT7:?V1H'^'4T07el^+t1."rkM#TWO!"%P?/*&7<-W:nFo"@-LPkT?GO;[`aQ00ZuV?b5;R3HT?S'?dY5L-#DR8:60"FatIY$K?K;K8F#%N/4j$kgH[g9KNh@3'X-,UUU_m>VFsS\K&,J]er[^0T=8*a?_l`ZT7l*H5)7;d@$`J@Q5kRFrplP_>;r2U5-fa(qe[3pS%:u6^))8s2$F^i\:'@:Xc4/X.Bc&o=!BV\a<#'C5:ZQXcBJf6_BoL26P:VIIoi59GEP8!I.LYOcDb`$c>:(C#QZ(hr&90R\`.0-iD&rdD^(?!aSs-B:b/q!?>=Kga6jca:CLP([A!JMp6aYUpf.B_9?W@cI+`j)PH&GkK"`qASjVW_W=Nn"*_-RF;8Gfj"fdQq:9>O!KP_`_bK0pWuM`?>3#n=2C>ppS>M>Q&IgDdVF(&Kf`g'7Q_r1%%Mpr:=oi;MIcHhMQoRVCF&D#k:nJ=cZ]2tVoEgHfkuI[iVB&7b4LLZmttoVDGfWWnO1mEfg.V7d+QDYRDpI(r+L*6u\1=krcNVK%Y`Sk5_*bsl-DF'U"tNXS8m1lArO;I*_=jTSm*h-L!VUTSrl%p$`]3%-S"R5Ek$a_2rX'AQIA?GoEH1F9Ad\u'5Qq>2j%IsE&fbW"q8Rb#s7T_eoHcKcoDT"G[A2#Xtk&Cc3/-(5SE-:dDr+7#j>CjYNrL%5@j:%!9Z%f_s/N(Ri[oQj_W#2jndIM[lJUZ7LK!J&@G#99T+V"+7h[.VjW<'d)O!a62[dU+?NIE$97q_7EcE=uQO.ZEYfBi,BsQj#FdSuG-lUTR';dEN4^dK8t]*p2K_XJEHo887YRKFT1oB1S!GnQjPT,(HrhM@/O]&X.Tgn'9-9F0OsM6T/,j4%L0@46#sVbHcCubs7!P<_t8:Lnm_'9pTJ(\hri\kg?@ab`oX-87dUuo,'fG<2V'H:7I^tVX7CNSU4QCB3Me'1\$qtl1/hV)G?Q1=aXPCrqY[?R1%34B6NuSgIDEKh#-nY#1ii(E[3"8/1+hb+QHc)LP_hG#D9/Pf6:*5,"GQV5/uf"Ncb!+VSY:WiTX)S6mG?T9N,Inf[_\hD".YFJ6/,C3!ThQ>YX:'$A!7neZnh1kqOW`'FaM\97SI[L%poJ3s^j]Ol33Z+g#rMV8dW2K+;s$(p=GLQZ%aqgc)E4`/';.AHN'R\aWrhW]RBZbh[YZ&p&k(cjgWF4e8YW'2cIdk*a50_q0"eI0Y>i/&=]dj2YsR0)[)IQH_>=&3=Q8%o?6P3eB&9.DHTCK4#%=m9Fd\4E+8W%($nlDL37K.o))($u.@3M!k#oE**iQ8V-Q4?4,>*r&*)/8_Kk[dSF$=LC`loa.HBm$m-T%Vp*qLH-eIN?O*@?LU8Deh1u9P@o\TPkgL_&G$8?eU7tSGj9%tfEMOPCKmJUp*O)R!F@5g\Tb!]0@80/O]J$'>j+mq0B*aXH_:&:>](_a"`mek)O_VZp%!GsMKU%7Z^s$qf0mTPA+:UMMfCU-VBtGjZ:kR,59)T/,Gq;sETJT0_r5MsM\+qP23H;q)i.)X@Q,cnNY2JIX!7>B9&]'=n5n0ZPF=2@KDO&)#Wf-J%#%S1M-DkuS!.)uNJ2*g:b1nU$2H>siO\i+R9UbF]eo&Wi(i'q$95#\c(1_E#UJNSKcKQ$u1/73Q0;bY%=@9pK&h>DH\,\6cFjW<$u>'&4Ukam5*j*3/O&Tb;ORWmV7p"GtQIMB=R=EpJHMIK&i>YLa3:dR#f+qi=N<:#G9H`gGbnr3$a8oAEZAG/I6iDf2c-VT,i+2Wop/$SFe9:5pDuQbgm>_WQDD\AnY/CHdd>e/qhQV4kCO;>dRo(&5!PW7:7snTT(WCqe,70PfI@oF7/_\>!h.V#UW4+[DJ.<%T-LO^K^B!8?ER^E8XcZ)teV,;ImiRDMl^_=>BHNr?%H[(fjoctU)]?6p6USFG2jO31RP@5[gsd0V/&Y?1?Iap]k[T"+4k0l.c4R>f[`ia.2T!LqY,h7[r:pL7X:C`&jjjX.*qm3_RhR_`rG:X;0]fbPFAU]c67*7YWB5U^d<=^k&BLP*FhD4"r,]P)X`$h/f5jhGYQd+h/".[t"C0=)E7cr@EiRtY!O3nuc"ZYW@Y_-%LL:n6qj1'>L]r>eV:mG&1O2ND7Iir+p,'-7Ga`J#$Q(]*+>^ET^n=g$Obs(Po9kPds!'Kelu'>NZoUN`nuro*.+iKm.%4TcUaDkH.u]Z40AA=(!d3)mK#=<3P?2;E5W8%f0@)`AV0LY?h\q7jT]M_q0`%q9:?cW+9s^9KEut+fg[/WVTBQEcp3g(.g%\oDSkP"dDNA^4"#GEachrUAnb+&E-_g4-Ak*`B];'>aoO$`%XMaYF8kGuS"/a>MTA.cb5&AF](d\r%#p-9d",Y'T_g[C#0Gu?o[=p7Zr>S/jZAVAQ#kZgNOe[eDFP+]\u]AGYF+c9)lfNI_V@mpDU6qRm71)$6qd3,&I%T$@9Z3I?lZ$seSm@UF(J0AOG#eAT6YKah*HKga-J8iDGY"%IGh.Q;6Af7/N5+cP(<^/_i[`P8Wp+$fp/>fKla2$_2MHb&]Q0hcsd%;]dHL?**\K?T^=c?URgG,\\)tK-Y?-9o2;QkNZ0HFqaeS@OrTllTd=l;lc(@Oof;_c1DZNJq%/%f@ebJ].Sm&l,4Xs3M:a2o=>*-oJqY&;oFN\_V/?m&dHt!(m)#WkuK&32%%\Ne479m>SI%GAg71a:M34%JbFTPG9JCkj0@!^'K@&C`[J0&f5Ue7NM!de^Kd2u'KINdePc\g#J(H`oEJX0MX;Zn7@(k+c+Udr9WOA]IGpN;(<,%:ebQGc@&omGEbjA]:.4mQ'+-N;Ua(n*Y04SX)7ku+'=`1',Z0d(WOW>]4qf`p(ue7F>jQ:^B#]bn&Q@'"9BL*:3rcMS_`bF!HC_kgeS;M&O.bBE,XM6hB*gC\3q7sk1b^FOaTb.jU:e=;`*Gm)3VE^`r1LB6lVdg`Ar/g=5e9f<=0JNPpHb(BL&nUA[#Pn3,=mWjB>1."<8IbUY\H"KoAF.cL'I[6;)@l#6&,T*JK(+JeW:%.q)'Z"Ke$j1D,!Zt4j#2WSOb[@W'h4kA<#0IA?C8WS&_Q@"9d/bYJ#hGcFHLjja&OSSPT:d+r2AiFgnG<1\3mP_-N#LhjKV^%P[Y-I5aiJdi=ZEjLUpatG_HKqI(4!o-302R9Q%cOM_)9kT@6.F0'S`j1#<+SW>b`-Zh;drs,VU#;),C2W@,?K`k(j3EtK!'VU6\+fL23*1IW7n5%7npZ<(t\5fcZ3(\%mQ$BK=j7P^.KL/JlO5$uFOGHhjn\Bp&2Fns#sVB7cmomgO[m=UFMm*YtYO1MUYjpuH$HT$t+&_>`L!?1()`$@9IQk19]orrG(7E]iJ>Fl,N_b;dqOU<`AK)kMl>\/)p2SF[g'b[Q$FgO\%HV,:7/c3-DD1p(S,T-oEpK04VV>)b!0_UQjDQ396&tebPLB"U]r1k+/OKl#G-4'Qpuk0dXsuEX,_0@<2m)"XsHQ2Po=HC0igdo!*D"M@0l/IWS'Bh)p%5l6K_"Z`,,GO*a.\*:7)d(:D0JfrQ=4ei>]lRUq+>]?AIjPFEl!%o"^Mj^u[-W=M:^%>J6r7G5#b/ube"aO59CRm^_a[]Q'K:m-e%).!p\?]<0LHQLn,GPB,0]oIb4"A+e[F;=>!L3XE56N.MJ"Temo-&Q)nJoONGrOHLmHh4VTH1Z)G^AMfA6X=;m(^k2Xk_73s!6dMnWalE])&W"7-UUAHk]%>=WF`:>_1G?qOYQYaK>K]-7k:-tM=usVC9/CcD=0>jF0bYbM*hDZ5l;fr&S37j#l;rND.^G*IKEgTQ\Y/(PrJ&dB/>;#0>6Zn?GOYQN(`I6lY@cok7LS]o>!l9r07o.T@CZ3TAR-Jd.=-C;3jhtab/`:/^KQUMRZ&8rP_:[QiZ,[S_3Sm[7A-a/R1@PTaZ-p"pO5kVSQ>lhM,M)9:FPQpS&#)L++S4]Gn(@4'Ib?^ZlYi0Vk?R7;*[K@<2tpDPLacd&h(&"r-hoFkFZ*Ef)V#7$uY[L@X:qY3]Q(SfZf2CNOq^urH&(E74!fqX&b]RJ\Km`-5df][TE,dhL0f_.T/W^IYgEB0Y(,C:B5@)5;[I]O.&q,T_W8R@Z"+=Le7.D[;Nj>:r?p,)tLaC[kqU)H[X)nTi%9nH"ZPSf4(jY[@)m>ki;fH$r:"q;EK2g]B2;),@`./0`Gk-@6j6jEgMG+6Oc[q7CLmH95f5((%@'1e?UGs`:%nP)pLS_rH=?L6;Lm^mY_)\,bO=_3Ek0f%Y\e"Bak(ml3qpe=LSpq1f+cD3@+&/$6R.>#/<`,k*VI)d2k!,5+:ga)0:iM)^_Os)@DGWV4%o#qUokWR*]3HMjU*GgbCK8l*$9M:5h5=:8TfB2-WhUTq<1MCVs*P\(@)&Amq[D!B+S>\R)@1ICe6HMLt#>Fd*/b(P!.p3AefVQjK#:_JFqdBY.Yr5_NT@Iu[l8>s=O-nM?DC#P8DB;Hc;LmO\Tq%Lj4cYS`QIc7!q*?=eF[f[\0**/;`?g#XS9H\&nN)B[jq6uH+AO+K!!*R*4mUF*Q"bG8g_.:)`kX$d9>T\E):#r;+,AaApulY6#M.bq$qpu'ct1BLs-N;_&^aiaL=.64!+/:r7t$P;kZ]u./AS)<$]nJH'4FZ+*3fggkE(>_'HfuJB"SP;9tT$s4HB;8@Z(7#8J3c(WGqJ)O5559:>VO/]A>sM*M[4$XG5lhHfUbV%cZ[l)aEQ^:1K\"S7r1G2g^E"HAH!Ku*o@dAh7@ct,nU,-d)FSEk0ZdJKFPAe]!&'ko^@5oq#c\G*/sjh#-D(bl5GFL)p831k/HE[jXH,OH0[JL>q<*d@/m2D5jjUC50GC!N:!3R]MlO0M0p#/po;uN5!oFb'FZ;5H8f3;NQ#ONillus_K55DJ,ZS9q9B6gfik\U8jf8NgcUdjUGd@&>&),c819"6X,l@%tTU]:;:aumgC)A@9F?EC8;f%2!aD6Hu4RYbf+Pbo2[e;D4u`.G5K\^Tt/(+\fJd'AesQ8:Gs;\HCD),09:;ZAD=D#L279G0HehR[D='#_>mYrXYN-mJ5nt;.QImR.ArSOhR[Pf.VY;^['fOY<)phC8`1bm6'raT1Lfd0X]a9e=@CnAIfm;:\.0UPtPoVWAbm`V!2hR\S9HFiVbBorj6jQH7E>iAUFB>Tm>(MLcUYuWIY6C\&N*\foDl&1"0qWprdjbC,QtE!ECA%4FT];6,pWS!Wa\a,OiJguWi]N,;/Mm/+^^``7W-LQVWA_i=WBRg92QTa73nl"PD(ej^Qs.8@88cZS]J:m26Y5iS"i'?rMN^F?&;]<$1`=V:U=*u[n29RPBR[^QR@C_;-[=1.pT+$p:2'=d-dIS>Ei"G10gLGn]`p>LRmfcl%NnN8LaQ\asS6!uhR*`2dECUbtdg+4:U$f3QW"<2e/,Q'!>gOZ_*D0ZWe44=pB$4oUt*K)#)lu,;.;G\H5:TIcZ+o&8uGM7Ikl^AZI_4)UDbX%L,=128%Rg(!beW0?q*G>qgfOD"K:h2pu"p"(n5Ll"+!6-h2i6kM2afnC5V&M7^s]iPe&Nr3-q9MTNBQmhk/Gu\;!a/QZP3fPQ*"RXqmMmu]]"$"4qnFdHOg='/BVd=q_Y`JQ?DT^kbN-=BX*BKsS'k:rS@U<'F0-sSC=Qn0,9n7&IH\eNfq)b3"%^q%&C/jR29=.)L,ab1hR=oRA83)/!eHBQVb8>0EsVTN])KpVmc8"30Hjapj2)@-Q=C2K-BL*k@Y6R8n/2Ol4OS3%:Be>$K(QT(pL?q,4Sp4J3RG`s;l?V!.6QL?K$*CD3q!57p20WZ>(W3OB`Xt>Y=cB0)hHh:q^IKc"g)lT@@JO?)cW+$J,]4+!$Cidp>O!cqRGo4QfLAJ-`[Hr,TeU&A5]>Y(HW_)Z.cQO9`s^0j"B]3l%edEIl1\\s)l#:EjCB@`Lk-3Bc1KhX7[_"+K$$eGb)_aSph2nl_7oN)7A0U]#1@n)[(E?)To1GL#L'YYBNPM_Kj6%+k-EA;1b*"SpI!\jc506YJf"\8oD7=loU^][5jR#ra9H&#foSb2.5?*]VhOJG&&N?;o=Hg%mM:nb0tW8-XUF02eJc=!2D-Zl^`WcifW6Q;mKMH*gpgVQ+$j$C9P@VgNam9]a5h'"W\/aPVh+d0d>9/p?_(BNL[)"O2-!loc4@=Q2`m=@%%?7kf`16`BgkiU$6SR_So(_$rK5\i^r+^At["Xl[(\e5?\0<`6uUqY`@>r<8fk`hfp;@"`ZJ:U7Bd6Ehfl6ufQ#[0M=F%dg,jstkl8-de_'[4E-1H##<"pu"Pese_SqKdW?CGkPVhgaPNKu0O67*Hf5Xt&E42c8HUn;tm!*cI$:lGrLV3,Xa^2;52:1W74U[c5/n>1ne@hnKb:7pCg]Fb2ua!!BRT^dRu37@n,j9TEKpIdDik']L`@+pc[i.1\oIV99+T%gEDMl@51uBc!;L4/>37+:XGW-Jn`cp+US5AZ"gN[ID3!,!RkmGTm@t\nI2;el"&0850"R]r2ciD(G^W=sM2NC[chED>mILc<=m7qYY1kD8)U@(<$:CgV#/2MZ)lm[V!91<"?moZ5d6B5WJZ7o'4n39$G\*#bWDEB@+aFHooCU7.jGb\E)aDNm#XVAMjYaOn:KC`HoI'F;\R@'i?Z^EUo,Mo`nC7t3,[\PlMu=IFXkJV+N^)TAJJm>tRd+d6O?6l7TKL(%>:Z]aAd'hBSW6o5e_Uk9!f9ZQP-7(0S,[0`s3W68:W`g3D)r9/[A?_e1NrLZO>&#r#bi.006YZHC;#?DVBZf$qlV*S'cY_bNL`"H]gamm:"-rm?:MpD\%;dSJeKpUh@N([I51BX?>`PuYHCDM>F/*qKaC$;@Ws\8$L/<0.IZT3cO:9Md%tZGHjk@]"*B2RKiCN)^iZR+#@SLAQ[`D5VJ>0RIHN%)_3-+F".bmgDj_B9sBm?RWC4lp,!Xrd4B@7#:u@)59EKVrVC!AmHjB66^huq*RT*'4OH4qGG4Z*5J6_Tm!4!gBQNg`ebVY]B3^(1dj#_POS,0eQgB$V,1)(K-mD5A.rrF1elV4iE]:?Q@arJA!2d'nnNi!d]r&HWd=t%mpUl\dO]WZiP&">2g9`pOk;QWa\8W']/Q5>%DWa*;>_7978r,`P2GR5r67'K6Y`6o6eJ)`\cR"1CDh\/7u&C&`ZOgq>Sf:>50k86ddJ=^,+*:ehESU(+TPI;mU]!&h*o)6@N^YW0/%d5]W?CZ0qf3cqGJfpsR]7U9Pk[;q394^jpW-fr7095lEL$al=P^tA8n\H.WCa$"k,2'8F!%mG,bO>"t$Sud3&_HB;/$EtZIVM#LROrl'?9R1n.IJ>b=qi59JS]T]E-3@sjYX21nj'^n/DqBSdLRT_g(Z0Uu,jY;SlGM!0IWX&>(K;W(&VWEXIhQ,dN)#.O_JC@G_cVb!n0?G[0!oT)'U\#&4E&t]M0Wd:DoctD\]uF,k#k7+&B@k2C`=dqh"8eZcZZ/Z9C\WM?#u/DoY$p5@<'QV^,R%n'`qY!4:NND8I-"PjCIsJnBa9?P/8uBBX>7>CLBUc&**s)6@d5\8`n5>Fao\O1*(2;4jS;DqF_R]oq1MaN=;*6\M;*H9EZEJh[suh8Hm%//'cUd.-lDV@*b/&2)/?ql,N4]ijmrc:et"^KfKjb/V@?qU+&@CLrD1i4.Df`_)RW'U;3iP]:qYO:3U+fhtegQ!\noKLJG5QO7-KKBBIah-@Z,dZQQ6;Ml5[B2BJ@TmI9]::Ra[.r*"f\mi4R4MI:Ef$;ULX@8\'N8TR6256?]QSFV+p`/.bGKMe`c!6o"j!IFY'[bTj[0,lVFE%`$m9hc/E*%sd/eT+,)eH>8K4U:C-X5F%dEkuc>aL.]ehW!VB?NN"Sc[bSUmG!DhDCq]3L+oO\$[=Dpt3"SsIQ#ahApmkm'1(W$Mf#3bZb%\ph`O@YX'NY/:8>pjtZ6_RES5E25@\APEr"NkDWXMOd=&sb2/g`(BuGKmc5EbLhd9%pVb&9e:\c8`Pua5gCFrj$/n9l)a^Ik-MGn1h9I>'J`<5pN[iAic;3$LJlLgRM3.h_TqQ@k5j$Il5e)f.([2E[q/7)!'XPA-`;UimVl5*@5Q&OCY.P(T4WD_HLUQ5+_Ymb$!hi[0sq/N#XQ%684Z9b*u#FLWS@#&Wm0:F9Tf=@ZOCT;4Y(EnB)_7(N*f7%_Xl0Qr]ec0Q34`)LrrBan/d5:d*1^euJiES687\X*\oH"Fk[1'#JrIMbc#E&Q2X"gip7%lCi6]d=Nlt,lG4ZRBf5FFDS^^pVoOVhj>M)fQBMgrg9kaB-r`j)reUrl50dCVq!Lb28:ZBj!pY_T0\.?]:N*aH?$Q9@H&;Gmnm1[^3ee]Zb3')1&(<[t]#gZ$Q_J"Q>F&,u`VD5NqX+S2]=F@5D6L*B,_0mq]ETV_hdJ`_2%Ic,p5qY-ZctY>iiXI2fSc;/;b5hM3=:==kJ$s<`=i^A6)<]`03l,X+P?;J0&"%41s%9G0TOdRUR!%+Ii2VE/qaBd:.MOu:ZP\@U@8gPa#8kVD$4efZq0#Qu;;sC6bZ;BiSK&-qJ:jgB#4%dW9_]rjRDQI4*t4LNs5)n<54S_LtOa_uM?c;?7Y-YtHjFKhbi>jfK+=*7$LI\-f;LeAGC2CE89YQ]K=(j2J>_>u$Wk/bODP2Gme`;rDn#3VHE)4t4T3nY.%Je1O:3+V=lM,`8Mga6B<&`h-^]@R=0c^*;W@Kr"@W=m#5gZ9$mrKFUT:s[@AK<2a(/brQf^+n&.D[%"gm7g=2uk3<#-cG?\\kUa+aV]$a:-flW&IbQ%4oVf)i1C]t3d16Vd1MGX\@9\q+m`>;?I&'J:(k'o_fahU&-P5A%Jnj\h6o[;+l0FI[&D=K:;p6f,r?-hT6525$nKpeU:5IU>MmC0c.6^@8gH&[lgC(&a]rIcc9M^G<4?]Xf_J7MO9!]I9a=Dakp_3bG@PShHODT+:hZs,a0*0LDW%ju[I^kmmPqWInK;ns28lM=d_J,tT89p%?>8_`k_$?e=JIgYL7k=_>jA!oZqS`qW'4"EIMB!%:A:@Lp(i+/8Qn&"Hj5oO9)7Wf]1+!Kg8C0Q(n%A9t7&ne)X9jAQ-@5A=3%C/hA1d`W2"da>IrqBFr0`Jhc!$Ao/j5#?Y3@EY8?Zugdkf(+*l-jG?66[Tq],ar0d(mn8\`:X>=d0#X0/sGQ=@RP$G;)LX9ksRFka5;Up_A"Jn8p;?(G);u48#HQE(HS"ZoabQG45(3#>5O8@FNQC6'6?rZa^n;D@r\3e\BKs]gW_`Z2cGjFE@6]jK36Laoo@8(AH(B:%=uu&2>.k@jYWSAl20(_+ZGfOV5VPB%W>bN`$QerWnSXmKP@#TlNVgSBP02E\RDBjNM"o+=K0W,#[66CEof1-PC/$$M=qs*jI"dX(I)ju@$2Op'IuTkFk(i/fbd6XLg!$9h&WgXkV-#2`R:/*k%%o#)Ll!OS#b[o(#V))<'p'UNb*+#5CiGroSJ[_,]2?``J!LcB,:*k"WZJ#KO=cVUWq6*_j*^P!=R$f6bKZs8\UhUV;;=cB[3G"PD>YdE2L-t"FD;5I1&ZA:l@..+:\'mO1g:^E+r:9P?hqGWU_7&jR,'`VA+b74_7+7$#$>AR+TVcYN@7,*@2dOq"e%9ZO=4'$gQ!Rn>b;dQDJMY;H[^j*Yo#j0Xd-6kLSkfMal0aY/jX<8I>bPOYj_2ZnN+k.ZN9Ya*A\Mp@=$&\^Sm._GR5bH-Z;d++7\0=H3+4@f>0"P<'1(Ee++q1F/-U-mIqIq^Y=cZe_Q;uPP3L$md+rHkrZ+5TQgW^f:0c_JsIi?1se,X)P7DGhZR2!hf_mE>Cf0Tl3XPImO),9pX3RPPF.aW+Q]^gp;_J\K[m#`m&,VN:A_`jI/NFdLkP5t%J4*UXre*2,BE'TI5Q`lXU(G$"@0jM:s3q\hmKM7SZ:])gnjNDI'?^;9[;+*dt[IGpSb%MXCsrr/7?pafM@>Q`Sjo$nYNQge=:hr@,754-,8iL/%6_"V-\hQ_@Tk-i#P%uI.VjlPe,D2.8#\,Hs\"'"ekr4gf&IA?3PJGM*i`*g-%#HSJ(I3\.#[/RcIaSgSoj_uB+r-UVFpe+iTq0XmbMX2;mX`ZWG?fCT4r645?K4"5UPXUs(R=FR#="#\"D4+cJL%s^mfk@0UV:s[IAYLcD(aMsD:!>4%U0sS@lK"9f(rpq3*R)^QF^X9m#`%f!bfL)8U4G"cW[':&=U&F:"89#s-t*HBGLm6pPXFuA&ONM@-$>2:OfFY+cFe,MC3Pj%'3)28!CI_EjC,/i7l[)bmH>om-45V'8,QIbp'($)?GA+Bhp_?"Nl_35$9S1cA,)2KIJa%/art,qjlp3dA3O;BoF^#o[_R7VbW"dOmDjOnS/^#Uppkrs:V"/ELO#u,l`pA;/eNuD5\J-d=_5YI,dq:_ruAuR3]D/.@a1jhV3#Q&@jWehm-3333*Os_K5MOd0bI9)9eQ1LfY=]kcY&O]FpRn&=fb's4+CF-%iWfRqG-2en6`L4`uXfo4b%j(L]U00JT#bj70@\aYMdRRlGN@VlhSa'*BD!0r`c#iQ8R!MPDD*kFF7B>/h'QI#:[R_3dM_9?mi4m*pG'F5D8Op?d6a\[L:Xlb_qP%r$;\&,E0[C1?U7F5GFe]c-A@5juRufH[MVKQH=F?j6Za^r\NcAlf`>pZ4:kWB)_uV-5h<,T.dXeNjmVpRblosBl9^;K0?E8@F`.$p!?J6oS8%eh^I&82olaOOOL.gZk@*cm5Jk:N`iO/RognreZY/tT',-!["JJ$JsQ4C]F+hG!8*PZrX.)IMM-:Jq:hOhs((pq!n'3*j@mPrP-K8YO1bT_maZj=,/+$1`X4ooB#^pi-jOEg#^9]=607%%/6p`QZ'c4a5cAlp[*nEjL60f_qfgB:^q"6SQo>%[OQb5%ptY8(>T1V+>:jC\pjZdO6',bJ&@Vjq_S18B__WQj;WbB]FN97!Kd$cdEHh.NJ#WGcr=JIU##94mWBUo4eJNlA(eX.e-EJ]?ah^R3#_PdFRj$D.]3UaU3?PkAM#%f)'-:4iTjHY,-re/[ZAA'sl%LIF(c6`B.Ij#lAdL>BU/hVAa7H&o)5lqXtdI_N);0$:b1I'ViuTn89*bc*Wm3_I.o]i("]Jn/lH)+n7u#?[.50M\nY>(;oi_o$S5Db:NQ&K%;5RO8/n_hmk%!foYX$-s["`B+ET8)Jo6+tR.N,4pnG(YuQn<^m-8P7(Y?,;^'Lq\/0Q`7V#V@jh7m_H%(65rI700qEMC^hP^GHq`B(?+"nesRdHG39q"qQ#%&IQ4"N']GG9OFNP>H__a'umK_5-DO/:Yi(c2JjJ\T2:)f>l[Qk//Z_[VSiFaKi&E*6Y[E@W$>[isq^Z28Y$h/n_/0^b&`H%$pXiY;Zjg[<)fm=sh'.OgD5;m"H&A\PT&?p'Qb?5<8T1!*WF-@>LcT6J3%\+E\jraW5r*[G^q;+DJJBl\jP7^R&';h@h3!<]<(?%?QV+GD4sVtdiR5pC71W(rDb^G#)pIih`TY!*AHo&/X=4d+!aok6/,2qah+4a)Ua?2+&@qu0?>O+[;b+,@>aI\)AmaOpp`,M"ED'jfVf4c&D=Np;\f5p@L_pO=7PYLh2"4qGj12\GP-I(XZBBXpr1j')<[dge;.H9==mdS;q%k8)CaB2>sZ[q-s&<-3SLYNjH/RZ0XUXZrn#1_8)#g?Cl?;9X.W!J(0!"@4@B`J[#Z"(3aAY8f3[H',Md.i#6]>V@km>L6E<*QI3BS.74ZDUKTMB:$DP=k2FDqE8`AL7Na!P7C!FNbT\PBV[SsD,WrCA2k&<+<@P8#J[HHFYQ0pNs:[e4=n5rlU;hJm.`g1/H4IR^S9Y'HCTiDUj27W#DEF3J'IV#gAlm"IXa3Z:P$#74ORce&AX<2;[cr:&RQG1DXLd31OqJsc[S_1>rLqG>m+(t*SF:SP)QN'Q)29P3Z%(uZB%engUkTGA1EuGgpUT1FErMRC]`.UPirG(m3D>f]?d1_3BJ\D3!igqJKO0?L4$76.J;u%m?DfnVFcFu!.$mM7m#1;6:p]]3ETi^'S(o7S(TKjOmWea65pnhloI[H^RL9q@6GTP:[Pqq'Z(I)6`tN3X`4YV:')Af0oN1,k^Dt5QBB0R(`mq#@>J([]HfJl83h8TNjPC-/"k440Z4/=2KOr*o8fPX>P^XJ#XQ-7e,^bh_5,Hu6mRGINK2$\`Y#Z3i5&GPT>soIrjO4`;?5/0AV1^a#u%X\.[m5d+J=VuhI("W_[R/i"rK`Abt@@MX&Ui\aU\h?6*Yuq6^*Xs0%lWs%Cg/;i^0Lp+U43/"?&Z@L+tMO$8G(%@l$r\%AkXa9f3'n%*[:4`cP\._^#=&i#NmJO&@sm9&l[9P"MU*YZXdfpJ)K0sa^it6JGZt@^iNQ3+.:su?]'bW!a.A3?d&[IW8!&)Et0nS`BoqoA!VqnJfA6.7h_C0DKfoQSO9`^)bj=$D[kpG^gY7l3,7J/[gNfSf%Ph'.EP";W#t/9H$m@/ZWLi&<@!7a2$_W*M6mSaa*XC8)H@o4Lg1:cSWJtHN*gNTjm:7"5\!5+(t)pI9?p%^.F&[Z7i43Fi_uOEUspO\#1Z_@<<`tN"),q!\oel)f1pBa["F5-QVAH_@.c?.0@BYb+CFID87F::k+FF%Ns$#3!JWuQ_8jOoN[D[eENf:)#lbe@9GV)O[(6t/,A`G]\#e*e:tI-rBR]!b:dYh/m00)R,r0Z#6N'!.6rlGno6heOfA+if4=8iXfjLN/;>;i*@91)%e*g3BS^H!l@%>UN*(E'IpEIm%1YjcLB\EMX'sCE9O&5(`\R*qf&nVE(dN`lCUc;%h8b&Pr!(gsSKh,,&8+$VKd7M??ZEmbbZ(5oJkZsODB:klHL:9;MHH7FRO\&M>)d,3"0daND_UYAYl%8Kj+lk]jmXUo5MhJ\U""i!kp(!gcf`h_Fk-aPM-=(o]TE:AQ4,l@rOcbXK4T\DP+!dd4ED?Wl_^tTJ_:?b^u]/t+YC6e"AQV94NkZ2)nb2.3++%IBsQCO3/O`#3hdd*J>nofdo.VmB$S]+@N?U>*Sf0?@E,oN`NeO%4-\"!q73JiX`Le8fZ-Sli5@K?FV@NBR#Yetm9F&2:E8m/=-bjWN]).Zr48NL&#&%5ULJ#XnG9"JJQk,!gG+qM5')&H@C7*0r#%:7!kjPe,uNaGXNmLtqn;6#/JbJ!_Lmfuo]9RkiiKt=I3pXtP;$aV#&9G9,'Vu2%V?a@?0Psk.?lJB6pD*k9B@mf_CaoZ52hhE[9dl;gtt((]?4rf6lX^Tqt[b\B.p5Ck"XfZJb)J,Ok/&\VAG-t[q:GQ$k5;MHWt1Cm)ct!%,*cPWaR[BP"J4_74qDC[_1O6*,O[u:(n!CELa:6[TV21b2Fr0jK8fJhb@R;S756&Z*hebEB1e>2HdApcqKkf`7!ApT!'fer9!Si%bmkglQjJ[m+Bj>gk;pX:tZZB\gq:=S"hTZ'R+ZD86TTOOll1_9SV]LmaXdDfQt:[4Wh0oXaoS9r8]Zg"*:-mCrj\A^h_d_[l-ZCEcpG[_g!.Z5rWV1XEc;2XP09ts&'.@;rs8B?QX0lB3HGY-[17&O)RO=!"98MI/Mgf4P.HTnat9@K7m"DSQ"l`TCSm;X>$A.FCj#;R_dcp?&RkM?-4Vt,6R4oQFK57Xt>fLebE5ufcInjuWr"O2Hn8co#9$,eefMf"G`'Jns"iupPBqTdE_R#F%\O!eMI<%[#;.p,K#Cs*$$j4bKY8'/K,umG0DfkjR;oL-:GUdIS%Ys5&)cNHNb"727OVeJ-J3'h(G?79+L(oJl5_`\Gp2H#.C-bZ1!!&!"2SnZ[$TV@PH.o]m&`1W^ng&?=Z;n#V5=Blf4CdO[S;m<@PEk;V$fDe2oG:2R&Nb)LTce_?Q/!3*:gebV:Gd:Pcr`giU`7^ZaH.E+1>,U'66-plP(SS'R]rJqT'a2a0X>dEhCg[`F9@rXN2V37";(c?2DKg>'Tq,aQOs-[P<\TLJ2P#JHS\gWgr?CKd4;p3"3(%J`+d5o>Df*AhAS=#0$*25DKDc4&2:7/)/PUdQP^+P>>/C6=8Og1e+?toh\,,;'l:0[1cQI^Jd,7HkLOOqW=;b*m[1Ze)(^rdVj9ohcf`ogIQELA,[0"=Yf1aZ*15Ku>m/'FfSnVdb"r8a#6_&1"EG/bB-YmgfI#m6i?diXV=Ci/uD;R76)P9LYH"*!lrknlc<#U^7K."W&1g_)u`3$kL9MnupLN8F![AesGC"."E!X['"\j^C$)cYK8"56ZC-;8+U8-V@Fu^*d[MlWLp@05M<-YOGQ!TiFDFRRtYBVc*J<_1o?Zo*s4g#FE)tUYB+0p!`Vt_S/qQF,)U0mRpZl*.Q#rNI]rt&8P984G9\8C711;!\4f.pX6,B)_5.5S`cVtG(=Z98XO^iD_`FP5O@ltl#VJQ?[>:Eo)>SJs#,3'o!@S&LM;GEg0$I;E[H/A9T^*&#YZjbC9gXlLsUNs[Te7h5N%I't!22oAQI3W&bA':_[^-B!l)FDad;&VAmm`F(6mO+haaOd#T]d[S*1DVLEQ]m4h)YsqJ"Ou7CSYDb)WD0O%iBFS035*JUW^jB(g8tXEkI"+Xs>qc-s6+>o7]Z)2Wo;cZNo&@LR,E_>Ur8>-OcU_9q)oEW0Pr`%=D`CA0CZ>l0m@mL9n[4L365;(8Sd$OrS/)\4[-dQ8hr\4t89a*HQmQJ^^2NHD[t`s"ErDHNj9gPh.N,A.aka=>Hrq7q&;p@?^C\8D9,fc_cYhMmQ$c".qs7f8Bq`jpd]JW6P,c:9.>`jYE[,\AR2=*?a'C(1H_d:o7J0j%fDd1YI)dajmqWmBVO6K2$1HQST(=-*E.rCYaXp(FahX0Q=3"hYMK2RnPZeOl(=')Q_4I9J#F&=(EY;eJ4,r5?1O]Gho&&_XP=0E0k2lY6`-_NkBUHb9esR`'nCNU)Ynm%*uo%8Q\5UNZ?4K6+L-QGFgK%LbX%DpeR+jB=Fc7E"["/qMfIWKN=WQ$4_m4DTl7#MGdN&4$noi^,a2V>I2N%:<]UZ*7q6lE3P[/[:9rMD:!GVqNPlYm#5OKN`2G/rePOWja"QY#N2e=KVld8>\9o$q*E\@-,U]Lnk(%I#B22NNF;D_/<.jKFKpRnMK9"1L=,[O#(7U7AaCu5r&*#+MO(PE[HSELh*)R61%E;^6DBTq2T]tMd8K21VJT&*TuTO#Lf7r2\oa$IkUOe"'rC.3_Fn61RM#3sE.uaUO2NJmim:7Am`#9EX(LTfkn1^Y6l^]t@'9]c_`+[>CB@=:^]]T%8#)f`[b(`Va+d-`c;5K^W84f'i8_D!cIS8g/qG3eQfGJ2?$*^(5Lm3_ib&&%J8F'Tga1b7g`Q5t6dd!`OG#DJG9e(H:[@t;Y%?A,b91BP!Q2Yr/ngOU&bX;-H_fJg>[^XBZ>aqOn@XC>.k2m,h7liI%]*+Dm]Gm1B7^s+.hEp'MhG)(_?YZNg]3jA:r^X_8%(0%,>R`=ulYsKQB![-L>(ARM?WMu>6sdC%i^:)7mQI.!fY^cN+ed6/[$E-!1h:qJq%F2<ATYH?;QMmhT>%hd9NeUg-)\"03A^F>N=mj\$DVGj)"(PpD.&r>r_7e?qc^k=&:$VeFuao3b(l5HddZ&DK+LEa+!:*6b3j0(jkn!NEZS(KP@5D$K5#VB%?%KlO*##i,-*#:Cer"?WN(od:bB&GYU2#57Xin&MY#`1Lt5un;t^`6ihbaP]tI*^HdGB=K5:%(fAlWZ0eO6td'au7hQGsIipXPq>d\nEfi`ZBi'iGh,[#"M1*`&`aB,R'%&S!,moTe^Gk_aH&m?D@\E:[F5h-;M+HMoak7@R&M?-[.%BGn;B:6--HXGZ+!+:`5l:)qh*YY=?FS5d,A^+=F]JX!bR7N/*L$F%#i*FF.TW/Pmd?K+%Adk#3Z5Ab4L"hZ8>A9REEJn2MS/TqteS.>JrQpr$[Z[(';"7L>[6am0-YV-$Q1?Xn=p=)TX#_Sq(.HSTs[S[nG4'd.K@2Y%=%nG$rm.-_=9pNuSd"8fVX;^Cm,M/L+e3CVsb\c[lu'[;2%-rHfGo;:Zp'm2>\BoG?3:fp$bT>Q/+;ImZN6==(&ZFLK[GA1DcrFa)HhD=jX)%GA6g`i9,p)pHA3'LQel.$N__\l4#3Bhf:'Ws>gmIbDIf[&D58j/MhdqYX%X=4XX`lSiX+grAne9ebHOgMV#T70`@bn`jD^^\@\u+a8(ojrm0*WN<]=NKR%/bgc_rgf&Bu_d%DK%<'Y+Ergm@imWO&q]n#p*'C*b2nWSCU"Q,a85nCQWW:KGcHPFhVd;$(L'WG6(AmW?`.F_dMHI.WiAc`L,g^3+SBY$c=jpU1*VYSq,K$g0;2Mg`B@KP-c+3A!([e)piaMGfl4SICgqkEbRo'4X'nB2deK%s]p4WG._;FRI,"<8a6\ASL.>[jZ\@5.@RU>-sQ?-cOTq2G]C'?q/@iMkF/f12U]5UPdR=I=NG5moZV$HD6(:9E@2ACj?<<"2(UJ.fg81]k[)_m2:k-UNF0GoSeF,U5,J&]pS+6=JcO8K4+a\4^Vu`8oZ9?J`tpd`WHMTeJ:oa1trKN"OTK=(:$QLOt5PT_YAjtnC$G-Tu8l[#;6[uT;@](6:0!LSEW==5)uMT2FcBS;#0)AGE_<]!Q"IR*$]A4`/DCuLijuoWjH&FE3q'qW+Y3nG8'+10UT;>hQ=1fZ-dsF;BhLR6_'oeh;M5@W/eF"mC!^FEZL5.1Z!HW?&r(c)k;:bVZ"EK_3u>75':DSq@g>)'3lSIS/BBjQb+.6\MtQ36QFf$?,,6AE9P4,XppI*,Wc$7LfG-&g3PCoInR#c\C]Ke=@.#YJGG$9LaiB97HuR!:rj7pme8HOn'd-&#SUUGM=:cpF:Q'^WaF3jDg7Kj#i^d.2F7"X#'g?j0aKGl#j@7o36YT7jbJ2n5nuk#:Wbk/KV70rKi5iS739ADU3ZT_5EDT6-4mAalH--"Oq<5,#'J\Xpiu`HpP5MN2SNM_$Y3I)PTIg2W+1JZJW"5paM#`E`::?Z4a8u7[$T6bN#P%"&*esXJC4($ma=75jnh_`gQHX[LYe2V2r8>ZMP'2-YK4Rr+s$g_`#8_tP=$I\98QEC53UJjDaQ&N5HVF44c.#*Sq&RmHU^Ah#I!u-,UZ>LVSXjkB^Id%tBO'da]$8Bu@qSFR9fdKt?fo4+@0JZ.Je7,J[lW`W7fOGHUJNJ<*R1UK)??G9irhTP;;\iG4eFHbp(Mak:;OWQI.i53k8=H4R[=2?ppK['S\l^87W:_HE^1+*J`H47HG`Oc'VL]6+)M92'-YbhQD$.H9;ugCah>eE]C)YpVWks+R(H@(F[W%9Pf-s@RNiVK`c%_k=t$=X#upIKjeE18_j/F5,lf5%C*/(TsI8?!R][!+[&7+)[-o=U1LmtiC)e$<$9;(CA%WT"2I9i_E0Fa3U8G+!15S7E^5]Si"1Ju!.]C+62e5mm`Cf>]Ban$Y[6U0#p>7>=iSETqnHAJ@\a\@P'B+Ee25YD`8:c[+Zo0ceDKQaJ`+ZGrL`FkjIZ]'n#n#K!542]TIKuVj5,PO$iJX9+srg\+Dm_=o).9IBSdKi-;g+t*tE"?X'3t\6)8A3+Z13f+L8odkL"9oqGK7[RgNLC0km[@\t8<#W:fA\Sf-+n9>3Q)o"4,E\#3MKJRKcic)g_4I6Of_TUf$bVGTl-$$WmgWkjQ,\ff4D+Xh\;6T)4fO&!tb]\)Dq;?"3pDY\<7/)^gYf;FmX^7@/=6]4$&=`pKT'=3sXLV.sCrV+u,iL0`tiEWH3lfep"joE`,+>U\@_lS_l!==%6au_\V^3@Ji'Q?"Lirl\TBgafEh/_cO"Z/A++V`%j1FF!i2\!)XXnGbk%#4;e[s@V;fPio%9?$F;EF3@))@oQNm+m*N+SoSh7jdsN]FpGcg\R3TI2KM6B4;4jA0L].*1I7`<>WNpl6O]r,:Vf7Bcii&HJFM$]DI5Q%=Xt]=h,E1oq_EA@Lco=Ufg3d,B^6[LOO;l`8YhSnj)KuURE%!Z#5mXmPDLi)X/YH"'D-6sJ^QMQ'Mq$Z4:fl4,T>F:k@Qu,r3SKY?OJ6ekr'+@kcW)NnbF;u1%=H7Np.c&j;1c[=1oQ^=\cI)/D+eq4?j-EmsW1A7:@PjUO+eYcQOus67Z?K\4(h<^32+.%WHLPa/Q/#YTQo6kV,IMEK_fT8P26ADE@us:.HVU)3=q%_Dl6;m[e7qC-f4)aJRmr"B*=k,q1u?hH39"A.NKEJP^VaqJ\4A^kRLI_P=5Z_[;u@/\iY4`EP<%@?1`@]#j[tG=nK&^,T:%OgEJ?mA/nQh`$A,!gTfb6o!js%%,-f!\:Q1E^gX,$<0pdC"[*RQfTPOG3Q7Ya^)]LlEO[$;5YFuq-(n(ca,2#0+D9i.@D$=Z=eLj56['.T%/h)#.?]7iT5j!Nh1.>U0meGkfQbMeIpi&CIDbCFmb^FQgiWC^DJ96L):!<3]1N-OC*"$-V;Ic#hM\26JFn(O7^M_@!_oFCqo"+n#'<\fGmuK+(o[Q)0e6s:NXq./AKRB,&0pdZl/h\6JcEj#?U`[[qI],K>El(W:r-4^,h)Jcl-3g\&o\.l(jbc5IdZGSB6kHjs.U!dYM@fnKmq`hjoc(!o;&3m?5`mCACXI@-/_1HgE=na".^\.U=9c*)T7ju%8Mu,[K9"ku!5H[)i6c3a]m858"afl*@/Ts[DO>/En8K3R+s[_Q.MLe9KM`f.GL,sHomA%jlQ\,FG(.>pa'-^\Yj,F[%PZ6X4B\fNh5F-lVaG5SilI[UIORRW:2e'A*[g:4n&MJC_YTmg=2'$eIrNRfkbgMCXu?#`*u'q7582R*%SWGV=ACur'`"F2otC$K>U/mZ?5m`%JSU!4Ss"9SK@TH&FAe)'eJ^(K:e>d7[)aMmHrkE_fag.r#^hW%:L]*KQtP6NG.b;SRcmT&crg.&lIu(43VFsf.QT?,8ULCPo!8.mO-prolh/VpN'Ippetg!GNVQL.#Ge]fqqF"/me]BNFMJ'pt[jQl^Wi;!SU.F="PN'BSsW!QY$GARXB8oO^p2BRGdF$tp871aiUR6Wr^a.[e]!e(2d59jLdaQtFHNr&EId(p:qi&Gs'@_$9lg1M*''[h?Os]_CtWO@en:bdMLk:4S&tiX%G2JIffB@X%Z5JKb^=og*"oPp76aHf6pSK%nD,LS#n]@nbN$oUB2=#-:FFi;*GDFooHUO8c,47]7=_0J.8E7'#AjZq(8pAA1rcbP.P[K_%1DIlPJ63Lr6:KcWJ.7sQ=@+3$_hop:b=%Im[VD7#GX0KFU`!*7a<.n[%*(B-&22KFr`PWAf)7]];ei_K[q;,PQZk"![ta%T$8MKqccNG5\cF0(Zp!epV4n!qa1*DMr5WV^?)KejbBQr4@]l-\&f>H@BG7(PUb?uZ*.YibJ>j?h][B6Z3r)E-=hiKCsS>,+Is?[UCgZPVMX,==CuK$5*mNCE\OI"4XVM#U<.RDl3]r;SXR=rS8\M%BiVM?3l2!U>i$=9I&Q@C_eODXkAMtIalZZRJMFW$Jm%(F+k;1JY;2L>%3.G_F.k7iJAA*u$8@qX9/&&W1WZMm8(iP7BeDGgmi6@19&F;4W-As-0NS:7+%>)91bBjX:!(e`/K5MBR+[WoLah4*;XRKLN!ToHGnea4GqTHfN)"-Pn?ErWP5!u09m1e]?Ebn!"3h8X&e1DOEEKsA=.r+3ZI`Og7D9DC"(2;Tkjqb\YNqS98n13'D"L2YGbk$P)4?aRBaed7"'YU_O&q1+8:.?<@CZAKl\F@CnYY9Y*&q%Va/I32ft^b<$^A3R*t,/McNI]/[Vh3h^o!Ctg]![qZ)[4F-&?<&gA68"st]lFg-%M>1>>]@WQFa\I-Blakbk\E@coZI.i_FPjgj(B0jK@OA9!7$9P5fpQU_;9/]6fFDa.&rk_$B^DaZBX`nAYtWnasqqCPCcJ[+Gc\`@U3D45iGlcZ6=Lh/M!DT#)YNF:c8)m,aLX<&A.BcR%"(uaqu&9:QQ_Dn_4Z/*o?O0h!@(pnn@(*Yg=_la-l0rm`9F+0b4$i4@A"_KTQU30p@um/t&Y59#EG=-75H?TAP9oLaES^&RN.3Yo9T/"@SM3p[*ut<2\,]hQtrHL:b.ZbB&FiBO;-&c?]q%C'\K,W/?]T'<`2rC64h>o92TKl7VKnf:9FR_B-6H:18J86>h"B#_^RmN1,:KX/"@<.d&O6Vcq!>lDI:==NqIm]HjKWlZ!(RnKoL!-X8>mGLs(FS55F`F;jN?ehDAob!b'ZLn[[GiM^5h/;;)c4B#uBWVC!eVZb*J-D3_kF^,W\aGW"a>+H`.A"=[;9](*+/:5Y6V3A1)Er*-N)\4[iR80@Z^8+WdjVH2J:qL=)UT9b=n8_TFZ3l\k*Ci#mBS+f8B54Zn66`<*P=H.(.XLa3[XN>fJN54_ZJC1_ZtFJRA-E0$=P:-LMqU**kjI,(4%aU'?lY]dq*JbfK*F(m_H7Lj)irgG4c)3H="+As$!qTi9%`+<$Yo3/+j++,Wk7"N/Zd%E+$4+lV9+*lh'9(12utR.\@R(YYc&@&BBV!bhqCRskg[5&uY'Pmi?PlG=b0\Da/E1Zn2hC%'o&Ld0Uf_JkJ>jIA?pl\\t)@49`C3qV_ojlrt'i?\C5a5QIc7Ygd>P%u`"Z(G@]7tMD]pJ4I8cl3SrYht;:o]C5*p2ADmC[=AGQU+1Ut/"W>q14$<$5YBerL`/#R/Oe/rB.j0qrT%]b&I@t685.Y@p)-2r#'3K(I,8'[bo,d*^(HVf!Xr4&*HecpO]W1bp]cG$N,;RWM!>S;\)Yil29:S"aGR$i>8$G5BVr!rXL.:dCkcV>!UJN$,IVDO$qscTq`0>.DqQS<5c6rKKI_WM^_>c>.XF/_Z_CMebsu2I.7idYS:6(OF9"SpYRWTk%o+t<1eb@Co%cUA#Ql)DZRsAZ?^3l.AFS2O7Md(iD$5@/A'1r"6P#Q,fFbP1M$aIV`V"2gS'-=S!Aq+7B23nDjtjp/skL1J6u'SE6d_>`I1h?`i)FPCUf^t%]Qbf]teg(u12p^MRhmH)K,WODbo&sDBcOBZpJf##T_1$q8!.4U>A3btGPdGAXnmFIui8#_%-cU^$c]cntfAZ5^T8#Qbqh4r0#PT4aQgH1c:m;AbWCPb:id6=@e?6kZIX7QkmRsSnQuDe*j7Q)HN&MP2Z`ILfT'JZ"J=)cqoXu;k7V4\?pE2po^m-q_j[.3:PF:jPK+\cefe/Qr`MI6Z*4g4I>GQSdph\4sE4$[$Rhc$NCrkAH-IAd^_^j5bGOtK7?BD9&VJuW:o_I6CJ#"n=Ojb+Vp,>m?Y-?*YoqS!>,a7YfK/ErLZK,1;dS+nhD7Sf=UG+R);-.pUj$&M5s08fKbSf110\:k`;P,6dVdhbM(jCC;BP-nf^UPi)9?!>n@2],4lMHs'TG(3$s8n0s^Lup&!Pu[Jh#Jk-=H%%(YC,__r*C$lY&BK/5&>15VHYXQ$*Z93Z?.rMQrnWupL8F(8_KM>)2eFmSFOm+``2h4]Kc.%e(+[Xma=n5X!O!bFN`GAARrhuo70*cDf8S5;nQJ`k+R27Aaj?"Ic5R*C+b>5E`Do%`"fJZj#c!PCW`CNu)ugPj0KkNRTH7UI-GBW&!t)<.hQ/Cd7=ntPI-SUJ$.^JFD%\;tbKH+M,KNtn12jM:blJ]ht.i@ID%2LJiQ!nrA7S$t4:]lD)H\S\eS0YFQV780O#1GdBU1G;[/aum>o46M=o:7_6OKA]"^Pu&`'WZb7F:JlV^SgR*M7aKVt52YTZQ9BBf;q"kZGN&&.%rI0o!1^`/YF!4`q0[[ufDX&pqE4"$#F#?s":68>q()E?H88V.));OBZ0u4"/.'R:dsF'5BG/MDmA*oUq+K_#=G!cB0,QsE)8>Y!V3q5H&1H$SSg.HKk5V/*0q[O.2I.k=&U`GO+?hkArfIkDT*mt!UnLgY3OFF$JHBi5*%L&Oi#7PlZ=Q'4&ERUS@CC1Z`H2a-e[m?[Ha[n/4PmB4U;=pX0OX>R&Ltt;XtMB'SrN]p:P+tYa75n_2.9:i"k7^uEAh2G^+N&0k1nuE$MXP0gsU;-FdSrEOEM0NroLt]juBsZ4's!%@JJ9*dXnfkR)c(#^!oGKc'/gfr&Sf7XthUhfO4FXI;76H7C=h3?4cL,efen,+T[-5lDX^m$qDWdI&F[b/L.sk1q]D7!g$P?rm_,X2/Dlkd@.SPad![rq22Kbpe)&Tuoh]*<`6cU9m14pcs/AJ6iYB1K(5&HPN'"Zn-J)%-b#9h,=;kM*5l=D3?F(4I]2]W/C-KTHd-Xn_ES@4JU">C1ifQWnanb\!-,btSE0Pj/bfY.M>N[URX7E\t7I[ZZYqr0k&=FN:u8(5+_b_jcNO-H#6M$fL5W\Kjn&)V7^LhO9Rs..6YX6C`k$,I3-UAJk3U2WW_<;KB$-Xf5(aW9oqc3ORI_[+9mfb5"t-6@ra$V,XMjeH:"s%aBu,DWBhe#R%.(n_.jB8]\D0pH&SWki%h-7k>i;NnS9/iYH5M$qmf=b8fbYIU3,VJfeI4Z%IqSnm6@HLf.2_#$l[W2!.r7oXX0F(W](o3c+!5f]V=SQ3U=Wf]GA0(BT"Ne3U4HD*CCkqrEsoTggA-6R]"0UT)nk-Y>eo';mld[KeiVabpYOg`n9BDNO4Y^$dG;Q_]:Ob?tkX4O7<'I?.g]DBd,u42MZmQEQ$Z\:,>#Df<#%X[)okAVB1D:9hS0R[qT_*EPL(YLm.1n"Pa.=<,#*R$'7`L?oIL;egB1pCRQSNsZM&(6BP^G)^JP^._;ik;)iG=;'*,0u[g[4`Q(T74kDmOR22ahjI5dH!+)BE,u_;EUSn^oiWlN]8c:&YSuOJo#p:]Y3+1q/S\"@cH5Lg^SoXI(7-sZMFD:7@).bu'Pob-'B;@)&%`G+mADDF9Elo24V-DR(6)O+,Lf4jLks,SC+?3jZ_c/g"tl1iRq_rL:^-o3"u5NgN.gpI_eN,fM_jSiU@(^$?TNK(P#]FThs(f]%K?gaM$>[h\+aA69dE6k1T7'[OrpHI]L?7-s#3lDPX*DF`eY>^LS+o'N64O^K_7!9ll\&.G[N";1=iD!3fb0*kbN&gNVIGX>&tF!33\V:qD,?DF%OfW(9b.f8DQ(9F>600c,R7!J$anRpe^TZb`[j$ZT^qb)>ANqRmb>e3=[\;9E%>\7L;qnY\Q3aKl*[UAtEr`]LgCq:LScXP>p@S>h,0Q68"S2=C*8atl`-;.A7@_,cW1LP,9AAH;(&=3Lhs$`C0Tism6>^d-_s6f31O;*j$O(+CfD]P^%)GiO5]g%pc?0ro);jRJ&H`u4idp'_qa"e:ad"Al.ZMDE<8Oi66uJ7`m<-GOSItWGS0=CPARr$b>7d$J9$7-*MZudqD/1X#E$j#D>G+]H%6(.Kg5YhrG"Nj#Essm[m2sr'i.ns0S9>BpA!grhHA;==6M1ITqfeb1r`RM,XU`dfUGBkR>m[J1kek\96Lo<.Z#KP&54C7AQ@/7*/b(BBpUSb!:"YCK,7Gq)$nmD"uu1U)1dqT8E>7>XIRLLWA1\71<@USRPGg",`X;t9nR.MVN!6BQEJc$ghI]GNFls%&t_.HgI>TaA8qUFD))u+72_%ni"@\i_E\RR#0G*+WtP\+1'MqT-EJsgElg\\67WiS60pEuLDa#u'XsSYcqphbp(8.i8&*s+Dh4mulfqY"N'N-EjZV"u-KtQoQj[oL1*.!VlF;q20HMnZ;%1O9_P-$]l3,F?:Mm%JC?#FmLRHmhR6FOD6AafKaRpg*&5c%C`#M.2XD18D\0M_b8.3XV&_*rrR["=KFQnVJn\dd?EI%eT6BaV4\W=<95N=!#h-e!c^;oO8^[un[tWm.^Yig_GG66+r#i"PVA1/EN)8N:C%3.6.DPA!c/FF6UB@5Kdm[QOi]u%.8W(eIA[UppeU&GL[4h$FCb:t[OPE_/A7kYTCNho)AXFFHD=q<`'83LL[5A:hOr#3Lf+U?C3TZLU-m`oMBeN92Z"+>,1;FC<$J9nYTl5!:5.amZC]ReQheDJg!pq8MA(lP39-8W;dZjq##:s;g;k<`*jP*B#J%=sn"ZJK2?YBc+hedWM?6R,KG[SnS!F,L+bHYR_>XDIZV$gG.pk,*W4@9<&Kp:/``jiALsA%MZhpXF1]/b.HlW`8!'AM963);dSXm&T["k_-o_lCN9]2ntq!&BOOhIAFS\)L]0D)jKp1<`#)Er<>17NK/iAGMAmF35$!hl3a9^`C.S+UgE=MN!eIo!1c%%l)L^X'OBp2]aHB=N24]q]Qg82U!(pq_A'ZufS1*agN)!E$N[&Iu,I;bk#kJ?Y"_UD(e/=!+&Apcf6-p?*:$m4%)H[+XPjhsd>g<%j.ero+[+i'31$qP1C32*IgZZ1D7[?4$:](QNj2u[gpO&A8SDsK^?-A=9#AVX$*M+%6f&,(J!qM96olE:D/J07)$5NI:MdEFNQQnV&L*0T2A40(AgFtN.*1ur/Hq8*%Y*hKGm/dNbFSn\A^PG$<"8e^XOmIK(f`&\>VOQVW5^IN=TRq+r"Ad5`:ieQXa>>G6$#Q&mN0uW>O&hh)M]&AG"!%&C$6,kd%J07P)sbuDoduR&@Y.Rkf?e$;8:N/-r`FKm,\OQG7*uHpJ9Q^p-)&G6UNaZu;G,:Gs0/u!;*8KX`ZKZ-B?P_d-:0E]LLcVSDlO%U9MIt$V1jMEcC_=e$tSb'E;pNsE]gDAQ8j>UXfT=uUre\O+gBk6e9t]l2QI<4-ede!;:FuT$UnD)`YoTR&#LF_T;0Rs:r.i9W!;3C:YGH5WBkn.Hg'8^5pCS$$DB`gYd>917l3d'(2smn?Wm9CWipPH))5^G]p2psbde*"Mr#K[TSJF%$fm\Hhjg/.`1(nE6]cDEU;A3Dem-R6F!hsZG?m=_jXIkKa-=7rdGuOZWQ'l@9Ss*:4H)ZXdWm;!\mrS;BUt+d"U_i,))RV!9#\+e+4f1Aqecg[_;2'knG=Ij&L=&_imo&&@138(%l"#\a+>;,n$mDs'/7+rjn1PaU->[eAf2?(ISEVlXN_j4X6+\s(_hVk96qYdX0T>e9s]"Z9;-jj9LMbO+d/g\TJm9i3*4`Z"F=kQal[5=/(&ZljXDW52Y8h0F4[dnt<1Ah=g><i&WtYVoWI'JI"-T'MsC4Uel6dTM.I/&eM?6<0+tn[jqfDT(4R0H9-MK&_VC"VU(fGn1nP+"pLTK!9mF"Ttfa0*=[8u(j(FbCh`;c_k$%Z;NBIn'[m[[4PFN>7UNX+Hd&\]ql*&3@T1K;TC1!`%9!UhgnXY_n)k7fkaG\9;RaclAXjhP;k^k_?LC"`dLKok]U]4ZEOA--9L'G\.>a6<-HFhCanRm?n@0;05>1T8WaG3-R%-7biS*@7f]:Zb**[gao%!3BWiZ>'P6.2?qKb%FT`t.0sQC3DebfZQNIKB,nh>K;(,3?=__)7f3:`-S&5!lNn[j7DU7G:%LkgXeTBp)SW/k(o]ZQ1RC@'T]4Nr+Vk@p7>SQ#BSGYl%:.9E7s$k_7,0F\i=%>l>g[T6kA\;BG4(7o':h",B'@[YH5KjI/`Wp:frqc6r*cPCZB@s?@C6-\8'o>GJmgl9pd.A+aZ:tM8-.gK+J<%+:qZU4@&/hV26*F!9Jp^ocDtppOP![iZI>E52U!MH4;hhnbNKh>mUDh[9!jf"ELdq\(EDV"6KauJ.='*:b!r!bZ:%9-e^PU8G\3R&GLF?CO+eioaE#j:.JDm@.T/SQK6=`LkSpjn*XLpL^(Ug0"jD_X46$]lo[EQ7X(QlC&m`,oprshgjB^rTEbF$)qj&.!UoF.8#K`2ER/'GFHZ^G1(F)kE)4afYOFa(i*(aAr;1(idgSI_Ucu`ba\soY@E[tfV"ZS\/2Q<-48Wq[2<)LF.W=g3VrU<;Y`n#uO)FT64oBrN0YRcnW9+-)L.+nN%Ss(4Ceb7<+asA\YbUl@XF>rJU[(5-Ol(Q:SY;_$]b;.jr`\bJ^"SaGYUU4lKbg0=MH(1u(6LA8;IuIl?-n#A\2J8FW,6%B9?5S=59U=YGp(4ck`YLhoSm:_NV2YbHi_3/UsGpS0Z*@N,fp[E!-c=pg:42ga^'$dgc:iC)qa)Bc1[-J-(i/I#AYL5ZU_K=cS`8o\qQdo(LD,*$Hb3]IqSE[<3c5;pXFn_J9mTuU/Z$Mk$G@+cI>#hEK@NZ5JOG$1kQ6M][^PRKn2@Y;q*iH`3,cZMb`:+%\Yf9)'&ru3U,=:"K?@+<,&)/%c984[Q@G.u^N!G2OBJ#8i*E[-9]J'Y/:'^o9Ll$YF$io&W+Me',NrIkZZnIgA#Je[(L>SR,p$hYP4XEDUm(Y=tqP;R[A1YM8!scbrLcPSaZV`t$mFYl.U*-Ca=i8jdLCuuVUU/'gr`e@A2pYo(h3C?%#%qk--KWWuoc9+A'18Zd>2XfjbOh//\J-`OQ4s?f,4#m!j0)[+=7Ql.%\cZCU"oh]H21cf[]*m?9D@3q?1psCVjMXk:tY?7qs%8E$:*O)J$em,Io,]p\R,%X_M"I[2P)2#,-Y#hTQ4]o_c-t28MX6<*#NL;p\n,b5rX4<..Gh#5i<]klWn2h_j]`HQ5qAk5rgnp$%V#0Z>%te#tpU%QbbtH(B+Rmr,6nHq\Is.Y!e1+ikKu4&*KQLCK'Cq.a(H#7TQQW@6h%oUEjZT$nlP90/_R?+"RPWmXQP&LRWMNMA05h&g]2Q!c&3\`sIY=V5gA$9Z_gB+JLD*>cBCWHJb^N4*SQjpnr%kZp%$RYUA2SjE^0$YYp_?!Ql9::k8:?%YP2KIT'U07IF?OmJ?Lqf@58j+Hr"Mn$SOk.8/E73nLH4FfVhl`_6O(S*H'5cRi1QIr4@j[!]`#]BOsH5<^-W'DW?d.JQ]QQ>Je+31nF0$-(ef98IK![KMTu7OM<4"!0RZbdP8[N`HesUoj;GN:Kk(JoSGf>$/0_j.6i`WW-s-d#HTp,fr@cF6'-L]EC1+Pna6hoh&A71`\Fo^/1?mc.LT8h$&/X1e`k4C5GZ4\k:a$'oi+-9:^sguH38oYFDaJ[LG$JSGSA#ZdXLD(#aZg(m1']jm61)aYl)R-eDCf$*;1=gc,bWXfN4+:*\tS04ZT9UefNiD/u/PE-5"T;!Oj+5GpP9Y6[LUJqJ=1<4\r`^k]1on`UnqeYM09/d>-p+WqZ;a`B-mF8>/'rnjL1&RgUoT\Kns_g#lYf=G87<=s'p]&I8M)6@KplPSts_ZLAV76p->,DafgRJh8s,"BenXMs/Iqsp&/#$N,j7;sB3;FOR@1pN=LWVn^[7TDqV]8U9Sq3J>Ic"qgOqs86MVXS%L8<0C8V&-#L'BG+6#Kq8c/<"B7-am-rh8$957m#P=5E[B3KJBAGP6!h!8'.`ar$9FaM>5_!'5]-6>c>X(cLL``Vjfjdg/`m`n^s\?-gcIrB+_SSEQAh#?j3K$:gXR"r)#;NK\u9`msLKM:\b/>VcXUY+LMCcqOP2OkE+k3]-g6cWZqc#Na6o?N%pXd0:!MP2IJiOFsI]gALMEgMq8u%fZXdD_dA0qO>Q_^Xr$nHYaHe:K]Lt$(7=AOrO6Pp-<%2=p%]L"Xu)?hmBDGA6D(..R6!>i]qKJiin:I6o-PVR#eTk8iiLOP_>(6'fH3m4l#:BH`S.Wg\-3(]39#`JZBHr_j+qJ\B*WMkb[n!JVE81'".oZ(T]Fl^A%:BlK2G28L0/mn]*@'gN:l;Mg\?ff3?lPB0fm4N,V0Fp?l(@T^uKA'+k(mI,K>D'@N$F-!l"":.#/i#kJmWHlcr).18ja(LeMu6,$&6uJRL9T#AIVbGT_g3lHK)eab+:!boloB8"VJ"C\5[Ral#"6&f#_3!5L^F7A)M#QZW%ue`DS;6c^u/RfMokNX&]s"-%kp,atnn3`jL6p)-mjF[C*dL#1L&37tMAq^eHHRDbC'8Nd3+D=lTUs0/042&B0aK32Ob5aM23%:6"ARYS'!Pp&D>$7/e2h&2smdS8W#+r)+p8hUh+MhCn^Z_RagAcq#6A+ghQfE(TrrqbD/R*n*Ap1Obt_VMlc',8eUpDuW-"bs$6rY^AiRb<;j.<#oG_a-6d]l:Te"[00U@9%-`Mo:lAH%)lGnUTkqrJg5\6WHUJ+//GCrGcm+flNt)G(^D/kpM9)":HJ>=$Y4L^SLDb!V1r\lgL:gmJ=T5Zi6,+O6f99p_n2LqR_129oj12khM47&.0jRm.p[:2;9SG"k4\^35?FiK`Z-4bmNl)Tb`dVR#/dW5R-J+%M.[8^u/eA,IF]@QS7Z2R>hN!\C+G$j6qD[L4'@@L\/.Pm!O0)AS^Yi'//I&(\Z=*#'O1B-^-]CIi/2q?/R'_,.'-POe3'`.l/:3a7U^4^1_O#LX]b6)cu]6acr:<_iqt(b&pj6da^0.e]/:Z2E`*fQq)qTDB1rkH2+&jDs@cY"S)N'+ADf3G:".#^-.u48,<=T0EU)>p2Dlf0&Ob`ek+$)fuRYKjAmr2<&bQN64XudA%_nO/.)Vg^`EUmBSc*O;\SpKU=\>&Dj$YCbtKS-tu\ceTp(Q[2;H!`YU,bY7$rJW(&\NpX3+`@_0880/ojpIG1$u-e;p)#@JX/gW=E2$_`=f9UgPnqnR:kI'7f)e&\PD[)A$_$6,P*OSVWj2Tn3C/m*R*W::M>R4&k.m!9gBh-LG3-'62Hh%bDl<5l&".+OXQ&q7!kd3dM.BkDIajX6Eg.rBsg]cB.iiPTR-ND$mLHjqLnS=O0$%5-3f#!^[F<*HdgrgqE29u`SH%Uo3Y7aF+XNVr7e4+@gYh)oL)@ON'khmZMCpkEo\\rDD$=NktPi>Tbmo-tB`A3XqQ,g"Y_'lAuH%QpSVf)2/oLrmj@RT3AIA?3PE),iB[[r[kO4/%VkK>6i"U&D<(7Ah`PL$2C,#EpGmM[9W[;#%!_^K5Ik'S)hH,M/EH#OQE+:X3n,Ye8^S_*.9u"\TP?EI32&JXDX2"-hMF3kcUc17uFUaAU?3u\&pe0qAJFQ5fep.NkktMcpfB*7)2)g^dN3'FCo@%VMPAM7r!Sj;J[(hc!2?`Wo*Jol^bJ_*he@9^J*7qmU;69hOYaZ4rPI.d2DV*2#GPA[XGZ+GhNS%D!%G:ngbFrC8ce"6A-9[oJ/hQKduDl8m/bK'G'J?'AUr]02YU\p"Xc\kOk+tO5]qX11THJ1Q$Pt%b)$S:[DVF-^!.GIZM+mjX]"PQ%]drN:>aJ"OjitT7*.EA6!C=HE`D`'h4/;U1`NB@!rrYZQV2$-++oamX;2RW.corfLH,85@qJk=me^+dHFl1=k4U87b<(>Xr"S_'-W=U(.7Ac;_k'Og:*e?ff5'##kQfncDcpe&`fK8K@-8s]&:Q?PTlhhYOd#\j$!)fZqoCA6eKQf%@pGjrq+V13fTb0*G+;!J4+GdbGL(S/c$gCRV%3ql+3O.7FUD^b.,l.PLOn\$@Z9e#H5OTnRF/h8cs5u6]X0EFaBX$]E:\RF\MN;'Kt0diRP3pJu>QDS>)n_R,JD3]kYnqgD,Q28`T5of(M7m**H!1PZYsi0(e"G*rmTa)`Gai3fE8^eU4@P<6'Kc%bV@]p6neE!Uubu8SM=.F-*pNlAZ*>;U>J2-k0V"_*0u4"7Q/_ngAqF4tDd$Vskf!oD^<7f:fYF=F:G`G7MYsFN=GB'HBXG_MFs1fD"4YYl4"Vd'+gT+EKrW5MQ%;(r\D\CS._C(t8s*@U]qCZ^U2IUr^7!niRa52IFbPf4@h)a2=hh*'K)]%275m%\K#?.;N5u+s`'(JVcr)$Do9ZPb*K7lR&2>,0VgES5PppMY`>i.k-'bkR9HY`U%/*DT@@W68-"*:[eL\MS0Iq#G#V9a\Nr^,6(t/E'3hZk8AAis&J-Y0]RiFFKpR45e4m92m2!%ZsfRq9eW'*1iUg&N0Dd6k$`@BZ`R3&_XmjLAkrd8IaH(*VNhgP:Bh)LT@8K3mR1Z8On?PX00*,R`od@q+6f2\<,*fmRQrAe,1a1Z#o3I#C(P7Ja2@<_q-R"uqTYjqS"qNnu"hDY7XC".c,/'92-0doD,9o9G?k)^rUQcj:XO,<fPMZ^Qh-^G!#"5-J+#TjPq\))0$TgJQ'OCTPUkU$gqEX:_\V]&K%4`8L6G7QIt,D"V\>'?\rh9f(RG&N1IdiD'k>7>U]DKo\2N+mpZ`6cI6A7kcfV7:ScGUC8LTi*G\$XYh"i40%8MZ8JG8Cb'.IK8[O];+g*M-3RpQ7j4&J5^F+sJVa4\mXq:?nQ7@5NKhRQ6j3:->R:'LGK[dGFd%HMXgV_V5L>_%&*tN?bGfJ2lELA0-=K-^=#5k^sVJF;I[123NK.cDJCKiMUH9g^TLJCX#*tacL/o"saP0fm>-B-lGa0XiuI`t40,:8sM&_Jg#-OI:nbMlFHecX?.J^SB:BrsX%Yp\eHf=+9$F[-h:O"0`N*0K07A:*6-U%*5,OmK$ZKC(_':rJ'iK-WV\iCi45"lN+*4MX)apm`!?pBLHt"Pbc."e@SL_fI;d\XXuf,%@F!f69-VigGrd=EDDFc>81SOo5kbOB@e)Xg&8[sG*<^'OG/uJJ1sri'of>)W5EIeDS(M^NX[1X>@Z1rf?7bF=)S*4+\-ejpJ!%T-6`Zm?jHlcpD>"#W?#Y=nij]o*4gAC*d#]@toa-WYAg"-XP)[lL09uao`iFTa$DQ%1*Rmjbge\!+4bZ4pu8B6?5(%Mf]>Bm5'A'BTVZlKn=5NfEUsY7qNUa:T@Uj-4c`5m^b?A^#N2TCroR$ajoNr;&a=D+ngBcFkg45*.'"&Y-gD+Obpln/YH8[-r?-?f;blOuJe('ggS1L3?(R*aNtk[[EPc2C"DBL\K5T/b;DZfff-iU4\(fsa3WjE=0$"i:C3L/V8<$Dj>f.@e\IiZ)B;(06:3t?8_C%,^h`6B..H5J24]FS)Vmsl1NkeEX1^9-P#a"9UT4#]r#fr[!%5Id#BB"1.@6oug%YmE@9-N:r@rR)c;U6FIGneX-#5>:V:#:,afu)me(q.DD5u/uh/NJV25WZ/D_^"-2\t5(HL!Kq6F$l!579?DCnlL/']Z->Ya&#\C/Fb]N^u75AgeO)UK13s7\205mO)XnoL4nc4nFD^A..!FY@B:,.&2b`iI)8J88_$G_d1XLa_%f;j3aNh?16W1m%$W@NE,X>o28orqKW_DJCFX0.Hf6p;`rKd>J.>KOb4S1aj#_*o"Wa#IRD`p!9[81I!*U5Pd0KPU%JApW)mV.-E:bRWDY6Fn*g,--R@>V&(77WhRW8=mi:J,CV.(cn)9nP]=^[Ys7h,:H?ppG'/Q?SD8`qhuGmI/0;PKVF!FcV^D$Q\kOeHDd,okBFP10(H_mkrW]1B=b%5S#4A?cn`k]r(\^DC!4$F/hqOlq'5-OGSUNM@P`tL@>*$=d$c"kKKB@q``m%Tn8!t-@"`%t`We*LDA-T>X)dV(Ak;c,@[-@u/L-%XG?l=^4`p\VMqD(Id8dDk\5Tp)LGg""+Ueo1Nj?./E+s!/8P)aAHg$6S0[;\U^CV=`%iMb$&e"T"+Y4GVrZFDe+1V?:-j#(t(ec^c6h:hj4#HQuNpJG0peODQq%Ru]de\".&h4^9:84.+7Tc<+-j^\'V,+X43T`_+UKM](47<155;2"(Zhb&]6]I,U`T@1l[*_LJ#ZF&XP`eBhb"pRa!DbBdkiFOVFZA-K?kaDH%h7`ltJl7`,Xs%CK)049)a+K^s`?&",;s0O'6=Gf*I,\d-Q$dcd,,kBrBi*G:f-2'%&A.=KscP@l7lQTN_g5f/lru<5Rjgf'\uGg.')iDbOACE,*#:I4g8aBFiB+]`Fq5L`sVOF"4bKjt(+B(?/2U'!)ONd)7WWe41o0+5[Ep)M,mkl11CdCYbGo*ZoYe$6:)g\2fHB#:sh-2lO+oe39095g7S5_f8T%+-Ln?)ahZVao.ToI;DEtH$d2/".=e!#/;tsf=k]WTL6:?JejRe59O,G0s'Ia[YZRR3YEj:o<1kL$XJ6IJ[UtNP$a(""7q##OcG&.p'CeY&^nDZCW"cNFRJ92>[R[Alk87jmu73k]m&q?4MZr;mM;i50De!Z%f)1e311+4RoUk'XHTVT\89u)lPhkAnDfpfq:+,m\uH25,tL#NI7p;ah,<:V)*64+6BENR8n0U\Gcnb.X@r4Xub38,r_l"*@i!:XK]'-qYTL`IX6U[3?7m$=)2Ptl\a+k_r?%hArSCd5bnT-LXfU%XYM,S\=Q_C1Kf0-:j!eFoft'6t&n:F[h9:5W#T5J,W.bKN)kL[[s'fKT:?gr!i)7(uP<<'G!O0)ZWAqbDoT,T++t4X4JkDVCPGO#(OK]c[Porp>aL%p1"\acq3fU^8EP]''"kf=RC7c0t2N>&ACF[96Vk?d+!B`aUaULi,<]8mPaZb@\Q01V]=8:`n\<7TZ7&)N:#Nknic<&aF\:ROK,2#pC!,I0q(/oY%QSY[YH^.46o,$mV:]cs_l#X;jhHl046Zl949;>S0`@%=N)A^Vt_A"5dQ>+^"jn_D!6L3)DW$!L7)\A8(j"qf6tBLe`'Z[Oj.HYY(NNm-'!^IFn1`WTd4>PZWcRUG43Z=boroJ7oFKJ]&&k_oY*770$9q;QE?IguM_&$Dg4JMFpHS@";Vt;H675#aGH&,p4K>!=0B5O[\m?\%M7R")b[Y*eRsu"4X+?(#es!8J1[W@Vt)/O6QS4[ruWH)iecn-L.:N,n)l.erpDlBpOBrJNSVS1*jq^&$=?tghWfZ\_!ear:#?mWeJCrp-7?c+57J78B.!#9T[+\"DAW,[$b_I`%80tRV5b6hq+V^N"Ha4$QD8*Rs+BT)j:_QGhj#a(9riJ%%3K2eHk%&.b$EMnHt8YFV/+.1[pki:t\PZ!H]%>g(NC=1*_-=/Uk/cAKuqm2)E>7g%-OZs!9q-WJH1bTWVK-dI*eer&>Mcm/L;m>6jZI^'HfP$5Ai;%-STqpJ4p%;FnEq]htJD.e?Sg]o63TSS#2]e8ahfG)8X?'QjuV2ChS"]A&;cs?:LWT<&b`Na'H]LdE0HIS/5(,aH?B*ooD'@8f`44c!cjBm:5fYC-Eji7K_7k'$r2V6H9.1U:.ikJ5ZLN3R@$KH;`:$^0U&l9RrE_$75ZMf#Y7?T'J0s6+\J6QeqaPtLMOMQ`$+2#_WG)en%R-p#+bkETK9R=oZ8)P=Qb3CWZ4sq(,1&X+5bBorpAmYG6(;`^/b'%j+nXi9gkHiJMAB@LAm6K)(5t"+(8`.n]cKi$'V&ZRQdifAcpT)E=UdAfm`*C]apU>qBO]+\dl;4h5jHmkdU&8^;O>sH;u4Rf1Miif'H\\cF8Q[>H^(J*`3&V7M+P.*8W=u5/.T_pGQXsk`uk>KU"&k\%23Z$6J>3jZrk9B2GAr@F=,gg#(n8H&ga6H>(W4#RBtD`/+VQY[TkfH[tOAOQpQ3PRHo\*:`$2E&SD_bp,+FX(nMgSAL/eHYX2L6.dh4\mO;8"I<(]S$YCVKL&j9Wgld;NLp:k4&20d0fH%L!:/:t)eKiOhfR>k+?\b0rIH5VHpZAo*,iB^C*T&?JDELbqc3jU-"ap`=cfbs&^E5hKMI!.Gr`p7/[rtkkeehOb7Qp^]oS4%HPUIuK%bWOlOGTd1L'UBR$=b:d$m_dX$n3$DIp_I>%Y2hOa?.N2_hoiZUcFM3%g[#<=lWZ6(k"1?A2oL(n/k\*5UsSP"^hR4.T:VB'3b]7@g4`QWuE.-IOF"TXTof#!"b/M+oF\kj!JaLH.rp'q/#\G=dO$l.j1i7Ia+88LLtJYT:*NdRe7!c&40>Db//"obPB\"@Grub4IdgsSX6)Z6L2n-`c"#nY"5E23_o6X050gfh!-Tp:=,`q/tj[_jZ@WhA2t)0#DWY1XkAJ^$U\\o)m(V_hb$0T6TO-`:.,9+A32%6iEKi.&JK3ul3kL!LKu"%qdU?[c#6SgA2TUs+\^Zj)DMj&r+8qY+AK7(jmkqT'DP*ihhBr9d@)'-a4Pah2%2[)?G=d9i&JHN?b@gC1%_90#2Cu%3L^@4@c,MXdL!1(#4JA/>IWCVn=,khr_H<&NB_^KUsG^KB?0q"(BHFM\)E1[JqG^Hmr.=9I'#Eg?G(fQ'iqcZJ\:O.)78(,nRTKq4LiN#&oPV[GugGD^cb$fW*k]toB#,"g\q6mRg,:MZVP/TM)SoQJ9/DQ40QQG!?0EES>AQ3c,EO2ON\'"PJS;'Q_BV3Ca(%%h0`)Y8YkEP6Vu2I++3&;I0'\HT_DC,2=f0256_+k[XQ!;O)-gX3>R-Z+fRBX%NP[_!).=nM2,qJ=3rtED>+@dP(^?;).#LDS(gsn8A:Wt,i#1A(\E!hr^"B3_oBYUq9f!Zu(AK\h<\,FEZ:a\9\3*u'F&"q?JcMSVR%Bj9H0a)RS9:K`k)TVQHA$]"3`ridi@STsV53-m#$f_KQKOOP>d8H71CZbg)kHIkaZj.k[(UXPI\4LRXo"-e]?G3+PBB4s%WTjfl1P%)i"dT+3OuqQFM:_9EY[5@`RkBP-5%bdI5=?@('_\/1GIA](i8OC`WUC(E1%XP8QauS]hCS++,lG&%-:5E@8@qZoZbmD=/BrZ@65N9AQF1jWDAK3js9/r9pL)KH33L0S-CN%Uts;R.%b]c:f$+>MW,aTX(]`E)Z1JNZR,CB/&p0d/P?'?0em&G_SbLOKcUhAAAMaFd_+r35+$j;eJoo]T'"`[iDBOfq&0-ul1FikhW\#.=JI$/Q0I?S-5/)J2BS#ni./a72"9Z.ke$D/L.Z*fm7B[_/X3E+_Z9[/B)Vd)_.$t`CQYWh(g\J)%*37LUs5&3$qp)>*.q@[$clJpN2=:O:J@%fdeH;IaNQDKDm>8_`Q*&9%G?>N`q/K?9>Psto\3@N@=aWNmBm.eR^n1uS\1"MjGS7)I:@-/pWLer\6.Tbt1#l&+ABWAqt)A)T.i)^9!+>Pmm\fqV9OqNMRK)+oWk8[@/A\j*G1M"1-2`.]8BZ,!V12co11YtP(*-btY;?t0gCoBSjmHu2!&7kuD5Yuj^2:Cm8G`e>:Qj=a>LrZSAq5T7dS>%4/!"IV6j4iqj'>orP;oG=ILN&^NK:O6CVa06(`i0*l6=`@s:K#4bBH8jCpZ=rIBehSG(rT6I`2bHif`]T^grKqfV!-nFjk4k\c$_2t8K2'BAMc)(0mo""E$9%6?+RpUgmL?1*Y,EES<D!3H$%(PaBm5;it5,;NoNce/ne]Ag_X\+Zb_fC7MF:ctM"MBYT04`[;:ZLo,YTDH$a?U;A<OAAI,;1()dSBcqHe2h\NQjR<_-:LV8P7OaK,5sM@4agF$4^e=6!$(]gMQ.^7AGptS;ShcKGo?O(W$grUG%XBU*q]*r%EYOg[JVJ7OdcQ_YdUp2fb:^2<:X-$ESLu#MBh:J,(9HGc`b?)6-%HDqcC-5^b?9>6f&_-9cX!"PEh8B,FE"d`eWp:P3PslEssdfaUJ"7FYshI`*+o)CX6Uo#TP'77VS$[7R@SE6)b'^C6B9JBqZ@nPTjFtkW%?S)F1[V$kH\k>nS"VZG\1%[3:i<'MMIp:eLra>:Kh*gl]pcN_(e9E_[DH1p(T9c=RkI'#Vf-("flNU[?7__Lg"&EQ,:jCp^B$p1X]#FQWfbTPRW17AB#I#2)B&H3d1CGQ^o^\eDHG_a5!r,\4(esR/+?7Kc$*@V&I7j;%'l,J/OM7nAMDSN)'\V5e\`p$"Lp>N_YW`jU@/i3#/WVC2Q,D#E5f9PFrnJr7i9de(a=@?_`16^YFN]FV.c:bE4.Ib:b6Q)W$;jd6FbB#:1C0m=J/i\gi7V]AG_4%KR\raqZ'He381LM42F?Y=$52pP(2Y2*e[#Jej0WjUhr=I/+i?+7cY:W%qEAB=Y35%(c7CM?MP)hG:DK&'&qDMq'jEq3!MCf^QjJ]uqFqVgk#CD9D0mhdr>1"2\5An0E`lDQXq6=>K%K.Oi>!0iOmOP4JQ0QFG1IDLnhQT_/Tachg5?8lq0M<)!2'36Ki=@]dmBGd&d]K\N\]gS0I]4/lK;2(3XFNQPpHBY&Opl=KA73@Q5U:q#u6&j`T<ROo$*l[)1,2GT/hN^HJ$K0mC!fBmAdNKeFqWsahRdOd@gY0b<,*nK+d4$,5G?@#\bM(jt9[W-*Z5h))K-fqF<`%TnOl[$f(InU!3",<[r?i!H2o(02;tfahf'T2<9-lXfBhNor1M0nu%$HTSToh^*uLE)fEq;6"kENDD*=EBjo@SWf0NnVNQ^"MMDE[(9eWY3FiiB4/,Qh1KjW\:B:B+7:8>3om(A+O#>khA(FaF,$s]KcNJqg6R#kr/3##2QN"Tn;AE7[`=k:CB!ABO1VCojJ.O6N\Pg<"L>MW8ZguKm93"K@c9]Y]ArlFeQiNUm`7KoB4C1os@*eHUrumFE^iUIfPpmLq!6-%qKrS=\PT%JT1*@`\.%luk6C"2PJIpV2Y,)FMs#UL(<:scrP#/<6$s#WX`,!jrfB]7N@0looqp0+8?D&6eZhlIHXB)&PA!5N'5tc#&j>b5'V8*P?7=m]QU\1IGoZ/Tm>Z%0@>]ipGo1rj&mGr^ll[`afk@8".\XrW!6"]Z?4#Z=`3.)7)4HJ>jmZ^=/.1HnMT)D*CM4'`.&ZO.ld7mHU!>HtS7/LJI_urJ&,VcA/(m]i.OpP.jJ7pE)M5ltOTq\D,-7#:Y80ipP1D4D0/B]`!$DLq.T\lncGf7I%X-18m)Nl5C=t3]jOD/"tAs-mUR90aG)&+p4&Tl6Q,,g;EQDdrh$s]t6WpW"SGY&a-og"+D[27]I:8`3>iYIm`>NngL`dm!>Jp$U&F@p[,IA+iO%cO8O+g/c,>]RYD>94Fk@Mq?U![4q"irVbl#C(4+PKQdCiIQcJiMM)HCbd5k#XjmSBR0T2T.V:Ic?&rmBf8.,XKO%@?t])#ukKn,e83n/5p"]e0&c'\MPHTS2+]?Z-Q+8!9>T8Hs4ri'1)gL#Hf!Qc8a$FAghgl2KH0*FreMu,TSC3_:tJ`P>PAe631lHLB05^SasM(a"$4oZ*DSdgtb]Q&5UsXh(l$#)bG22c!M_-28X";hbSC\MT_NbZgKdIK&>UA!C+6E'[d$1C$qQjT(t\tf*ZF0Lg`TpGE[A)0HoO?;6>+"Lu/=r=u2&]q'e`dRO+YAH/XQ^L_GVe$:32H%#kfl)R7&0'2K@GPG'4[+bp8n,BKe(Y_s1A",9>IrB'qal0>HZ%j:?R'52hC5nQD%UHD%IciSfM\#7('qmZiE3I[nn(9HoboY3R;PRfS)cPCt5_Fa+e*`LKPe>.ZZ@#6s5qiZ"eE<[eb8\rWfR3gKP37TgH(%dWK_(O5j&VHfTT)a$fWUsYLB<6k!5,N*>",V4H-KA_!eU_brGg1c3L:e%]BEqllJsLlMOXF*YE%![H63d1i/T`2(b#JEoa2HSj^nlN%?CR-QD]iiAMC!UMX*>CJ0U@C8]DT`DgqTU9q-lo-?`%Lnr\BIEB<2`<$JLRnQHfACHXjgdKE]`GCuF"d@I-F%W(TdRk:5n#7h/RB:S%8he)NuS9&5e,ZVF3D)mL>36*b*VbMk4^_rjt4e6q0NMq\eZjKH=9Z`Wc2dXt/M38XMF"_ogISC+X!\daLh)pWUGr]:N4'7"bhk.COIHP$D5nKqA1&cd`5?"_a\qK((/*[D%8JGAjg1k?.u_LpO\+EOLPKeYf5BERG0'OhK1Di)<:;'leu1D4oS\H`YoS*7hD:@":AsX!+JlU3I?d@6I`-+dDKH`\3?R@M(&nTh'q&\Z'FI<7sVX'u$o%gAHe!oCcA3o#<%BA,(A?>Am&*6!7n6PD,bo3-kWG@q6[j.]Q*kMI440E@:,P(QSLWGfRLY/`Rs?u5`<^!lm,H/1gsq^Jl%eN^g;F0Vc/mpM>q"$CAs3aqc?.Rr+)`aFfV+bh]'lUbnS[->hZ`heTB>74Yq,SNQMc?tskoa_JN+q-[ZLCU)cP/pDM">b#U8=[KHr(J)Zr7.CrEQI?YU4)*B-a<,RI3uEet),,_L;EK6SUQ*.%3mB@;CnqpQ1dWq4Stq?QF>&+9a4PhYVq%MP,j)iZZ5^o6Y==kBRDfQ'4#=+Vm?p[*DdVP%fI)=Y1fW/]\")!V_\O4P;:mrL;7em%dUacI.lAJ@m?fWc?$pTXkl&QFC7AL#+Qt`0E]4Kq4230eb:dK33uQokB5$5^V@^<$-MUTZ2X$,?4<.SCDVNXW&Y>#(;-PNZ84Hg=DOd)3I&fCIS'n1n_oeU2N0p#!UabAa-<7uB"ChZ$RhVM=D)W6g30CP#R'Tj=R3^%YL#1YW*E2VF'L,r4d+;Ue-Q9B(!0[`,C&Xg8DGHd1)V/nHb@W#H*"ji1%&5Y]WH]]hW9nI(8?g<)K<)8U,#em0nGMhK!4Ra#qUkk+p@q9Y83*`,)?!6`W"FD"-p?h`H#/9(oW%1C1S3?YV3sB\9B4l<<$cV'+Vbq,a@]6=K&Y/+olj$k$7bVo[S8:Q&]/tO4[#iJ;`g1f%iM@ARMku^7^03Rb`bQq+o(^`K30Yl2F,dWfC%fiS\%112l-'Z,1o;&)SqK7mn=r%glN"0sm26+-jHj.gZR]Ddkj$=/@T%c.!Do(CK(9'gBhHgeY=/WT466%M8VEKA?=Z$Kc=8keE(p/n]E[E(DXPNUj+Me5,ZsN\Wd/HdA=[@Ia#cd(d4`Q[:MgTS*C/dXEM'^a,Xqr-;cPHr"7kNoG?..k]n1D5OkHTD&iR`F7p'%N`f@on+eoX6;S[hict91L7ec%JR@N4T8[5V'XjTDR2!KgU/flj[^eh%""'1spDC[T?WJlT`;9'NUFAd8kRF]As5,2`N[[,_1a?l^sDN%MR_$3%2VKScj1L(_M\^R#%s5Q9]ICQ=/!i'l<4G?0tZNNhTYfJW?LB.Rc*;mY7h&Uhh>t1r8!LLbgD^:/^BTaIGW5/Rh<5JK%aLE44+_!Al$__:J9`-Ra(VkU1r)d,W>Sl-VH?WL3DO9'j;5eS"XsXVdRe-L1[Qc-N#ck1*X2te)>+4,+U7&7b5T+r6nm?P+,PbKHXqoTft7*.YaV%#.hhq%P]7DC/'4JUo9));6n&]F(>_"l$7;XM`S+6@>+$I@_cH]>GA3,lm;l(X6T"#U>s%$#cIO!f*1^8-oGH&)nQ0N\W]A;WaS:rDj*&.Z%E?s[d]DWWG]Sk0F`jhqSAcH)DI'jU3bL/A.[(F,7(#Bqkq^+b0.W_S/5GeqVb]m1@<9@;P&1e9\pC/0lAO-nu!I)\@'j&@WK?C4K=D[j"h1MmWOSL#j2@2g5%Z7n9_gt$"G`iD/\p,/D.&[$c>eMeXM(;g>1Zq<;ge%MS'FQcR0;5X-QC3NV(k4PQ@Nl_eKNBKEN">Me=8k`(4ZrUn0"-)+fM%%!ZGa-X-\)0Tic4cOMi[_4*e9VaNKB,9M30O!>047MA>*=8gE-E!jN[Wb_Hc^9nL/OYhY9,^:$BneJIRC;f$0k:Admcg0K8[O7OA'n7@8oke)="a5*,/hVmZt5,g.i";e,@%i7VjA^1t+NH[6KX[0X*/=qJs5d:*ek#@<>T\a\SfWkQj(L$m2_'<.113g`7l#+f_l'B;DK\-_Hn`%.3P9gW@DhRZY?[@2PathcN?P!hK"lZ72)[:(GsXj]\\c9cDHi[rmRRRPY]5l;$"eCG/pUC(]KVC^cmCYTbX%NV[mFoA#U,,E^WXuCagaigpnD[QeF?&!%qE8%$&!b[;6cp=ILW$*=l:Q7hTd7G[\a!mEmf+L19R^0B83BBhYDbuP#2WL!0^uSYBboCa5t=jgGGm^g[*Dq6\DR!7N)f``qk\t3]Mqj%%P3a%9]S7JYgWniQVc5BSg]Z2B:Opr[HS1)]Ff7AOT#K<-+do`/>Hjo>`bXldESn'YQ-7\P6MAVD-So;1enXSKf>8R](f#s&Dd3El->j.R;LT;Lu@Ka.aMu%I%9.Ud>2<6s[SN0o&"_#]eLWA)%<]FZKQL6$d#0"qQ1nMp,H0ZBcu?W[XBs-N5,s#tqdad!9_<)aQcX?[.h1,#)+,.TLT61P_YVt3<7^q%`\_TA[4=(2CoK'Tf9hlmI,LKIm*t&;im4Hndtp+1bp`YasKAn($-"EaSgllY=@pL6-[='U^]@b",$^?5S*7\#@lod!<+X$@N[d^:.>F!8JG$cOK=76NddE=V&r(FU"'DRhuY'ZL;XSX&CW$)pD,PHo[ic5G/64n\T11e+H40oYZT<'.TD+5+pB#AKGoa]\KIY';*hjY)]6O_T%iuUjp`R[LcB)Q`E(X&#Qp8OpmmD^;LQ%99H*@--IX[Co&oS6e\PuX4DM6L/*:MJclpD\a?2FW+HB?r<$Gmk;p'YNO<[bFk0Z\jSZ:K[k43NGl0j?RAJ*6UV=$P"D6pS"bu?hpX2`C_K5pLb.?N?+l++GRjr%bIm7++K:Kblk`bquSb:V1HHUG5lr!]dl`9fD=7fUeSWTs^d(L>G6U\d\m5(*NN$ASSR9-:ZEB\g'?HE%;]pbL-g=#q@iPUBnXcB10_"V#5XA@Wp,n&i]7;hQIb;S5N,er#!@^Ka:1:GCcn'F-tfBm>>^8+%!?n&C?31[MMrh0'*qpA/YhBd%0ugXbY?Z0.'[?bqF0n`DdsLU\Hp*SV5$g^44BdPKl%t2slGW9Ece")nJ2ci/K=T#VP6<^tDthH0-;%qmjTJ&.oJ24o6iphEbT2coZ5?_@?(sN[06%QYU&heSB;R'"JblZfh'rX!-NKg[Q1aU!d-==tZaYnSP9)h]Rp:UAa[RT7$F*.?A#!Rl'p)\AHf5VB(^*>ZpWqo_S\[9m]^g0"`'\o$n(*&C6q,aSNtm,br1p=;%1T&>Qt?@R9eN4s>TeQM`Z8/YIb86;g4,HeR[r^+lg2hH@RIoCn!FOi^0jb'b%Wdf+Qbjn$]p-?%alAqp>D$fm79Ut1d@2D6i6nY60OTk/J1-D@4Pr)4boAso1,hl*>Rdj`bLU5ao`uFWGKe@AF\:_5Cloa6g"\DHk13Q-P)+_eq(p(gAlC%OM=a@._@1FCcs6Bn&ZPnEacjm%\KrFcbsepm`YOGUN`=F*_oLSEFmD(@6k*^mL=*>WB/_^J_#gLd3Nluo.V'8!;[[$\]r\=H7(]ldV6$_[4,j%GR_G%(eI73gqX"#-S-JJ0S9e=>g+a?(FE3/b8df#OMQPeat0EEbXmC_^qL%d;C7#>i[.B\jXbtqk(^][,haAL!+_n@Pc58t9a+?D6U2O@O'*q5UXVTb?kBN>"as:0G2$R=mJ.K+F9nB"U)+B8GNdsdH(]J:fd@R0IMQjPQD:[CWm5!=29J1^^>K]n-W-kF#"$c1Gr=&=Q_2+VZoa3YegKCE<c),M[+LX'Gl2FTj%H8@.bcRL-XdO!N,Zf4S1?th0rJ0lYngd+k6t41D`6KO=a@lP?40Q9.>&j#I8*m2nRL[?_8A9W;auf=X1fA,%'5C*`?<0p6PtB+cH\Q-:3:j*d-ga'L#QbbhB!6%Xk9^J5aZYM::BV%Z"ire2_#[ZQHK;"*`FB6Cm1;@Or9f;Lj.t5P;EbHYu&f6%L'+f1f2b'&B!^9VV0"6$.UK^,"N\(CfG\7.4'@^W#c^pBj>\W7@9E&Ba=6N_YUD["1bUA%2E%rCKG.g8S*jDIU'#An':<-1HP6`G4CpR47ZgC5&g&VDDJc;W9PU?Of!W/YnhtP>XJ^5"XF8*ErI+_U`,l'^:QB!6fM;5?G3MW.#;r2[GD\H\@M2)4edDa0Y5^aD_0@r\)^PgJ:[hsQ_6WkD`1<]tM@4nPRirXiQEL\Yqo_bQ8.g(:drI<^ShM6n6LkDfE-IIHGn+Z_jVebs%is2Bm1B&$X5,ur[e/L;:3i!^)Ho"gl.hrVkJA9=JciHibPb85'$m5h?r>1)El^Oi0f_n;PIc/pr7m9$g.J`+<;k)Y4D3!R\IMeN:$@9(^hKki8kbFt6KXEkLOMmj2lq?+t[o]B1M%l"%Xg=+j.9K>uSKrZ.N)dG@"po\!1KF9(Y"d?d1PgK7MmD2IChmo/hZZfWS3e*0Z:PGW;Dp6"m<_#!;i>L4`iZ%qD@CZ"$snhR+>t19GgLB6r;l0g+%>Q3--]bLj1G*G4psPVUlJ?"#;c)(ICEOYrYX:TU3S\]55ruSNDPT1oZ79q6[TC>O?X7\2J=S9Wg3=`qXj>_6eD(S9>:a!QPcSU/Z78o`4'S@EFs;A`CSQ$8_/lT'h=Am&fqCJ'F!_aLn8=0!fSaC6e[`AsZ8)&G=UCm8E_[P0K@Qmi6e!Fpru@RFR?%dr9#$,G2::hFbphfsBlGuGG56/!c+2&IENIC:gpkr[(rj*JX;<+7;BWjRND\#kC#.iOHVNsirEq-QD/0?9iTP7ZPALQS,n31g9\5--pqeV)6KS^gH+=jB%V:/1jO[OE6V%?5TbJ-:KLQY2(nOg=^RcBnoj@e$N!?OrK#u+9m08,4r$m[tJu9CR0"Q/I*"e@E.7o>-@'glX3Y3`qB+1JIJk)_+7[==?iS7_?]+El0Q0_"d7)7MsWh(>#gYJ--^Ia*CO(h:W"Qtf$d1_6LB%1:s(dR@b;Reu,C94I"EA9>j7V*pp`Zg=jIG?7t0bIAeV57s-XVB2]KM[me,S:0lZP4&rO?tZW+H\SqC$ES#O@4)RKQ>l^#\<3O/m4XL!7G>F#uH4%JlS%-+se(W#uX5m+_$0M!#\;@=sA.9]=X:tH.<@H@d@fB&YRu$)];mEUAj=U8$F!=JQmjLj9rLR41M`YiUS#B#EnV>0ne"9?I35@;S!B-Ha.!-=fAFYru`!h8,hIO#p,[_I!49Oi!rKFCG2%eP`)[eU[9be+BnI1pMp5LB[lc0"jh=s&b%4IW#8?jI#(j<;!M!HV8M\$i->5R,^;PRXZqK+Y?:c/Q@ohqcZ%@GMsl_6/J+S?<7PeY(XXCK-ZioV8FiJ3*Mn^!AjTL)4,aJ\a9O96V!.XjU%m=)r;+430*ejt1`JeS*1;pY"mRnMnm08oo7Oc3PtHZ\JE4%Va]$=2gNQT:)A@`p1>_,AGhRFPmVbX<(Y!C^H?WuODNLd[u2(fg`1U/[eJV5g&@&Sqk3S@6E2tR&k67pMV1N(373Fm)E.\tH&0P#K_3J,=BIGK;E0!"AY:h!.QG3RCb7@kgVe+];M)3Za=7kZ!+XV>)Ao`p`.omq(^@g]>+t*./AM'9oWQ'W(0,hciNI@`rnj@[.QSM;=X>p0eFRe;?RJ&i1gA91]Q?"JL+5-otQu"*I"39MtkR2'kj.KJ#[qO:&p`/Lgo*:aARS@3@"a!1Oj)+Ba:7KJar7JCK)a85KX-Lbt3Jco(r/(>Ld>m\F9t]'<2IO*T?0RFC-CG,D%$4a?R0hn^qO@[<(!3:Ln4pN8U9QM;R+!L`EkYDNM'e$[&=L\X,gJnpUHY7e9u#S3XZ8uhQg76mlR&j!(2$F8=7MH(T$Rf4'gN%s@gV+#4#!jW9$#k/*%YCFOMmiKK0X,fDcS]RG_lAd=,%NXfKN/(4K6;p6CR4K-Jc(r,a6#Q6U:GIDUSBdc:2GZ>^6$F@565Lg^Y)@Yu4G"p*?Mf5=jkk-cSMB_4VWn.GMS2V):Y0:`o7Q"?&a=f1>&q"o#Q'41ZZUEl?@gQ+\BFcKVg@"&M-j3+:b2kPF)5sRhhl!cNsYLg.aal>G2--bBH[fWMfj2K;_Mq=c$;Y90n0lQK'*e]ke5;W3_ZNm%<5a8/=h[#Zn;!-)Tg^[3NYeHSD`YTr3,DNo92-C,2Ap+;eW(I`EsTYTGsWoI5rP+oN=]*W1RGC]k'T%G"XQp<\d[h!=@Y.YE$@K?:'pSPL-po*o)b,(F;[-JL*:\`[IN?_Y[%o30$#Tm;L5F4.m+G)O?9'Gig^sYkeCS8SFml/NGUP_d$1?o0Xb3BC=R)Y%Y,Q0pfa"p_53?mc\1[$91m=>V],f!oGrMfDX>p6PN$Ir`OS.,#g4"^(`5[UN)Qk;X=PbKTSXrjN+g&o:&8@qVLXh#RSIC6M4bC%FW+j=N6Fa6#_Sc6d@m:EGSV.__[-C%>t-Bab[EQ!#KWFd/kXng1J7^c7*kQXOq-%k7")TJ6M*O2t0`*KWS'r+*SM/SEirR8T$$?Bh]idIggb%JToM2j.?oC2O91rGfX1TH]9FHU2o(X6)A%N';\G:FWSlo8QmQ>NEk0cDIn@sXBAbmoXt%/:-Nr-E4!F&rMT@)c\qKeY$<#r'm[MJAn$l6C&3omBk$$\PtlfqW%M*$\=nBQ6`/W'-N-)U7E5_[0sfW_9iC?b7YHKI*pDEr(ROL^B5QJXNMa`0qs'4G_Au9b)YK`UBA>N-Q4LFW>uI@RrS;92MG,"M0aogF2VD@KEgjD&U[>27Pt4bdGQelT5TF@3Z`<8H4SB6=UE$-CuD#_Cq1gi-g\.JuBF@Rb)Y)iF0Eg$#:Tu'YTZA=MBOk[>cFZK@T,G^u[J(lrP^3*!hk5V[IG_7&Z#&>^c2\W-/hZ"6a@Q[]-dLHQ5JuG&X;9M[:J$ug\]2md'AOtP?YN5M"!XqlH;J\d:oo>G+MfGW%\t5pcuH$W=V7?@@$sVh8k;:1"ISm%>UJ_&d6e1GrpcB_R$`a.-p8ld"*:/BY0)9&CrJ[Q/1q,g!ZcNM.OaG)_<)(i[2U(h><>P;^]dj'c/(26@TqF>,m;e3Y>&#:jmKWZ!U1jdTS)]27g#E;'/l1Cu-9;C(]#Pjj2^`)Gd[7!@bOWo;YQWT5_P(Xq>ce=u]*bt\I<+Hh[.!`;?"55f_^oS.9JJj1Z/*?Uc5C_5hjWHnfX[1nNOHQM]#m[(snOM>qPG*[!T)4d!_,MQ!?%3X!0d[kX'8[Pl23;9DHQ=^uM3?+LhY#32Zkc+89eA5bQ<@c%-9:'#Ki*qGWoRY6N!gindM3d13LH46d`Bqs=DpQg)T)o[1!DAm1!OCZ,Z&66/1IYU$lN0o&6+OuW63+K&0Jaj+tQ">eb^NKb9PB!-S>80gprrjA-bSbS`9VL/uua:=X9/%lQqaf,^.m&T^F,^0`::08Ie;<9bCr2B!H]$*\K$999pXs;^2Ql3gdM6AW[n(PO+F`>Vk,e7nFL&%?nnTh/8K5trACFI35um\^*6jk8cS>/`Z?"%N)Bbo-b]&B,+J3LdMZ3PNosslblm],$L*p#%_4[8+UF[rMXNHf;EWHH6)G$u!"p.>[Ekmou^bT(gp^D\KI0lu?2$e(ijX*FgiaWA&^*gGBh5/8*$"+I/OB-tlT*PNoh!YTl`lp0WcRb6E3$>($%Zh)58:gHfXnlKIVkfmEV_#jhNe!KZokd)DdpcdL]&"k!k'[^-5l_N`EbcHo1nWN@_E!t)%+2)TX=(86@X-H(@q=fgJriMD8OYcZ'o83F\lPRM9d6>I!JHQoZj^cD:&RSt;A_YZR!;$4I!-NskBq:'M=rmS!hrYIOYTaHE\O3j8eo2e.1@M91.HggJrCsq:nT6E!AXYs:nf'@Z7-3EEWR@t&s[,2%$VS8*1>q2D])^k_DM72&^q^f.l<`nE,(_9WQ,G"c$Wj)(uPi`3X@spnL&#)k_%>Z8+,sHg@OJ8YC@r!bhCAG%Ed!;F@,#RqmuLWN&Y_iPbY56jEfUt>t:^dETII7":fREO@]Y.oVfH1k'`XS`"CRL/l5m'N%rL"L+X+F_;^+DiddpSTa_'DMeqgj[Im[SRA81Ge\uQ2IQUgi#g:mZV`WR&tG2:en+sN*Z,BrH<61ij^;cC('3Weq]&gB`jGp5YA4HutPdHkuQ\UJqG`JfSGcFR1/idVW'Ff#%;Pbn$E2*Va/``^Bu.MaNrO,TMfE(s?]YF$A)Uas$/Pe4I3Hr#aCU):r>Ks2M>6*[;D$L:NB5e=S$;3a9u$RSal\)0C;T?`"p&QsbVA+d@#"8[5is''sHq:Ml[6=K1BM#eJ&1Omfh+3fEbN1fUmX`3U6@W.^18ll#teF>SqKf#6\a]26ZWYc`oW+)QB?slnX[ZO.9]VhR@8o7$1'ie!M??<'GN#YZRZ*Zt(.j?k%+Bj9OZ][>8:L;j8]U)r_Pe6d&d@huXOmnrY"c[RIC`01RLeXcEY02E.M<`[FA;oGB7sL:]iMLQLE,[*q)*Z_M./'sgTAZPtW.AsiMja]L)*kiHuoK/F##tRp!UiIL42Zh);F7n3)''jA*>_pn7Yu;V6,Apl_^dDtDlL!(KRb>2W61Hp%B/WDaC@M)0M]h#m>lPB]Z$D8Cq$4"KgZ/CJIPO)P85-i5#G$B?*"U/nLn83=X_ZkkkN<]oGu1o$)Bg\!Lnb"VirC<%BUI#:fb"E#!to:$`_@?[(*/OQ4hi"mkR7\:PCfM(AIeq8_<7.hfb^.&73),'3mmDGb'W`4#j;dp^eTbNcr!A*1pehYPQX79,68-;-nn7]_[9!uNBooC^T=/89X9:GMO9j=0[+,QaXM0W#n9L7`)/6'<(&"^VQ2HeaOU@P[0U?,^e,1E"X!rbA0PQ].2)k_@^*d=WW+pZWID'CfmOnp76WrRDU_U>5>P\:B%OrTM!5LCUYQrYKbK`]thdtAc9A$-,b1R:+Z%BW;4dF'_b&a-e0-mC02mMf*a*_Ge_gZ-uuE(2pM^/$a&q";O5a$cncl\<1r,XSN^)$#m/ODa]@*[R/]EsfjY`.?3'!osUf8:D=@;RP0+,U/&a.fe=0G21s9-ES1ub!=[*KiA(%6bpQ"#scl=W@B>sVM2-?WJM58r]R@q'MrP4n\$EcTmg=3YQP>KUu0(J:3ui*2]7eJF,P*.p,198tnYA\"2^ptiA6A[:qPBY'PR]qK9FQo=ZC#hA6GOpj*9sl9\a+!:GStuF`M07F-EY@q`;Zn']Ipn1IG,6@DYYW66Jf2#bE5N_"Dr_/k/*c)/*L\W0m+\.ri%YFeq,UOI"ZP>#/,<:"0^;D*7/[rk7o_'[UI/YjZg0%,DPHdSAi<+*Yg#(Zr$G$P1n`rJ:D]of;r^WK7B'T4+.A3Xj#qQ\;IM.V<$:,a)t^dsZ@$9)fB?.jONr)DGtU8tb==YO\[el(Q')-_XO:/XE+D(`9)u'f)eCYQLOnR-FlS*2$FZ\L)BBW\QH-s#GMpBn&n'(/:6SHl=Sk0sIe*)Q:Y7[*$b(jtEoq.=e+H\>9oQO=@/$,)WLW#M5A/T4s&q3g@-f-;'0RN3FOrZV8gm>A$SVlAp`?HgpPj-;&OkgeJWa=Xc@edl813?B6_mjAqK7[+XirRt&[D=pD\omA=%m:RPo9P(9cfC(9GYJ=#jLQu8`KM&0D_2N/.XpsTol[c?hI?EYeY\gQJGcCj+74!%ZY=dms(Z([$EBT0?lXO8?,&h6q4&>#)]:0:mRQ+?ml@#TV,g>-lPC=.AWbqLmY%b+pnB^L`*1lBISgQ@OYu%814\XN07S)W$lAYR4:NpKdA(CMP>uAVLiJ1R\6I4JV"K$8KeF4@Mj\qM%_%)>#HQD'o3U%(P$j$j6?C-Qs`.NK8i<].2i`Opa!q(F8PoA$+ki:MY2knT5c\9P_snZKF*ea@1"GS#nSpB.1/>'#^Z3[2'PqX"%X+""54YY2tR*I!iO*fI=tu5e^YAN'SnS#!C0Hq+-'nA"Mlal$moAXOboqaKU.@$(4p4o!XWRE(5=+^"f3CeM"8S/M$raGq-#tP@NVE!P$,\Z\uW&SZul.%Ya!l?BVG)mI+W2+QsN&h?og@j]0D)KWB5-\hcud,m8p=g_UsBtEm/3b<60O1bn5WhL<('L6X-cCa9%YQ2MMO-=A@]YOe<+lOT#R@mGn^nNmpB0fH73]llAlL]Wo9;j,)R[`:h&m_N02>A'YVUjA>64sb?63I:R%oS8;dN&W0a&e@?HR_<`-mO,#hk):`@8Q0kW^Wj&O[N"@mD(I9&pT*O5b1kWsCV6O,^OQo\3;HAH&tD9!*%NpW"b0nC$C-5b)o=8n\8-<7aH]4AmV@I4ULJ[!1`__t_Y*3@)XdH$0,KNf>')ZsRX@\X._!j(GMd[a+i2`U(2U2pqpE7G0Hiu]+GEl2AkWaoVh,_WSJfJM-Z,-[m+H06N>Bm3Ij9aUn\d0`dNkBHmheoU&gh=^iMlA_S77fa"P(&CG?%LKf_='(X!b$qAp.r(ZkT5-Sd9h8aG&6GS(mHq>GO\HI**b;:0/kMU=!eAGs.,7"Nn4C`b#;g1sYD"CIJ:@]`,(So3K7QKj]G1iTiAM2T.ASj=E*s)LP@b=9aQF1TY3h;cr_,!&UX]Mi_3N,)_C6BX1?mh/8*Ld6d.=1q#^VS[`u[/mWDu&l8X)_ok<4T2Ts8@!;6-_]=DiET:1o7:1'F6#OU@KZ2t>pX%oOF[?>ZshE0mh)QrE"`+MjW8N:P'Z>O1$$\UsNTPXD9=?o:Y)sTZDZ'J?3oPLkIKPLb^tVRAg>2!trf[('rKq%2)@b,"tEZ9E@ZuOAJdW9/KX9K*d(N?slWf"I#('(dCKL/t.Ln>p:1ZHAjgLJJ:+MZOI`Paur''jE/6mHXUqbp!PoF,:&5&=_jYXeA7'T=r=N;IW4jk`e,,JV_MGZ*%V@r&N^OP1_IDlacRFg^hQFMY(HF+NcCp?q-HN&C\GUMHJ(->c\i:*,'.@6kROt6;Vj42JdTWdl!%dX:B'0[9?Od8XlboPd.ZZ[Yo"!<<3gm&]?uD3i^1k"/XOE)B1Rt8F;N->u'@\S7Vke,YST]7\J\2>t#Tj4.=<7r\::P=*&A$D::?6R$]:q7d9ebi]-liM^%B(t/.bQQBTA@Y,@Kb3kPH"MTfE`6p@Xb3QFn2S\t,YQd!qYp,4MYhQR@2c3=#lA-Z^Mup4e=mE`fQN&m8V'Yi]sW>ma!+/RGUeuOdE"25C)_"X7%n%Zs1CU5WL%o/PJ"kZP6a:^lP7#lnQA"hmIFR-$LQekkT/TqfkX4ffKA2r@$Dt)K+n9F+F;sOW4-.sB>Om%)#B.$[*d"'m_kl&\e-9WDKi4HSBE.3eW$W'(JGZcBt6m##h"1!f8p?!GDn2/!^$ALsm`@.cK[F00h)%:4M$8$0^HuIbb:.5I[GGja<`%K&sp*b+>gChq).Rn,1VI#-Lmo>6a>+uC@W8b(_j![*1_&UX)p_TFc,6Er44e;Ari;T^Vt%)fX@5'kU*MDWKC6g]6qEHY(%mq8u(!1CW.UR6W=5$o)"-c6`S`QfJLI:k/+V0ook2B]&OP9K<,@:bp0bZ9k[a+63u$:09BlCYj+Wk^KN&a$1._bi.l:lR/ffV'T>X8P8>;m)Ar5Z3n](oGa%oYF5OH"#_?VLMl`'TWU#YXK@K.7AD]Ui"28/%0R3Xa^'E0ijH[)[KaQNJ_o7h!bh*XD/LWNDAhWR=.[hT:%#:E_b7#IC#b8h,,+m)ALbjG=UE*q[b\;eV;T'p7b&n;H*@5$FK-[?]6m0!n3^P!u:th'PO:Fc5!d$9h"_`QGaXj@V4AOqdGJ7RTfeR]3]&2Fgp[-:`mL)Ju:dj:[b\pit+/4\J_?R6qC2ATA/MoYVX+WIe5kDfdHU&T0GRLQ<[DZhd[faCe*n6DrDa/u8YMbCP>cf+0*-?<^Mo?)1>JfjMeocS_d3,TSUKa,Os[@f_Cl!pa/%/YW&#Aa^"n+H1*H(R%Ch=<=?FRZ#e$t)%]ZC7;4>?&-BO([`:A(q0a\i$[jLEJpJ;N7_TVP3XR20*/sS)?X7&NP4`5YL'o^amNe.kIEV6&Qm(ri7I;ePA6!Y,s8gNorCBAN;_l\510=k6/4:NMCEFKLLd9GUJ/ON8l&U6OnjpQ\6T].3^JSJVK!RV.j76Gbc3T)All3Y`06SBH"85dh!<8N$6OU8M_&mR.CL3r(;`#Yfd(ojlk=ft[m$hf(:nc,9^@/e6mk+L6):gI%^4!"h8EI=EBn7*pACKa8]!_OK)XdYe_Sk6jOhn*XlAW\qB\[MaLlZ6:0:Gm^\;FB%^XNE3fKt>*QVI'1/[C0WCO7>JMVTdcpCREVAqJ%e$=$YNmt#"4iB39&VX#B0ZOF'Rm.=NotV>X<.XSLG,E&_rAnm[V?:p.SPkW"@?Sh>8gs&H&9`n@)7sTsiuiY4R4DXVh-(V8r&c]mjudF1=A&_==2afA5dZeIBK`;IH`1HGQr%\F]V)7=aJ^aO2o^'1&rn0goZaTE6j7%oZ:F&=6O=k7WgneJa+;M.R6D$f#dgFruLt2cXlM0nSnlAOG*@*/"f7OA25N_>Yis3?tFcp#Qj\T\O_sFrput="l6E2J&:FP"4uq;mL2AS8L2fN;_<2RQfL;M=u$ud=c#AIV1VD]t8<0r(i]7s/s)-,_gITG8gkt,&i+3?n8((d*@&JR.DFQ0HU[+qB(#%6>(rr/[[ZREph9uR`U3Br#a,A_[IRq/@ZP$2`g@.9@ht@6klF61j9-[g)"ZUHA/,nCdQ-[4uo8i05D,KCUuD)0;-9UM:,-+b7*OE0ap=&pPH]=?':1PtU.rB'5'lBEga'(4'13ZSiIn-js3LqhA^;&/%5on;8>m!]Yar%1@D=d$W:?6\_eGEk9HjWg;%ndL$f,XWJN@sea+>sina%HJ?Mj3FJh:.\Z@S++?&X#L(WH4XN8Il>sX<*pSU:l\/cA(^nbg*,81F38,cnNNf%a?AZTuE%?rH$++2I_[#3*19nA8\86CX&2(B!2.VUWMHB;j"A=$a$2ILHFJK/4\0*n#tCCVrnohFpZ*-7O"cmJBb7*k;l&X@t'^[L/Klr4QQ:'RC28\^:L*CrpVQrL=F6VKdCg(![bG!1k3DJOO.XKDc:"g$/eTZ4)EU]b:HXmM!],8Qb+TY_,gOYFA87\1OD)Dtj$/)AAsee9WtAW=XF2'BikKs@kdL`%0tpDY,aX.^='1eeo,O[LAUpJ"!rQpeuoPnO?q?#a&se1+n$$-:>u).kY(.U6qo)f6,[Ue#0/UXOpc\WD(M7Lpk,Vf;_/&74>m:(p'`N>mkec8rV^W/;%RAg+F;ru^,=jPDL)$2>?'*5XTNTKjK;[7<]L"p;>9=34=b/.Q/-b01dD$">;;jH+bL468:5P^#M4^op'(+Jj$pnE.0V5FWPG7HGHSJ(]EO-cu1fUQ.M;=:qV'TusgXHt8n94[D\U'ubljIY+IK&8?6D':7)\DO%6NJlK8l2783n29,_21OU'c^?=R;a:"rc'),Fb\Rk!YLQ?q#m-NK`D!>oPf[bY-g0R@^b&HX@4"&>rU_Qd(8qh>iLlS2.\`X!EYiQ($c-Z[>m?<2ph:.FeTPUH>eVoP#XbH<)8%"D7p\S\_TA09m+?.7@je&@j3L]##U=Jem*k*(V)Xh%j;TT9M$>8LBIL&$Qls.YJL?(a5cl\g=Y*'*PlK:QTNb_[,'60#C[=bhrRmT*3-sl#Gc!N@ma#J(@RE70G*Bgf")UdiHigm24d>&jVU;+6EN+s.h^=Y2M5_kWYUiK?7KccOWd'7?a*5%[HLaR8C9o$Yq_h`st5H_O5ePN=2\+f.?Fc`if2>M;Nlog9%3[QIam0Z$V?]?1TYW_]g`NE.%1Yj"W311#@X$!^"g#^fPL/W9J3uB%4a$\#;RV\=hJ:>4GiUY`"Z2%tW+c>82)da@-n%o'NkeH@)8E[enp^\1!B^Uq5t&MC?%OmfVh59b391Y\-!8A;GbEKa1R0+iQqY4YWRUO&R7chD":Ybf=4>@^*`1@Io[m?d-O`g.;XZF6K/j]gKtI^(K`148OmA`(pTdAgY6]Zt%RsR=-Eg`3Zf!^O@LIaEY=Rg<.7Z2WIdT+2I4>(#+2Jl;'(ir=SAa<6S[H>Y,Z;m>[`ci^<`e:$GW-R)iL-p@gJ$+gF3%lNF@9@EKNlG%IfL&2VqpLWA.*/.Rp-mWCOBjbXWJ;-rE-kM9!WX;TK5DP%M-Fq?K=N["AD3C>h="FG-coSB7?GGOTE&TX9U"',u?H<;P'hZk.&lL"j7)]j:+V>A!"s;Uo\FJ>;im[/-F(C&noH."b;6d,%[_tsuOS+d*n@C`'XY\ko>=^!5p$m&>3`B!t8>cJ2f9>G'aflGKm7?7!nnANOIoTDD@)kUaj?Ber($5h@oZe1FO1X/Rh^3;I[.,,%.3'pp,$;]*GY:49?:[,(oqj:7@Y&b%-S]ag!&]3J^`kl5Em/Y0Wq[n3[94f(P6>1B,$]OC-#k[tu%2:Y`K,KXuO*K\Rm3mu66m9!P^$T;t(rS/YqfG$NrM_eZEd^dUp5/5pR>guFYQkK++O,>T\d8!k#08!aP!2Bg.REo37YD+F#V(^r%$41NdSk4MN^1qq82O79Kd2Z\@77'BU2KAda+!+KE+qB3+bBS$W*CHqmeZn\N.3KcH@@1E+NYa&KE`[[pbA7r+,0o2YL5n;ol4]X#A%=4YsgcZ_+J.d$H0C`R4@JtMA\dLH!pu9)(km$@r\nm/)Crk$\[G#:\U'P-M0'kp$.7&OsV$<1l-ip$\#m_0",W:E[i/fle@@"CQtD#tiVg-p\WaEAlSXL'!eaBI1]8EW[X>Uhb'.Xl>eYD]MT,Tl?.9.sZe:C'ntmiuRFoJT`"p;\r'c)Fb/s$!8o'"bmIW(b*Ln_4];7^sEO@WOeE@.nV1*"ObXS6)rV6+NX]I"*0ZMM:h40K8JnMb1mumq)g1Rm'`#-?5,3[>6/jp2kN_n9]S(2VPGfdk+:*JpIolb=P/HAa=F*Ea(!;Fe#hcT=8J^[(7bDITh]m6ncY,rVJ)RA0KV3-cqVj@M\?#Q'aHaY_js6Q]iG!B9IRMliO6p!EX^=Xj2UgE3naI,h2W#d:kEA_=n09]P'^mhsPC0HF@\6lFeQ"Blbn/aJY\p_E3c,SgrN#ti[Ke2liIO!5+0]5kd!hLH8MkD2EI+%!Ng\rSl8uL=aJ$Y^Q0$Yr=H1kN0ie9f#(/KiR,6/pB>]SPgl0Z:Uhj/B*[K\o)]a33#P@.lQ;+5s#mX!Q"s@AP8@!=(;u%&fe%QkE0EYhENm*acY]BR&$=okX/Au.M+q`:sA)*T*?Eet?g/Xe1(1sd)_@m(%a#6QF!X@WFTb\!@*'EDs3.EQSo&L+::!VT@&/T\W@B3mLELXo,bUqB=b[$I1;al[+NYgMV/h5`!s/ZnJO+qq0hF/5%%.V$./`7P>EclRR@DbI)GZoV!N_iJ_Yt[Ima<.M)$I(?:SZ>Jp+)J#nT9*\+(/"jn@m5Lj/sk*)&CCqpmS.AiUFD(qGG'Jr4UJo=N?*rY3Hb1'jI]hO\iM#74J`f*Aq3\;=?4A2^3/1W@76-tEr47%/d6L4g[?@$D.kr.!jWRPuSRo,A'`n:$FQ``5uVpDd]GNcJ+OfSHof?:HHgU'tQNH/Bo8#B<]d&2./fPM/e(OO4(\-mm#3KeT9CJ[-=7%'sX+)8]3c_a5<(+NVgIjQe>Q=6lh^gWI#gN1O!1sA64YP1E7rT[PMqQcqJ#R6TId(lsIT*;;>YFhOdcZG[H-VI\8e2P!oZ.'m&3:F.8\.0\:tDuFF7U:GXlk&p6\q2,OR6'A+VXu\"DFI.)?N6).0=0jLa=3:U*r9lOOsjn:tr&iM,(gfoWLOYq?[Y1+0n[Ufc^Ce>\-+*_*RSoqG4$=!S!rD,p4K:7)#T4LQjbiiVNR\\J@U#4G8BNW)=Ga5Ck(:#NhU$n\;a7["bRfP]FtDE9JbAO:ER6rjbQ6JMsLLdsr7R5]$1e3KG(u7J^cXJXf'SM$2521%+Z3=NC_se'jNHo>0G*r`&t@i1HELXBHNl@AR(-80Y?c_koZ-MSroe:GAp2pi#ZeKYI+1l^f#[ig_Ob/$-W@l0I`k4en"HHAG.KpIQV1PVJ"p@Ne`C"gALhI'EL&d)1$%Nk=*AQpkdsfL65c4fqqO_C)?r3fKY)+TD-'B`B2fZ->A@md`Sq4I%."<5A3Bu$"Vb1^=8MQ%71KG&t705PbD@BW*%0FKmR;!fM+_X3+N5gd#"qX"XL(YeJ[DqpX'P&?IZo.Pa)i^*A!>;2$7:Zdd2K93\9<84)8VE0/<(/j4aN;6p#Rj=J(f;*?J<3J9q&it3aq?:fj985[p;iUe0I,]H52I??l6ZR27$*Wh;$0!O@/BFrBk`1KW_fU#EQ5H'^'3Xt9i@ZaW=T4=dW#I'8g^7j!R\p#?0rG9T/&S,kW3m+3:+ChI*8o>#fERc[D+boqibdg4S'qs,HTL2^Lu;4%<-Z2KcZd5bb3TaOoV;S_B-49r$NhDkjO7fkqiW=as'+q+GHX9G_\;bQW=5D;&)un$pqm!ZU=tP'3h_;l%hAcA>qABM=[V.hHR)EK@>'lhhQ[HNCR0?NZ#Te/8]A5lM\#FCqmGW'6jgg/.X&".&S-BM(>n0/LghL)7!V[1k8IXk]kJbk?+]/&!lN-e%=Z'GBWUU8um8bR/*N&2dY2Q@Ob<[OW>C'PIcA+#))s):hH?lBXWXjWZ#&"EF\d\-eW"E.91b4UG$L]B_FhmRtZdR;!8@73tFiFj\c=:`_GbLLmQhYJlX+YSscG1a-ZR;k6djVJb04M0X6K(Yl$+iaX2.?\C>%>_X:tFWAM7W*Ip^AHT)TeU4#2NlBcM(;j5[.iI(&,gViXRdnc_qmD'IRVi@+6A5[Rk"))QK;?K[hA@XJ:&5Z3%8/$k<[SBDHJ3iDA/8iOt(-@ZBBE\"hA9VqP3o*ZSWf[0F5'gB=Kok%:tQAH.@\GA_7L^2ZD:AAADT4,MjjM?j/-1B*:+.pR+bi+oF;hL.fJ$u.tP2-9D:1d&sRA85PcY:)]N[R";$1MSJuWcmD[UT"W@AdYi)..j?^rr+DNVDa!r,8QNo(eYgi>a:tQHFLZ2<%e;8^Fapkf##:9R-$)DC"5EUIJ#hU4a%6A<#meC2X.i7lPgXiVnW"#P37/r!j0G/F;KZ-*/?!?afcgu(qb<>^nVbE&]PN)Xi7ht'=YflP]"*@M6;)mX%'1*)J6Br8u$+B4>3[IUH8S8sDGWGsB2ZSRAg;m-ahGKXp_^08DH\bF\q[EJ]OWX0j,.0F2NL%Tj+ja%>=NI5/]_mpu'!U#;A.H9J?]VZ'e[lH'f46aP2rqKl,HT[DMb6n*Nne[i&@rJAO&s45OIL"&;/!9Go'OJZ2hfcQf;BYdo>XMPWm/E_Z%%?*[QTZ%+,#O>*s?)&Z/S)<6&1P>`5@A]ro/OT)&2fQo&0*P=qc(3Mpm?4tn0Ne9k\Rf2]+h-X(58CH;)[8r00*"Bem)CR_3Jni4Y84Fq%4)L>)UT:A['oDI^IXd88(h^@ums/n*d/^"8fJan(mnW#PZk,S$="&+ccj_,5Rr6n_lf^rGN^f:^E(\/`0&;u/Tqjeg;SC*[f+Qu!N.$-qLe(b>41rE=b42W=%S&&W1BWW[*\a"dZP:C,6*:a:f'AUWV:i9]ka5_Oo``(?66'J&Ea=o,fDF6H)drd6%P6*1U"Cl8/*=,2iMNMQ+kN%pkm`BambY#)#,B3+2Hf!Wlaq.)s?XMofj%=*P)Zeqqpp`V/HX.],CHkAQECODtd1kOY2=ArjJJGo2!tO-YJ4)4r>p+$Dmh9/(dJ+'\%Sa3:Z.k\q"pKd-Q*9eMj;iC?8":aeCVr7p8`O)ZqHhXg&-oBlMg]ZmYJ,f4[_Gkb.E//'[&+Ge(&"&NM16u'eYU0[1q9'NJS`X'-Z04Kpe9-_p#D2l82jrBSkl%*0XdAgmUX0I%DM[uUJ6\aFC\k`a&)eEaAW<48V=D,i@PrA*[GD/@0pD,;^R601)u),P+s1R.gXLGeKKU7h(r@Dq:st`<2s[7aQ0PurL[qj`V$#e0UV^L+ISo-U8Pl)lJ:H#L=R-a9(i.M2>SU<]tt"AINH^5<_XnMJrdp^ss\Ad3f.bIMf4\G^]AO&H2Li'F*$"5^A3[nEmt[]R=$`MU'UG8sHQF6c(MjmK+,r$&(s5.7TEkF8>ZXJf,\RS^kXk,8LBaG`^7CU$X5,51C9K?6TW"ljWZii)iH#hj\f3Xto$f)1!fB_Xru5Fu>i#O[[i1sFj=C)KJ$.CKoPY[ecIFp.O3r=?eDS$rESYhI5*\6_cS5!BJ9g;rV?b(+Z*k50U,8#)%fSn\AH<"jP77et6.%slsbnHqq4^TQeNCSu"f1hMjV+<9YN&2DkM4j0d@0%#e&I:e3aAQ]R9+P>E^#Fs=Hg=1"ZZJ=QCAsBOu!(7A)P#"XB7p3/0=!5iY<\ATBY\6tr`A%!"0o2Vk_\UsmI2)'K99:h(u;2$-h##jSr3m@?rS_\VhNN%qi[,9]%q@=nTAosCuV>B>ej=S_T?^tZM5'JtZKPc^t,e^qRZ>4Q?c2P06A*tOaiYT&7d)\WMk0s*LB"jFBo0WL!m@YC'.UVX>IguN+o`?CNrfd[<=U8<33G\R$$d7Nm;&>;Y9-O@[jLT"aFT"#VdoBLOA/@EL*i^!,b>kE>\.9&^Fc`8Cjkmq!/t,G7?2E3q9P.V5,VaR(NSD18`L:$VnKHe&I4eJ_[4s8AW;8'r+^*mb[1;]cbaB$Qq]"Rm=o#CdX\,VI8O[;,X4*p(rsm&MeH2-JO=H-=K$bS-0Si8^Jf73R$R-a]W$JXOe[*>Da.k<"h;CE6ki+^i?5H]@UB@ipj./&qR<(&4')Cub!uN6]\?;l8mXqs/jEE(%m/"ApH^+,dVNE&nPZe,"PUEEfL5#7fA.>1RY#pB6W]kik0N1Cn&@)s7Nd,$",uOo;.2d[VDIr7e3!0FJQI[h=:cNnKR&1_`k`^OG^.gHDbT]!ikOTAI=-AIVY"%H\OKbbM+7?_.^7Ms)j1f3"*81bK6Ft+b'(tp8k6IEl(b/hti#>-9"Bn](^\5EZ`+\+14RM\KsOWgS6LgO7PH>qZd[/mFO:IVY`'T^EdZ\>Cu,cHkG#h$qIUqrZ=5EA[Y8A8Ri19+tT!g4m:mI,3l*,K`@0FGj>6kQ$i"a@(>d&lk!MJ4G+qA]5PfQ*KLn^*p=P#Vqri):hi9AG>=VF0#3q_Up[nr/)U"5JZ)]*RbY,"79FF\1ESJl,(>>CS9Le,$R.QfW@##S]^J\1*YPg_7;Go]rUm\l92i`&db)VdL22IQV_.o_dW*n-RhnC\E8G#X&aG,VCVqh:HVMri@Ye0Q/2=IgH#lZe@PBnM#HO+k]4sN]8"9U(aShqO^D]1Fj/-;H3in9LP^h%@CQ,AlCF=3'gNl"T^._"U'L<"Zbq=*S?Ff=HIJ-nE:"mhjF%t42p,&#F4C/6".9LjaD7]YrmH>W@?RdVVl3PfY";*d.hWpBPK1\>/--U3+DKU(D%kUJ+=/e1((j:^obYKTM-ufM7Punj]E\7oN,YdA\oX+JPO-LmmU+B/UecM%N38@&Ed^ZNuS8@6KuS@OKG"9lLJM73.Jf[*,+OF!6b4>TM@TG(;sumeR;.p?Y^KO``RTQkfBjsX_*oO]$5A,`gApd$SS@NK*Db8&H2J,t66:3:Fio?k\PpkD2?4`5&H;G3U4J-!L'WY`JgR.PVP0B.WW^,8k!JZ8fs3Td3$8[Y&FYXFhBqKHmQ;8[9Zn'J!@frp7OZ90JQ9F4)Pg`8<5@"(CDLl)KG#nuYg.\3,YkLh@Sr`P?eqdGEX=MAVsZNNeq\k[H;.]F(Y[+IAuXFl*2=q^qCVP5KK%ddpR3-qh"%S>A<@6;sngoK83CBC6-!a:GRL`iS=*&\\0=OF3*UloaS8He(57BI>aV4hG$F[jB9U5Z/lC^-):K;ukGZ4)RD!@_Jl&2FD;7%7$V!3ldJ5so>b_0kdoiVL=BO!Sb_=XqBt?`R@BC0M2=@IR+RnCLt.Qbu[69K3i-)+HfU6%q/_]1L4b=i]*Q"q6rhUq_fBUI`5uT(S%m;4^]pF#gBm6O*t#`/V65VM>r4qHMkL6.&hDfL+A4GB^^n1")-1IXYO1n&M6k-QO9UcUEll#r./e:mE1Ja\L8%AnR&Gg$_ilorV.5Z>"k1]QN'Kl(qHDF&mH/*I,hO\/D/ee]d@JQZ@O1?LGI9aHL[l]O7Lf5a!'Xc->%*g7G3H=[_lJ8NZ7edlV]p1P^OY*iYK\)H.MFD_BVi$iLo.j_aeu3/-%<[[B=c=O'd0e8`FC(E(S'3e9%$4^Cel4:cXU_ma*N=g`"t^++#f9X8iG1e^4U[qr*!VPGg`]'nFJLcR`s9(4Z*rG/clc^O1B(SDoXK@D?jVD,/JY-J`?]9[]UHGNDa"bi0U;a:FmqEX)NO?A#[E[]mDB)0X=XAuc8p?^blL7I[ntoF+l&-Uqe*&nUCj\pm#4UTsTr[%f;(82XKu:Qa'OaL@9>7@F?1ki3RaH8cP;g#bG)Ai!JNQ(OT:4BaJ1UZLQajKfsB"'H5%Ek(WVIhgAW>?J)ZrgR=(l,tWLiRq!a@=:[l1So=CVu`h:#h\X]O7?\RI>('[erd#Rjc_5a&f*_F=:,VesU1\k&\0.nkc(l2)Ph%@I!O$on'VgeT[U)9)E(]H1:Sur9:iCeb*P1SV[*ZR<$N4&ECqE>pQg.0)"Ndjr7e-N[3OU:Apn1$-2CB`,K"-G0_?dCu_VgWL#0[::PQ.n^1M,'Uc"b6#^@L[kK6-$5+,+9fTPHO-<@-r9\ej2lTi1HXdAnVPR>5b6Y(eb4.mb0j*T--IRe2.hc0#Ke:1H&Y.R]-M!T?,KftN\E5A%>YXeIa7bhI.<4p1Ag9X8DW*$O8-pom"FJigm*Ke#Wc9L57?5D!O/4W[L[Of`4"'&o_taQ']hkYGN6VC![q,cP)`IIkK\BteX.4&Uha0[P&B_E!p\IC/O,FR:k9S\*>9m"=cCE&AA,D784J13p9tA@X0mGk1IcD`0^h`QPLq2">c&MHX0'Z)jG'q1@"\+,>1U._<^C:)8_Gc>LXn?)k3hcCZI.:dbL!E!l])%,q+iWKbp;S_@CO.P3,K15R<^3J4]PSi)WM2IKnVZ-"iC[5j6)`o9Y#UA!t!@$]b+k&\>Y$@E)/__)N!KkOo5&7$-0">K(pnf6r,FM*nK[.Jhr2?g+%#]BSj1*aX]6o&Q]H!K9-QOT<]ZKRnYqDGMloY$VpI8+3Pe(O5rm[5e*1QN!PB^t>98ZfI]T.G#dUXudU12"9Z?5J>fAu^\uf2QiO#KOZ5SI?nI+uT[U>:jpR\Y4-RbP]X<)6K"HuO@\9"0:7O1NCka4C3S.P._>,A#5W;(P.TNsK0'Y4kkMNnV^O+c[]p2s&*QMM+0o,HC_-(aePWQLNH)j=M:16aff+Tpr^-8,p:P4(d1u:l2'Jb4?Bd]7(a"ic7GFHiO<'q7P^AgHr6gY90.7APt#j%c.?^YRaZA2'Tb;4bg"((aW9AL-GE3#qk>u5-H(snGfBa@g)Xcj04_4cJcR[Sl=RY`De)VlrsI:U5lH^\I$K<[n%4!kO#:X%^7h]KtmVgmtrLS%E/rg9bJo@\bl^KjKU[hTP:C(!H67MUrj@?`QR97hSo?n35NVd=MAj'P-W=ndsP3`mF$Wcps>rc@ps>oO74k>/&f*iD5aPQ\cY'k\PIcKi9cs@;&Tk3#iq,C)29F;+=To37)R'VBrCd)5ghIh&IL@GP"#`uTsEo*hB:H&#BS"[jWjTIJO]JsHU3=ljG+NW4<[4s$Xhi'GZ?P^AI$"&N5pkoVc:\R^qgGTC]sQ(5sul%"O'ukXH1=;+jB1aL<+J,Y0ORJRg+p1NQnBPtBhU?=%:`,tR-TnKV(&=.3>i9(1r_8EC9eTA"pG5FNo?h1UmNq`!+KHD&B5$n0d\TU/XA8);56"FeB]I$&j\7b9T$/3:4s)l'2^cX&HkH>^r(d,![OA)32Nj_fXPFY5rkal":g;see.=BjH;LCV]9\R`8<8MWO04&fBIjbuM_d8eQ`Mdm@#=Vd`!0d+'[X7KK;WDbIGn[9SS?'NJ8[lCC7EK&Ml&1KHJCh/Vdq$n2J;:pfkJ`eIg)Rk,O)71kZD5rPInP-K15F];6?Uh_\=W8=n2RR;%-Z4&5*9X.,_g=8JF'a2WV_'@5BXbJ&N=.*(7S*I7=(+NX[^?f(%&*&->GXsaeCg>#%a$r9P6`9Cn,7C*XN;,%Pn\#2RUuXsXZala6l@F>l'Q+U3K:=@+=aIKCI(tX!"%m;[.X6YJaF$A5?1!'%[3XZrXAIVmQ-[Y-:V,>0Q8a(*C-4W,!"f";m/"\l`W]1&a@hA+6B9daNWA8mGG=52*Mg*W8iSJ)C0K[Hcoo.4i1b[.Vq@H&kjG_J5W`o1F!F._=<>C0s1uW`&O1ePhL\uN8FYaqMo;6+^S(G;\VA-7&FVH9M$^Kj!$lPkZ1VQeqId\UkVuL/MjA4UE^-N$(:p1@r9,0uT;2%IH?^)2e#j;4_f8:<(cX4P7j5b.,\ekK$bIQi,*8@D(Wq'&2q3@SF`YEFGu.KU6@p\OKnH`r?pcg_TG9:O,H3rF(9*[8<`"m6(C>)8BH2_'.g3NpBHP.grie;'B1XT1O'f>RfEd6X$ae?*!Zb@$;D^*W&gTaW5d:JBs'Doq1_ik%bmah."@,Wm'ek=iA0Zp[0[pb)7$IgPb1+p70XNTg`DWMT&@<#Q$qs2(1-iblN?n]mOY&Da`0CH,,Hs@/J=q1D5*#g01,P)BH&nt8]4m"6CHTnurc&-4!W69f]b7k=I)!72bNfJe<%fApbLqT?E<2_T%l?%E8LN$K1o-9#e$@!hn&fV>Ym+M&\c]?$:HQ>8$0i8Bge)Nq\'T[.?PrD)53k"#["+"TVuQK$:2F*10?f'M+%a_U/`@a:c\%/2V@SWaN=T1@fW:`Jhu;Cj49XkV"C#b.)VaQ^#`jr]WVJ4)r&qmg"Dn8l&#hXiEgeOrcDd1U0Z3%Y^#"+Y*YN2LX*TTE?o$$kX:HrE%j8deR>VL4];_,F@Rj7iXfAK1$QTt=V;!R`mM0gIHej](brVC4/+g1SK)oII^l9M=bo8cilJJ&,VjT,_#f3lh3:M`6DSsX.40#$17k@!]$CB"m5lG#?mX;d)`%c_;;l:gS82ZG6n%ap%B$CHTZA_VR;LO+ff$=HK#!uF;SU2StSFHI^b@*m$E!+7@p@[7/T*=?p"0P#s@B*73f?cAXB`8$;'Ahk.+9/@e*8m#Uebf1Q\`'a!XTbADU3$F=m3TrnfHndMd&;,Rq#k3@cR#k+H#k'.*JbaDk/W&1)hA9NIHtimE:DO8r90>lOr%#$8&(_4W?Q;fp'#`N]#;Dcr"T!Z9n`>DAf.L6Z3eq[4-qQaa'LZJfl4kq0[8e=j_Z=1bgmp">oiY$UklgBiX=U1J36NcnRP#_bH%L=J4AaM^7nWjrAbX,FLFJ=S?mdia&;g!4&+"0G2+Do\=HZ\ue]Kus]Mp$$ZQXfIFj-cFAjAQS3o12*Kq&rJN]FA7Zg2M_E>nCKg>9KT[WC;4"iDj3f@aVn9@H-50i7Z5FUnJkD"Y57,*D=0(L[gsSd>RKi48=m-H*%Ynre;#?g;Rb&iP0*KZl-0XuDcs."Q6!o#JAqCO([mW5-kZSWY"97H4d/FNk2::d1eJF'K.IufSLLS2NT*C8PYh)S50=$heXb(VX\bJ83X1CkAm(fbO#5=keR>dm6/5Hm+KXipQhRW!Dd5mD/OrIuWBi,Sl)k"'8>L#"^6c#:9h)YbnX%2I^DFl/Fi#fNs["Lb9Jq&HCs-'O-5XH;,F4F28&^CiJWnVaVHZ)0`"6`Dfiu@1SA"9YVBUr"5I:Ra:RnmW3gt?NpMr'!H3)!<;2-S;dK;`"7iCMp8ii_-70F*:`W=gHgDEYEEpsdcQ)^`,%u9BQ6*jH_P7(:s@VAGg&:Ukf(KKuA*B;"#%SC68nM8b,WhsVVfEe7/Ns6V.RpctTRM6E9./["m!s4if`NbXfr3pL-...0WZhW'a9:Jc!!Fg"^4T0^;DCk)S1p:B4JC&`Dalm`Na5U/N$eu@VMrqKIdP_,eL)k,UV0nE@bri,,Sbp+XW/]4]=1t9C^$$m&GLWB+bk/e6TTKZob(jJS[F]%KI&E_W]!gP=3FWlNWlWTc]J`Dn\Nk2N*bVGbY]AKh@$dP;X:N-2?%+LJ09-YPDi@O^OV..,MHpAXMp@FGI:J@(KIDDWccm47oCFS&sc+C".O"HMr?c)5:!$6$6HHXjY02b[qnN96-:3p-##&uV>(LAQp[C\;2_9EUuJH;pU!I@3N@-PRU))SHXk/f*I.IfkLL6fh^3=/-Wbt=s5Zkuq3R4VNCRglUH:5,3XG1tuJG$[$3n]!;n`PHfZNg<-cj+4SK0O(d0Bb:K(*cs5T*#X9H\MPoC/e.$U3(Qn,'a2M!'fi(38AeRtC%%2rfP7(9Z\>b:ZW,M/opZ=HD_%<#aH2$''me&e;!qo^)c43mCW3;d?2nA%r[%\WL^9W,+X`JK2&V@82b3]?+=%")]C6lcnd"Gf9%S%m,HCijrsf2ar"&qfJ-8$))SE+XPT(dd2LW.DfCd%fC@1%\c5#qqBdRKBkKN?a_(8rV8)*==[ZPsY]W5[1*+CHlGAR-?)A8Yuq+o6H;%.P2pjT%A^4`D4@m(5e&"$.AS6;N%4d[?d,Sg:Cq"?tg%6/;'=dD7MTl/grm&RqXeKlC*#Sl/jk#b!\p*_ehbD`q#I9/\OeO/NCp!-[LKcSttQ)Gj"&8)8A.uq&s$XhL/$R&J9OfY'(ES$h`*7gf/p?P8&D)MY_&.KqV?&(0SSNpR"BF_l/G8PA/&L&L/5SXAg#l;X`:/F#?;7t"LKU54r7r\4\]b>1HaVhoq+Y1W/&840DFSj;:VX+E?4:S#E4kq;+9FaRGU5fU4$YFQI,@J\)!Gil@Df-`BYq%q:kHi9\=Or*)%fdo?fnu[M9UXD%_oVqp7V$:NE#o=:U#d>$L<^Wf#=.o[Aji+/cU;3XfSfRYauuGKG/3M7RB79U(#cq`*oX<5W5Chmk/3#4pAK@^#POg!V2Irm_uA]W..1r)UX4p$.C0FT&%@:[2U+M:c9H6Z0!D=3?SVk[SK9=3MHWb.\Ur:$KA6Q<'"J;\_lZBui^9aV)5i*FRpm?_CqZh8Q)];d?p52n1-,]Vla::6!XAkN@VS`:>=#\)pkPu%&H\rq6fUB+DHha&+.37?o^P-7'CHAM1D;>"Q$H1SlN454f][gTK>T1W_a[=Z9dMeP,nag%7R`'9eQJ+`Q%iaWUnEO*-isI99a3TY8S*_^%Rq/X5nQ09g1rW'8W"dg0PE9I+R,+IOoT0:OF9k,#7(p=//J$Xc[/`rjtaT_=t4K1E#%Q8%>7Q6Cg7>`f's5Y9a^u?9/PkP>_Qr*649$[g"IlTk%^JATdZ'5cNct2/3F6c5@9&tdUY5mJLL@a*aI=t13bK#UU<4"IC;o1XqpMk;!O0`e^U[tfth-B3-9PJ[FCmt;]8!Le=,T[-od]Y"cu4p3S"UH[2A-Q1kqZ/glC$BX?)jVm-NaTL>m/$:i)5Ed`C80G4P8g$0;$S`lPIkQ5'nCj#u5(;B?$qo"t^-D-I>B-OpD=9#j.:F2H9`9%t!m#:6UA,X-7o,9Y_5>o40t*84.=6;!uN%1iX5Hc!J-MUO!.H7DCu\8=$M',c@=Hk)s2nbQn7$TllT!q=u2XYl;1Vglj_@JYT'[k:(g.>?a*>t@^$tFLMYmJ?oH"sq0!0hp_&9573d.f_1@pJm4eNE`*HM8P4rqB0n\I5!Se.mQXtMUg:'KgHL95ma"4?o$OL,V!t>32@Sq1rdI'.1#ukPT$jTTZjdE+S&"9fefr3(D$4ACeWbAA4W*IU3VW9]l#+M<>3.lqU%'UR-;dF]]^G$^ZohUX(cht.q%P'e4BAZ-4K+3TcJ#hVtKB)Mt_tH>[V:qfG-43>Xn10Y-;N$]m9#LlB.8'Z<"S.CSjij2TVp+Qj$Lm%bjb#uDL+\.6WOI,hr+1Cu/%9"Yls"5`KHp%=P$QUXEFM!='nPmJ/Or^B?LU#e]+$H-H!,dRBr-2`MtL,iP,XbfUIZ_%mDJG=ncBot426uf%7.$nP)Q\qJ9bT4BB7(N,Ana<1E.=O18[Wa#9n4/+LGT1J.C$@MKCo1F[imXA?[J6C6h2C(*Ma;ON!eTmUi^U(AO4#aDpR^Dsmb94%-&+n=Kri"47Xr63FiNgcf,]nj->Z/,DLOUV+HSiq]8%S3.O5'!/,Oi\N?_G=C?Cfa(P$ANUlj3Q2m,uhOG^\g9CGE:f,T=ef/[;?$D6RjQ<%?T9Y&mn^]%ifn#XD1Gq#CP;5TEFio.->53/[1GkK;>J)%U8\mW+"K_b<8t!a$As;=YQcWf&,nM4d_R5'X]:m3gc35R5Fc1u_fnFb$W6X)9mSb1H;L3bL1.GTEo-MU9EH-a)=D(m^NCtc[9l#W-`cmr]V7Q(5"1[;bWlVI\<<`o++ukr&19j^JC.^gOhSPR0%E))!O;qVFMaa="E7af,+"p:M321QelI(+iY0Vh$fE8)Y.=4"Q_Qf6i++I@[t>5:IMjY68@1e+:2,]%1m,c)n>$^"Fl)Hb348".67R7sPPCcE8,6!Z2)G4[=(P)4aHA@N&lN6E;=e.=n[852\o&If&7Lq3kAghbCW;=hVRXGN#!WSAchr4p5^@&ehnT#C-o><6PlQ;Zr^+Zm\RV*,ql'$((%C*F/H6hIUZ,npL_O[Vo0bVI6?8CS9/D&q$?O4FQYI^e(%c^4\r!$HMT'2qKK6Ah(b+F8Kf,[Fm[@>[NcQ3p*<.>X-;1D$?*+os\"1I@V.2)2Xn';;KFS01q#qoXX<9)-(f,f`.Q'-&6!M8&.n.#<[CR)0i]Bu;)SK[clpa:1iRTZI8b;i<,f0G"H/OEpRMA:_NA)*3D](Mh@Wk2#e[LkGXt"?Y\-:W#o?HB2nbC\A\,pL5.0*jB1SaCcdi69UKS/f:-F@RCN`C[cDlLN_]p&-o@J0D'&LehOK,"6]qg,`3g"OD_Y0LKF](kW`XI79ZGAc&YLK$4EeMDnuVW=\D&FNR(?fANq@]_6Y+8=sDXJ%YC'JSH"CU.l8n`hi;;WX"+T']-`]*30bF+**I2+uqV^,ciT!1J%U4t*iIR5QNacC-R+[V()A30$R;/HD+i0$Z+BikH%Qgp"J8d<3Qon*C.%;>T3K!i)Ls,tK.![hohiG@uL9rZaZadPb4M8=t3?HZPk]cme(*7,m12Q/g7%:MN2aHPK2.>a$&*]eVX!5W$eep7MT__=eY-FgX+c'Tb=uh?`35[j<_0#t`&Mu361qtjWk`GE@&j;c=3Y/b)&+Z?CZj6:(FukuEJUmd["b+/*aSP%`0^1`U=\1;8&N/N-;(t2H_BK?(7a0$!+Y5+!%&T!,.*F$_+Nd;2aIjr<+JO^m#_:-<$4)0>.S<3-=b(o\Khu\AW[MO9*"j(o@Nf9<-_Md]/gfeqT\d)XeEC07/]/N[@D=pI>6QBM(f^e32FdK0W4st-E&^0[4Zjh:n#>R+OjIOc3/8=fQtk^WWWJiV8@0Rr.PV:W.*rZf#ZAkt66RP"?IPLXI,%YU]/oOOBm.PZQ&&DV*/p,Y6Z3K^q;U2-.;VU[TM;r/^Y'RX&ZEdl2'Ya\dt@mse"efRr/Lp3CM:p(E[1WtcO(Y.5=eTV8>?k92NXG_a_=GA/Jnq!K[mf-tZq#@+#?,N3sNg@=nsk80npI"@41;!sCC/OO4_06:sWG8H;DQ'**hU:o01)^e"`s+FB2$o_/oqr^I"mae)cSn"65i=:jSuff7ZpcJ];(\fo::d1-;D"@ED378lqujT^]Q<@T^?H[^*s-r1q8S[/?QM6:aSU#9"BI0qM?#BVi/:*Io:P&0cTms%tQ,\[A^*/*mFNAefDW$n.1OA.VkWu#f01VO]83eD?d^hJSS+XV!!BjS!&Qbjbe[qK5le"Y)GW=DdU27^8nM1`it(,;m1Yqj3)#*P[U6@j3I-L!?*@0Ht;6h@2t3S8FF`T!7(GR.?W;$uKq9/FNNAu&-7WY>$mf[9S^_(R\ZJ_@pJ'8RXi`:&]-$(?[?QR_@&6=/neN#N&63.t;;DRb*V*>&,lIg^nC!<&1aBNjCr@1Gq:kH:Q"'4K:H@jhRR9u@P-=L6QD!Si?q(f/fa?/YG?-aN#E)OA=OfaMo/-$46bKH*lJS5M719r>s:BHZOj6Y(;3a>?qS)$K$O0ORrkQ!4]sV:#dh7`'@ukh^hm8h--YO0QMc^(qk`#Vgp?5J>,'-W?;I3#jW1B&\Fm@h"I9dgPbnED5S8L&)pp^S8>-Zq`mZE>C3_.^9YRnW:KBe#&<5*iW1:PTLXN9[+&!LlaN;]!A(AV6Xrh,&"br4FUfK=C\]$i[_79VZ0:cYrH8:;8c4P.s!0-d*D0aG@n-?ILuq4.b%(o<"lc2:G2YNSpC9@X/Zb5qe.A\,Gls?'G6+OdR1S_1&D6M5Em$dJq#:l]_H-OpO;T'q&V>kVd?(+QNNjr(S)I8qt^,9><>mo)^@q8ja89G$@+7Ce=b^njo9Q%hu5k;s8.:APPq-KJ)1)gq=4Jt8,XO[s5U`as8(L-s,[2pc2W:m?hOE%nGg]35Ipf\li4l]s81FCs)7m"5&^"ArVqo8f=/BbnGI^LF8mEYYZRdj_Zk\tni3i,ae8Nejnp4/I3KVsA"FYsKk'gi_uoq=nV900rQ'pAdKWn!25@>KRB*9#D-\pu_[rZ*jE*q7\dM1JJNXjVMpDF<@-i,<:LTg%:C9dBRPTUgf'3$`Z%pKeC;n3>,o'GOMH<)q$'ne9OU8_+?SpsXXj1iP']IAq_WWI?XbDG3:rJ/t=f4CBEsm[j%ZE!+DrQLPUgh9<)PFd*aM'TqYrp?`EHP6TDXY(M]i%2jC=oe]`sH.A%3!s!hO9YS&kM.j]6Bi-1Eca0(r.:+7l9Tthnkii_DQ4K=bYN41YkWu7*ogfRSAdgb6\4>R'b.%Gh1-%:-?&)E0G/-B5&d8fXGg]8\jB2B3o,YiJLt\9>`t=f\n,m"/l/kP&gP[`5(tVg1o\<&.#V:#*uo[V@'XAE#@r&;2DOSb[:-FGrYk4K..erA%DncS4es2&!8n61j[@gMr'j`\WE5)S0;]gr5eu=i[K\=hjV,sB[kD*]Q%@D7*`*2HlS-36m(KG%!_Y9S97\8n-WY&#:fQXe0LM$`3Bq)*#(YTW.=XAfb6Ej`.F^WZ6,-`/%7hGl'^ZG+Wjn"3b`[bee,A8<1@9Q@H-H!1LOGIu8Hg:sDVUeeHq\mW;DFiMD53)%1V>H]*pqhXC.s47jLIW&a#Y,\tH7L8t_"i#`4qJ![JRR+D@A0ch'NMmJ/F%"7hQr9G"blh<^nR!0UK6c\2&GlAHtWV2BcG_akk76@Z\%kTE'+I=M/Z`)'a82f?E<%FSHhZ(R'MBc[hF.NeSi^YpjD%=W)u5M>%G\'GaJI13&!:(BC[!VnpKo/Qh4mkY[n+rSc24lgE9Q>FI2_8"aUc1UmZa/01\+-4cK_o$*XL]'c#W;o0*\WE7>Ad/@+-fE&[5JQ^.rr8Bm'jW\oec4!\WN[LLrN;[jkP;f@oY^qZ#";J_6%A-B/F`1,s2G`U?1H&Jd@mpn%;mVNW6u^!61?M%5`*<4R0$skF:dEq=Uk4)-2;?#%10I5BBPWSbMKsQH8G]!s)rlJt2=j^lZV+*1oft'f=VYb6$c]4X:4$3slki;Zm5!*iJGL$6-r$$X/PuoDDk6sTds5NH;V[=%=hf8&! +#<== diff --git a/wscript b/wscript new file mode 100644 index 0000000..55e30ce --- /dev/null +++ b/wscript @@ -0,0 +1,490 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import Params, types, sys, Runner + +# the following two variables are used by the target "waf dist" +VERSION='2.0-pre' +APPNAME='lighttpd' + +# these variables are mandatory ('/' are converted automatically) +srcdir = '.' +blddir = 'build' + +def set_options(opt): + # the gcc module provides a --debug-level option + opt.tool_options('compiler_cc') + #opt.add_option('--with-xattr', action='store_true', help='xattr-support for the stat-cache [default: off]', dest='xattr', default = False) + #opt.add_option('--with-mysql', action='store_true', help='with mysql-support for the mod_sql_vhost [default: off]', dest = 'mysql', default = False) + #opt.add_option('--with-postgresql', action='store_true', help='with postgress-support for the mod_sql_vhost [default: off]', dest = 'postgresql', default = False) + opt.add_option('--with-openssl', action='store_true', help='with openssl-support [default: off]', dest = 'openssl', default = False) + #opt.add_option('--with-pcre', action='store_true', help='with regex support [default: on]', dest = 'pcre', default = True) + #opt.add_option('--with-webdav-props', action='store_true', help='with property-support for mod_webdav [default: off]', dest = 'webdavprops', default = False) + #opt.add_option('--with-sqlite3', action='store_true', help='with property-support [sqlite3] for mod_webdav [default: off]', dest = 'sqlite3', default = False) + #opt.add_option('--with-bzip', action='store_true', help='with bzip2-support for mod_compress [default: off]', dest = 'bzip', default = False) + #opt.add_option('--with-zlib', action='store_true', help='with deflate-support for mod_compress [default: on]', dest = 'zlib', default = True) + #opt.add_option('--with-ldap', action='store_true', help='with LDAP-support for the mod_auth [default: off]', dest = 'ldap', default = False) + #opt.add_option('--with-libaio', action='store_true', help='with libaio for linux [default: off]', dest = 'libaio', default = False) + #opt.add_option('--with-libfcgi', action='store_true', help='with libfcgi for fcgi-stat-accel [default: off]', dest = 'libfcgi', default = False) + opt.add_option('--with-lua', action='store_true', help='with lua 5.1 for mod_magnet [default: off]', dest = 'lua', default = False) +# opt.add_option('--with-glib', action='store_true', help='with glib support for internal caches [default: on]', dest = 'glib', default = True) + opt.add_option('--with-all', action='store_true', help='Enable all features', dest = 'all', default = False) + opt.add_option('--build-static', action='store_true', help='build a static lighttpd with all modules added', dest = 'buildstatic', default = False) + opt.add_option('--append', action='store', help='Append string to binary names / library dir', dest = 'append', default = '') + opt.add_option('--lib-dir', action='store', help='Module directory [default: prefix + /lib/lighttpd + append]', dest = 'libdir', default = '') + +from Tools.config_c import enumerator_base, check_data + +class typesize_enumerator(enumerator_base): + def __init__(self, conf): + enumerator_base.__init__(self, conf) + self.typename = '' + + self.headers = [] + + self.include_paths = [] + self.libs = [] + self.lib_paths = [] + + self.flags = '' + self.define = '' + self.uselib = '' + + def error(self): + errmsg = 'test program would not run' + if self.message: errmsg += '\n%s' % self.message + fatal(errmsg) + + def run_cache(self, retval): + if self.want_message: + self.conf.check_message('type size (cached)', '', 1, option=retval['result']) + + def validate(self): + if not self.typename: + fatal('type size enumerator needs code to compile and run!') + + def run_test(self): + code = '' + + code = [] + code.append('#include \n') + for header in self.headers: + code.append('#include <%s>\n' % header) + + code.append('int main(){printf("%%zu\\n", sizeof(%s));\nreturn 0;\n}\n' % self.typename) + + oldlibpath = self.env['LIBPATH'] + oldlib = self.env['LIB'] + + self.env['LIB'] = self.libs + self.env['LIBPATH'] = self.lib_paths + + obj = check_data() + obj.code = "\n".join(code) + obj.env = self.env + obj.uselib = 'lighty ' + self.uselib + obj.includes = self.include_paths + obj.force_compiler = 1 # getattr(self, 'force_compiler', None) + obj.execute = 1 + + ret = self.conf.run_check(obj) + tsize = '' + if ret != False: tsize = ret['result'] + self.conf.check_message('typesize %s' % self.typename, '', ret != False, option=' (%s)' % tsize) + + if ret != False: + self.conf.define(self.define, int(tsize)) + else: + self.conf.undefine(self.define) + + self.env['LIB'] = oldlib + self.env['LIBPATH'] = oldlibpath + + return ret + +def tolist(x): + if type(x) is types.ListType: + return x + return [x] + +def env_mod(conf, use): + types = [ 'LIB', 'STATICLIB', 'LIBPATH', 'CPPPATH', 'CXXDEFINES', 'CCFLAGS', 'CXXFLAGS', 'LINKFLAGS' ] + bak = {} + for t in types: + bak[t] = conf.env[t] + for u in use: + conf.env[t] = tolist(conf.env[t]) + tolist(conf.env['%s_%s' % (t, u)]) + return bak + +def env_mod_revert(conf, bak): + for (k,v) in bak.items(): + conf.env[k] = v + +def CHECK_INCLUDE_FILES(conf, header, define, uselib = '', path = None, mandatory = 0, use = []): + envbak = env_mod(conf, use) + hconf = conf.create_header_configurator() + hconf.mandatory = mandatory + hconf.name = header + hconf.uselib_store = uselib + hconf.define = define + if path: hconf.path += path + res = hconf.run() + env_mod_revert(conf, envbak) + return res + +def CHECK_FUNCTION_EXISTS(conf, func, define, headers = None, libs = None, use = []): + envbak = env_mod(conf, use) + hconf = conf.create_function_enumerator() + hconf.function = func + hconf.define = define + if headers: hconf.headers += headers + if libs: hconf.libs += libs + hconf.custom_code = 'void %s(); void *p;\np=(void*)(%s);' % (func, func) + res = hconf.run() + env_mod_revert(conf, envbak) + return res + +def CHECK_TYPE_SIZE(conf, typename, define, headers = None, use = []): + envbak = env_mod(conf, use) + hconf = typesize_enumerator(conf) + hconf.typename = typename + hconf.define = define + hconf.headers = [] + if headers: hconf.headers += headers + res = hconf.run() + env_mod_revert(conf, envbak) + return res + +def CHECK_LIBRARY_EXISTS(conf, lib, func, define, mandatory = 1, uselib = None, use = []): + envbak = env_mod(conf, use) + if not uselib: uselib = lib.upper() + hconf = conf.create_library_configurator() + hconf.mandatory = mandatory + hconf.name = lib + hconf.uselib_store = uselib + hconf.define = define + hconf.code = 'int main() {\nvoid %s(); void *p;\np=(void*)(%s);\nreturn 0;\n}\n' % (func, func) + res = hconf.run() + env_mod_revert(conf, envbak) + return res + +def CONFIGTOOL(conf, binary, uselib, define = ''): + hconf = conf.create_cfgtool_configurator() + hconf.binary = binary + hconf.uselib_store = uselib + hconf.define = define + res = hconf.run() + return res + +def PKGCONFIG(conf, name, uselib = None, define = '', version = '', mandatory = 0): + if not uselib: uselib = name + hconf = conf.create_pkgconfig_configurator() + hconf.name = name + hconf.version = version + hconf.uselib_store = uselib + hconf.define = define + hconf.mandatory = mandatory + res = hconf.run() + return res + +def configure(conf): + opts = Params.g_options + + conf.check_tool('compiler_cc') + + if not opts.libdir: + opts.libdir = opts.prefix + "/lib/lighttpd" + opts.append + conf.sub_config('src') + + if opts.all: +# for o in "xattr mysql postgresql openssl pcre webdavprops sqlite3 bzip zlib ldap libfcgi lua glib".split(" "): + for o in "lua".split(" "): + setattr(opts, o, True) + + #if opts.webdavprops: + #opts.sqlite3 = True + #opts.xml = opts.uuid = True + #else: + #opts.xml = opts.uuid = False + + conf.define("LIGHTTPD_VERSION_ID", 20000) + conf.define("PACKAGE_NAME", APPNAME) + conf.define("PACKAGE_VERSION", VERSION) + conf.define("LIBRARY_DIR", opts.libdir) + + common_ccflags = [ + '-std=gnu99', '-Wall', '-g', '-Wshadow', '-W', '-pedantic', + ] + lighty_common_ccflags = [ + '-fPIC', + '-DHAVE_CONFIG_H', '-D_GNU_SOURCE', + '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE', '-D_LARGE_FILES', + ] + conf.env['CCFLAGS'] += common_ccflags + conf.env['CCFLAGS_lighty'] += lighty_common_ccflags + conf.env['CCFLAGS_lightymod'] += lighty_common_ccflags + conf.env['plugin_PREFIX'] = '' + conf.env['LINKFLAGS_lighty'] += [ '-export-dynamic' ] + conf.env['LINKFLAGS_lightymod'] += [ '-module', '-export-dynamic', '-avoid-version', '-W,l-no-undefined' ] + conf.env['LINKFLAGS_thread'] += [ '-pthread' ] + + if sys.platform == 'linux': + conf.env['LIB_lighty'] += ['rt'] + + CHECK_INCLUDE_FILES(conf, "sys/devpoll.h", "HAVE_SYS_DEVPOLL_H") + CHECK_INCLUDE_FILES(conf, "sys/epoll.h", "HAVE_SYS_EPOLL_H") + CHECK_INCLUDE_FILES(conf, "sys/event.h", "HAVE_SYS_EVENT_H") + CHECK_INCLUDE_FILES(conf, "sys/mman.h", "HAVE_SYS_MMAN_H") + CHECK_INCLUDE_FILES(conf, "sys/poll.h", "HAVE_SYS_POLL_H") + CHECK_INCLUDE_FILES(conf, "sys/port.h", "HAVE_SYS_PORT_H") + CHECK_INCLUDE_FILES(conf, "sys/prctl.h", "HAVE_SYS_PRCTL_H") + CHECK_INCLUDE_FILES(conf, "sys/resource.h", "HAVE_SYS_RESOURCE_H") + CHECK_INCLUDE_FILES(conf, "sys/sendfile.h", "HAVE_SYS_SENDFILE_H") + CHECK_INCLUDE_FILES(conf, "sys/select.h", "HAVE_SYS_SELECT_H") + CHECK_INCLUDE_FILES(conf, "sys/syslimits.h", "HAVE_SYS_SYSLIMITS_H") + CHECK_INCLUDE_FILES(conf, "sys/types.h", "HAVE_SYS_TYPES_H") + CHECK_INCLUDE_FILES(conf, "sys/uio.h", "HAVE_SYS_UIO_H") + CHECK_INCLUDE_FILES(conf, "sys/un.h", "HAVE_SYS_UN_H") + CHECK_INCLUDE_FILES(conf, "sys/wait.h", "HAVE_SYS_WAIT_H") + CHECK_INCLUDE_FILES(conf, "sys/time.h", "HAVE_SYS_TIME_H") + CHECK_INCLUDE_FILES(conf, "time.h", "HAVE_TIME_H") + CHECK_INCLUDE_FILES(conf, "unistd.h", "HAVE_UNISTD_H") + CHECK_INCLUDE_FILES(conf, "pthread.h", "HAVE_PTHREAD_H") + + CHECK_INCLUDE_FILES(conf, "getopt.h", "HAVE_GETOPT_H") + CHECK_INCLUDE_FILES(conf, "inttypes.h", "HAVE_INTTYPES_H") + + CHECK_INCLUDE_FILES(conf, "poll.h", "HAVE_POLL_H") + CHECK_INCLUDE_FILES(conf, "pwd.h", "HAVE_PWD_H") + + CHECK_INCLUDE_FILES(conf, "stddef.h", "HAVE_STDDEF_H") + CHECK_INCLUDE_FILES(conf, "stdint.h", "HAVE_STDINT_H") + CHECK_INCLUDE_FILES(conf, "syslog.h", "HAVE_SYSLOG_H") + + CHECK_INCLUDE_FILES(conf, "aio.h", "HAVE_AIO_H") + + CHECK_INCLUDE_FILES(conf, "sys/inotify.h", "HAVE_SYS_INOTIFY_H") + if conf.is_defined("HAVE_SYS_INOTIFY_H"): + CHECK_FUNCTION_EXISTS(conf, "inotify_init", "HAVE_INOTIFY_INIT") + + headers = []; + if conf.is_defined("HAVE_SYS_TYPES_H"): headers.append('sys/types.h') + if conf.is_defined("HAVE_STDINT_H"): headers.append('stdint.h') + if conf.is_defined("HAVE_STDDEF_H"): headers.append('stddef.h') + if conf.is_defined("HAVE_INTTYPES_H"): headers.append('inttypes.h') + + CHECK_TYPE_SIZE(conf, "socklen_t", "HAVE_SOCKLEN_T", headers + ['sys/socket.h'], ['lighty']) + + CHECK_TYPE_SIZE(conf, "long", "SIZEOF_LONG", headers) + CHECK_TYPE_SIZE(conf, "off_t", "SIZEOF_OFF_T", headers) + + CHECK_FUNCTION_EXISTS(conf, "chroot", "HAVE_CHROOT") + CHECK_FUNCTION_EXISTS(conf, "crypt", "HAVE_CRYPT") + CHECK_FUNCTION_EXISTS(conf, "epoll_ctl", "HAVE_EPOLL_CTL") + CHECK_FUNCTION_EXISTS(conf, "fork", "HAVE_FORK") + CHECK_FUNCTION_EXISTS(conf, "getrlimit", "HAVE_GETRLIMIT") + CHECK_FUNCTION_EXISTS(conf, "getuid", "HAVE_GETUID") + CHECK_FUNCTION_EXISTS(conf, "gmtime_r", "HAVE_GMTIME_R") + CHECK_FUNCTION_EXISTS(conf, "inet_ntop", "HAVE_INET_NTOP") + CHECK_FUNCTION_EXISTS(conf, "kqueue", "HAVE_KQUEUE") + CHECK_FUNCTION_EXISTS(conf, "localtime_r", "HAVE_LOCALTIME_R") + CHECK_FUNCTION_EXISTS(conf, "lstat", "HAVE_LSTAT") + CHECK_FUNCTION_EXISTS(conf, "madvise", "HAVE_MADVISE") + CHECK_FUNCTION_EXISTS(conf, "memcpy", "HAVE_MEMCPY") + CHECK_FUNCTION_EXISTS(conf, "memset", "HAVE_MEMSET") + CHECK_FUNCTION_EXISTS(conf, "mmap", "HAVE_MMAP") + CHECK_FUNCTION_EXISTS(conf, "pathconf", "HAVE_PATHCONF") + CHECK_FUNCTION_EXISTS(conf, "poll", "HAVE_POLL") + CHECK_FUNCTION_EXISTS(conf, "port_create", "HAVE_PORT_CREATE") + CHECK_FUNCTION_EXISTS(conf, "prctl", "HAVE_PRCTL") + CHECK_FUNCTION_EXISTS(conf, "pread", "HAVE_PREAD") + CHECK_FUNCTION_EXISTS(conf, "posix_fadvise", "HAVE_POSIX_FADVISE") + CHECK_FUNCTION_EXISTS(conf, "select", "HAVE_SELECT") + CHECK_FUNCTION_EXISTS(conf, "sendfile", "HAVE_SENDFILE") + CHECK_FUNCTION_EXISTS(conf, "sendfile64", "HAVE_SENDFILE64") + CHECK_FUNCTION_EXISTS(conf, "sendfilev", "HAVE_SENDFILEV") + CHECK_FUNCTION_EXISTS(conf, "sigaction", "HAVE_SIGACTION") + CHECK_FUNCTION_EXISTS(conf, "signal", "HAVE_SIGNAL") + CHECK_FUNCTION_EXISTS(conf, "sigtimedwait", "HAVE_SIGTIMEDWAIT") + CHECK_FUNCTION_EXISTS(conf, "strptime", "HAVE_STRPTIME") + CHECK_FUNCTION_EXISTS(conf, "syslog", "HAVE_SYSLOG") + CHECK_FUNCTION_EXISTS(conf, "writev", "HAVE_WRITEV") + CHECK_FUNCTION_EXISTS(conf, "inet_aton", "HAVE_INET_ATON") + CHECK_FUNCTION_EXISTS(conf, "inet_atop", "HAVE_IPV6") + CHECK_FUNCTION_EXISTS(conf, "strtoll", "HAVE_STRTOLL") + + CHECK_INCLUDE_FILES(conf, "tap.h", "HAVE_LIBTAP_H", uselib = 'tap') + CHECK_LIBRARY_EXISTS(conf, "tap", "plan_tests", "HAVE_LIBTAP", uselib = 'tap', mandatory = 0) + + #if opts.xattr: + #CHECK_INCLUDE_FILES(conf, "attr/attributes.h", "HAVE_ATTR_ATTRIBUTES_H") + + #if opts.mysql: + #if not CONFIGTOOL(conf, 'mysql_config', uselib = 'mysql'): + #CHECK_INCLUDE_FILES(conf, "mysql.h", "HAVE_MYSQL_H", uselib = 'mysql', path = ['/usr/include/mysql'], mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "mysqlclient", "mysql_real_connect", "HAVE_LIBMYSQL", uselib = 'mysql') + #else: + #conf.define("HAVE_MYSQL_H", 1) + #conf.define("HAVE_LIBMYSQL", 1) + + #if opts.postgresql: + #if not CONFIGTOOL(conf, 'pg_config', uselib = 'postgresql'): + #CHECK_INCLUDE_FILES(conf, "libpq-fe.h", "HAVE_LIBPQ_FE_H", uselib = 'postgresql', path = ['/usr/include/pgsql'], mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "pq", "PQconnectdb", "HAVE_LIBPQ", uselib = 'postgresql') + #else: + #conf.define("HAVE_LIBPQ_FE_H", 1) + #conf.define("HAVE_LIBPQ", 1) + + if opts.openssl: + CHECK_INCLUDE_FILES(conf, "openssl/ssl.h", "HAVE_OPENSSL_SSL_H", uselib = 'openssl', mandatory = 1) + CHECK_LIBRARY_EXISTS(conf, "crypto", "BIO_f_base64", "HAVE_LIBCRYPTO", uselib = 'openssl') + CHECK_LIBRARY_EXISTS(conf, "ssl", "SSL_new", "HAVE_LIBSSL", uselib = 'openssl') + conf.define("OPENSSL_NO_KRB5", 1) + + #if opts.bzip: + #CHECK_INCLUDE_FILES(conf, "bzlib.h", "HAVE_BZLIB_H", uselib = 'bzip', mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "bz2", "BZ2_bzCompressInit", "HAVE_LIBBZ2", uselib = 'bzip') + + #if opts.ldap: + #CHECK_INCLUDE_FILES(conf, "ldap.h", "HAVE_LDAP_H", uselib = 'ldap', mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "ldap", "ldap_open", "HAVE_LIBLDAP", uselib = 'ldap') + + #if opts.libaio: + #CHECK_INCLUDE_FILES(conf, "libaio.h", "HAVE_LIBAIO_H", uselib = 'libaio', mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "aio", "io_getevents", "HAVE_LIBAIO", uselib = 'libaio') + + #if opts.xml: + #if CONFIGTOOL(conf, 'xml2-config', uselib = 'xml'): + #CHECK_INCLUDE_FILES(conf, "libxml/tree.h", "HAVE_LIBXML_H", mandatory = 1, uselib='xml', use = ['xml']) + #else: + #CHECK_INCLUDE_FILES(conf, "libxml.h", "HAVE_LIBXML_H", mandatory = 1, uselib='xml', use = ['xml']) + #CHECK_LIBRARY_EXISTS(conf, "xml2", "xmlParseChunk", "HAVE_LIBXML", uselib='xml', use = ['xml']) + + #if opts.pcre: + #CONFIGTOOL(conf, 'pcre-config', uselib = 'pcre') + #CHECK_INCLUDE_FILES(conf, "pcre.h", "HAVE_PCRE_H", mandatory = 1, uselib = 'pcre', use = ['pcre']) + #CHECK_LIBRARY_EXISTS(conf, "pcre", "pcre_exec", "HAVE_LIBPCRE", uselib = 'pcre', use = ['pcre']) + + #if opts.sqlite3: + #CHECK_INCLUDE_FILES(conf, "sqlite3.h", "HAVE_SQLITE3_H", uselib = 'sqlite3', mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "sqlite3", "sqlite3_reset", "HAVE_SQLITE3", uselib = 'sqlite3') + + PKGCONFIG(conf, "glib-2.0", uselib = 'glib', mandatory = 1) + incdir = conf.env['CPPPATH_glib'][0] + conf.env['CPPPATH_glib'] += [ incdir+'/glib-2.0/', incdir + '/glib-2.0/include/' ] + CHECK_INCLUDE_FILES(conf, "glib.h", "HAVE_GLIB_H", uselib = 'glib', use = ['glib'], mandatory = 1) + + #if opts.libfcgi: + #CHECK_INCLUDE_FILES(conf, "fastcgi.h", "HAVE_FASTCGI_H", uselib = 'libfcgi') + #if not conf.is_defined("HAVE_FASTCGI_H"): + #CHECK_INCLUDE_FILES(conf, "fastcgi/fastcgi.h", "HAVE_FASTCGI_FASTCGI_H", uselib = 'libfcgi', mandatory = 1) + #CHECK_LIBRARY_EXISTS(conf, "fcgi", "FCGI_Accept", "HAVE_LIBFCGI", uselib = 'libfcgi') + + #if opts.uuid: + #CHECK_INCLUDE_FILES(conf, "uuid/uuid.h", "HAVE_UUID_H") + #CHECK_LIBRARY_EXISTS(conf, "uuid", "uuid_generate", "HAVE_LIBUUID") + #if not conf.is_defined("HAVE_LIBUUID"): + #CHECK_FUNCTION_EXISTS(conf, "uuid_generate", "HAVE_LIBUUID") + + #if opts.zlib: + #CHECK_INCLUDE_FILES(conf, "zlib.h", "HAVE_ZLIB_H", uselib = 'zlib', mandatory = 1) + #if sys.platform != "win32": + #CHECK_LIBRARY_EXISTS(conf, "z", "deflate", "HAVE_LIBZ", uselib = 'zlib') + #else: + #(CHECK_LIBRARY_EXISTS(conf, "z", "deflate", "HAVE_LIBZ", mandatory = 0, uselib = 'zlib') or + #CHECK_LIBRARY_EXISTS(conf, "zlib", "deflate", "HAVE_LIBZ", mandatory = 0, uselib = 'zlib') or + #CHECK_LIBRARY_EXISTS(conf, "zdll", "deflate", "HAVE_LIBZ", mandatory = 1, uselib = 'zlib')) + + if opts.lua: + if not PKGCONFIG(conf, "lua5.1", uselib = 'lua', mandatory = 0): + conf.env['LIB_lua'] = [ 'm' ] + CHECK_INCLUDE_FILES(conf, "lua.h", "HAVE_LUA_H", uselib = 'lua', use = ['lua'], mandatory = 1) + CHECK_LIBRARY_EXISTS(conf, "lua", "lua_setfield", "HAVE_LIBLUA", uselib = 'lua', use = ['lua']) + else: + conf.define("HAVE_LUA_H", 1) + conf.define("HAVE_LIBLUA", 1) + + if not opts.buildstatic: + CHECK_INCLUDE_FILES(conf, "dlfcn.h", "HAVE_DLFCN_H", uselib = 'dl') + if conf.is_defined("HAVE_DLFCN_H"): + CHECK_LIBRARY_EXISTS(conf, "dl", "dlopen", "HAVE_LIBDL", uselib = 'dl') + + CHECK_INCLUDE_FILES(conf, "crypt.h", "HAVE_CRYPT_H", uselib = 'crypt') + if conf.is_defined("HAVE_CRYPT_H"): + CHECK_LIBRARY_EXISTS(conf, "crypt", "crypt", "HAVE_LIBCRYPT", uselib = 'crypt') + + conf.write_config_header('src/config.h') + +def build(bld): + # process subfolders from here + bld.add_subdirs('src') + + #bld.add_manual_dependency('src/main.c', 'some dependency string') + + # the following example shows how to add a dependency on the output of a function + #def dep_func(): + # import time + # return str(time.time()) + #bld.add_manual_dependency('src/main.c', dep_func) + +class TestObject: + def __init__(self, label, filename): + self.m_linktask = self + self.link_task = self + self.m_outputs = [self] + self.m_type = 'program' + self.unit_test = True + self.env = 0 + self.label = label + self.filename = filename + + def abspath(self, env): + return self.filename + + def bldpath(self, env): + return self.label + +def run_tests(): + import UnitTest, Object + env = Params.g_build.env() + srctestnode = Params.g_build.m_srcnode.find_dir('tests') + prepare = srctestnode.find_source('prepare.sh') + runtests = srctestnode.find_source('run-tests.pl') + cleanup = srctestnode.find_source('cleanup.sh') + + print + + import os + os.environ['srcdir'] = srctestnode.abspath() + os.environ['top_builddir'] = srctestnode.m_parent.abspath(env) + if Params.g_options.verbose: os.environ['VERBOSE'] = '1' + + Runner.exec_command_interact(prepare.abspath()) + print + + singletest = '' # '*.t' or '.t' or '' + if singletest: + objsave = Object.g_allobjs + + tests = [] + for f in srctestnode.files(): + if f.m_name.endswith(singletest): + tests.append(TestObject(f.m_name, f.abspath())) + Object.g_allobjs = tests + + unittest = UnitTest.unit_test() + unittest.want_to_see_test_output = Params.g_options.verbose + unittest.want_to_see_test_error = Params.g_options.verbose + unittest.run() + unittest.print_results() + + Object.g_allobjs = objsave + else: + Runner.exec_command_interact(runtests.abspath()) + print + + Runner.exec_command_interact(cleanup.abspath()) + print + +def shutdown(): + if Params.g_commands['check']: run_tests()