kore/0000755000175000001440000000000012527355661011077 5ustar jorisuserskore/RELEASE0000644000175000001440000000027612527355634012107 0ustar jorisusersThis is the official release for Kore 1.2.3. If you want the current version, use git to clone the following: https://github.com/jorisvink/kore/ See the README file for more information. kore/examples/0000755000175000001440000000000012527355514012712 5ustar jorisuserskore/examples/video_stream/0000755000175000001440000000000012527355514015373 5ustar jorisuserskore/examples/video_stream/README.md0000644000175000001440000000103012527355514016644 0ustar jorisusersA simple HTML5 video streaming service using Kore. Building: ``` You must first place a test video inside the videos/ folder. I tested this using Big Buck Bunny (ogg version) on Chrome. But any video that can be played with HTML5 works. If you did not save your video as videos/video.ogg make sure you update the assets/video.html file to point to the right video. When done, run a kore build. ``` Run: ``` kore run ``` Visit the URI and you should see a video stream. Frontend parts from video.js: http://www.videojs.com/ kore/examples/video_stream/conf/0000755000175000001440000000000012527355514016320 5ustar jorisuserskore/examples/video_stream/conf/video_stream.conf0000755000175000001440000000047012527355514021654 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./video_stream.so init tls_dhparam dh2048.pem spdy_idle_time 600 http_keepalive_time 600 domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key accesslog access.log static / serve_page dynamic ^/[a-z]*.[a-z0-9]{3}$ video_stream } kore/examples/video_stream/.gitignore0000755000175000001440000000004212527355514017362 0ustar jorisusers*.o .objs stream.so assets.h cert kore/examples/video_stream/videos/0000755000175000001440000000000012527355514016664 5ustar jorisuserskore/examples/video_stream/videos/placeholder0000644000175000001440000000003712527355514021071 0ustar jorisusersDrop your HTML5 videos in here kore/examples/video_stream/src/0000755000175000001440000000000012527355514016162 5ustar jorisuserskore/examples/video_stream/src/stream.c0000755000175000001440000001422712527355514017632 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include "assets.h" struct video { int fd; int ref; off_t size; char *path; u_int8_t *data; void *base; TAILQ_ENTRY(video) list; }; void init(int); int serve_page(struct http_request *); int video_stream(struct http_request *); static void video_unmap(struct video *); static int video_stream_finish(struct netbuf *); static int video_mmap(struct http_request *, struct video *); static int video_open(struct http_request *, struct video **); TAILQ_HEAD(, video) videos; void init(int state) { switch (state) { case KORE_MODULE_LOAD: TAILQ_INIT(&videos); break; case KORE_MODULE_UNLOAD: fatal("cannot reload this module, i should fix this"); break; } } int serve_page(struct http_request *req) { http_response_header(req, "content-type", "text/html"); http_response_stream(req, 200, asset_video_html, asset_len_video_html, NULL, NULL); return (KORE_RESULT_OK); } int video_stream(struct http_request *req) { struct video *v; off_t start, end; int n, err, status; char *header, *bytes, *range[3], rb[128], *ext, ctype[32]; if (!video_open(req, &v)) return (KORE_RESULT_OK); if ((ext = strrchr(req->path, '.')) == NULL) { v->ref--; http_response(req, 400, NULL, 0); return (KORE_RESULT_OK); } if (!kore_snprintf(ctype, sizeof(ctype), NULL, "video/%s", ext + 1)) { v->ref--; http_response(req, 500, NULL, 0); return (KORE_RESULT_OK); } kore_log(LOG_NOTICE, "%p: opened %s (%s) for streaming (%ld ref:%d)", req->owner, v->path, ctype, v->size, v->ref); if (http_request_header(req, "range", &header)) { if ((bytes = strchr(header, '=')) == NULL) { v->ref--; http_response(req, 416, NULL, 0); return (KORE_RESULT_OK); } bytes++; n = kore_split_string(bytes, "-", range, 2); if (n == 0) { v->ref--; http_response(req, 416, NULL, 0); return (KORE_RESULT_OK); } if (n >= 1) { start = kore_strtonum64(range[0], 1, &err); if (err != KORE_RESULT_OK) { v->ref--; http_response(req, 416, NULL, 0); return (KORE_RESULT_OK); } } if (n > 1) { end = kore_strtonum64(range[1], 1, &err); if (err != KORE_RESULT_OK) { v->ref--; http_response(req, 416, NULL, 0); return (KORE_RESULT_OK); } } else { end = 0; } if (end == 0) end = v->size; if (start > end || start > v->size || end > v->size) { v->ref--; http_response(req, 416, NULL, 0); return (KORE_RESULT_OK); } status = 206; if (!kore_snprintf(rb, sizeof(rb), NULL, "bytes %ld-%ld/%ld", start, end - 1, v->size)) { v->ref--; http_response(req, 500, NULL, 0); return (KORE_RESULT_OK); } kore_log(LOG_NOTICE, "%p: %s sending: %ld-%ld/%ld", req->owner, v->path, start, end - 1, v->size); http_response_header(req, "content-range", rb); } else { start = 0; status = 200; end = v->size; } http_response_header(req, "content-type", ctype); http_response_header(req, "accept-ranges", "bytes"); http_response_stream(req, status, v->data + start, end - start, video_stream_finish, v); return (KORE_RESULT_OK); } static int video_open(struct http_request *req, struct video **out) { struct stat st; struct video *v; char fpath[MAXPATHLEN]; if (!kore_snprintf(fpath, sizeof(fpath), NULL, "videos%s", req->path)) { http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); } TAILQ_FOREACH(v, &videos, list) { if (!strcmp(v->path, fpath)) { if (video_mmap(req, v)) { *out = v; return (KORE_RESULT_OK); } close(v->fd); TAILQ_REMOVE(&videos, v, list); kore_mem_free(v->path); kore_mem_free(v); http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); } } v = kore_malloc(sizeof(*v)); v->ref = 0; v->base = NULL; v->data = NULL; v->path = kore_strdup(fpath); if ((v->fd = open(fpath, O_RDONLY)) == -1) { kore_mem_free(v->path); kore_mem_free(v); if (errno == ENOENT) http_response(req, 404, NULL, 0); else http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); } if (fstat(v->fd, &st) == -1) { close(v->fd); kore_mem_free(v->path); kore_mem_free(v); http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); } v->size = st.st_size; if (!video_mmap(req, v)) { close(v->fd); kore_mem_free(v->path); kore_mem_free(v); http_response(req, 500, NULL, 0); return (KORE_RESULT_ERROR); } *out = v; TAILQ_INSERT_TAIL(&videos, v, list); return (KORE_RESULT_OK); } static int video_mmap(struct http_request *req, struct video *v) { if (v->base != NULL && v->data != NULL) { v->ref++; return (KORE_RESULT_OK); } v->base = mmap(NULL, v->size, PROT_READ, MAP_SHARED, v->fd, 0); if (v->base == MAP_FAILED) return (KORE_RESULT_ERROR); v->ref++; v->data = v->base; return (KORE_RESULT_OK); } static int video_stream_finish(struct netbuf *nb) { struct video *v = nb->extra; v->ref--; kore_log(LOG_NOTICE, "%p: video stream %s done (%d/%d ref:%d)", nb->owner, v->path, nb->s_off, nb->b_len, v->ref); if (v->ref == 0) video_unmap(v); return (KORE_RESULT_OK); } static void video_unmap(struct video *v) { if (munmap(v->base, v->size) == -1) { kore_log(LOG_ERR, "munmap(%s): %s", v->path, errno_s); } else { v->base = NULL; v->data = NULL; kore_log(LOG_NOTICE, "unmapped %s for streaming, no refs left", v->path); } } kore/examples/video_stream/assets/0000755000175000001440000000000012527355514016675 5ustar jorisuserskore/examples/video_stream/assets/video.html0000644000175000001440000000072112527355514020671 0ustar jorisusers Video stream over Kore kore/examples/generic/0000755000175000001440000000000012527355513014325 5ustar jorisuserskore/examples/generic/README.md0000644000175000001440000000033312527355513015603 0ustar jorisusersGeneric Kore application that shows off a few things: * File uploads (/upload) * Authentication blocks (/private) * base64 encoding tests (/b64test) * Parameter validator tests (/params-test) Run: ``` # kore run ``` kore/examples/generic/conf/0000755000175000001440000000000012527355513015252 5ustar jorisuserskore/examples/generic/conf/generic.conf0000644000175000001440000000207212527355513017536 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./generic.so example_load tls_dhparam dh2048.pem validator v_example function v_example_func validator v_regex regex ^/test/[a-z]*$ validator v_number regex ^[0-9]*$ validator v_session function v_session_validate authentication auth_example { authentication_type cookie authentication_value session_id authentication_validator v_session authentication_uri /private } domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key accesslog kore_access.log static /css/style.css serve_style_css static / serve_index static /intro.jpg serve_intro static /b64test serve_b64test static /spdy-reset serve_spdyreset static /upload serve_file_upload static /validator serve_validator static /params-test serve_params_test static /private serve_private static /private/test serve_private_test auth_example params post /params-test { validate test1 v_example validate test2 v_regex } params get /params-test { validate arg1 v_example validate id v_number } } kore/examples/generic/src/0000755000175000001440000000000012527355513015114 5ustar jorisuserskore/examples/generic/src/example.c0000644000175000001440000002045512527355513016721 0ustar jorisusers/* * Copyright (c) 2013 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "assets.h" int example_load(int); int serve_style_css(struct http_request *); int serve_index(struct http_request *); int serve_intro(struct http_request *); int serve_b64test(struct http_request *); int serve_spdyreset(struct http_request *); int serve_file_upload(struct http_request *); int serve_validator(struct http_request *); int serve_params_test(struct http_request *); int serve_private(struct http_request *); int serve_private_test(struct http_request *); int v_example_func(struct http_request *, char *); int v_session_validate(struct http_request *, char *); void test_base64(u_int8_t *, u_int32_t, struct kore_buf *); char *b64tests[] = { "1234567890", "One two three four five", "Man", "any carnal pleasure.", "any carnal pleasure", "any carnal pleas", "I am a nobody, nobody is perfect, therefor I am.", NULL }; int example_load(int state) { switch (state) { case KORE_MODULE_LOAD: kore_log(LOG_NOTICE, "module loading"); break; case KORE_MODULE_UNLOAD: kore_log(LOG_NOTICE, "module unloading"); break; default: kore_log(LOG_NOTICE, "state %d unknown!", state); break; } return (KORE_RESULT_OK); } int serve_style_css(struct http_request *req) { char *date; time_t tstamp; tstamp = 0; if (http_request_header(req, "if-modified-since", &date)) { tstamp = kore_date_to_time(date); kore_mem_free(date); kore_debug("header was present with %ld", tstamp); } if (tstamp != 0 && tstamp <= asset_mtime_style_css) { http_response(req, 304, NULL, 0); } else { date = kore_time_to_date(asset_mtime_style_css); if (date != NULL) http_response_header(req, "last-modified", date); http_response_header(req, "content-type", "text/css"); http_response(req, 200, asset_style_css, asset_len_style_css); } return (KORE_RESULT_OK); } int serve_index(struct http_request *req) { http_response_header(req, "content-type", "text/html"); http_response(req, 200, asset_index_html, asset_len_index_html); return (KORE_RESULT_OK); } int serve_intro(struct http_request *req) { http_response_header(req, "content-type", "image/jpg"); http_response(req, 200, asset_intro_jpg, asset_len_intro_jpg); return (KORE_RESULT_OK); } int serve_b64test(struct http_request *req) { int i; u_int32_t len; struct kore_buf *res; u_int8_t *data; res = kore_buf_create(1024); for (i = 0; b64tests[i] != NULL; i++) test_base64((u_int8_t *)b64tests[i], strlen(b64tests[i]), res); data = kore_buf_release(res, &len); http_response_header(req, "content-type", "text/plain"); http_response(req, 200, data, len); kore_mem_free(data); return (KORE_RESULT_OK); } int serve_spdyreset(struct http_request *req) { spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK); return (KORE_RESULT_OK); } int serve_file_upload(struct http_request *req) { int r; u_int8_t *d; struct kore_buf *b; u_int32_t len; char *name, buf[BUFSIZ]; b = kore_buf_create(asset_len_upload_html); kore_buf_append(b, asset_upload_html, asset_len_upload_html); if (req->method == HTTP_METHOD_POST) { http_populate_multipart_form(req, &r); if (http_argument_get_string("firstname", &name, &len)) { kore_buf_replace_string(b, "$firstname$", name, len); } else { kore_buf_replace_string(b, "$firstname$", NULL, 0); } if (http_file_lookup(req, "file", &name, &d, &len)) { (void)snprintf(buf, sizeof(buf), "%s is %d bytes", name, len); kore_buf_replace_string(b, "$upload$", buf, strlen(buf)); } else { kore_buf_replace_string(b, "$upload$", NULL, 0); } } else { kore_buf_replace_string(b, "$upload$", NULL, 0); kore_buf_replace_string(b, "$firstname$", NULL, 0); } d = kore_buf_release(b, &len); http_response_header(req, "content-type", "text/html"); http_response(req, 200, d, len); kore_mem_free(d); return (KORE_RESULT_OK); } void test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res) { char *in; u_int32_t len; u_int8_t *out; kore_buf_appendf(res, "test '%s'\n", src); if (!kore_base64_encode(src, slen, &in)) { kore_buf_appendf(res, "encoding '%s' failed\n", src); } else { kore_buf_appendf(res, "encoded: '%s'\n", in); if (!kore_base64_decode(in, &out, &len)) { kore_buf_appendf(res, "decoding failed\n"); } else { kore_buf_appendf(res, "decoded: "); kore_buf_append(res, out, len); kore_buf_appendf(res, "\n"); kore_mem_free(out); } kore_mem_free(in); } kore_buf_appendf(res, "\n"); } int serve_validator(struct http_request *req) { if (kore_validator_run(NULL, "v_example", "test")) kore_log(LOG_NOTICE, "v_example ok (expected)"); else kore_log(LOG_NOTICE, "v_example failed"); if (kore_validator_run(NULL, "v_regex", "/test/123")) kore_log(LOG_NOTICE, "regex #1 ok"); else kore_log(LOG_NOTICE, "regex #1 failed (expected)"); if (kore_validator_run(NULL, "v_regex", "/test/joris")) kore_log(LOG_NOTICE, "regex #2 ok (expected)"); else kore_log(LOG_NOTICE, "regex #2 failed"); http_response(req, 200, "OK", 2); return (KORE_RESULT_OK); } int serve_params_test(struct http_request *req) { struct kore_buf *b; u_int8_t *d; u_int32_t len; int r, i; char *test, name[10]; http_populate_arguments(req); b = kore_buf_create(asset_len_params_html); kore_buf_append(b, asset_params_html, asset_len_params_html); /* * The GET parameters will be filtered out on POST. */ if (http_argument_get_string("arg1", &test, &len)) { kore_buf_replace_string(b, "$arg1$", test, len); } else { kore_buf_replace_string(b, "$arg1$", NULL, 0); } if (http_argument_get_string("arg2", &test, &len)) { kore_buf_replace_string(b, "$arg2$", test, len); } else { kore_buf_replace_string(b, "$arg2$", NULL, 0); } if (req->method == HTTP_METHOD_GET) { kore_buf_replace_string(b, "$test1$", NULL, 0); kore_buf_replace_string(b, "$test2$", NULL, 0); kore_buf_replace_string(b, "$test3$", NULL, 0); if (http_argument_get_uint16("id", &r)) kore_log(LOG_NOTICE, "id: %d", r); else kore_log(LOG_NOTICE, "No id set"); http_response_header(req, "content-type", "text/html"); d = kore_buf_release(b, &len); http_response(req, 200, d, len); kore_mem_free(d); return (KORE_RESULT_OK); } for (i = 1; i < 4; i++) { (void)snprintf(name, sizeof(name), "test%d", i); if (http_argument_get_string(name, &test, &len)) { (void)snprintf(name, sizeof(name), "$test%d$", i); kore_buf_replace_string(b, name, test, len); } else { (void)snprintf(name, sizeof(name), "$test%d$", i); kore_buf_replace_string(b, name, NULL, 0); } } http_response_header(req, "content-type", "text/html"); d = kore_buf_release(b, &len); http_response(req, 200, d, len); kore_mem_free(d); return (KORE_RESULT_OK); } int serve_private(struct http_request *req) { http_response_header(req, "content-type", "text/html"); http_response_header(req, "set-cookie", "session_id=test123"); http_response(req, 200, asset_private_html, asset_len_private_html); return (KORE_RESULT_OK); } int serve_private_test(struct http_request *req) { http_response_header(req, "content-type", "text/html"); http_response(req, 200, asset_private_test_html, asset_len_private_test_html); return (KORE_RESULT_OK); } int v_example_func(struct http_request *req, char *data) { kore_log(LOG_NOTICE, "v_example_func called"); if (!strcmp(data, "test")) return (KORE_RESULT_OK); return (KORE_RESULT_ERROR); } int v_session_validate(struct http_request *req, char *data) { kore_log(LOG_NOTICE, "v_session_validate: %s", data); if (!strcmp(data, "test123")) return (KORE_RESULT_OK); return (KORE_RESULT_ERROR); } kore/examples/generic/assets/0000755000175000001440000000000012527355513015627 5ustar jorisuserskore/examples/generic/assets/private_test.html0000644000175000001440000000054112527355513021226 0ustar jorisusers Kore Authentication tests

If you see this, the authentication worked. This page should redirect back to /private once you remove your session_id cookie.

kore/examples/generic/assets/params.html0000644000175000001440000000227112527355513020002 0ustar jorisusers Kore params test

You can pass one GET parameter (arg1), any other GET parameter will be filtered out

Only two out of the three input fields will be visible to Kore.

The first field accepts the input "test"

The second field accepts anything like /test/[a-z]*

The third field will be removed by Kore, as it is not in the params block configured for this page.

GET param arg1: $arg1$

GET param arg2: $arg2$

test1: $test1$

test2: $test2$

test3: $test3$

kore/examples/generic/assets/intro.jpg0000644000175000001440000314303612527355513017476 0ustar jorisusersJFIFHH XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmExifMM*V^(ifHH C        C   " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?n2sUȆ~ѡϨj_v_RxW ެG P¼ҬGf2'S=jxEA1֧ }*+2xN=8vE8K8 %^jH MQޞ3iĨbjXAPpzsJE\z1I03ҢN LyJ:RpAbQr4}=i<*ڀ 8>>9PKD|z x8=񎹩;5"~4xOQv2uG*_&X͊<`gw֢S:~ac֞s۽=G>%`uTx^=?:1@b|R8t9vxJ9{@<ԑz2>X`Ԩ31ҝ"â7ޥ b S3g9"8hGW$.92>sgKpT}: kp10|.8늒EEg8㊚0=L$`Nj$sF)\$vO>>NN &ģ; H@jCO9R-DT^3'Z`cԀ xc㎾ǧJHjPGP .4Jۃ-c=3Unwb-M]58V sI9@u2uV1V6 ` T5fRW^Ĺֺ)= nsjI(]k1Yz1+RZPvpE#0woc1@Xyrk]gI;L<<ï_NkN_\ӡrI+^d1wLTztd:Ժ2cLѵ(h(<һ|'C=:-d+Iǿ5%#ǚCqHܹXr Z`㊍2xQ7іd`T,8w= sXU+t%|d0H*t5(>՛z^ԱU["Z_mgԡ~Tf78|@N*d*!Sg&8MW*y}jUAk-D0^^x皙qv1\\FH>(G=1O q7#qR㊨99ǭ+:JDJ͖Lwz PK'ˌ|hGUy*Ufsh&[pIO+9jq!56+1N?¬J zV rq0˴1ШFyj 3\8 . 魀َ:Mk 'mUYoaMcn<`<MAF6ӎESõˀ8N+b=)Ƨq8$1zȷ[ze:}:7I,s[T.]i@r1]tRӯUyw2cYFhDBy5v$IVJ6A?Zд^Nh.qQ]}&͌~UjAIA,yqVҫ>bzVH'|sJS;w60kDOA0F Oڣ?O>czu0zt&8'816<j u5br@85]?ZsD/&ٲDHյ i3 J>_\#uvL$j_s~Y3֯Bxⵃ! QO*vN P~3W)Xg5FF!'Rin\+nͺpj>xm=jIUML'vI♪ql}qV/; tt37"ԭg`s}y1 XmqV`eGszrShn7735<p}q\o0ȯM/تrHsxY8aFR$j峰lSC`Ρc94 sҤe`ޢrsϹ'pܜ:cء,!M!8ڐ8R %Q@cv1}4rtǠ9B33@J( \ZJ(s3IEQEQE򤢊\*Ol(iH⓪Ҕ{P8E@&x@ =ix=)=iXߝisNw%sQ8j2Jޞ?Z9NzROJjN?\P)H:tA޸}h׊u;p}*XƘ3T.dp9M~튕pU6JP{txV"qS TJR N:*T`Tь>DT122N&}:cFO5:Uc CR!"Iu'Z.=I >c9{)\dS) x=מEXTS2jSF3q'qQH7"A:(yҦVWH GEC0O҆2? qӜbN~?DJ: g4`zS9=׌sڜ{C=n=>AT$⋈rqRLNghl:tv'Y$py9 Rjҏ3n֝jڄs08OhzyloA6<Ԑ\#6ќ`lzsNRU2 j wgE *pI+/N~ G_J9Rqܙ3КpGDcߚxd;fka~MJ :}ED:c*tqrsT8=j$qR&Z*!R)<ЖH.1"`8S;G) qӌӆ3ԃM_1RKcOœ-rctQǥH2HJwN)~itzq?/9LmIsLcҤPX8i0 &w8C9>SLp); @pϥ?9ۊjñCӭ+9@rF{/A׎WOOPy1H84:R9yN8ǜjj8'r8qSzց(>Q;Az4 \qJy#@טhz8z<~TÜdzSF)}ǃҗҎ:qZEXP?74[XR?L1ԁw&Zf8VU=i4w,ӽ80 u۱L hY' 7E@'=V'$:jK`?4~x$v;x8'p)J?/;w1][4yQqOS0G81JR$qjGӵ@ǽIAUD"~kVNG=H;>w{TyUq7D=*ߞ~N8Npqڵ];6|sZvz;5mnJ/~+xNmXހzT99/b=hೌe+.A3E@sUdz(#( *Hjy=zԎ8S_Y=ru-;8l6IVmC) ڣed$sOvF6pEI"sj-ۏzp,ԑE ׁORIF)>hBx9J|D0ԑM| t=c8Yչ95.:VFz'(ӑ=z*Ac)( *2*|4zT+X+9Jǽ9=8^֩r7_¢x` UUk2[ |V@M] :➣RTй3T.zը\DE+Ei- *9'>vֳբ!F+ k eO'ZhQb/-6r::l¸g7֧A=EN ΔJlӿscU-&㜜s]*O`r:vq~(ёUE\OBnF8#yQHu" ? RGJ,!M;#L@d[TlZsɆ=E4&azZn@L'%z~VBs.PJ>j'mFG8zγ,#bT9U.Rqv^oӣrxˡ'?NcTo.J/Bbe.> (8 (4PEPEPEPE)I@J;Jp?-7z~x!#f|zS;?)4 ڀ i`HTH ]:♂=qڄ?+dw <NF:wzЃR'Ɛ Qր1zq:GԸ/Z\y .$TQ0s>>:w$r28W>j(0OO*iWP㚚<\Zq=:]I*J885 7zqjT?82L$\T:1D;ԉvɣpp*AjpDcRbMDjӾjD:[Vv+N=+XVθ`jODB@&)$:ⴅu%JvJX&9 ǩMͰ8jD9ϭR UsRrm>ǧ5$kF=ӵMAq"PHԉ1B:"r1ϵ;KDOA2>=Li\ih=qޙ$ʊ9=*ӝBYFEB)e=A➄ ?JrlMGbE\Jz!f3 TX[BpN1VǀzS!g_1MDʥT3Nd|Tq@j]&:ӝɓI)yOR1hAr0)CtD,T>WךC7|Bz.G} !s]sΈH[JWԻןzU3:>֋ :qNQFr9 4},=~'N=Fj0Gv5';x8 P{֤ᇩN1֫q"@87wJ:.2A(9 OL3p$_CNR00>ǯ4 L.;'ZzM5ԃ9ナbBiסO֤֣iç'S1Nz@\yPzfz`͠pz9ޜcp{ҏ\/zRw#Қǭ(' PXp6Z;ZqJ90BJ◽#r EvoqQ]m1d`p)*AN )} c+Kppq֘34+z3-۰ 5r:osҹfBOCۭI`GR*sS R/[ϴ` E^c%Mb*1rܵf͟k 5g&n<dwޚU7*NR!'Y)l1L.mcA/Bۛ9O|J瞆 7өSNǭ&yL3ގklnRM?J^ }\Vbzp\O$P^8p}i; /Rۀ0;wpn}zӽ1ޚ>(=;S2NOQQ(i14Huө))1u~;M̑})GOOzju"}j"֔TeR9C w>v4<Ҍv@p}h#')h'r}*9׽H`v4)߽#GzÚӅް<fmLH$ҮT֬۶1ڹSEP>4.O=iQREdq[B,GךT"[:UخThCүGg6'#>EҧLv hke86#'MT+aj VrbSJoO|V*9=)DcCfW9!?(j׵@o|QÝ@hWN#yjqIL'S|Sb*'5mSJs\r z xP{ Hhy|zR{ 3|?aW/=1MR1SO/@q҈@O=a8hQu\c(H\dqVmmZ}ZpWXM@JԱ>$JҬAߊ}5OcOJ>J;ƀ"pE*SdR/'N`qֈ)\8EQJ\P34ޜšzH?JZ(hSqX<S֚>*zP( ( ( ( ( ;}(){P p(''ާ€+1xi9=:O8a)4(?/*d 0~\TH(*=(ZZA֗ ֆH:E+c#j ?AiJ}Q84ǾyM;5?JI8ݏҞy'Svq[q})s1j@%aezҌqB~=)B> ¡M;?7 =#zQ1ۊGN'x!0:\[c\@ w?J.W@S< 縦ïRsN 村ӦGsߥ+lN)6qzuW}Ttت"TSAՠICQ(F3Dx\`dtk2 Ua8huR(995^@> 5 MFy^ԧN(>xӸO콅Szˠё843N+qM#\Ӑ֙ בBCJ8w T00?3Qc$3O<Jn2n)sh8(G%OZx<`dwFxŒS*& p=3ޢS2ةS;}I>Gj=y"p=1JL(ўSr*DZ~CR7$I,zjXL~^7>$nXIܕHR@_9=h.1SKMImX i;rjz4wZ$VZO|:Ӗ\&ܐiI\$E lXuP$GP4&kj 1TBOZ\pjD۱a_=(][94+q%ŭp|jnƜI#;Xy$ z:z3Hv$oǚE=BggM14=HTD; oI"Ѕ2x8P!@¿-]O,dLqW 9jԄ☮~ni0g֔(Og^Ll>,=rAA[uԱJryOm IUAըOXI'y˅Eohd7<⫠W8'Y;15=kURY\ѵGdӭ͆v{Oa2*[VBy' qkC Th*U3R늧ar+ITUr$iʸg.0qͼE.p9rhǶiHC֗rjv)F38;qӊ^78W&ࡻ cm楰zgcֹ3V/($W.:<4 Q7Unnc[4V ⤁ݹkAl7Ɂн ;i t4t'EFw`ךI($;TrL֨z<}*VN1S*h5_PZY8-(& }j,8UB/#ӭKUiR3q.(ӚLzUFyTCVD2Ф­[V10+^[{\CV"PiU1S D:ۦX}㎕j[%bztJxE0!qjh *?\56ninvU<#KW?9g<};}*OfsK,XS4qU߭?8^ԄZȩ?J tW5z JBwZqKQtIMǩV 9~F*E8}=F֢ .@<:OV,>w5%-i9QuMR*1)Ѯx ޣu>?.=LA@8d4iH9crB9#i II'4㱠 Yh ?:ێs@A=lt40*&< 5$$E$d@1Fҥ3ϵ:AAzF<:)(((($zҞ }{ncF(^i6jb1_΀ Tyڬ08d?ZTJ9)i䞧5!,q&TOZ:t iN};b?ʥ zpy4z. P0:Sg_@M5!(nF";|=F0yyvz\4@isOJޕ,db{rnL֦> 9< |)săO8Q{ug=(O =ʀxy4*'J8/q\vz{qN_bG.3G `sK\ldq֜2*"$N ܫ7%};T1[9*E ϩrM<9qMBJ');KsENRQ8 i]cx8jIm88z}"H?~BJ 3N0gzt^?.)ǥ(9qzҕHOzQ҄&;8d;P{~t ێœқ3ʜ?ZC)I psZLh\}ʂM8˜8sҕ!ݸSGr{ ?JPpqt(cg&S];R'2)32ypjUB&j<NGnCsR&A'2Ƹ+6E ך8J5]jϽAFc@չb~D 3%.EJ;+ ˏP5VIYFF8<*TAJn:M cP뮅zXŎؕ9i2 gc[O5*ae,(`Q.0Z, `ŋhj[2ul=߽S#>TR[%U*%K# H6y;cBmd8=+ֶ.G'8[SIhuq PO6`gJmr6F3`c#5m)EܭD5=*Ӡ9 )INhB;h܌S VC3ޘp=jzy9⭭*>z`o֣rsB`)!_ Lz$TTvPv`j5&8XۜV줱5V!v<|Ͻ)|*9= 4Is+u(#V}k@Ii1OJT|/XNg/sl[^^Orb*"tηbH MDWd3⠖[깓6{!Xߚpq֫niwsN&f8 T[ w@IJޘ)ïq@ީB7w5\B=)Ӟ)hԪ3R"㞆 vE :gQ@ 4ă&p1ހF)IL9֛hM] RN9#A(R}8w49K@ht (':ϊjM(Za)sJ@&9ɥ<)N( T.V_㩨itJ1NހC0sӨKEb֔z=hN1ޒq֛)zv c\.rsM3?:p:Ԋ28N㽊NJmwQ*׾hPNGj0jx>A#aJ84gҋ3R 8>`95-Qy#sdtrsR#"Ƶ%@BjxT8SsEJ>\}i| Tk#<ԙ;.s׵H@)>a ȩ`g<+HH"*dE;_X*| 9\i%(k'HPH1}2d\Ԫr& 0@JɆmr~eeu54lx8۩P 8I늨R{tՄpHh#o\ִ&a)ԌTIGZ15$lA)dp:d}(}璘Z88 (zbڐqsCЕO5 T(F{pM%!12stcb0׊r;tp(Oo>_Z.TI pJ1i~{( 9ZR Ԏ<&j'G&=ll {u>Ȣ1+/ݾF}\9rbOR\/ UC glsx[w*Ӊ <$zlg8n tvViN4 yZӤ_$ EyR=t'5_*\zPJW-p\WncRښ:Sn\)$HǴON)vH9HSqJM "h p:Ҝ瞔HRN  5=ێG5qr~fݑr lU-ԏJ4cNyXo;)-$l6O Y0GjɎzG\F:R YF}L<7XR~Fv* u"y+"_UteBpgl19#XL-+tLأ?J|N|ª#5UR$Cv搿i3Zd w2XVQGu-dRfdvx~b;!j1X)`<)FۜFA0x@_$vsGبR9=G- žFhw7(w0>)UFCZ`bҦ}> ֤qߥj}#[Vs&gƘN;U yzXS?[HOM✱)"׏zy#*K{rT qOIj88VME㡩cC؞[6 !14\3R*zI)hNv^q֣hL uЕ$ d:1ޠu.! {U$qteGN*30j#lx8"ZH9?Z38bٻ4 ;;ԭW,9"5b(=j"MZ` sZ65GLw(ՈuSo#r I#棖'ȨV#t8kI&hFwco d<{uJ2jk7bC:+&8A⺡+hYzTSp:RqQZl P1ґJSbGZ'(w={JԑZmq]̛鋜l犻{ 8n@*7릒EC:M-_1Slۇ\lX=9(?έ}?G=hcЁMzҘtGhAd89E:Ӗ#Sf3aʐ8sJO9?H8ބQwz ^JsOG8'jz%ۨx4'=x"zS҆!=iI<J|̗;z{b'zB): 8ӭ9x40x݊zM1;Ssr`g$GJNa#=jJOn$g 9<ˠuǽ>8욦_f_y<5!=j2dqY1Jp;T6\Vd8gY#-3C D؈j]ñP8aK UWS>Vj穥YKv%2=?kwqzt5_'O&vyt 23ZSͺ<&qk4y }ь9}* 8Wz\ϵ8gGsҀmӎTi<#*%ۃj1u5Z!xr2/6⟟/Ry{U:5<uɨp4AqҐt=›=8P>sF:O?*sJZhc:c=*D9D늕ǽTD??-2LsJݣ4^}Xp? XVXӺNVǵ9֘Xi sZM׊4דC1Cq֤\fRy*d>C.UlmEKGaEQE=*\j$#zv{Pzޕ֛@lR{Ҝƒ )sJ}hހ4!OJ"y1Q;t4{4RaVbV*ɓnGLZqY=3ӵ9cϦiTSDůAF9=Pd i$RG@7q*X#t4#i<jU=K{1֕R t.8zSӭKx^銕29wVC=?,Tjr:ԋ8+V&0;S|\sPp08,Fp=8v gh w X2uSj99=A<̕xzL)9i^Ho3OQ}3L9w`JH4~DW&1N*%qRW:@=E9x8)Jr&ytUzcS DyZ9*GAQ9UIJ00G d瞸!x!Pur1Uv:h˨fYz[MAcXH\Gz*Z嚺+3p NյesklV֝rA^}Jv;a;eVgXWՁt^)yxQOB&+;WA֠#'=lvR5RpLs= shUALj 8!5Ժ38XF8N֘dR(Vf2OҤ^})ޝNw!!N_z)})ˁPXU'sӭ(R&Q=NOO1EבN4A>4s }G\`R R3N RJ?Q&"3O]Gܨn=? ǖR~sҠ,HZ[$މN[riHTq=Eg9XqW'8P9$ >܍ӎ'w4KK"0,9nV8$qո@1ǥg)hj>!XaI N׀+Wj)+ =UՎ8bbF2qڥ;Vr4$߽LxϵM0'>#9L?E`<b1U`izc 5aҫD@*@''""{^oSUGs84=f6pw;zUVޜ'#Gɱr3ҍ/ xh4r׵ *Axi<+Ek0" =`8ղ˛Q:U#( \.=JLS!@TR;`;tx= ^sJQhR+s ~Ƌǵ]TF̑EWrGҜ=󊷰 qXy)6hzj`}=YaoJx~Ѹ3mp=b8qӽ\HʘZ=Ewk|8#A>g\Vc9T |5(zӀ"zgެJx^|s`cӄ|9ڀ9BR0/c8glqA1SLKE!qV}sK R½3#~u=n2c>xB{Fg=Ō P;Nщ-2ie B5+ht)VkDsl*6=I'4q[Mʎ:,J'#5xN*e0FkOd6Q[wN1R۟Zb<0+"&/[׭KY$`ը#n}k&kH׎Fr=1Vaҥ,/h'#=SVXp;(+ =@ eh~\TZQeUbPڠ{E>ƶQJ9nmd%6a}=O!\5|t=R "zUaEk IʫbC 8&s)ԅnb Pp1L*$l*M&vKJЌ+2ٱޭ$^Jph$bBNj6n犍 й zVDrSN0=iLLR=ɫ 9j..Td\X~`[@~T;Rtإ61Z64zAlR'F=H}<j68[@SXzNG$sO"0:ֺPSҳ@{3+F[ETpyf&ZB6Q]<[DQ3b8㊪ۉ8<⛧\ɒ,9:rǥ_0ϩvvӚS$[dzSjBjGie;@dF3g=rjs9R"qӨRosN q>l>SHmBsR"<Ӓ#ҭ'Ћ31H%nzz4݀M;HWCLhd$ԟg=0A)zuis"IXw$P=c8M&B<{=t4;\"脹>Nem۰$TCjbE ND9kKh?#RE5< yY)M9zQvt+1Iu&\\JF@<{Qޙ#NJiぞ)ozBu5nxJkP`XE0QH7`Ӯ(sPƒ(2?*\pJNޘK=qI#F828㞴M @ Z 1Q"zԩ)JV'SsڜUYJ~qw)8 $8dB_H7z6b=)ez@nF:԰g7$2Z,`.ĝvjրN)7dR4@*C c sS[+VKby?Ƴ[Xp;歼+;SRFsuQgzwZfMl^}}PdFGTy_qdք! kp<֝*جInTUe0c& +;WS>cPO v$)ѷ'ԼUxƦLn)xPscsQWL)#V-s=+3Q9AJH[F#jH_Jtk;Rh KTRB$nFyh]CMJO^:{vh Yq]zjy" =iʹjXrEW=h`i&d ZhAQ`;r~l\dV2V*V4To;r+EcU|n>>HrF1pzT78-*4b3zQ(T妥SN}1=vQМYܻ t* RtB#qJI3XSԾhҰSG1cW;v:N9To\Xf!"1حT'jul G^Vx9"5etwm$[hp; r1 I% cKؒ3Rz5f m&)NR IeUGFuR9P皑p֪|gQ{N偀:Ny$ipO={Uɭ Ԓ0Zz=Zz枹4}Kí*Θ\S> `$~Oit4ORG|dSREHj3U;I98mЏ*~&j91y8ϡqIkLr8$qзn3 NqgXwRqRV"Ul0/9 l}P=s4nպ0r!}as0ʤ`v0+xIE?QKWgk>Ljc;oOҁ=)D۠?:pzP0=sTc"ΞGg@XAN_QsԠ]$+19Ԍ?ZSG0t$S֏8tM( i$a'):9 6$lG^ȐA) )yǶ ȗ \qӽ^i!jpisSҝb,aGQ֞>*_CWHڠձ48՘ăp=}+=8<<x\~ѳHӁ\Z$)M9UvM^dV VghdZP4$uTs5@ޞ]lQu<RwJ8sL-Z(;v;~@;.17L7`'9>2.W*4#늱ʌgI oAx3ާaW mYv&@:qmrG!# },Sg(ĒbޒK}4wF_ r<̨h5* Y-Bȹ HP>B3КӴW qkOR'g*w4E(9])$`$@Hf{քAdCsSǧ 94==F)?EXzIz7pO)#f3Ҹ nv?&Ny^goThzCZ NN(t{Xך/X#Dx8ҤRq5䊧f+HmTzG8[qZ ڝ8lj۠I,# H{jDܤPtPȀ bP8zD.VX?Z J܊EG5 )`Zy }E7 Of N{VњBjW;2(?G-㧭mkt9s tv9n];c#G1jf*۶F2Va8kDF3sOPoΩQBse$O5l t⎃+OfOlzykH}#擂)31mI{Tl8@yA~*C#Xqԩ JMm(aJ׭6I=~ ?2Pyv\y?QR 0Oc@A7|Ӕ jX5\ȥEeO4Й8oN(TYr=kd H&14`z)Z>>:)Nt~5fj8 xh/8|Fg#S1Ž R $@ +1ҫ)sހ-?Z8EJJU4qA9JE4A怣ޝE&~PczRO'ӊ\~x# $-!GvКk}(r7ZltdPO}j'=9uޚSz(M(0RF^iة!8)#>@R>PZ1HN ;w5;~xYqPZfONxAִ zi؏`Q]N08jِH2%e9S9:)3ZsBͳ ןV=:0KF=hB3J[?JnyV-%Qj9d xJp6[B 1PzN*c5 S9±= ؂z2z.cZqI #N+FėtA 9m;q53֚RO&j̾WacYw hc`NATt]Ja8jDaJqR)N*^=)sQgҔGK񟗮i5Q qc^9JOUh['957j`E^nYI:z "[}ߠb>ۭC+~<pZB$UA3R ެByCY]"H/t_JoA EqUN{$ w&ղe)I^I*sCo\NQkzRX<{-^U`XldUԧi)-p uUO?ʺ'֨_D"Pӳ1qNO AFsPsJNG}sQxjxXwۚL= a@zUPP3۽^۴- Z HϾ)Oj M''ڳփ@y8":(ZZDjSO:=j*{TMТqۊUb1U! l~0Z^T 4{4S7S)82T.ү)acj-)>ST;8lg'QENZF臩'Bp)y=*4?/& JM8^NqLRNxjnŅx=*E=*qo<6ZnW({qP#ԑ9UX4R}_֣GsR$g`jAN'#aA)Q1H W4yʞ9={TF3PCqxb:;*}qҝc5[폩0qhc7)FJWU#>Ocu< =FqC/<J%q5:zqn)qB3ThG:昣Tr?&ߛkuzr'c8:WbyF88߽ZDEP3Ҩ81ґǽRsNt֚—?)JOiGޟM0`/֕0E4Sէp1ץ*9Q\Qq~xkϒ@lq\E%9}i=l6")( \zRG^1bQ{ 3ҫ2FIҬێzОbNkFUV 1]4ь݉HtUczRZf _hzi;?SD- ٧g qQ8ǵ=1T<9欤3PEUWОqU|#AԱzsP\ Or gQ^SBp*^@bizw4Ĝrkr7&SۡE8*pFI⧇M(K֖N=*q~J`sޅ۞A*t6]&]o*zSNp?fW56-&zt8*z4rj2=~^ChN7$=iJhiNS?J[ Ԋ7 Ĺ>PqMyh 2vp?F;w桐g85\bTGC96ֲL]PF:VQUh]Tֆ^j$ԃUP涋%U8.{Q3j'sL~[88ph]E&xqHQN\Ӫ09.qTsM803ȧd`s_)h =q^8)Q=ԴyE7ZAӽ\;msӵNU*y@ĩJ $c8W1X ߏJ3qRQPPՐR9/g/jn4Dn*8Jk7#N1l)P:ǷjG= 4RsIJ(@iy7# T]T߮=(TП΢c`/j54Kc@5":'ґǾ)\S`dzS{RxiGNhr)i\J޴XxSsBw.qC3sJ=0jB8)Iw:zT};PL>QIqN`7gEH!^4`~h)EI0iqGLxSN4U qJcޘ qnH\ T N1b" qQf!qS+sךH5(Sǭ|˚=1S#9qL|.A;HH.IըߥSE'E#=I+E8\zteGQV#9 ڶqѲbHr!Gz֞&ќqV.'gIEj@8\wq9[;fs5cGtc&PHm&{U_ҢZD~~5$R ɮZ5nUrzfcS^C 汌,k) !ǥOg d=i])hs_sb)<ou$ڻA+j1؁YN8ⱴY1N.$x⥏^,=6L#N=3MqQrnUQ8A}0֬͒T49*- MF8^3R8'E5rXu(W^HGqW\qW1v1`N3XV$PE:+pRُ…Lۂ=jͯLAڤ4rz*1;xI'*\]ˎ)(BVVM=1E|bT\=JйF:T2QXjgrnvBGZ, לU{r}OI<.OZjsI[aEOy2z]E;pEhCǀ#4L6jZӎ<#{S#N4m@VP fNθZ@Jr`t4ϖPC aLqJ%bQUؔO8'*īt9".䶭rq֭^{kA_1kFK]* 8J(9;GH\q|UGiÖCwp梸&n: *pyV3$.ʌsYS1>GdpHy9[V@dNR1*)HL*H3VT7k@'LnXf)ɓߎזvs(FFO$v; QRմ)+J0^qwTKN)<~ir_YsRDω_\Ոߎݑii^2~Z]F;\`qZӳVӨccSiv\ ";VtTH\0՝+Y&l{P:MSk,BpI9$j"MNZِj$j8D͢ϴүBʌdTPZE]YiOQTf$tA8N +X+]40:*5oԊr:+YKK *ȑz`ujnsY}* Rzv{X.ڗ7]xS/ןzF%ҝ84cSQCtVZQO#9uEv%μNtMX$Dy { ; uSgmȿ4sjγO|#SSި.=h猌4(IU`V|O11b/>^Ԩy**dcd/FN:՘ysY'ڬ&8*4LЄYG FOT&JBo'V^Vbw#2.~8⠕jUevpVٲs1RFzI29TDߧj>T$D͂8 In*?7BkX6cJr8j:VVԔ8z*PA`UxT9X[8^:Rp+xcr~Tޕz_զA'cߎiQ!sN?t0&<89w_"׊\ >O<8鞔qA~iaך~p0#5&ӑw R$6 &4\VՏzaSR6JBWR3XԟBphGHw=H\sБW#SO1BX\I dT7N\G銥F*Rq ,Hqy !x[-LY00 &sF9ElheiQW8⢒Lt'nabk>^5FYO4/`g֫23gQBc(6;|Sv<Ǚru3Ȩf׵9xl{u4Ǧxj<}?KHa0?Z :E:wroV8}WLsֻ 9N3QR\GC1oƪLĎu4g 7*\Г qMi8`Gݤ7~(ad>6;I?Z#H?5U<`dRA#Zxp`uϭG'88`=*)ho@H>cH=:ROT؈~*߭R`y@ۭ5d`8{g#7;5Gg&Y[2V i94ץ5~H>ZQG9J*G'2g*V@nj^U#SXd ڢu9q+8VfLTUH;R1S!MDM8g7w9W|HcJ|9U1Ԋ8R]1NAXs!84`]c/jۜ &ZP1@ h#ӥ%(cS|B>I2⏳1;("}2'8qY\V1=kJ1!\h`æ9EZҝHk)*Wc3{t8'ҝ59c8BpY3A"[ d1EiB՝n_Z9z&erqץ?$ Tu߆'44qکn4,FzTٳnd.&1ɫp5Zxlw"FԑaLڠt_czwy*B +Hz~03Z6" տQWg:e\snDs9z!86XyUjeV66"n1L=+.;ɫq)⛋=\szz#ک ?T\Rvqfr=*c8YQ9rTz%h @Hji n51NCzQ=Fa`7aG8BU()'Ң'zT(9╘$|OJ&F (=ք,[F:uxNVѹПNݫ9))0jV$`cQJ U]Bg541uju ˜ૌ18'8uzU[rMYҥ,z(Î8Lܙ"aJsH? 7"- (E&9ǁKz*zޣ^s{3fD'*kpjzsʎ֕>v(+w!9֭O,5@C1[¢$iدo,XqV%PO)VmQCbMm$vPJC|L0T7Y:Npaxl.C0O0 4)>[D GSo`g=)@SLUiNdUI W k"ܩ׵_[Mjа{$<~l`Ү[| $Do7rj $8N 2aceb,Ri9CNjcSLqJb_,Bajfat#Z} bz֭B$cPlpIVr FDc= <ԗ}49G'˙QZXM/V`#%O!x'Axj&Lw)gU$9#OiOִD&=ԑ܃4/8/<QVԑXTn9L=J# 9G+@&9Lv^FARR#1LTpO\Yr8c)ؒ"1ٳ K45XtqOq҂0qT'&dn㚤<A>mdj[󊶮0zVtB8aĄzըWT~V^ Z̥3.GbF;TLĄSsT} NM8+=`*Ӂ]0Yɭ.ـbb:?ZоJ˘׊Z+38Et,yݐj1BT=*dn9":YC}zT8aUb댐jt$?NqֱZcl VbpGF*6<ZŢe/\R|=j0zX9GjQVвMF}G;l/<ՈeVm28_ >*8`皅惿~֓=2}sY+4}zWɡ.]'n4O<4QGT؎n= $U9ztL&gZ@rZddf:j>qLA#ޞ!䌎{Sׯ^$@S !84ߧJ%AtQ^HaA!xM9y#ǑOH94@p*uG򎧧 |kdDE0㌏ZWr@5Y[8s(w,`~A AR.DK TejWI!WR@ipiˑkeloY>Q[jeo XEJi>^xt<OZC; =?:zSc##=K,"X qU`A$ⷌ[,)cj(zJmw\/i3Mi0QN&85"pZ Ԩu?Z!XpF3)xǸV9㨥&ry)'<Jþp)&0|LR_^֢qSpez*ju>Ì֩\ܒ8c*]T}ᜐ/Zp3Qrr:D5RtpjgqUGS swVnOJ^:[xb}q9~QNQHtS #(O p;DYu(_}]Qm Jbf\dBvNZ.ZQY?IEӱ\A>š Px>(3@r98H=9ހ+}-=qR\&[J\c9qK{c%ڧAT-F 5l(8~u27Z4}HBJ1L hnzQf~`7<0'{zԠq14|RJ>I(NO&}\;P = 0uҞ;FxE*c=N)3zSi?:M @_zoޚ߭-K3V#~8w6NҰ3TPj@Ns"X ^r:оK"h$w GAPF0p8P1zQpPq{1y⛝gVABwObʶ[j}.& L( cW=Fވ)E~h@A8$qR-Ԛ%F% SmX4{#s3Y`>jyƪ\9MtFZ56V #V7I}[9q׵k*)%ax,W "rڱR&el}7{HPǁҫHN?ɧG\Na:I:p;:V"@h*î@泌N;rnY3[@T#Fy\:=8/I$RW Vap`ՑYe U'w^#Ɂ׷TL\4rj4*6R{`I2jc=xpGJ턚9dܯ 8գ~EH vLg'&}L0nۚnx<qC>8Z$$QUxrG qQ9ϥTea8\KryZ؁ZQ҃VjN;&,VAq$yW`pX@LpDԩ G*iZpM8ڧkQ"F4#vUxnB=)cqWFҹTQI\G@MO2(= A!}݌|=(VvWti`IÃj)b隕vӭl%"cVL(#=kdxbǴ [*V0i7s6 sйٮӞ1S$@='WK+Dpr6Rt=+bku$bRmY-k1jxsWߑzSq&lШ{VbwtJ(]_F>%֬Fqcuue>D7KB&PjHc4QBw#BnAWTжZ5@AКWTq>pkE# g&y~2( sU[*Z-u4mdP94Kߐ:V@b<֒Ef玆)IR sSGzhqץ8tY l4㌂3ZN8uL͒4{J玔oִmw$pئf( UOmy5d#5UFjHi+Y vӔws:ѻZdBHX$qXjGS)F+XHq8tZy6:֬;mPF,HdUVZF89lAAYvщHQJz şNJz:Uuf'rd]*f#BsSr12ZKuɠ5H\6@*Mw"1hAM@Kboʺ ¡AyRj%Ŋ8w4!lwϵJ"zP:hblO԰[8浖 85" ߥZá:|V( }j@vZU8jEbŽƤXjQZ*i\1¡NVͱ8+*˞qV.@eı%b+?\L$9랹5<'8_isrUGnJ >QZd:0=jDHq&H9Fz<*CҴD\Sv 9)<Ŀ(Rgj0xԌK%ߚT5\7<,M>q-ѸNSԟl:LAm7rq87uI*%#"AҚbsJǧ<搏Zd1= 9H1zs5E 3b6F*tOSz9b~~_wˊN*Y|R8OjAS;8LP£~})Ny|c z3G83j皘1\{)H'OGJ3Up,G曷 H Rr* \†hOcK}ƅ┨>P!t>F=Y4`~"\OJj ș:  )<p=zS )Z:g9ߚzӿwwiRqg\NI*Cڭ66qUseDR3*SFy$j3S/W*TjJF>#B@ 1WSϽ;q{֚&NHO捧ךu9@@q |@v3G$M.i:U^(3R/w~7B@Ґu:r@=A4梐u9pjݚBpjAEYuOΠ29'[zsn$)Hq,r5 V9nT];"|/MTS%p} KaޫFqJZweHsNU7\J,3s@a3U}iۯ"'?( ~@'PIZ745x)a9YP8ʁKs9C)qV8%cU-ͩu< P;cОGZqDƥFˆ\'qժT9+AjNNI8O J8f4#J"2H8NW%A (.GSS~CIbN*ʷFTX "Ɠ' gۊմ]Tcs5ӥf[Zƻxn<X**V2=ہd3UciÞP^UHqՀ^1I'NT}*|N{T7S.'"6LWa#48*G$Zr_Ke; Bs)FMia&!|lSZz.Bp=)$W{!(#qRB;umVm$4s '=*͌#f[.Gj# V3F4P'2,r6Ar 3H3zl3pې= q4w֣{ظɥ#<Ȭ!pjH$g9ǭW+b?9":U(dR~oRjBw(䁂sXΣXL͹ՍhZJ0FzkNH' (ߚH$cך{yҳ-jeQӞ*oG%Svhr͸:[v=3ک犹n{N*dZR~Bݾ\zUdgNkFlp21WẑL3ӽO>4r~ `wD˕9$D g&MvTvqK<2 矦+43@<]ʝ~V z溣#)Dgz͌LŽ:ՙ8g,pM)4gœq޳lԪ#n)zjBt:\L#Hd'{So(njT8&^:dT Th\oԐ*hqpIS{H .2*x^vx c*HϹڪMhdZ\g u4Q]i K20*$ djHM=jO$m<ғbi.%lɤݓP>iː}1G5Ô}sNC="?SiCz1֡>bo8Mv&nSOFә1Mv~Nj1c4"E8I=iRZDvU;1ssO^樑JUgHy#fۜ 80܊'8S) \ڜ{xb;v=94??6)ąi#=ix<f@p=jeU2OMRzA˭hbGNK\ך4>!>ZqP 9xE1L?HdwrjE1R/)M 14@@Q@ ;R)i+JRpi?LEPw#`8=*)zՆ=qMeh9"MZ  _6sV(=a_N1WJPT~4M#'RX ),o/zXLz<28J.sW({V,ysvI9ϭrզ\'+3ӭQQnUcpks)ȳSFF&Joc6qR$N*lK5!dx⧊PISRG!lɩMc- =zR0H>m=8Ts/yZUn9j8fˈUl*z  :EPl~2* GlXVR2cgSCahe<52c c5"ɧ`NŰ$fV;=UiqQsls֞OlUcnH8N繫PJ PZʊ-0r!5J?ՈwfH2:FN8k?"E皵֩8VPq֓lV, C&T\}36R傍Z`X\rM'znZӥ}iw gjH*qMG6T9^bYLg\ mnMVۜYh=jPqTՁG&ޜS'GF21MA$'Z~*8kBЍ C}Ih m@=`Rr}WgQP1 ]4T婃axiI2ܝqWW;qYW)&޵QUoӥd~L>Pp)M舔u#5JpT#ֲ~H#qZ$hrG-/Qa5Ҭ!3U$i v-4vb9L7&qҜ$Sd֋̬^2f dYJܑҬDezJQM Sx<J/f4[3ppG^z2æqJ(M/֞pHzzq Yc9-v7s(ߒOsMBPOsRgZi۵H3p`hrN9s*nqCV2 OۃNEJUx"[:Y`u 4XBj :z֨C:PQ4S ֳss<\f!G48TwS;PBrpgy4P͜z֛#4=iU:dINKehK$F9`Lrzw)S4;JQrzZ-u}D'zVpa;Seo֐ݬK ݑ{qT3rjh_t4Ķ$~v֑gقդnȾT(jn00GWc%`p=)K~5dQJ1U,=pjlTzposPٗ ͜ sdvU;; W{㦦;}MEH9#5إ2&S3PžšdtPxF8P3J8cZWN94~U#o[@jנU3)+r>C@׀)s\$ԩ!N3UccӑלUňPs {RәIJbW;'jnJ$⚑$$}zҒ@$\󞔢D9W0 B4hǧBH*Nh:OƑTҟ隞 %p r 8j)9js)>tE&NdƥTǵCY ^iY)8 kBAG2&̲"VYI&O⦎R=E/hi=\Uvh<ӥ'B;SA$ς>Mӯ5 `sl(H\6;^sZKg)ffۍӋӓX0qڜ.I={V4@9f"b{:PYK\8DzRU{龅Tv HXNr+Lj;dc I䞕v܅lyϧs'VS~WPjh\Ka81E!VWN[5`r)N1Z̀#0ldd.$KDZypz)]fld3S@x4q:Si~Q'֣ҥ\p:fО3ɫ08gX$*eبh8  #=̀3cA)Azh~~`*SU)'Ǯ}(Vl $cb,Fpr3ҥR1<Й8IO=MV$Z(YmL?9$TNz).f[ߜnÐ3g5nہ{h&, U/US8%D=P<;Sԁ=*|PEtSן\+85<&8`zBHDJ*b`z).q׽BI&6N&ǩ<֤3PZۈxҔsNEjG^;fΘ9`L&ޞ +#I"@ScJ|t"鏦)iQr*M8?dly=1Ss_ZqEձ"ԁSS`"SDQV`*L0< ;JD޼r\~n*c||ܙ#go^8J9:T1@0=Rv l@㊖498S3 #ROC9J"f'788`N(t\p{xqM_9RH RdۂۊzTdgOZ9\ dQ5Rď{`H=r`לUFyʭmYL=j-ǵDCzS 8=MM~RxZru.Ő@P3V!`U#Fj#[3LzS[gezUv9lֽ )cSwH:#sRZ#:Ul֧Hqlj1;1]t6y"L9瑚r M`D[kn(Fj6ҤLgN;b8?M\,0B'C#yI:n]hQ18CN ʢF3 -ڔ͚/(WAќ֤V9ץ4/Sq֪%+0 ffO(r1i=jD ?֘Ď4tnq*yd;y<J|g1Vg朖qG+ 8"md.dT~1Ob1Ցl{TC*) ul pq+TQ72{u|~U2hD2y`zqsl/3kr+ ]HjLx'8?*.&1ީHTNcH-9#v9%5cEhV=iҨb K@O,|`W} {?7:1 iy曁)݋A3ۜ8wH<`COF :SvUȪEnS!UT\~"Lֵd15 _{<*B 0Sb:Lq'f-*~_zhiN}HMWM9UHFi SMSw֣i?f4u#*4֤_Nx%N4y3P.qЊCWZ'N8jHַ$ 5 =iŸ Y; ښ[ր^);q@~ sRPwiGZq2S j6n*249>=(iAӆ;P3sIE8斓>H:ҟSԊ^بGZ$.9:B "@C9;i~Ghߥ/z(FZu!(8 b: &@*Hи?3u`4t(b>GZh3J֛|ҜP SR^P(: ?Q@w (Q?[[qc޹&Yk ^Z{k? B*ROVcQ)<\t>#2Cbvlz~5/֥^4N1qG3=+=Y qXWqz84.cU^qOrp3ҞIlUiQ㎵,mϸq]%6ʪMK u?4$ԍ68NLgm rFA9-̚5PG=jL/gd#*2p@Qpɧt7#4S(l#V!Ajr=qRp3JlcAX r2@fy(n684V'P0W!@֫c94}ӚYCSFx3AN2 $gfs*Q21ql D7BzS##>(H*Q+:e&5ֆݙ.OzEF`sG#>iUU΂ݐ 殬;U9{xhFD]ETpF:U:c|A@✪hkЭ LyjH77оRgҥH[M[{qSO7pZT*Q1VTe$Թbp:cYGPya5=y=Gg)hTbJֱ;?**f-jliURw`gb$ΥSZ+3بҘPhsiр9:͕2(H[`h3jDأ"Ad|pqVut+Gqxz;szSҴPF|Dp).@"('?)T9RFR=y<D91϶*EC q;FIi;gZ9;'iz։x Oy?+!ݍLIڟ#@&v Jz>;`{Z'H=VV>XcJZ횫 teq3(rZ4z>89S[Gbd8qbhҵji ZO=\BM; F|q1,\X6{#ZC9ޥ&AޑVpOPG<\1@Fdt5m:9aEj~iZ2׎Tq֯H4W:]'R)"y}i5MS1QPV Z7+"ҥPG5*JrǵRBF) 7֚$TM;"1"U)s2HȥG\qJx*S3 )\T{Nzb(]杒8d攭iY@qJXL)zN1.qHXר)?Ts"z|}~NSOޚ`L0*==)+`tiO㏥2=Av0RP:E0cU{i3ߵ-yQCq@3sޚHɦ}֖rO\T01Q'JvxSuANNR9czўs 5}(b=zXKPB}3@Zc}i=K=hhtqGoz(_*Gozp#8EGNCڀM'44ׯ4Z?h(- <ӊdJ(s@֙5ߑi>.q+b< z@ RϭF28J/ϥK1E@BᶬO 1WɟHt_V54GА1P-*hjz =Md5dSz|sRFNE6rG-U=Mgڬ#(kZ8r*r8@1EN5Ա 4?Z1׵OjMv2@sRvUxbzQt)H> s=)$2.E&^1O{u5KpJP]صqV`#5@jt^QG;MmO~RB~qRd:ԪBs_Z+jLHRlG`zb2Z 1RsSn]7~Ow8^zӡbqphhZq0$RJωޥVfѢyu9V`lOQ=*xZQ& ]o+ҬFwY汚6<4ˠp3֨Zɘ񞕚؉;K2 qpsq 95J) HPgzE<q)TMZZ&F{Es֟֞FiĶS;`H}sOO7ԫv#H[a|\5/q8Yobl),X"tjS0NhRd]&5#V ALA Ay _\R;q o\Jq(9<8pMT˴>pXGM]pW0sTG\3Qr 9V"=R1STvBH@=*XGLipMNFEM`tpG~8+NO+\1 =*W|sU(B8G:Q$M)cP֤5VQpVq6! >;g^\ jv=(.N=IK"^is)=+R-.쎽=)Tg >S{h$)^x5֢q#& EtHn+NHc[x;x = ] 㱩UU:Rb:e$YcR<@㑐E82*.Sv'l Aw(L` jAgqKuCR(9qTL R1j L^A<){dc"E PocT1ޠ1ߡW&#"~.xR!?7QqJHےpO ?։#/NԃӞheqj &L+u<Ÿ"0K1?_ZWU#R0kXvyv# t*5~1)Q:c`{$╔5/9$sF}NJr6Д8-yr3ڨV OV8Jv@f"69?Jʧ۵Uc94nA#W0I|SsҤ+/5{֗І 4vM3S|ԂչHO>HHv3Rn5=i뎹1"=q&zRG^瑞i@׵MB~t)w QO@m*21M9#"d3H`ri(Qڜ01n@4Ю=zڞ8wsO݁ןRdbuF {Q.[d}jb`xǠr')H:%N[a8$c l?Zp8l=aOZp8n{U8+ߟJl_<֘4cIϯҝɱ/!)ޛU#94184#\R'O5Ex#488"0G:wKdԙS'cpx4c#ӥ&@ɥ8@=)@R@#==x0M" ~֣Pvޞ:rj`8zw~S' FOjU>׭(1?{h֛88@y ֛K\=h=I'@=ғ< g"z@=qAP Sޘ:sNCpM-})WJ@N>Q@ <})(oj\ǵ6|gTJxw~G<ȡϱ=TbgO hRhph`i#H染L9N,q=q4(A+Aw9,8S {Hz<Jhtd{Tzcޛ$SjXJ֥F*88 5,}0VNg4DdT0#tiňut0on"`j,RDTd Ig97py2[,w5";U@y#zQa)X ЎjDv8RB zi10ҦNNzsT`?ʧ+&j Aը8SGFj5=) T8wڧf{rW oO֪03r} alHG*U>[} /^T}[r* ✯9IX+oJ榈uNXCs) 5 =H.W!":qR`gNsHO@9IҰQq{SS2AzԨ1P$R4{x!>2H"u9l :S? p9H)IOQ>Qץ??1Q1构ʪNC`U5lv7gޥaߊ}B⦍8Klp;E'vCRlI*E8=~])=X[BN}h9QcOޡ8{DHv@ls֠F,l25VBw& |zE7~0sqN099=?yB)4J1qRoQ*_1'ݑ'[91J1!LZnsp'S'5v '\~0a*8"L`E;' tQYԃNnBtr?J9U*cޢA'b7O 8Uɧy(K"NT7_T8=¦RA$6 RVq֩Q}4QmX4ST 9_&M;S8⪫ p{T={Pw,b @N"z,/"ϙ"ԟTSԱ:qC,<ڔ?=sQG'79`sOSӞRquiwuTVn䞔A }*X R!p)=h8ALAqT RdvJUܵ~'ԑOSqMZc8Hxj9+7E>6⫫saNõ,NzzӃ`cX,Fܑ۵HvVV"9 4BڿLւqu$/ڗqM Ԝ=iN늀vvVL6~L< _8<,+Fip UÁp*r:NUO0pwNW'w%d#8W?/\*Doy=))u. `s^U=)LB(n1P:r7~] Ւ*T<3ip8&#pM 0 x#)[m)בO pB>^zR=v'S֞zzsIа֜6=)ONӶ%6xzrj<Ԑ:\ĥb8y8PsO zIlN U)\>N3n4;}S?8qzS_0ː8%@Slq2!YN~n*?0`OIo9/P;}Nz .,(Q5䑊#qRЖcqL zcz843B*M8:NRqSd`T'#z- sI^j~45jbQ-! H'.NA ⩙>\{Rtiĸ\,2{;m9# .I1Us=i9U)as&NzZ$z171r;8K ^4S.R ѻWy#]Ċ|-pHjw?yRR6yqWV9Row5"yI(ZqN zs37#,0F{vwĚr B1zw59XԃUp`>('m늮bZ,t>8R!qTt&FP1BN85|X^*D &gcގp>[zsN.SBq!qSrF9)@$AsiUSO3ue==t@3qUԓ9=H"ʌdS`u4])*<)@$/hǮi+ >qMLvlK߽4"DbSҥVץU-ךr6GRQ;~F \zG98&vץ0=(;Ni\ C{Pgq֜RoCUQW+څ?7~nNϾ(OuR x)aؚbldžNuE?pi&qJO`j>N_iM^2E.N}jabUqnu0҃Ev[9M|iJA֔rKH:ҔVINe*S899 s*< r}F#&~@ 8Lp9=h=>=sښO:н^)hu1P{4 Q5HϽ:QAn)IրNri p:Pn9~))A@ )(=zi%!i?.Gq@4>9/N Z\LRqI@oZ3i}sSOSj<~4#Zp*0~QJ[ӏJs7 爴 nM_\O`,=?J=}ZDʱن: tWiJ=ޓ>ο+hQohPZE.R-Ji HS|/iPRI8 q3(Ԛ#Z U8N Ir2+ñs=Ьwc'#cȩѸKeݜ)#*FޤuS;3&jXpHS;2zje[jrj\aE$"sNa1WACԜTS`::T܃OZ #5*٤f,MMJqPxS?$Nńl/J82HI\E]82>sITNAmsQ8zZwuT=槖 ԁĎ$L}sG"5&[ A=~P:X mpi1U#Zss܊ieaiA#3Z $䱹f9O<{b~@վUSqAW,=c?Njl7&ZA4p ҩ$&'rGaNrzUu2O*A֝-FP3iTqץ@?zvSbb99p*`8:S;:*DlýURzrJcI"e[3Rl֫)#$W5qx7yңa]gfe)Qu'97~tX8R=jt fN7NZV` |&ҞJ,+s X68SrҾNG*pG=f[,7a[ b8E.sK/*8qN9Ӂ0H],8<ӢnxB[4s5qMg~N9Zw%XzO93jLrK(<v9C84گaqҕ$žqU~Pd>a)HFq֔w# |гOSn:҇W0Jzpp{҂=y]M1Xpրrq}j=å/ +1tj?.GZsgnlU:iRb$Rpz8#9Ԝdh8cU|4R6%Όc4wW2bzc-3w)Ul89!q{Pj`~d9=.==)26hVh[BUhw`8=O"M2lHzq(bx߅=ߊqސ<4=x5WDH0?Ɯ* N<o&+ 6*4n? P&hO֜94q\±3_]oZw `Jp?:1JqEURȨ7wWGz"KC$T!8M4ԂŌtgE;TO)!8iC~bJGOv&j )sKV&SK߿JPF89AKZ?dMH sRQ֠s1Xqv:T s&C1ӽ(?.j<<5"lHE80JO?/O2usP֕OODTyj4'u5IVZ9OˎDNqҞ^y38.N "lJNREh'|O<Bw<)h8 (NFJPNx9^;R}M.}:Ӹl=Ifv$ZPFn .xお<zT.{7<ڀIzSS=48c;%3OGzSL-GG @sM('!qE/AM:U&;d})4GG0K٦>xsM0uIE0zvze.{zPdLZFzsQq\J~>O.s@?*\֊vP{s@gsKL4g.N:#R}8h=7#z3PiqK@ E 8Z<=y)GZJ(@J@X<`\cN4GqFG=FhvE&@PH?ZZ Q@ RMzp#hO`Gf,g+̯ӧ(T"ӿC//G3$ڝܓM wlQ5J KMu_,xZ5{0; >]IMyK>m(ʚؖiP.qϙJx\L⪽z !{3ӀJ:d0}ѓڜAڲ:&sOSP)=*hz!xzTpH隅pzYU`HަEqMPqdu2mǩN0}*h3"N01?ҫT@P2x udʣ |xޢq,ܞ3*PF>_¡JØ=859N烟J'U~2GC3$JBYBSQ5]K2:S&Lx9GQQ=ڐH<3Q1N_Zb&vȩyǿZO26U$LRP >#h+) {T֫dT&Qc?Ҕcp`횘1STɢ늑3J=jh̼ƤL2HL!u7 Dzc<~5 m_J gOV O=) Oq5W2yR.=90j~^)Zޜ:*v0qSџ4 OCwVϥ)1(,0zSո2N@#LgH& xҜ$PçCNSpxKp-FGRqR㚩qXzⓉ7YFqԠ`c>Q[ Ԡ8׷8T)UOa!8TP/zԁ9jl:u5L z 0yKVN1;b]}*?.;椋I5 X:望iMK:%uӌӕj68Fy ҹ-=9ȧzb`@d;~n+ BX zԃJyyYaN_01Pӕj;&FR8)=)1&A֕ޞ0¤L#bϿ"5&z~T [=E@5"ac=8w䫜OJGMDzIq;v'OAFbp@K(#Ba zg?QBbA^)H91H +2:МwjO\gD/"6\;<Q`L =8{PpzG㸩H[(lg9sT2'S8ZO-8}qU)\~e wrVG=y)K?i Eaӆ~][ޞE;2px(bOQ9zaO9yҡU`8ȧxއoy,ny1P;vtIaX/9+W-p;S:GX G}jHj2zS^Ővs=_U@yNmGY“@XcMYV9pn;U )Ay"pݳJ;u;s3֟1֖^ldR+ߥV3JNXW֜f@E<7B'S<1qUՉ.2dXG ә\WS )y(b% r9<;㎕8lӇ PtMc5nx<);-á.rp Hc#~@X' )WYx<`(nuǥ83ڠcqޜ89#4'$h;7Ɂ֜8a88c)4tH U)@ P@5"lJԚU=BCNSjbS럥!l(f?\xIIɠ:NϦ@pBx,EpM9H 8^8p{<7QN.qg.xOw6ֆ *u)|gQ@*U3~(b ݩNާD;ޚbR縤vTRȦ֕x9\Dsv@>J=z3ZuϽ=i ău=)KsLC^R}3QzU$ gWS =)A5IQҘJ8?Zw"Ċ~QקZPpO4̟ZPN= UPx*<})LC?Zp#jfN"1UpÁJ:1O{Q ֚O@ۯjrchzfibl?' 昇NJp4N_c0E87{Tyɥ&0:]PqQ0׵('SNCLx<Қ8)œsL{(()?(zP95?Z\j~@=gc҃Z|°=)xN)JF?*NQց 49(/zzn{҃Қ`;i{f˵ y8AIޓ< f8Qړ8='AqIE}7p)P9?\S"qM$AIށ֣J\S2;g4ќzLs׭ <4O(n8LzR}h4Q@'>g=)yKs@'SzS>sӷ:&sZw;n梺!iGH]47m@׈ѿ)׉gIolG )f`s?~[w,۠"Ьp,#&m+ݚBJA\y79>jD s࠺lWV^+BC__~!k.Y BĚn%7sq^}lr(N׬}_n;-~3^=B|t/+ľ'aWJKQ,#wsUoe-4 9C[+ԨݤݾGLpT/ڋC"RwuIHٛ$5_o+:TƩ4y6֪QتnVD2Hfcm s$[3Ұ/JU[2IfQ(;Vss{5[B Jʼ'\jn8, 9uRqЊv(T)Izr>"G\Յ^ނHN&#J =X&Q=ԑ JHZobh EH TR\88cl/S>˚#NbtzTp?I sGOcU+j`:g HYdչ3Jb'dܟBx@p*8bZBH|urq22sS*=MBzڤL} &t`a@`'O=Xt 1Rz):㚖mMB9OЃbRyP:T=DJO9OO΢CR3R_Τ񩾕ׁN^J3ȩ#psQF>QT})Q4|~5*; ]3{zgLnhCH"U?p>1IC=p)!yƤI@H} O\RL8=~~^8=i,)֜:|BA=N1 ]O^  'o@0yR?Ї*L9iNBe$OL5 |w.bʒON'ByH:}DDZRӮ= H$&0o0lp;IB֞8$GZZ t*?7ZtggӶly#>:T)qFr3H,Հlob[1Jd{p \TOJw g$)"Tl1R!c#5'ӷZtd{P;ڜ䞜S'DNǵ72:-AsRHzҩG1U4'&$ ^վa cӵrfnzӔڟc+̘xёרOoZv3iarlץ;u&= 2S$➭ )PH;w;ҜO3QF{cSӚH-t5 a5rxJH+/Q;ؗp=8~}*`iއ'"3)I֕qbW%yϧPu枧3Ґ'K 8)Jq{qҢI3LCԜ=;ӷ #={3d;?8 NviaяN;qgCsrqUryX@Z:'94'< M&Ȫhx$q)펕=Fiޔ"E_ȦtSV&(SN=)8ցy<ϭ4|U&uMB1֔pzӸtOҝFj`y1T!x&P;CZz0*&{҂@8!'zw$xX6|s`~_|q54ȴ%zž)+I1?3eNJևU<+7:/.$VIv$5\{;J䧾Ȳcu9&J ziidGw8}OtdInbpYR˸Wgت8ޗql'дSm]#;]:"Ҽr\-o.~!\4+|c #ִQ̿k),=0*nًuF7ڷ~^SbqF .TguJCNMLߚ$jx qV ŌpO2:b)T9+h,lA5A=q9*U9#p*E?/֋hRob3G*XϭU`J6 9#IRX9=CR&=t*AQVړzdgpϵ=j@ӵ.F3DԪFW\dZw#o=,XLƝ_sN#=~yӽI9#ޢ swj[iAޠzp܆ ReH)ccȪ;չEȴi~~OZs籡IZHqXt?>UP(9*8(co0GHsZ*AI-!AO=3#0QT۠sNBr9u?6@8bwxz c e~zz8  iA=*aךr=:zT3UZ[ :zb`qijNzJ 9$=I"F3U'(nw%c|;r  ө֐YRzr_«FqҤ ޝ$NIԎ'\H?Sш.kaN > 瞆N:pM.N85&叵@  `sҞ?PPoBp`gv81UЍH*iشmHπj@ЎR] z 8ҡ ?N8=? KԝX ӕUi6yHi#)O\glcza] gJu ezғ Q,!wjgCOF*l'mA;T @|P?"Q}){ OySGcJdpbNd nRh sPv@NE~ӳS ԗ"~]j88SHQ1ST6%is#[$b0=6H2piH%qFpj2S@ӥFqڕ9:!\F ҩyq}Tjzv)\4Q3Ӳ{uI"@!$9sS3RHnxvF F zU) yE1RtM7{t1D (oM0$'֍fbaF:ўNJ0{"\.H֣֕OwLI皉X.F9<ӸJ3ڗ<5bh^O^@v.Rb)A4{G8;8QKך?(ScҘs.j2q9x?(\`19O:pIϸqF~S֟0>F S3ӳPߨI׽Ҙ=OJ7si !*6>ǵ<n)A3NIy`94 p"zdaX/(< TJOwaؓ#׊ FOjGs 'TEsJץ;4?>4[]hSNx㎴y= 3^*0/֗pu$Mƣ/,Kץ9,pyLh∼$h8$V,ҩjpx==iI8- GPtH׭~E\1x;Ǿ5;G%b+\x_$)Pnw{յ? jzfk![/~p_nxSW:~eous)VP}@_^$&\3~76w'FQw N7?c~ :gZ̐xP/h=:WzIJ1v !>Os7ق A4(~~-a[>iFw&g]CZb+Ay'"[(bYzkJÖż1r{UT$C4/LKh96f?ʠDGNK6#9KaK1Q˘aצG=hm0%$#Vݮ"V2x9Bht&EnxC5jƳ!֦JL! qS[0q[wF3ɪ(7d3PqjXvRQ7r*:{aSCgޫ! R@&{:#>n;+ALĜUxzSA(mr$dFs#Ԋ'K\?0/@: 朇{R]P5"`$H0qRޫuyzR&L㩩dpqQGZr' cJ;q^6u5 a E8) ֥SJhXzTs2# ܖ FOj<l'Ҟsb2sҤsP`朌0:e Ԋ^8Vq.s~/1YqjD?(뚬*E}kBZ,)Ξ "evRAbe9 gpV ҥB6UaAO"g+t,[iNU#֤)C ԜwVGcu杆ޅaҞ:TE= ix5"pV6v ;hX =pjE 1]V:M 2N3ߥHzZv$w敄[ r1PFp9<"BX2zT91=Jbp$ԊYX3ԁsӌRkBa_R#z;Px8NH pHhZ= K:*6^=sN,zZEBۊvO=*c[h$c4`qVF=H@Z@8'3UCr{2ZVIW1RnsKqX=@bH1U;)~c :wqԊxp;P;AR&Bg/¹lr)c7#ri' ov89_ : q802*Xj[/{ j@=ѸjV-z#sUP}R ["xTI#)3SO]8.rUC9jPۊm0bʱ$❸gT7͓x|㞴;epH^[p_֝+u=? CzgPAnULޞqNXSzSYdOJrȥqRٓ9'ޫqJ;ص8FGnYIFir ϹUmTE`JD\q;w9<0ҏ5qZvcrڐzӲ8Njw@O)'bFA43b@ ޏ98*ӭ>F.t]Rqi;?FGnM>9(Ip=bܲ@*E|?&ExR qݲo8/>1&O=G-&%'ЇVY|6^)}@]Brc5#1OR/w$VpcGx Oj}$`bVO [Oq49/ӷl?4OOj]gM'+ymLH?Ƒ1[o?ƚ.ĺQS޵ D}> w$G9mj*^֝g@txEI,WQQx|O?JJ^ڝgRp?:U=pMr_{H8V*?ɖ&Gf)8<6ҦWU3|2?g 35JNsݎ19-$?,,zLqT{:,ޒ;āpn} p|)}~Rj<(O3=**iX=-On{ךP~z⥋w&iԶļU-H }A'Ur>3P_ 񋙛ЈW2V&sԁySW’|۱H/ mg\>\{*ٖgӔ+ɿmxd\Нoj>0'؟k 80Ҽt|`6\8Ǡq ˯b1UU;bsyKzW/- \bEb8#H}ցJr6ä嵕ﺝ I-|] ucڋޞv<#I=[ɦLH%>жdS:׆nܵrTmOmi֪a{Xwpkjĵ̕[4yBRgS9r|dO!p.j|iؙm9r#BgΜXg־zyjWN+ Қ>3Jq:/wECsGnO>zΒ|c*Z.M4|^ *--4+mg}*_Hحbi[?d*IAJvvh9X ufs־q/ǝ;5vꠓS`һ`-Tr)V|{(k &Ӆ<~qp|U 1;~+xeKD2r%ծcg4_0//[GQ,_戂#F# CRkcS?^)@հcMV'L\@u2?:}%x 3@M7o[@ XA)ZwN0~aaFjS&zeK )ASx7]O||M mиb}TQqIJH5YAN xw q| ˶5kGrj+#r3*m` = |z>"QQ)彍:?۝Nk!*rbs}ih^yQc|7|Asjܚ>Oͪ]14B}&SNTw+']׷sUgcxJ9AAPqWƉ?1u}WH>CMbTWgٍ2t:zMō n)Lm{u 94ZԮc-Bɭ>}&qIF3"Q.fRa B|SRe9bN׹:} 9Ԟ.o'8x68v<_{Fj=W~95_\?Nd|CiD_J)~8c܆_0}&G? g+ɥ@& zMLqukկsU~+݊|W Jhޯ%xKpI=*.HbnxÇ$v1jp9{OIjXj^*ZXQEϳ$#'&Qφj(n\,yFR8Yzmpx9b1Bb<Ђ[k6E=ʀN |nS[\1*myۻ=j~7'% ʈ|NGWs%XP}pH.۰?:WĽ.t-n} 7!XӨQvPE[¯RHƿ:"|h5i,.u hX~q^WFTѴ%S6%|M#›?Xn.xR+\IOaxí}GY/\faK:梳\jڕ#~zRܶoy^&_~|ii ^6glP_rƾOGΨK>?ZZǸZ|2M+oc*JFkgQZu5?Ya#Dt'ę+ !1{+ǭezofm%Ѹx kd3UI_1ыn(Ƥ~9Ay4"&=1eYH}t}~*=jKfi"fX62OnFW,QW]u[,e',N sW ܕnks4eqk>W6}.spzWEqdԞ+e2 OVlQ9iV %fRڕk1 GgUFIu-yH7uO mf.^ֲnVIf+k{tv'Rs&(cUhP 4<+YSrudwFXNME<ȬT-"nxw/br+Tu\111Tt;ܯ##+b(HUʀsX,;&`КΚ^&ei;Gpj[*}j瘖DdS+_A%%65 ȒFsX׷-:a'&{_my\N*ZDIMze捣V;'55p\$Lz޶ѫ-XI:9^ܗ=%qjJUO<TlsپS)9$*#U"69h-׎Sҫ!=3OqR4.'O^@13Ҟ\m["΋h20yR '֦^½˱FjP},1J:zu4MqIp>U\QJE"I 秥Ks׵SILR 4X2n*f#0iJ9h[^8bnZ$ڣL3e[ ǥJqTb%fQyR\֥R(x},n5. v>:ҞR)Sï\1P89i8$;㎴(ԏC孋ўȧsE&] |s`iُ➤T'@}HsE?`uBUcy?:qp7bn:j`0G:+tZ Mw4Q'$w c8QѻRО$v5Vܾ3n*E 8 pR{FzzГ!U.=]SYs.a?/4Y▌JqJ`bEޞ.IS뺫{Qpzt=:tc=ue@M=SO8\u>69ہ1ȧ_>,w 2kFkn8NF vԭwmDy*TIVkʎpGYKZ VG 2Rfo㞽T8Pr} jzgN?m#isFJ~q\-l>?tp7RSkD7ӇQQk_yF7 E&}~[X>M߆zX޸:'l5c )<%_(A}?ex|tvqCKЀVL)4WIxKɁ֦V@⼉(N =jH~(e9iTWYaJT.F0Fy*Rqid;cn [G=^ӒLɊuRŝ$&9yb>–|ož~}⾚v ׽#|ZV>?Q{Xk#S Fq^1[8׷,blU'qfBَAw݊gK{3\A xA5r?ycDvOџ_ٵLA>I: _<ū- ??_ٕ8uGApi(5 xG4_Qb*F=ۥ=dk¬@{&0Y{vQH}3i(#5F֔&ke UO*5o$q{枳Y66JÊ|Errd :>?OUSNe W|A 7$ `*9> d^ʨ 12,@oBjA8I_0 \At 'AYL]#[F1NYUN )־L7v?x[+Ơz_S2r5,3^\_!o 4Yn9~(ɗqDPqNHxXf,o=)Śk=)9厞>K35sQNKA]G b89|A3s?йC{#OUt)b-3<_7 f$M6sy$oH5+Z<­H!5 b$=Pu Lτdk1;if|vi0cRZX:֙fm6t+6Ԯ e5( h]dıCu7t)_:ZװMxli/,8dUmcW^7?t~(щ ^< A8O[ʡm1PF0=I}||..4$9Sq}K^4_׳$FY?&TvLeP{ [9@nf>vghL;dLyp;SWNA>};i'cżR5#!TijJT#tn$_lTgow`N{pkVi F}Y8vJH.}H>&xO D~'hKw#寘v68Ni&Iym+hXL] S ޝ- a_2#tU=j;sUI쉖2⦎[&ǵE/M,?ʒbn 9ǥ.DbG WOic4>+eN+"x'>1_b+|G f-|R'śpN6w_?o721! <9^ȟϛYh{mj{>.+e=2d0$5 Azu?gfM6QzŦ`u&N :7o9jB .q &W=o$eaGoȳE g&@xRѰd1'ߊilg@qg gM6oĝ6Mxxtp>օHKuY3T~lSW' u)?54m t4 9-jvƞ!w &F6$D;\,UCI֏`hԌt'!dv>gx]5+'ڒTL`y ֊mc?hOXJj NĺY|:fPrc!{mƥ{柰Di:oIuB6=XĚz5HpxE*x/ u9:/.v95K<λpTl'ki5{qs9oJm^47XzlcBtXԖj~ȇU%:85 qdd|֢SY?P.ᷯWr :Q ^_"j7LcZD9e5i:J㊳q 9U苲W`<҃sIos{&|v95QWwE6v $ջD6*NInLTWn lZ,~Do/]Jk#^Y/r,6,Lrɪ6ԃRGu̯U.ƞ"ah1OJdwrg$R2*neP'&p#oGoJf^.3؎Kr $x߷"zo ${8j=%[$@rjKs1@}rjLq0"!i*+bf3iv"WVMfc)SZτIcT;;2י&VrS**q+7CSfhՕ`76 Eӯ:I%Ϡ^2Nj;R\m9IuTmAΧl5QCNy$8#J߿qEC,WYö-zj/-7 H5`ZZXԞ4gg##݊@ѿ:f.Dm Z&rբ#K2̽3~ni!)$$' jüy>z0 0QȺRu@o)} 2n@q4ox4qJ6JǡT?;#$ZP 㧭Ev= )#v#5uB#C3 {Qpi9ZӭM96F\#UR:m]V$PԲH%lF, \t* s c!gy0@٧xv sIAPzCZBхT [Sf>]#\+`krY yj۹?QБU;iRZ[j>F^d+XII?"l[:e[]ۓG&soq} G.'䊺e3+`՝${?5#fVuwxBݝ׽'IdR$ARǑ j$qK8XKuqyՔcn {Ukʎ@qT. !{s=Q?)@*1GcME%mٟj%j/jFIkO[60nKKJ1cԮ{PFEeR Cu#V*W1,*:9bjՑ)A*.Ēx9\CaW0%=W!Xe v-_ZHeHUGI!uR(?Zv-y~^' heJC*&ZV[y-ײ⬭Ɋ' W4e:S]A8>c6##uE#9N[j]/6*[w[RH*TAe\Bvnʱ/CQ]>Sȩ!kSKYˇqM|pH錊 ZKpB NQ&ѐoZim<kG$Bی曎O{.D6FrK+aJ1K,y9SXKbD=OYlTkv)G2wwtʲ}ȫ:'X5oLnq‹sKǩ*3DbKcs❪+yry|` ZEտ,KܫciGt.?g8ft &7j_.79*ͶU,ÀqQa!*^D;%FiĪBjuHդ 2$ o\Ʃc;Q06nw2X.OWoVTʑʎhmV3Vn-Ym\sm$1sZ(_FO:%jꛤs(+YpH&!PwڭZK"R28o-Ԁ[.IQZj7Z|+$ʓɍ*ؒbU5+Z3RH5t:n Uݷ*EYo$v OL6qB1z ȻgAh!l%IE?#>]\<9aV-VM_bGtq5 ,8f<֬mq&W4tF>j%{Yqߌ}jv@z!sfkkRZ]|p8&m.c(>nf[i~W[gB O Rʼ@~ec=kDOh'exS#]m"TS-x[GȦjEM8Ќv9h偐>^y .0ϑQȗl.3qSn7NYd?bjVo֒:@es=fLyy(WP{iqfkYSoCO+k^Zyhk d%846b+ Ӷ BHp*L  f=McoA kaZń"MCJZnR>TūCi ,2"gmD|IVK:k #9lQKrY[W8cgX\)72OF dbG|%Ghc[*694R=J4k}_-H,9Ȧ]\#i:f7SRZ p=*8FYw!`:Ryr2Y/[KhL^[꿥p<g;oS`"oƪ0Fs;5 q._J1tX1+T}kY)u<[6:䚨3*1~؊s T7ҽUsbZ,)N-tDWHwfey}kb\c1U.ʹp۬dܳEa9P}d)ٴbj*XЊ$GP!W`f95{jZ̨F484.hiGIrRKe`pI z ˑ1qݫ, ȉ2%?wNFPSUy.RwwqLn<[ գ) `[ns54f;O*sjfwv6"1I,vݞt$zUrp ziM䝝͔_mSrhzG LH]ަQMWiOZjV:q+u\֗mĿ./;wkICJBe{~Z5Κgvp9WEqԫePք]D5[_GtwFF~U !QҼ{^/Xo`LUj;=j{M" s;#W~:H "%o|W)=9p#kb4j_6H~hj,R6{zWɥ[Rϥ\ɞ~ )_%kf: _J*T/#`ҏODF؛#b$-~xOׇO>a}f3X ~ԩ(9׌1M&glcU]My |O9oO}ЩW~%][Q.#&߷+*Os^L o;U}B*Ӷ%U4}8XZD=yLˎJ_Q؟k.rpMOH\z%:a"r)< GnOU5,#19p*5I-=?z}~TO5?,W/=i`YA'?jGovz~;ׇ&cFcYP+7ہC"ˍf=WZ3s0D~y(%['#wj򐪾} _d /u7+|LOVMto?oNƾ cL1Eq#I:0\(=1>OPuKuS+\z3 Fa\JJ04d #wuzʆ%뇋3RI;6VwQ>1 c5bXpGn9<+]tH-]Npu梷B[wSAj>I wt3}ΌxZ pOj`럡z(g`-1ޤB+diƯޤ jz֐3p4E}OW]>~=}a_EÏsu5.#2r}Փ L.:Hnmp=֤|,+ J#%>/:V4SXvɺy+xxnoy N*Y5L!ϡ BVԸ7E$ZfGfbjŰ7)'ٹT2bߝ802u<'$6!YHjhd4Ö8)gCG樒G $~Uc>[̮L'du5eq#6#k䀾aӞ1Q(Te39 펕$M.Y4j;'$ۭ.Ek ZY&L'c{T>5XW b@tf#`)W9@09;ǷM,C3*c|RiCq5ee7 eAM?ga|ۢxل\7=:̓a@f\UfBwH5˓$ë M- -~}`(mN۪=RDӑԌiƚhUm;J0s5n͌zK$Xh"#1#4r&hY&2Ev=֒p `}"T>LTlJI$Plf%s,v4E6Hb<䊯 IMjsBJ_YpK.=ifVG3T-ڒYWj6늗Nۊ59ff \?!{R+=Է! O*"Hd w]j13zEWg1|\f}, pBroCKp `zqL૸''~˅M7/O/8G]H ܹ0cb(eg@T,54ɐh&"#'ܻk@^}N T13ly=۱9=/5M+Ij  \EUȠ(sY6ȻT烜=YܤkPMn$eFn5.t#R54l WFD#VS*Xc}+!,\6͏L֍FPzRimL-9gz*d(XqȽO7`t;,d;f^;3Vl.#1l2:b&~V&\1ӂi IM)US*0?JnZ7"v㩤H'! *ȊlcɌDC VfkqƢz! v8-wA+1rޛ,Q!A)v o,W*(w)+[jeJ[vXwUΈU'9= p.$`rVB%5q"+̽vm7FW' IG^ 'aHfU#= _{t3E$`sWn4X1>UbbFЧqUû UeVtCД-S#TY׷Qc5,1ġߵU$oa^?QZo-ǧlԾaf%RA5mhq]C6Xf1E* rO+^Yų]2HlsQ^Ko#泅٥I虍!_)5caveHֽI q}jX.c]7"+'s 03;n>9ֺS3׫/ H![\0- glUf *QQAf\{}&_%vc;6ո4IE7ՐMg%NT&VRvcͶ{]|ը6=Ҟ kWdeIlĄUӒEߚ֊AnÝ : :m8,.HWgqRi $aD#L$Rd4Ds QZ7"cNw $'9GIm4!B[opk/++S[Kff#Mi[:dS޲.K`(=IZ [b]41MFjXRK}f|.0$\Cp%al\6܈U"PFpE&DZSy=qI顾dq1UUҦLCQn=zqKf)[a<6ڸS(%n*+H8dIniAx݀;RNI-L•ɕO^Ey~]+4OesLICV)):N#F2ȭޭ_ZX$˴73\=k{U8sWY$)ғ\3ܽקpzʫv :(o.EU! >1UNpy7m;*ϕej#_3$2=3zy9Ij̥-rY*ƍ|fOXҭbVt! i\XpVi6}*jVLs2ޒ-t gy4$1T糒9ZHwdVU(Mې|UV+Y7;utpk.(wpiQ`W rij!$`9dɫ7kuc+:c-: '\\\~̺ٝ} (v|ߝk[x6Y,-̮>rIh]7k90AcTc nBw,>UG-M҂J掝Ea=CtJ4X C+vHW"éq\tk,Ö3HAf;}J01Us"D=ylBmgiU˅pj{{kH`2y , kbt~Sɥ[ɍo,O㡳̎ŦJHf 3NH/ִo/.0A!?++6;dRK79:I 9@ZiYXLgu!G7wqrFeźI8$r05Y@(8i㈇`ߢ_ v:vV| ҜJ¹-rf%U_i[Ci2J\҄Zjymi6I2H2}zU#PcDT$HL$ ##>IZ)E׹~|x7dTA8o(!巑?%մ_;۾:y':>WmH;*{U b,.RLGְ|C)ZΘ"[%Ԑo% ¬Szzl%[򳃻uS}PE)Gr*^cPKEP: ّO)bNB]Kt7/0rpqZ7%cUmwQʼWL3"4m`ÀNJR7,I.nE4,z՘`v9\ XS-+>dq^U%Αn!;wO0 ZIkaL_rcHo7g8EO&?2z$@̣-:R}-xAYܙ&ju]J2èB ƥݭAI=|4 7?ZЀZ]DV\$s\%ݎ4w0(ṡwOѢ)WYi$oqSvEjTIqTV4"qaXK"]8T&ѭ'Ҍյ &iwڙPTq׼1Ӄ\^g6յj7?5F ;\,%f쌠cv:8K[n֙>a%G9+ڣv{q-̬JVN`-nW{VΕ.>rԷzLꧪ/aomr| )U7i՝{mc`NUm Yi\a!Zby5,MAn@Нc|6l{-r$n>UH !k-+Csd9<'Erv2 Tlnҵ[e4]Cں1uo?FVU͎mm[ѻ`nG!ݚdQqV!]Mleb# ighȿwG9iG3˲|Gm+1Iju1+{/\=l2W5]o` #Ů[o{t<m;ID^":k\TB*q]i;]OU\A"yTBHq^;BYDE\~ZKU! L k:tgj0̽[ e <цk5dMP*;l/"h_G G薑Eoq]8_19)ٷn-[-zQl5+`RaK=!7Y.Kl%[=&.nv}T:Υ4R4o r-=涗}kv]A?2q.nxcH9iھ\䔆/uXE2s ϖ }N@Z{- @Zek~V$1|#>]%aT')S$оTOu1 y%Q@_+*7񩸐\ڱAq"OٮsGXҦHUoA5=ynNj߆F$ l=%#ycW)E7vTErJHQUװf;8Sqiba]Oo*@/E'RVHCgXB3a] F>sN&o-XrA-|eo4sIaɦLѼ?wKq&o} Ԃ_6T<5? xcOU<ִAZUҌya9O/7Zv[Rw8z WP/ifQ~jIwZ~x ]Iǥc^b쎺8hE^_6 q#Bn%85Fi_2} \\XC( ]mMf))C tj>!(6ް&\9$u5nQ$#;ⳓ%O]+RҖp Wޫqc v g T^{fY 4iKUQU,r0 PHۿc 9毗kcJIB,a szVZ۹zq|RfMDR컪K-̨CUTk7MAu#FeqHX1:U6+whlnbX'fa-Z&'xrDX@ӄyr=Mszƚ^x؝sZ:JLHUjV,P`ޙvdim(O |VRZgrҲm:m1aS]ga*[XWFGw(nTEK#NOݻʹIcv+Ҝ&;^;9fv;k3THXf?{"q⢶.ds#62 ^} Wg61 UiaʛS>aSJ[ ȻV8zeP,P"zTsX>x]7őVbtjc!p]Z~B$f-7Pm9$|EJN nt5~紦gʃ\ [[1ۋ ,}MXkBX AkZu9U2t{.s*m㊑Kb@>pqS6ɕ䁆D{ FX  +bxUV%tKv" q֋2A NnO>&bYI~cV.!"5q9"ɸ֒ݟpCޛ+(XֈcDPƪFŽ q`['8Io1ŗΛ:`-3rBEX>@Bj`J|C/hc2'5P9,zTǟ-ޤǍϭ Rb0sBqQ˼7& n)r/!yTF(OjI\NV#ьfpCFdidޯt5\vG;TcU2J4-̜.T` մp)ؤI9#8JVݐžI6MEkpXF/Z$ʐ,**+Pr4'U_K2ya!2`2d6#=*q* HI2Haw)T"R4ހ}7`̹ jy `a9h*p&qT#\UPJӰIJ"MEt5fy[; :E 9R}KG0!5s5`TsRs9-l7Y%\qÖ;KU I/vVガ<ȨgE1s9#g'qVP[ud:ct95.2<ҿrrD|ο5b Hi%Ao/ 'Z+aۡ9E[Rmt5(df5G`x$]}MY5_RJe1.H>,~Z:Ɋ.$pQZZDyQN@_OS[@K"ī('cV-6ȡ0#biL~NfyDKGBEȭ+[̮1lY73*7gnvZ3vaD`ǽVӧ͵AU=>홛'O^GZ )u\:Uk"Tr/8~ebzsXN Vkra#^MhԗGKj8<ԈE|!\p]su 9SnTPr:Hz $e9RN7zRZR6qX2k62p1S%ƞ=60 5NT[[m+@HD`ST6mbxRWhf $iA8[}j#%{4ofrͣ\#T^N(桟QdnlW.[Z)=H|:DaD,v`氿TA9Im<o`+MYM+#f)vtYy c޹˒;?tHfvB&D%=t0xn8Ac"/.E[b;#򬹴ܒ1U$鲻pG9~ϭ;Uy5p2+/x1!+5G<W!=J9wwȬ3 npMU2vQ銱qrӧ"g#RԚw2ZW3ڭ@?Βɕ >`]ȧiO5]편SJoc1{m ?e=$F>a*:JB2)n'if,G)Ïx5L,1GyW@>8PKGV3TEGpM63H[RiHc^zDvʫ |g5.d-Z{}^+@[*ІEdkg~GigP(\[CP(˖2ip+:Y[y ڋ6@aeR~S!RvVcwжz3,m pjͦ~πSa=PDZ鑎Ӯ p`%cnV6#f]nv"v5Iu1 *9vA w\WBQF+>Y]v) f,zdvr(ֆU-3˴\a@3bHlT wܻcdQPT\ƇK> CqHqv*hm @뵫IY- 4)hSzn2NkN;p;i-bj,/a4rU#<_XthH<Tu֪-X]}ѓWW#<$ q Izٯ`|Fi=5a=-s [F_-Yy1`I,՗Y3p8-Pn)=dvylr峚ˊ' '<}Η207Tb|EERQ\T[T3l cuxf[Jukp!$}Û3c-f5gQe3>P $(\lΊ0J W@E,̼>b 32:"H7DAӟYqxY;XS-yl+YBÕHrB wom!VN3ƠnU<5s4ݴYYqV?X}QJчPo/Cb[FgE Mt{KRzS.AbzTۿ 8\t4&e56[Kdr6C m*rc9ig$( 8`t+Ic Y*vz8XpF S,śoʓ7lhC2*\ޯ]Oo/-h*7l_KPŹ=tb /sH4 <ہ+7a?N<ђٖ- &WBdbf!(Iajm7M[xy.P3WzNV0r͵j%BvFWTѦrN \~,3՛x,.Iڍ''W\ +7N8?K{BĆ9xBYrs@Ӯ/UVD+kZA(+ڣ,u Y+ŎH8v䊣quNn&L^@Dm b䢒Z y_S1=kr;X åKg^z⡃[gsc7Skyx#[m5,입q0 9B%;6#vk]Xn⹦ffԢ欕g]n'cM皵e?Ҡ]4FS+=V-C"`8R+]֣I~%8<0r''" ^,OP [yHDS@9-heN>v?ٛVƚ]Eeڤc湵!_Hj~ >mGi@$m?7&-$ ׊kj`oƫ_\3mz~})%d͹+ٛRAKs `T^S[VXQN:jK>pCc*H5c{$vnUL4A4Rr8M7q5j.75oS98|ڌI {Ua7Vo*pj"Xգq^3?+-ɗȦ$idU$kW èHnfX_ň- z}%LCp~7SeN1MK&═4\Bvͦ] |Eg2☕nW̧*jL)RWun2sTtk{_U1[:)2[:axl;n.Q dU0'()%/~B5HJ(7P*J^!IQ",x Ѷӻ%qƋ6TZeuYrk2N xQcsSӠUmmbVk‹CᶏNnGbc %ͯ{@rSv`3SvM.${*ei+c k.<+K<@7P09j:Ev飐7 0W?ysXy9*/ X]?.t# /2N8[0xy^vMfYmu ~\2] .g {s^$olnדbF@5T䝢)FK>'!_#'֚;%y.\֢HD*tRCm6'a:tIimnfݬ1wNC3ZHB8;X;"g&{3hO)18B1nu\/:d$gQ{2㸔Cq yN E]^5ƫ0H4np^2QR 'Ҋev/r5;;#x{Y@x;^oqTs+]ݓd\40ӫC\& -ʌ3kҴ 3 4Pxuiw1Y # lX54ŽwjNQt<{Y-YQkQQ-5VB3kI'HlcS8~=cRnP?)M4)\^a৐*ZQ!UlbH  UY9T {vU8Y6Bl"htגVV~?|] uZ &k{:dŒ|~n⩨&s% OI^ǕQ_&,8 A/G\̈W9 a*7@5V@_꫙u/RO _g[Ml#Ҷ>$h!\돮·UȻT˻<;qzHRSQwLn kq $iZ mcg W8w)s=Vj6w6UӠH8_S^ <&9b:lPAxgBG2D3X6slpZsy$.o,+wxVZLm&Ľf?ZڿѢ)VTX DѢ:,w4J,c'5j7o PrA~>\ r(WKgbXW<ɪϤ\8"CXF[jZ}&g̪O8*1Z6PlHqTմAL{hݮbb~ *I;M&~ֺ\jZ\K>pzDa*K}>-!Zm2;>o5 it9P>PYyd8Xȃ;Y#eway I>?yEZ2&c8焼d+ϙ3 ˈO9]g:>[f0~5M]0hZ?onWq~9]/șF=*;2"Awr 5kuZ/݀?|92?sZ>C%YNJVtTJJ<z<2E#f=9\ڬ-$76ޫhS#Goz%,tA\|ӫQwpq3V{<\NXW7$4ȭ*7.rkZԙ*c7\t>G3ki@2 qިog8jet[;[[tDVFG+y*)RD2UOw+h9;nBe;3ȥ%mM[s$y I=8L\zSq@G6Sjow 2vj)l$+*ȫ.K b Y5ev,--d$i|liI}π >İZȰc ޔVDoNwױ$   kd#1#_lG Yyr8-O rƱCISZ6;JOqI]g>s2jsL c;ʝّoa Z"уX_xVDEz|U kEdg]HTd2}5 {VRj]M_4Zc,!9Wm$li@MeFbP1~1T2;Ėtw @(YzVGȳNy?XZZp:Ut2B6 D9瓃NT8;^ G4|;Sȣs4as= ]`Q ;d1o<|1MT @xVyHc1;*,++]X0bI8OÁ=2_lf[ڇauXO$$Gҹԯ݋r[sYuy,W#7 i8OZɒyz = MءR1V;Տms*G4S3&zsM2dr!l<)xekť~<Q\ɸ0su<.;T"n){\c: ImZI!IXLnpE6r>bF{R!9Sd=-@Ҝ7nAI Q,u&}ZX8޴_60r 5~8[$#{>r嵮T;Aqk.YU;qjѕ4lƕIqVd@$&=3&]x0VsnmԿY)>AC/bֆ6羉f_(zTM %0}jG_0NA)&6jVI1sp#.7! ʙ'$tɫ=ر\ĭ>5ͣV,"Y\P^i."C}(N~]X{TEa1TȬ\(eS=aqR$+_Ut4S',HՀY>@xþ*wA wgu]}Lkr_J؋[kîj)!=AYH!w]%f彙C٢ KicPҧ3CrmSNP}*]=w:X6@,=jйr"=si&-OQ'-+#w`>>FmZ)F'Nֵ7-L0Vm[x;#5rSʷHwdk7eh 4YwN3QY6Rzm椠[ܔ֎rd~Q)m P,7z%TYۈm.REjM@) >kQ)'- LUbXHb-ch Ī}%rO|eb sޜ?1s8qIY";꼯y*2ITW 38㱫v\0ϰZlN6QJ+ȾUL f3S9Uwjͤ-dIQW|*KxRZ(>z/՗i@zrl:qoVtQcFj!Ғ3LhpTiɝBZY({e3(q3OkswS#av۞H뚮<9eg =2i5m٤m4o&9/3#=GJksNkr=!-+sUlԃ 'M`rܴwv'$HPUJ8ɔ30OZfH20>=o]ʊO֊c)PҨ&ұ4فHEuCn, +'DJi#<79a`R{rais=8[6)EY +ջ]NyʸP v-MçҫуI靼UV7S~״ k_"8 6dv0nhL;W V=ޏe=Z)T:Wqɾ]Nkhܮh8ML`G5vKg%c׊gBQɍm5 XNՕ#1z[@EA=J_:Q+)Gy+nc=Ji h+OOYd؊ǻqhfu~Mʩ(NJ[6 YxLmIep]dwZ{G؞fOUF.s+toP% ˑV䱰Jƙj5b6+F!A%D?m j@#*k)1ޟgrOHsv]ɈFHhQܭi2)#*Sp6S--3* IM.[Փ-MK W1f'mTDfbyҧF[S$A>lusJ*Vղ48e@iM(੭%юGCO˜|ڷQwm{ϚrPhzQc`8(K(\p2\ 4jgv4沲f-§wpj+| 5fImwr9 ES]9.ub6`QR6[5vebIF* Ѝ[-tk$nlb; &p(JRZ QwlùY(듌OY#ȫU&UX(<޵ 7y幫$屟>ݟSO.'f]8Sn$BPu")$Eɓғ8؃NIUx9o^L q%b8.l-:g$Tn*/B{7):@ oaڪE+@sIn"RAt=*X^;DP񦬲\ [  qIC1Ų.㜇9iF.mfً rr?-<[Vi|y?hvV,PI!gtG߱Odac dipqo*ݤonc0Jp2X)$E40U.B`jQl\UwY2`۱%c'{kl&fiK! frXҥec8Ե63eZ{ O^bĖm47dT@3P V?s`2r7/uLI;r_ݹ|ю2 'K*!aЃL@aOP_FUcM^h|c7SS4zյF#8-(G 늵FZU"ԭnM9ߑVZQ 7 VE\@sEٴ829Z*I Qkn`Z;Gs4@*mZF@н×p;Ҍ~Ԛ[…2O^!5=W*T5Zy9@8&_ՌN1r!&sN+ :V*8+լ082s[e.mv㊗T&לdIY_Z\ *}nU[[@ ^qe5kQ-NSZ4uE>[nj{cY!'jeȋK$nhdO]m-2Mzݳ 1P27q,F[Q ç:MHIsRb.T;(fn̛u=fk[VǩJbXl آ(m, S $iItCP <.TqƺIwTgδ%L[Lt$7&WdL$tFȴg;(`[O-!޹o-Fy6]K'3^΋5Dywv]ծ밅Q}+UQrXj qIu/)Fė{R¼rκR퍺۵yʣ5~{QyNXSIhcI*RVRl5.aks3D7ZKh䙈cp뾉|:H@?dxT[4V]q43,ncu|.>➞u>=2bXZR`F8R\K-fhgdOGsiVG-u 8#*jKh2wvѱ?ҽ pت#`]<$iÎNMCeK 9i>*k) [m'vaVio 'cZr& uWNWவnYaAҵ.X!qNkKKk )584ΰeQȂӕIҶj2I\O7-[V^&k1mw\ I!8ִe"6Ov N4#H֞R qvYIgqr(p37}EGZp܁sau.H]ƙ/6ecedQ>mRZżQsjbLȳ[taV*tk6YZjzx|;gLIrȤ/ݧhO^\.k"H[4)x# 1ڻ5{h|cg'>y9Qm~%Wu-z&fo/g#F*މc܆[ps'1wU563XlmlQv3f%ʓ"c$a?]v|`dp #> jݼ࢕#xuՂ<)?L5M(K(\c{/B+ kC, m00$(K*I{#jTn;A&pZ-5Ȭ7anx'Kmbo8$DlnD Z8M&3$JjZ}ݓ$ѳIKgA{3\_e@˒|?z__ږҐ1Xtl_\!gij<}iIݷ<^?*CWo YVm|\0'+$nt5HnX95{nðnn| cz|Y 4J yLq#$0I Ok*=>Y-Y0\:4`x?JiVh;$tR3\#!8POZOzvɴ̤z^is6Q ǝ*=Rc9h.D? \QN]q*kF[dRZ夏fJ#fJLyJEަT6+qꖱAi껓VgNKJ1˷9vYD~VQG?H6tuJ] f\^5 {˂âF}{YOrM,znst)vOm/wB]aA/@=gT]˹Ts[{k"7[sp@庐eS#5jŦ"q3Y5 .hX+bViO0G5å]PY8k*m;Q^'GXjAᵱ_CvJv֯s BOρdИ5,e4X qS HJ} I\&qql˖e\Qn~`t$" 9ݙm8IeH8?wW V+/^2Vl|% vlS+ך6Et#Sr{]+lRSTkEg"N {nb ΍\ﷆ6Px;rÚ|P\S]/n?-y+ jMELd LJ5Ar ŻA\NJ ƣ^I+] "*6QC;&[).`~R3Stifup)[0::˳#R)<3X^)~jn|5pVmH?,: -39!S_4ϖ]d]/Q&PHr+?09-@~x] Ŵ #ӏk`j:\v[÷g >2RvjjDv NrzEe-]'QF1on/oojn^KȩNOPEi?zlmYtzt* мEi+/fleqX?ٲK3`VnDڶnVݲO_0jmNeHc'*pJMFg1C' U=lTΖ;e/Ď cc5hpk -GV׬aWL#n٫hoΙ`kНȬKX.'.|C-PZ[Ϙ=}봾kePegQG/*J.O_ʱr!I-}WŎaq,pj-BajϡVɻ!2@ $ )_S:69K<n$Z}K5tS֞ڋ fIoJ|c,^m5?S*Dylf^?h9lctE \l'U+ss}its>lc< ͻP~&m.cj曬iVwr=}렖kq-ʹv߻~~uwE q`xAnf;x~Aj4#)9kk$3i㕧IqHLvx ?Zd9ly4V-yZ)ŴaWL9(v6~7 :ul|t/h&+ u废;IXwKMh/U0*(Ւon8,hҹhH9As -@,*8"ѫ9c|vI7۞?030MhOorjPHnKsfF>insͼr#0Rqlj,qǜ<v=+itF QmIJ$iڄۛ|b59-W<-(xa=ހRoMEI"O:+M,ѾlvGeYBΉ|QЂ{ 'e{ʱξf&Idf9P:zzUR8dQZ@F l`3H)ko]o`ә%"fYٓhuZ"(Jr\W=ea!>; 5mI]LIh^|RES=k5 EUKfVPn%GZ<[lm㷾M="񭥯ë,)H1r8~x/fëg"O2?.0 V*8ʭ8&^hd$F7uj@ gT͇R{bٮy9_Fld<.br1hİQULjL$U&)_[|2rvUcR@w${ք"]{"Op;fmPP n$gipJ2g>=PzϷ"'ӊ2X,jl1A=趄ՔHڝr gp ֚nv\p"TM"e$̃,G8ˁVŻE\J{rJ,8maJ1'q4Yv0F1Vc~{:j4%&]yir )n}6;de'5`诹\ޒ jF'1wj7ʰV -1Ֆxb_NTPN1%gE(;2r"R ##TRFnrqӞzD\qRIjb'$u"Ϝء& 2V9֛p造|ï5#Y«[UxkBc4vw MIT`(`,>E^RzY'BAf0jeE AجLq#JMhUL1eϨKkcr$: 䲌aTd^)d`N15r).$oE1%NݣڨÎO8V@};p[Avz$! c77 p Fǀ3g;ITq)X㰪pPw R EK1nN֖-3'|?wV#ڣ842tz]ڀYmǮEJgD+\f@SJ͜ c[3ZʡdA˨͵U)hR!Mj(8VR9P:V{iOLU-.G;dcZk%GixΫU/|B2ELuVY"08O#]A:Wc6rV" PyC}ԭf[p=jk`@'xBuTǴW8~*E?M(gT94d̄Ft)5 mVG4J8b~oϽY#+܅/ҳܾ4o+J>jO/A}I[l1:LC[m &7;<`9dҎݜH _sSO$"qb$"N%*ƛ= 5mV#i'R.FCfL>x8k^=Vju9?L;Q=O iJl%g kvqW{ 'R mK7?Ր&Vg#dTkkV$t#5{Z 213f51,A8&"ɼd>+^+Xf+F@=HVeZщ\.gsYN-$) #p5sOط ճ m0~-j;\2v6H؁Yf/'6A-ˎ ;0mH#[Q)i1[3I"(95zYl-* ъ;uwV9T֥w1 iJ'6ifRǂ><>T}&Ԍ-7L,%X uzEV(1#sodj1.%qil^<.|+6\jq uI1݀5<*oc8AWY1YwvE&2c/l+SІ5IKXZZZ D0wbJ+ERk?KId@+]E1$cW.DnrÚ [Ș`c f+؀4-,NUlU6\<p8ˏWVKF*U"@4pq `*Փ[.Dr1=Tܺs9 &,yӅ8&#(bmaͲAG@kJ@p 5:S 9m]H]1 x0z Ս]|vζ7RZ?L~kiZ] <#sJ4MZҎ9ɳGl)O-tڹp^t92MO޵Xwt-Cܥ9J# mhXK<-"`O$Ĝa:U'm C4V}ZR K7{m24Ź<֌SKlgk&vCr{62}K0,pfF->  ѹ!Bm k:c҇x.ulxd rH]1;W?j}6[h,1E凔nzEsQVZqGu h=rx&I yT%麟s8VK'ҁӡ8E}U`nc겆O\Zp)D2 qZ^i4/Is";}JdG3WvfRGji_ooP:+3Vc-qpJWex{,'6BxwUQBH8 |*dVh=JYaǷZm K8W丶24mr#QZ̶m=MF2UI{_1#օ,]698kK{D*!(d ]GOӥf%-H5j)3畴Fq g?+UF&[G2q|"bph˨ 7BQ[Zՙ-HM,@*[Z'9.[ֵ)ldq68').3xcZHB.UVG*ou9dTZD>cSe)ޠG2 ӼȮG`VtSL\DOAcYUf8錑T\ qM&t;mPm-7F5nZqV w `|`i-ܜѯx{ deFVX(jbSE9"X_W·-]J]JluLKB1`1ǭEe< ڴHC]ғop*kx-e I#uHdHSj\^ ͚k3Z%ݼ*"VBK ϶X( 5vI0b ˍBnF?iNW٥v%ll0 TvywXK*L.|ѯ;vr*涡\ǦjׇO͢#bt6̸lgjսn<ݪ9íf⭩d4r߁ DGeaҫG!i*8_ZY0K s;`JAz|Hk.{6(Y]n%JrSq(M]NrTI9mھqaKWThVdG Vtx?isSd\أ Gd D9̘9z_fG$N9^#hg+!SE+͎er$iA$mSKhe#sUte/Ai.&leX׼9UoFNc`&K, ⦒NDStg[դvEKp|q\“u5e+.[SfX65It}:|۴D'5e&|9]1ֶH0UpjyURE&I"Q茱h62IZ,dlEsrxOJo;9T9;A>J<,q932jJ7 MHDrt2sV|5b*՝!bz) F7(媙?hĩ {Oˎ3QzoeoQOOzc\_MX0t4dm> h Ks~#@qYk{wi+e⍹! ."KyZh,Y_y9I CV+u DxQp+Ե[6-lGAynouŽLQ+7SQZ>d=]W?[cyn-~ ,cYޢ[ 'LYnSNFkrm|<|3e&[ VMۼN24{p> ḩ[xt@A }*DjWg7o&ZZZG,m^1qtyU5Y,fQg*kҔM0B6\[1:ך$sbxYX!I}0>meYIC%c5Qɝ$,yÆ?W$eH@rvz|PiR g5_Z]KF|)}NqnZсjq34l `mLǏNXf O An⮴7U'唺}L @?:554v\譌GB5k5娓jCYCsJ;s6bjAgF * =!$XoDEO λ xiƋ \~b|Qf1a}셪R'_!NIG/Vkma1&5y>cfv=88Xdk pkRl-^7N`V҂z=QCt[7lU_ěƥxmmʺŸp\n3 /УTgVu5=J4 YkI'vlKGA.2Hnض[)jYxz" h.}+$ZT[]~n]gYsҿ2$ԭo7R+,n:GZ6ƪLzǸKpCڇKc U ʠfrQWZ6!RLR5GFI\U5gY垧)1?PԴ}*Hv<4i e&0D4^3Slr6zeH?wn`ԧsZPIn1PGϱ΍5‘H,r_G Hry--nPc(Fitt1#L6HeunkIO@Ws3KQISΛHP%ާ*ڹFH=Hkb ZV@1 {udr3V2n’z(XY$j1k֟Xw+W>&m2v g$ԨIǩons(>?B3K .t0GSUI3]&:F*;f}2NJ;j>~ՄnR ^DHڱ|o,,0 **k1-tî_۳ F7$9Qu/ Hv˯_ά j$2|ǥOM-7 ҳg%dB+n_E: 8 6¥IT`fy]}|#r /C َL'4{עk^ľ[ݳp?PWD帶f<;kI>hU)+sGHXFiR ^E`_MeyY7|ŗ%}!ҼPjĺ噍Cv1?7-ܦ,kV9c3J-"c{RԬ5^)ծ##(!Ȋx@#h^C\4,owq[CMĐX#?!vO4|S^ܤK$ijF|L6=Q{>xO,`f]?LKuk FWƵM\,/1%e#+Kn<²~#ؤzd^$,1]ܷe>Ў䃐 A=LSgD%nG¾15;+#n?Ţ5iR+vf |gra}Fh߳>{*TcҴD\m]$9 --ݨ^Ukc6[kҤ>9j9 f|'uw$ͺҮyS8RGmo+g3me/X>*ӮOK=ĎV`h-~X)OV}еCe95/-Akl\گkZ^m^BpAϭZgzēi#,pw5/'d rW9k)B5('k%s:ǽ uX>2~ѿ5xRH$׀j:ơ9ig,Ie6$pT(XKw魏_mgǚ7VO}^2TڦK}w+aA+a^]8k.VGaۺjx Z$V#;q/\=f l^ Q3TP̜Js]UǯjӡD:wHӃ0pUU RGeg-m:(Rr#4]ީ\cGZŅqu:wS85K$p z5K9Iebp:䵑C;Z]$eܮKI $!v0_enȄ(Z!X`c4MslRW,1p&B jbV=95>Cuc4kH/Ie`<`I=)&sAl*z 4$pTM>0pO^ZOh.P+:KZ0T|t [c$gfXSՖŶ `9\ȵ-49{| .sashac(ˤ$}0q[F[VG/7#Bz>9PO- c5h35q *[dkƗ}D=P3X {]&@ÏEm0sd7^QtВc(@ha54s5YQVXSwc4K"'>[#562@^HcD3BɱULcڴi$Z6[TNf]6[d}jӦ@\6;)Wpl/%35M$ gAhIu\wjXDy-޺.HX1w Pt3a"5fYW+cֵDLԐ*Zە11s@JYcj;(Őv\ )|H5Y[cYziMjeD-2vO -ު̈́dUY/3SQS^-em˜c85n+hF W^ D5;H[jHzQ蔖yd8Rܥ9%"\mRX '1,L}$)RWY`ET۴Ӡ8RErቦi>il~Z ո)Kﻚ^[ yf כ\S.[),єCu҅kΔ-ʤ=,yd2?uZivӎwMw$Ƥyo, MLcg̍e'f:Le-^bĆt|ƲMAJca_ J)(SnAq20V ]*x닰9#6i^33S[KL$f'p:j*^IUneu=@XF :a:kLC6iL *$Bi+g6ݑg wIN%2 [|Qw!@@Q`ϥ5&1~C]J(ax+>+;f] q[wr `unsU y%\ns NN;8):f"Lie, ]4[C72y核b|z\"V9TfSP6 '>Ȳ35#5cyesQ=e[}j9[[s(dfr܌ӭCF1J@s&3Vem7 :2 =ꍭ7%+Һ HW#*Cj|ȮB3MrKN:7QoWQI*c3>eQxc8Ӛ>Uϙݒ[f֥:i+(p{hBa@쬢}@>^,滝iʺpđq2Thr!8sC"8+$DZvϘoxkȗ"$ȬM/{gX?A*'=ݚPEݹ&M`jחPH NiiЙTwktzJ):D:ޅ R~n rz~][$`xDf\#ֱrNQBdi5ҞsC$6#UVǽR8GsZks:[-R"C5ukWfq2͌GִyGX7jrb&&/}ǡN@+/tMlS^G!?&"w.Q+uC".3l!:m-HOli6#)'9)5TGPxp#VrF{78sVttDFZ6L6$XLcRKkkx]1Q{/f&VٷäGڂFpλkWB nur{P~+iQhGKGfyʖ b?n6I/:U|?%= 1bH(=%ԛt%zTRHʊ',Glf[+(ɩ-Das Vq޵ZUxtV%<ٹ\tiPb`lSlE"~UjMM2^cjw[S-wgv-D:/[r夎>9_4(/oBжU>b0j;^F^$ iĖdȽ>կc ׬ @kƖH&^ 'QԄd-$${`>VJO ]Ν(##>`Rȯq:N^'x ,du*qWS#hw#_8 CZxu&!Cuܝ9z ܩqbNn,7Er ;KӖ3џƺ]T׵MF qVN>fT:YDSڹ{dV[}B#vu0I?Z].M5>d ԏʊrZͪ#,x\es!+cTčlGMírOIo쫠Z VMyvW 0QVNqZ:=r+t3uWZ$x`c>GI6G '11UxKF@$QA[K89]AV1]ز41!sϛkJ]iElTd-dfN*֋vY 2!<]58͊y`5mg/s敽մ(u8|z(c&VuO2I^QS᷼y"̬ ?^+cHK4T)*ז)ap(1Ar8[S,KN$gxULz[Ggm"ǟjHm Vj j\|=IinjsE#'YTGnXKoq \FļgɅf$]WN%\FiSخY+F5,Cl%#?yFk"Hq\%zC+-/4o }f U֬O5PIд~hVі>ziڤ6F˭:[2HyG:塍up4 [N23uurmTfoZURVI{O?tL}qZWmVPd 1OZ 떎nK .x{J ݴ2Y SxRw/>4mhTp Sƴ%cI">RR5}k!/RL( XB;k~#c "_"~9k ZچIi%O""Ƚ#݃'rLaOX9s"n$z)=IW3EM7%yӆl`?҈ն{G-Yp o.cTx  CG]Ћ2[jH2"RWOHLs+A9*擫ʮ z|6w~,6!Wicq=iDchl]Fi-{ڼydxJ`p\$<ҟ P<  1 k >dmZu2j! :kX~|X?玼9-^$70)X\'9(#oNrluf%%`?O xM|FxQ\! 5+G繮N+jhRU)Kݏ{O^0u=bxaVc+Gdӿ$ v1#w^iq$&1g=j=lD SZ~0xxR qk6퀏7N5<1a8/=LU~ήdVa_kF ,RFH8= ![=7Yf\d0*9kF\$p/{Ed$~bNUa$[h%UBi= uّA$RDKJ$4ܬXUbv.NVbFxۻ.U]i E|rܜ⠺aa#9=.kcA'ޫkHB,1Q'knz e9+jwGg=9QA`r1(.(6&H皞u\{ъi"m;9ϥfi$nzZvvibyn]I9BxB:s ,yfzR}ߊal}$hLmX0kKw46{*f -x2 Gl63MXD%W)!kn֊D)肤,dMj ^H9⡕ ó'dݚ1 `8\٣#;RZjJљI呍͟ZՃb٪#zAnjySy *EV[7.KUk&"`}j+`$_OJ1\㨗T6Odv ,sk`H<>zSX ̻004vhfЎZӆoܲҴ56pJO UI0wiIaKf3F2`(?δ#Bd@\9jYtC"׎j4wfE#*^mch<WEFm\5#)Xrw-%[*3F9V#62+Da6RSӽE|lR$u) rsa\v+ :$W[Qty,C6F;Vg*݊מnHQ[i1]/=Z]{Tj6: @d\WUQ)HVNc3H8lv@3mV2aFF=ZC)Y#&xbeTg+Ԩ5> {`/koɷLl= RrBHtG|g V,.db0'jC[^j)g(r?v+rՌ셴)n'ҥ{p:(',kMß1cT" mYySS>ڭY +iLqȣ:|

k鯭>i^2YH~fLҥ62PնD_걞TGk3ғnAn_3$e³09ɫ67cȲ2#b9_#PF(z 7eb? *U5z@JG)aW X<آ -U=HB贻:w).bwS s,ZZz9 G;NNN<ڳ ZBיAJ IE+ ӏJǼաcV-B*Qv-QaZ,\&f"I2zm}rJj!Ϩ'حw @뺳-#ºq5jUi1zFcn߭Uܵ4#nP6\SDp *qU L4KױfQlϽPO#~> VhM+ 45w][Z;r#ˌShٕpzu_ؔϡ>\>4Ac}F)[NI=úC]Qniڇ]MX*N0Lմ:Vjsi%9iz )`gKyw6$ -߆V{jDdD#jp95jQ{c\ӭղh&IpdZvHK1Кd2zdqxLz^Nz˱u1q#:on`9$j3єᦍkUIIV 'j \YK8`ySfr֥ \7d.7>RIzt0wA%ǫUk|HUK*rR+g|ۺUo4DG?-H?n}~1vF]I˖MRLRbiFX4ą~Α&hYI09;TSvf"<0\é,?;4{F6OБn?tV ##u5-[q)s.h:|,ۖDG;zku#] jDX5L]بn48d7Xg3FNjE[^;rP3"v3%iZ3Ir+';®܋8@Ж)ɽ*U٥>d".cGk{,\39=?h[ڻcq;lB펇8RICކ-upvonp811:F;qq3fhW=*n[s5;leU}G5.2f$]m1֖kyН Rzs c,#hQM}$֖A EtJ̾^Y'ɰ08T3-ki'3$>D5'mс͜RZ+:+rDb$m7,}qQX]C$}AiF#N1{p7KQ\)?kZ)X!#9H-9ȏIQV3w,/"04 {(;m8m:][CIJcJvƓtws ޝy@;=r.ւC3 Rl =W8b-QWf˻nÀpFkơI8k:k$*ejN+OK,u$@jJ㦣kEgc JN>A"4kMYp4a< g4C)Ղq@swF#D""N Q%=?~xD\дNk\om r=JΪNC?Y8){M]YACe[rI ?P\0^0rxpzG5躰HB&G':#([-Ϩ|qQNJCGgi>l e1[Y²UnHsQ ~uha&)G_3J2(aٓ,I4j:E'5""V`3VEwHЎFN;:e-n&c-V+p>+JV{YA0sV4Hb(%:N&nif-.;!#5KNt٤=Я5O jJI!Qe1VW'0hdӝE&K Hs|!x{fjWL[w6EfPx5nwMfi '5>~BV7W Htس[8ۓYzZ4/ʀ)''4wdk)cERkVn0xujh^d4E}pX\3N[= %\Ii;qi/=6X&9T%psE2ZcqjK"IZ>n#JFa.[jVFF0M]-co=-C! gwRd*syp//U^IA[OMͭ-[9->.ʵskwE@xs] mVpqIs|ڮ g>uXDIʹ,&|EXƴ-ֆo4N' ^oRXe6ғ:Mf?89~}yRU㲿6dt`5nST^PCsXkVpuwvW?,'9i6iyn/exfmB@dV%ty]&d:?pz\U}.(RHS\lb38 10qquJoPwc"t1m'XҚ6JG1P堸Kyv `]`jc>ESrs[Z50n\Rg_nxSA΋{E/O3?v&ċN~U_" eW3y-;]3ҴّQZEc(V>Gxc VGu_ϧ9pFrشHFTk'U,{$M2r~T_/.d$A \ի[+({3A'\ |f-N}m >R{&KZ3}kWo6XVruӃNz~c[^,+ͳG!ň3WS05Kc3p3U6v[eEYs|Z L=jO]\vIfџhx|RudzԏIPn Jea=qg$]ܑ' z}̟uZQl,]*rUZnV^o8~STƍuuH~QU+]ighɎ&QVlZ2N=EWkTLqIaF(ڲHXܷQa:yVr~9XYyVJx5-臨ބΰ%{+.[$NdBgljp>W,Z!m0ou8ʔQCO3c~yZEN::)ɥXi9 {+g$1T=OdR<5,΂7 *ƕduͩb352qY t&yqo0E]hP%J6f-|R.b]> EwSJSjRMXlIK$ge<{sYZǁIᄹn~L?*aç]с_ֺ=3]OŹ lV>v:o携}j%+ٺgYP_Lm%Ty r|IEjVȠZuT8/N=MZz~it%+)+O77jp*ZY[5ݴ\"l>׼!!AK{ x:MUeԮvnsעN)hL$V]B.I\U";aƶ^akI4>aχMkYEP(G>0Tӽq9iwa#7R\0VP7 gѤg*l\C &YD0;5MxlGLǏJRLSm]ڪ7m&seW,-o_t)msqssq>< ܢfvZtmwq5Ʌ9]?4R-~J(© a7 tJڹLq'bݝ槲OH@nxug5n[t.zL~^&7be.W^mBk-iQZZܕ)T*^<дpwfebݡ,lAy YXZl&nc>έYι-(#ŷ=eüpج-SzjZ&x\|D@:Dzuxqֶt:%qQZɨ:y4̽Gn&2c߷?@)/'ba}rwZ׿B4d?x¥Q?(jI6{% 5V&n/EH$G?Y5N4u䌟qVi;6H@$D8(IYi(i$ %ei05/j75 */ c *ִ5Q A]٤.b2?ۚ%6չP[Y?^~5}V4x?Oרw (yg>j^\ +v0eAc?]I˜%Y9;/G}%UTυ-`x.פ#OF7m) 5;ٚ^J7S߆YX%9kҼ1oi -|.*4Z2&=NLC .7WoF̝HY~MD{ ]-β$kd/& 2=C9t,fs*P{ ?V5{mܨ+KJVg#FX=k5Hm;V]GiS+&0DQؙWw=z{bk9ܱ(HB3^],k`k;"|sgzPX8n6NrKC9[`6@v4yXa$1]Vm2eJJ܊TKMc8Z*>\Iじ'[\* Vv’#Kh)_W5BsL,6inNоxXT ՝57~Sӭ?Lm8Ek/(rOOvYnAFzS]C0ϨWj.w&6Fzȉ]_z$D97vw<;&IX9ޠE2HXU`7w+'W] 懫W.6˓K|k5QpeTXpW`fUdNܺ^I#[0ZY3׷"F%ͷ6Nȝ95>=\ft?mÿm[< ֢W%X`,HDc+,޲'P] msq@gl8ͭ0IP64`:Ћ,Py|5[k`Wt9;15FjإSەbҙFM0^dȩ4$#w8\dR+yVu ݉9ms޲oIYnRr.W*w~ pNr8[cnHqs 4İ+XmbZ&@!y>ԷI$[ 19$ZQ]E=hXy|<ۈE#Ä`S:HQ F=څ,"$^ÓZ73ar' +"xQ&Ps sՉ3[\=bLK'+G]KP%|5_yg9NTZi򛓺د_ %;yjqs[[yw_fZEi&4In-So %&LA:Z- |qޯ[[]y#֊"p1U."{ n3VJ ]-D Sm{G D7)\fg 'a?_̻TS)$U9s-P ;U֌zVAAj%﷊5 b_b9zHi,H-tlխ53FN/-]R/$[mOaS{ #d!8H  ^7GR"$xt^Web@gg윥r6ǵ^Ao.d-JUثb1M wZmX#6i q +3v\no2+5B>RStIC gDwf2 n<)]1[\ jRdSl&DVִ DɧV/,0%׌NS ZSU =;BqM%mȩ) 2Jɭ BUL>+%C*X1_:A1 T%w= 'XCV6\허-"1qO#V , g#ԔtlSA\B93[3.P8`J#FLTTBӚ.QQ.~5HjvB;y_Uc‡uzқK|}@ =4W0ܒ%=ȫbDC*)p+xk;Qz[ǝ3'p(iSt7nd[+wϥO]G8^JòWd;=ƤDLi&y3 1P:-hLВoP[hv'ǝ$#ypl5ז8N+WՃ%q'HY.|d- %y9q+JZN" 0x,ՌpF +bes.a-ݫk0֯bmB[+9"E~56$[Pi2ZI ޏhs+:iF%HhSk{h 9͚mWO]TX8Mm,#:g%'6$-1,m$`LSW&K{}/U|Y}|sz9Zz1f B`jݯ896P%D`ヶܴ3vNۉL\'OGw;6vee Iʸ]@HKDIs̆Pw{lH&5H'ig2"o*SV M*$(+sj|3t =OZsq{28qWM7bcq3FǏ9odB٬=#QB{Kw璞KOՋɎk%˱\,e۞Y^u8uxǵ!K $8|X7`s[F:hsT+=>Eka(]ҫ (4x"^\;py$Eh~jm{\`7=9=;Iaf8d0cWZ"RAԠs־%ie!6)#+f+ vc ⯚1|ɹ@S)Yfp7*Ɵqpҁ'CpBva5o/B`~,TЈRIc,u:mJdUSz's/~ֹ̫SznR>xU9?zD蚕ݬ3f'皏I2ᥘIvtHԽ * b(K(iH/60V#XwE$?0F;cT2B)t8#>8"+Mj˜bMu@:S!ӮD&FOXnԔKA/qԎ՟$ lU*F}뤵E:9 $r"g< QKAr5?m(6?+贽NIj$"lB{by :j ;LߖFl/a@&X^i+ˑgJNqG> fݶ kX|AkipwP{ks~hqbsUrGoV# |+c]OteX7IuB*N@XJ"-ݗf9flfe5±Le9i,<8vBynSH4g '" LUbP.g5ci^N2N E.D{A,F$:mrsӮ,F0f  GW;W6\="af4떿"M?iT72Ucͱy!H۴rRuǖvdhRf8Kq%%nS*i!qn20iNr$ֳS[Xъ87bm**]OLZNF+!s+ƣ#bg5NoI {{OBZwuC[ "t׳F]]v@6ըl.se3C  aCp.1rE\k CcUuX[K"yq 61ng?L iA\\iRŏg/JNrju>##ky)6F[Ti\3kċmfJrKvxSndM ckg7N)Bj6-#>.#ep,s5Zt:zջ4e'>MxFh<دL F:C0K.0T8^+FR|:Ẹwcj-ǕY{Woy]X#Nז\uxbh"wnۡ5r+ke-9W+:M?\ү51jӛyqӢL0mr:.GЮ'i/Kw7`Edj6[zE1Xg\q4\.omM7JDAȿy-ֵ#v(v ,{>si=>uM&gMuEpΤ0<`d^!F8 f;d锵'-$⧑b笐9bN:=]?nhtY3X?˥6'qjJ#CҕYu[5x"P~fg>kJRb7E\H@z`jj$rxI6ul&y1Cx0:)kww0E V?pW֦Yt6=U1T3ዃ\FWH+DA֔qfvFP冂(ܼQ2~ռͰB˘Ͻr2@B5vȒx6#I #2 ´V"Ά;*M>k:ϛʷtsB%ݢF$~UX[;#~Z6z +南3Wγn6fNowDm&rxO3j,OJ6+tKg)Q-W{f52-uq3(MH=PY5_1JEy+?ۢcُN޻.0 Ig*Y^n<8eUNՙև6Xt\HT ΩGdq%մ:sY O]r2-*k.VkSPԼe'48ҺGo iqHˌ Ơmo4'HG\Ig͞i[!6vbw]yv:/ݮ:Onj [ ~5x^wrWr{C?Cmc:΍ 9hQњrO7Z"x >f=+;Ot6&T:V"<.9 yAb|Z|̭ΝG֒ΣoGc[G%S&፜O/U>PϻKhֆ&;|V.ZF7Z679U4!LZU?ՅJb`rv'?jq-^ ʂk^V1wZe͜:eMCWNiNKX:X]DkgWNkw,qGյ{,1@q,@]a%ԗ1(ʱ5M`ӓX3t^ V;+u~QJrԴWȹ!? k!е OSԼ?LVO4Y2[xw77,@ªU{7 XZ=lcIo,A=ɯ?j/V--l,,~f,,k03UWǞ2.e]On(ǥxkմ:ۻxÃ\ԗca#8޳;Ҳ۝ذto֖ @a9^OF9wCNN[nWD՚K%푂sQ^϶%|deم'HZ ?ZSZj);ʷ,:3*%⣜2[JʒIݝTJwVv mPHMVQ$MdECs,`ӎ?:wU(¥NRHOSS _3bezi%.n#f3w0iZ۲e W=2nv9T#TeqM]d]_<>T\snT2d;df9OkK7@Gn NJ̼ALXe"U2u+iXw67J1WfІ]og\!?.Mn:DqCM Bьy!Oz*;̀NmM[z!F] M*2O9QBGcQ-YY=*ZFr|Ic%UXzQ9ݟnznrxJݓXXd%LG-<0<{KMEmn?avmɈssUy*$I Xa)ʩԖOcln@!7ǵenOf( %JSB k_Z֬L}k'MҡG`XVRm 0D6KԚ{-4U-[n+;YC-ܲ^<CjCNI#0,`fuQ3ҒQ`Yc_sqt&ʐ=ke&:D>p Vy-tQg'`꿅TWf#s9*SX3JXݴp*(q sOwb9^֒;Pb dm8ڭҐJq%ox;8cr޾}ۺɟ™4l|a%dFb%yʇ2VL'fw9%V,#zѴF*/>_Qu;79@dpO5Z[Hr󮰙juI0G(nFB rdҏ8mYrUqj71SCW$ֆ݋ Z;Ҍ"p-޵V-YHG#\fQmh?X yP4 `u R "W Jh_;J'"\AT6>lBsU~޲> rJD\Q]Yx'+c&_!G! 2I#GO^I_D);nLf3zZįesޗI"K{ 4S*1%}/WdVÒWE'Ycq&4hFzM%iYvcV,v/$2(\58'8g\FB*Rd:.Zx UO^p,~xZiAqqnXe'9܇ۉt!pBILYJѾ$i H׵GmRX\'Ӛ̴BvcqbpORW{SQF*8Z4;Hzu,=Ğt[B:kɯ*뺍&=x9VrHNv),kk;&3G|Bqjh$pAPN\Ѻ8ɦv&e 7J UI?|@9J1]ĭ*Q$$CqU&dɧhL=.TV<>j*)uKqȘb Ӿ @gZA s]3Q5匕9QpkCJ ls5oP", vܞS%_U8Z)U`FYgEr: ;2\B(=b7ԉ>ejq@O!4!|Hs\mtJHJ,k&[;"Ҽn]+d>aH:c59my8Us\V`xW\ȼvj|9NnIёЌU9lUN*'f%y1I 7MIsJ+qhlj_f=8LUKX潄Ei2nq"{:eqU;XR>M&m Ҧ]"U7q "L(~_?Yr$ȍ=x<єeMȓ%SMTvqrDKR7+5K6JpiƝsCmXS4P,jqҲtoT+fq&m/Ӟ1깬e6mNGqiW/&"zVl*w# 2ö]fUmc*Putj~Vtϗ 'qN*C&ré=j$TLU-bON팏.k5v2l[;I%l5u$bxfՒ~/UG^j]<̓ϑr*ԛ' $j4.çAPiZߟ߱;_t.bBа/"KyXdn&+VGD)#46@9sj|͹fBqBc8:]8|\wdr++K;YY_AV,jc8MݩӾ;f#wbFjz<7RQ<ٿ,lܑXqYڇ߹f`81:-+O/ p0:jB"5A!t6tښJQ孊~M::g א 5R$Lt-i4M1FΠwWp\k)>F=( c:MCG5Vbe 11G4e{0`Jdis1N1ݔ|SCl.5 N?"KOvN+FO&b.sz*͞ 7;OPwfV5(rn/O]KN}ݑO5-^dT9X/#nt"2k|;Tq3=rEii9>9@'΄NVDWb%9Z9K%kB}/g/5[U:ʤrj\?nzqh^q2)cmG#'D5E|drs]aD7e,}uP5F7Wu;ۘ78e \7SV|RA0k)7ZT+b8)4%ܲM,g:~U~;YDwd(z ⦸9#t>nKy?vPBg}庳XjN0[?ң_*|!imᵔ!Sxv9.0 M[ 0Cjka&ՖxxP9tz9-J[op*y|;!6Pf=Y,/r0J5-*9XYvZU,7A jZk6&8<ӆFMgm4(FySL1OӴ? *%'^j[G}6s*14v6p_*Ȫ1|F^GGzp(UѮ\yV.)\`m0XsWҥ̬atu57t=pU!FX/Z3b,).5c,RL曵N0OǣZ(Db*ݮ:)cZ㮵VY Gr+֡Ɠyrcm({&E){ V}ľZR?1t?4oi2=YWZĀrk8ŧtUINsB.(FQIo,oo>V[WLe21Zɧf&:֑k@8[&syZci0K(aZM&֏υV ""[u3[H"`yI5h {^?:M^цxn[Zǚr_4hҧf u,MA颞ؙtب浲͍~U4 (I(V`rWU-c?j$>ZyW'mɄI!7~oó>ps &\XP)"c!p r]1MY UeմK$''7Nއwx}cY!Fp!l5cQo!T0 ͧ+@Jַms} P$rF_OJx ni40F8uW+[cDfNU/٠m=r+۷.HEﭴVuɞA%hb1b@ k)+a[u+#Ʋq6Ic%2@}("28 䜊I_\%K{|Ցps/ jj;9$9ZNt婕*%?gk%%bhz Y_ =kѣEs64Dd sz{vO3D]mYªM'.OOȯiE#fanjڷ|5]28L>k>=A|Z汼#b`$Q8tTgIGNWS$b2AY2CX߅af{NH>;!F޶.I |\+(Ք[w^V\#cFKMzIч*ko^܉9ǚV":3BcNp@ Ue1+Y){P^i+%J{t)~fל 3`:U.o'!-s;=d\5\ FrbTqœRWe O1rE7VA}6@ [}w6WA1G1밂|w^(ܐ1nnkE}.3qˠtM2 13? 5ֵ$7 Bx4Z\FhmĶyU;%~G:SoދȚ客jזgVΣFc{}6t޻p4+ŗdq6_0\Odp1N^W8UR45 r-MZ 5-r,O]厓\yulm=҈w{VcjS*Ƥ~oyU_gO *н}|sSiwK,c5y\O[gKЖu.N>dCtT-'#fMwܘ`K}0?֓P9$iI xF}+3u]AegN3ϭw?hmR劸GJs,T+\G *Ռ{0ݪX[Y:[sP:Ɠ}^?9azso^>:uUR$a+m7&4\ 3KÖɆIH'kSjvB85[K|)V8{Yzœ%myQQy̋ w?\W66S#k:A+r":&u&]W?'/yq"4JGc-Nv@kOqU޵m$oClne>bǖ*0f'BL  -̦D[xcUtɆ|@ASIEȝ ,#y|`ԭe\.QkiXݎ>&iVVȯ }ÎjZFT޴|QžQ4r;y7jܩiT²իIlұx}"U-ըHY1Ziro#:!zv_ |Fwk/єKO?%Ս-2ӏl͚į٭-nƻO׽{  xßi?bv?#W]SS,3\jqr RU=]?s Rx=\5/r7zzNKvY*m?t\\&fQ_O{[7zMAC̈wֽ?^+]O<H@C۞¢Xu,<>ObZ'9'x+ xOEFk4Ql%\&G~k'/~ҥX}nq:mP[zdW^4׻M7NMm_ x>KNe*6ܜvϿ_|[xQuˡ%p- JV{{"#Uf67o7d5jFq4|他䞹&鴖GȪшf:Oݰ!osx5䁂0}* %35ܥuZwvHG zRZMjCx`}5 EpM*0pï6AFgۻ.\#^)XB@Cw+";$/jK_mIq.M>`7rMXH;b֮ۘl3nO6*˹Un<ӄ_p\VeT8I#Kg z֡ ap3qP1ʹ 9ӕ\RwZ&ei% BqN[m̌x۾r1, j?+aJɑΒaÌ-:C X?aʤ;ҧiĖyί4z˹3g3vPjǻf]b5\ا} =JZh$g?^jucP'j8h!sTPǷn{Hij%bd~1Ҫ8*_,=ӹZIv2o96 \n;=No7*X cҴs$S|K`ton/u&&[M#.SIJPIY>w^0OBf}rjj[FQ$UL3ZE 0ry;d+p ^]YùtpiǖDc$lA>P3Qh+{4z?na_CYԎ#BFwֱ)Y݊RYAmx e$+A'۩Cn2agI ;GMEWL;[ C}ҝ U =i. zKdVbPtæ; A|)#D}$ f TOZ%#{8Z Ap :khn{ըFAS̚p5 a;\U.d.*N>{~>դn4!JzXb3SZڲY8+֠HÂl[B-.~ɴճg_v>KoH1T޴i *m.Ƥ"O[8O(IP8ΎLFRsԬ!-3ړOspZRyFlvFiglr ޯZ@sڰt[;jG Rp$-|%,a䗂B\j>W;hH}VIm3x:2=)|.١'fSB+):ꖀKp̧?1Cb0D)$;21LF# l^hv7@hwB7G ٖC#5nB(6YT+~O{Cw4%8іwG~>5ۏI#|O(\86XӴm'<ͫSycdC*.FP;غ8fXw+(plRKT0,p) g5XA(XT㑚υ ?8S-\4l=2$4r:b2Wjw.nGMly5iQ SȳYf"T\sS$QzY1*)PŴy@[ձ s($qYWZ ' w"Isjj$E?)fR~ viJU4H_cF4l3$lc S ^3yaw(3/nmM܁Tfx٬=g$VE]ΏLmJBZHQq\ŕ#8ՃlTN1}mX[QI&8#žosY m5a]D|cnI-Lۺd1\C,eee0[de犖wwU’!G)ZI5/ڜ.YxS5kEOa5΋*/0JA*hi%denkBΡ8?Fu=5'fz5)IntFńI4SIܗB-a5èo. dA TtcPG.k`s:V쎉4?.<#41Idw+޴eo&^O@MeIH9yfUb7` RF0 &5 g lTZnWCz1Y$ϸ}Z D,sݥΨc%@2I3T9Frl `RNynkT+X:ٽN*? D2~V|3%.ўC˔hۨ!?^IU+K9LV9VCQV6h[G^yZ'l:^>"Ka+ZTӮ]֚j?Λn9Z@LH&:gگ!GJ-6育HOZw縁0Hᚨ;ʴ9c*,]E+_]79h>T sZzz@B0WiI%bVԭxQ }MHkډ߲BeUB+u%ŵUrN8jQ@ŹXkw}3@%=*94),=qP䖈 I]=eL fw=Ɇ'5.wV^*G AF!y;":YTa..9nN1Wt݇{)iԚb 34Y,bp Pȷ`nckK"7s/b5oNr嶧l \`lqPER4Bv6VΊZjи+t\SQJ0taTwp Kb8W"WQt[Ŷyc`^OCh}WR{Ʉܜ泬F/o4*%CvOWOjmc8르+$y$.k֓tbY#VU;UI녮S()(9:%URNS 2u4HU NQ+hJ*x/leڶ?tVRJJP /ү]-V&>ֵ䄏K'fZ\]N>-#Y:V{[l=9+I\+noD0]+YuvNhÜWi.Āgx bBF*=9mc9ӳRrm/K֠lF99*QClͼ@r*Ưx1KY`تKjWq\OlwP|̛h:EԧmrUWm|#*yjsi?[pFK#cY:f*]I,Hz|~u6i]$uiv\cۏ´l3ES[:JȊ QVvC"9h$abaohlheVe+,dX[-gZ0gξMdn[E2x.k'n~]wi>֓Y% OEs:Vݠ{ nt #v$qD~SnzE)Eŧ8HR=g )eZʖyH/Zlj^ZO12+?>+ZuUP;9vz0:+Au+Bn*Dձ+Ϭi,an4Ԏ~k:t{M_2 ۢ?*Niu%VRo2tmUP˦\J \t^|j[gʵ`Ht%A+Y}CF+)tJܚ\QhS͊^idPCn]8_\3OξXW<ͬqҚ՞ AgZO\I֩y–ם_Vwh݊"U$ʬĖE{;8T7I٣y=Vsưl41d.cWE~Ё,dfМNJ+~Ri}#GNЇeOT/5ȎqrZ5zHK OxF%d ?8*`ci_Q+z`Hij)}q X⼮?`<.IU>8ծ-ʶڔDnuo^lOE\fgݵ3"K2!qJ8q\\)Lm.o:O#~5mmu[k+^Ő87/6MmZ^Fu] ?/|w[8[KJI@w^wa 4"-}nTKkoþ.ТhḆI0BXI5#EV٣{R Ia{HujMAÑbl/^"Q↞Nu\eZ!vIȀ*$'_W_Yaiu:Eu6ɭVys#BcZ6d9+oA}?McdIx:tܣ&.hqV6;ndKG5jd7;dEQʪ󚩮 - P`jh6kֵ(#򫜴SeM;RE?F`A&Ggu $aE[^[xLRƠҳ|2ڤS yܬ ԟi잟ycP'Ym"'=:'R/Ms t3xk K?S`vO@<ͅ*P4ښQEQoO#\fXaCҡ+ux-ߐK<; 0֮Pto(?uh66yd KvxtUM7tzM޺'>Y^ أ:|ܟҴgk܊Uj=-K=!/g5qҸ]sZJdT o+;+ j~onbMHEnL|(RX&̖4ϋPèN&F~-.<)4(QHA^իjނOYk{Os i]FGO[a8 5GtS]w7+  ׽̺|+9T+IQT##&K !Gz^oj\Ix6a[ME.}P6z^ΈwjmkOM|Y;QIsӍw٘}ϻUFŶqj)~|""BkT ff&#Z =IoN& Մ/i<Ah ں}^=9A2,`8Q vm^\ü\O)#?ְ縸*$9VvMP9JFwU9^fT읬ie^P`>ql Å K1, lcԹo#pjҳ2v] aĊGd犒Sr|ZϵADGJ}bI|UrZmw ι>Sj"#RQKsCd[`}jV߲>-fLcfgQSIsFpN10Z`,$vi'}Dɨ`4mU +ف!dP]ɧk%v*(CJhL~ҼϧV+j ۓY%PGOabVF.ED[qLeL݃@3'$kNBYUV)=YD'CdsM}{ny' J=똹_4Ǹ ==贉3LiյL22Y Wg]0"r d<+ ԁJ.&9fȑa#187,Yc]t̰xO'* F+(Ź"Ls>,GٱJkvlHɿw̱#rx!>уr5c bh-H֜Y2i+\œeZVƐL8YRi#u S\NNYMmIsyO5 0O 1T1ͰbbޥzjmRinbr8&&zI_vРc'{oOlXj+$A%7>@T'Rz2H=7\ݜu-݋ Uy-R(VvPvQ%5fòA/"b9Ċ!5vXdsCRv5J6A1h,1WQcsOYӤrT[v^rOnKStGrD@y.-ivN3FJXB8jžE$sP?yr:F5 \bFjK;{U]ukeH]dBs5i1e8% WN4N.:"y!mo+H\K[K"usȭ P*!F){QuQo/#Ofaa`LUƯO5UT1Pڱ:Sү.ms'>V}|b l-k_8>jYrr.YRCoJU)f3+x13)fO)h_޲qV$wRKvݝ^OCER_ GS趃GJʤ`VYhPVgk5 BtHJ3>6R-Y76ĖXP`a+&.fthmKՒ6U8uD6)grsU}nbg~RS4PqZZQ3Si"bO S$R od+/ lU$S[YZ3'c!ǭZT N*(d}+ ة渆$gך+|.ƌ"ۅ9?t`Sd<Ҵwu: .D.$zV}Aq1Ȭ…wsN}ړ@-B33Q5̂*fn;>qvܖ5 #ͩ< ut18m-d}ZR0qv+>!%})]Fҝ TjԊ+$#ZBJF.);R&kd^:Զj[Vh Mgu,ۄVLciGe=)ŵg- Lu9[>s =Yp*[NZpi. #8-Isqmfi74 P͹PkJ-IYH,fU.՛- nMHN<_FAy #Ԙm7b8nsJm%!$9ܖ8@dp31m vOZF[E֠{J(#Vz@1w4m8JnS .nWJ9*0..\~uU! 0=>QL ы_@qz44Lu_yK2k6­I|I`#+ql^P~۪ƓkALKu#ZL)u9֢eH[)sqZl.ȁTqQs0CJ0ݼjy.UfiEq Sn/#UP*363P[;%n~V:V}—|C2ZI*`3sKXɹ8]U\&2lڥ7kEpܩu曧\jVdwMkҦV' 楶eǖՌb'Id/sPMSK;ta]Ɗ%%D 5Nk&}^OJnoqSrQ0l4x cnbÎ+WOӮ]h>jWX %؏fEd-N5\NRW5ty2Yg&LRZIFG5Nns%$pzU{?XY@ fVK]9Z ip09UiQV\pGmֲ|\F#c4kNN_ :=?GiF9 Ԟk/MuQa_)j3r EDZz2 XqܲG8ȭ{"qL; 2\FÓmj,o+3OzV}XnlzĖU7JGƮZ?MUbq&keB=Ң!nyK[-Ǖ"<֑ъHx_0ҡ`c\|ՑUIYEmmm<֝;+|mhN+in|#j E) 9^^:qMOtPI7QC j:u"h^L95oHke2E._K&G!֢U$ 0hN{ú .75<"u +CIH=bfq/|d0^<$?͊on[Ҡp>9j橢Mz5l?&8ԕy&&SQ,[nc $VgL w#W]KpJmhi8,cEoTAErl1%Oқ<13 R) ZM8ZJ'Eڡ.%Hb& XRTg W_xÛ?v1SS>iQ$b*q~O4w,xZQqmoV}އ8g]}7$1uv5*:'&J*̯œƳI-kS/4ʈ\`q5| HIeX]̷skwlNQTjgiM) U"ƪnefFGaKUUx|HXNE*mz#lf,h єFٯxۯW8A\|`95j]nSIiU rzYd\HeM{7aqPZY픎 sk< LnfF+H;6qMȗI@Y$ku1;֥:mF?͊ĨKEWPjMݜZq~ p&ÅXc#rynd՗kN[Q#H5HYӅ{1:cjAlVLzP-Dp={֝ƿݪ6ٛsFu]JR~zͺt{\|FH8r۴FU80[RA]zT#+j^o[}@[< ;Is\em#Ӑv5_P%űY -`k NH]Za(!ȭG#!#БTom\\@䅓^ }/Tu:xTvjާYiO&O #xy>a?zRZ%]K1^ ucͳ0V1%tWZ}~$rI mYo)2Ct+Mjv™}?VekBmf9ͮx&_[Ǜ<(5xTE2-~v\hep/Z+BfHXk:U\O,.Y43,y䏚{;L\[X,R!v5dY6(x/ί[ʢbBb9P˖d*k`WEOV5e4{]X.:H3'Z_\[vI=?z0 j GfCiGT  G2tf>󸵭wTuY͐?ZĻ{jݿƵ,bTzk~#f{7U23D2 sBV0nY]]$enr7K8g5c,{T_ 464>XNjϭMiixZ05i:%%e9'%efI<EbFve5*弑Ju9p*D6<6h7cKZ!YvA_ KXn` ʴ}-q:ns4DHݒ:ي f"8XmNd)H$w*#*].mZk¤7PIVZY7ͷ?+?ZܚOcmxNfo!mKpiH ݜUɓs1V3s-{Kf&+yT zn 3LlTN($=lamyXAFkF"RLUb%X 挌ְ+#zPt4IJ[q,բZ6¶hȮAT9,,=js|f*mu[.gnҼ^=1hZ: mEb%*Iy(s")Ԝw:>w4,@$ ]WN⾶ q>&ݯa>"M&a3,,9`:eus~?N?Ay+#_]7lnzJ^ R+Yb<)ϊF`2QhN\;$UXഛMBnz(9z$Mg]\qcIiojbY_fpfkk'7W=([:O&m8ZE$RA yGֶF 8vN'NԴեO{eDڋ؃m汷oj8ۂq^n|iL j&Y.%$qSJWqx+ U7jrc\ԃ_y\ vY^Kpem9 Wu%ݬ%{"3r̸$V׆t _{)lgN[1^ϷΤfI8q{1-;Tf+&C1m 9u}7Pu UsAߎpMڔ1%K&vAx$]qVUuڹ<sY9J1aU'*ksBéDGRc#gj3F5?qh#a5.7 p?*蓌a{Rr [D]:ݼr 1gIpƫq"jvckVLB̻'h4hW<mN,z~G]XJ$mϽgKỜ "ubUW6%Wknm|b'%"RMjgZ|8#E{{Ź(]|[}Wh??I[ᴾ^>X_κ_ P,m&g QYB-97ՔB4-a#q4gK)^waj?=Q;y#=/L]U0w<@kJU-VҖ#ά/A>M8.u-jYLMq9+դP9'=R*|]F`VSoDD kH_E!K:nx{j"2$tU ]U`H ~ukIX5(ҦRq]. 9;,<{wꬅz"҄:Q|ߏ5٤WwO-w.AK;[Փ+rf ri7}NSP"[oohIc.Ydɫ_M8ivd-]6ȸ ̇$VV\'HNi5^:'bc/2vVxF[6XuY@?Jח}^ّ_SR~!Rךl޹Ea' m ֊{u咰yvZv/>mglu>&b2<򝑝V/gEe eXGMI&tOS|Og:4'X~UGo G$t aU|җ51]ڪۋe 9zVu##fPi1_3.v*ڸ ^hvg+ҵ!nWw$ z=ͤ]Dѿ>L)"a׽u-N9-X!'I-SI^G \p?*4ld %|= iԵ4-]"..-gΔe4yu+1x5X7ֺw +l@ 1,G[ZwK@FXʵ_#PRZRMU.1$zⴵl&ֵdM 'kKV&Ӟ#hV)1i{cԴ1l ~U%\1]+DrJ-FARװT~%u{+YܦS>cJ;]N+J4D/L^> Y\0̏N S`DV0$0PM5V88=xr9i,*ޕoz RIwup,nҩ-Q~P§$ɡMG196NJFFT&}RGm>+o iKɧ#&Lۊ ^Ѭ"^|Y1[&kCZ9+ԾIJ_E \hzqԍ;UY'/,>URI?{=4=Og4FS[4go}XD,՞a ͮ(~ӑ]֟$zYΘJ6Kqg{{Ls4K4+^*kU%v*q|P嗕= ['K?ZWtS0jޤvB뷅k$(Õ6gKK[ er% I|.gZMsAZY(.a1Cu  #Wԯd x'4{1TҙK`eգq+*ek_}5X^spn8 \![UL mrg;.VFn\[Je pnkd@QĊY2;}2,M-9R2xªT7v2HZ*:mRw ukˍ7ydL~P)*ܒQ.zX ̝ĘVQ+r8uj[i k^adtǾk/_[a8U)J^:7WJ֮&H8&^J负C2\aÂ"gPA-j"1Mb~YSzE8׌5&O:lƛxoMiwۈ #dU6 w* h'?\-fI#;#ִkIh/KAE>\!&.}g2A,Ι (j5]J|J[ (%T_i$)<騵mY rĴEG${YKa?:$e@Vps\iFC%Ѐ|G|e<tֶFqHڎԵ1b-Ϥ}^}-.!|ӜWkRúEKp?*{cjR[n,Cr'o'JZ+UQ>9x Q\Ev `VdW-{P4cW<9inTdV3=JH%ʖK0ErJ/ p;Et~6B+zV06˵yv.'`7 a}jRH28Ӽ)= zrK0X);,878^ZI˕tnjڒcV+'jZyIN95G$b/F ڵݽ$|qOM6QOe #9B9t3 FO/aڥ7s7sC*^z",cdr LpC&BjG#Zw|SMvT2p"04Ȣty V9 }GzdkIE/yj[,iy<_l~_0x$NqR4DR*rdU݊2Gv[ڪ܉"o@}EF%cDz*К魼, M(OT۾֛78Q<*8b[M{r`,Uɵ`0H6ļqMT ⥵y[`aXm7f27*erFeKK{9 I1xMu: U{* eHH=sdr{9s(j[L?Σxê1s3J3 )r鹵ݺ6Zp$\8xXNpESӦu ]Ll8qG6XR̄A= Hvhm*0jq{jBTsܟJm6c(a u&KFUAĎ2J*9h [F.[8\#qYg;lwIԠYKM68ZxB3ϥD7VH״V|O\T۴ҍqZ\3F2y'ǥj\T*?a=-֣[Mh K>Q"DY]*5xAR yzW;in/pFMF湊Gh[C^ 6ibXOWX&Js+:K,ojod(ҳ͔A +>%nCjqpƑf-Oiyp=lňې$Hܤ#ޫih&cҭl|r߬.)%s>yvCN@v^bʨ7n&JdS(rU8BA-(d8ҷt!)n˜TcXdiOCk'R6cFj",Kk-XVB9<ם">VY- >fшhrV1p=iw;SYzEH#zT:<̷@ٷZ]d_6N ]ݵ%PY09nqř1U..:?"&rȤ3#Gj[c~sQC>N6+CCX I&6i ε[A4Tmn&篭.p9Q:jUcFa8V_%;.: SR;GJF+K}>ټ4M;+*voVIFW~=렶L,k9l_z'.)+#NpHAtpy{oz\2*&y7BnousM|5mwn"W:kAR:GaB:YcSTD[jLז;w *P*ЛtJ WZ\\nּ:0u_zyWZͷYI?u\(n赝9ܻ=pmrwi -վ|AA\<3Z7w1h,Wg5gx~\wj 'ʛ-#5jjqgIu;R$bǧRZu ]MN[OgdadAfNqdrnfqOJ:M9E,s!Q2=ܳ7#?9pZo7b+L2gh$O]ڃ3&1e;=!Ӳ5qbcupmP $(`°fnm Lz7J^ of vYTug ops grw JM}eN i>~S8/_M:trj1_1R:o3,9W:K yw$5H.=oӷѭ stwʞkKَ2nB%}I&Vm# sY9h-V;f1qIZ[*bPZo{1W5&|-mYVT'ӴK8SjzJ&Q`5kYDKm pኩ/-EcP㤭')gOw5/. [Xt_$ _2gc5- ?RTUl7zH*;[Sjf#s+2Yxxx'+Q!3;k59Wd=NqF6<.v՝K v]혯P狙cU-pCkz$Ա$F{k_OPCɲ^qvIE{<1v@Z躝"2;7B=bmFFz#){I0#9V? ݬ~bPaS!9r#D2q*HYuMDBFO$IcEs g5SVI?caQvs[H+YtNJ޴%cV;{y}?Kٕ~t[İib5Uպ&85:K{^f'`l d}J S/mtIjo.j.S#'OZ(?z[CtO'hUImuN<Ս:ذc*OQ'^KӚzAcQ)wF 1[mcIHHhVfdki#FF@fg7˦V"fiN2v%Ӟ.RO #;X#5353,AflxnGlGRV5Ts+/i=+gDۙWqZ)&f1o8` ݈d"onWz4jVZ}mgm-19kkٲxkOyXZϙsr|t[u~[Y?,r~cu2kuVF䝢EEfsڏD_!ʷknxʑTkr%FYM7]"Je@:_9}3P?9YN.Ě ˜gλm2")~αYT􈮭8猜:u`uIU9d&T+Ki+پN:2w{®r9RЪBX[\ [θkݞyS VۭE+}̐HQx>w)8AjaRyIi#h2ùh~Q9JJwнkYcqҨ_k/gVzXH$Su=)U-f5Z*ה=ImMXX sTu Hl5yH?xöOt$9<]&įʮ5OQ'-|CK{ uOWVKvYܽAj AW)ZpkIGB&[wwxG({\'&erb"CSCgxl#k^J[s^Z'3RU#XIߛ8uyfS4?H9pȧƮ_C2]L9t"w%]9r\\Ӈ,[b^ /%ǜ$jHfAByơwP>R#gOfB9L?gx/L)󩴍Oa+DEkIY_QӖ5j?-~[- _4+8>e&tɧ,F>,mqݕohʴ ګ[ ye{ie֫: HYFщ;lxjq%W/sSIi(N´|C]M[nb`V*o/CZ"+k~`yt#+snm 0F$p2+:u(n5Nҭk_Zv}fIe-H+d0H9ܬ8]rk}NY5g5V͸ȼq`~uѴ*A`HIYq2<R?ǩm 8csU[eg\OKe \\3-Nm#\4 5T}No5v);|B[UggM+#kk<'ʹ̹&6wr һifRÉHs׵yp"FWi>|.jއ=8F3QnZugSj>ߤtr+^/\ :|Y"U$o؉ACe:\/qcn8 :IM:+3R#)“W-i\N'k5E>esKr#/Z5ƛc~:3Lcߧ0SheV->f`#Fi9Oqko[8ȮJRJcg;h7Xg,p@kBYa &?:4 >$"r;vLvʛ Qk%K6bx_ɒ+&b~P59ENOAFbGxm{* ( @aK'PĢ-]AP?H#m7<sƦI5h;v?kl˖I{TxoPK]$>"5xɵN)SWށy[+ #Oh !7cC"o"IXYamcZ:@ Zp\:3<KnZ8&oyT4k[bN{WZV6//^%Ob'Ue9.+J.Rw5m-̭&xSkT]G#HKco ~PJZ^6fONw bAJ{7iyn^:Gm Q|Ȑ:Wo{o&g9e#5O HGoL`y@dN;2F|xm Mg dΠ{ѤH^BrCc_F_:|V^Qϝ(Z/(R{t$2ʽ(7:6M`f/ac-mPl3Z_mxЏS9yjփx4QVzmZP:Ӂ] MxI+f;I!C^;~nnnF=A˟_{oKuo^.RJzϝurˌ3KW5N/V}B~~)S*.Yw;QE|j"Ƨ\}\  QJc.Kg$Vq ]~Wh3KTiz96A"qqQWh8HyО0sKFqiO hU7_QYpH/\cևk1B+6fSJ${] v8ɨ] |L)뎔eEhkm7gzieķJ!%TgF^q*dev~,l yA#U&w5%ߗp5(Ȝ+~z W;OPjjIG;֑Vg%=IizvYvdSVZ 6C7USYһlmv^B_pSN'%8ϵVev (WN.*aI qWd k+o ҳR<4!8 9 -غqZ;"eieDoE12~bsRG>$u^;Q}ߵ͎ Yc u'jͬeNrɫPf64ΤeA*#YF6gh.rH8`7cvsU/~vz)6e[[EX1VnkpsQ ;8(à5 F02WwFY2%,"NÊnb|1\aaӣe!kVB4fݶS ×R޺AeÄvSCr]dg#Gvfn"SmY㵐ےxݜO4=@ZDF5 1Tv%:('v6y죌Ÿ{֍W@ +}lA5LvR $RVWe9] T!\`\K_:\!`uϜE~=*٣#RꠒM-4I&̯` i\30L`yvێKu5=0E>#.}Ȼ3pёt>S s#'Lxv$RkDH_ )gQ_jvu+Į'xs)i+6)]-dէ\Ɓ3sҩ3z"rQOB:Y RO2ަ#CZ3GxWgHD@&hgy=2OS$QOѢvbqZ-E##q5FڋFYd'z$ \)C\Ҵ|n[^dr:{V\ʜgZzMH!"ubtlr67 >P,yj-sWuBL(6@Mr ,$I{JZ5Wk\^SHq+@ӗc k*p@ۏZ,[0ٴުȎV7*GH yJi۽rPL^[tVF}a%Ub:ܭQ^[\~Ʌ#* L(qW$$ p=559=qCem D8\9jcN=Nz)r2}1ZV1sm8W2Bv*Qް甹z5 >jU=[Ctp"y'YQJ Qrv*8d89Rv՜Kcw|ߕ`".$ +ѯgX#e31S(Qэ d, bK`ss܊hF_\eVgߵim.G29,C-a銿n4'"\g5=dp=vݯsx8+c94:7 {HqI`FzS[wש,[a<Q/nBԦ$贻d`".'t}+P1oM.N݋v3i=vj3VQlɜ]xv&i"3&u%ŸFUG՜]u~G,&6)302'OJmŬ )bPK1Ì`mI/#t U[b+};eլ`\E=EhGdqKfN)%"jOj cʘZ۹ѭGJ4 ]BIYUOSY*4 1[jɨf٧'zk9f;b p%It-lJKϱp-y뫕zj[7&kԵt{PN^'YjjW Դ:h`=v +qƂj&gi)r'U6v:Ұ]+%A&m;V Kd9f6Ű0@8zu ڈʚq_K-X_dm01ֶt&y#j=A.oFn#zsY9h֥S:j4o4GgsHJn.PkԼ=L_SӴAoMԒ!$Pm9яȸl-1FnRZ ȧIhOw-O鰉mTB'8K-5(# 3Y3\@21^[G/^`s@*0-g ydw8cvzW{}4jL k$@oKHvZs LuX۲6i:)a)]sV8Ck#SAȍ?κoGo3BB/ץyl?PF+ԆaX?idѳ1tmwmk^ZM2gf|PؾkF+-tyeTsI]Gk"X$bQ-їR `zW76@IGi7&~@[w앑s%^8zQFnX_B,G1]Z$Čǥ'[C\ ַm 1#;m6 êm!SoTȮZ&M۸:U%%r-7d73C,*W?=asi{8Z"yܬn}5\Mx-AO'` !$@ rIZS6(yrLYId}G(2z 4UbjP\$(H{IkyVy;ݻ+MWm-^?|>}#W34Qfә SYZd&\u=dB- uKX>\mT36=GN7f$+I&Ce,EG9~kD)9=LIJG v;>^.\[4! gkWd[JX6Zۭ^ⶍ F`ۻ[|TTGMO\WQ׈[KkWюA;6@"\Ώ+VJw*rX-bT1M m81ne m(QZxy]Ye /`י8Dͯ+zmRzt#ZoY+l/Xd۩S5;#5)@?Zӟr)RP4.t+ ).cUŔL0%u' ӭbO,\U?咺"vD:3\+,>38i3$>SU8OG h1Y3Z$HS=\枋cTWe[OyַQ4}#U4'{$ ݽyb,uX$%_+Lu:MSubrs"խn&vaYz$ÃcrNIQ`Y2d%k64L OY$:Ik[ݛ39=R}; ғ{ڟ2w [v< TxrY|in@YՠK&#*fTV۝уp՜x_NàV.ll@Cj$тQ Yoļgq|Jj^P4邙kzoCFʶ7Л[—8`jxt#Gk/ĢKI7LF ">yMwlbc[Z2]xty|Imq G)Ve\oHR+Q=>jѴ ۏ5`֜iqrԥi-^L=[rv)5h~7\ޠ'vqTt{yԤ+Қ)r|Ry$ qSe֣aaS{&c'H۝62\bM:zTY+XGݴ,tiy.].ir\mˀc6^3GWz7gaiAG 6$K™0 ]'u+#Oi+rݛzJ~K"PE295x<`45X,Q'zu ZS"~2|̅I(f3^![}B*$>Z߾O*)S k>QVT6ƃ>myn$D /f̥RQ\wVfXmK[p9pk;_oMeHu+ֆ,jilFvծ5MLdJͧNeBj#]Oɺeb0 ٳ$=K)[+Pخk;&NiG,>J+騦ݎ+7(|O,nƱ|K{r$/% ?X,m-m2v ])E[n օ%(^y.2E^53`]NcOjeˌEsiP:%)y-q[> n|<ʲ❖M%%iE!'%*~TtH.bkQǙU6"jq2/ ZAmI۰YhĞ,ڴ2,#u=kwrҶ !|Ek>֟Ry"kxM[EFčJrZGcOg6־g|0ͺd:^ |?XJ>ƭ,ZNyֿ|CyerR,(7H0 OEvcBi#4!뭧qe-dyBFF:_x.g˞ W@ZܰɣԔ~xd䝧sВ-E-J@G^1G@a'Fe/|rJ4`U=iv&7ZfSöo]O5H-/CN-q<^bKFcʤz;:CFM8W~&2~쥧:Z޷/EzLj4-.'y/Д<{[:K@nظt+Eų.Lk:畤S*J<cA<;]>^g?Za.Ȼy:pϵr>&d7G%SV򦦯fNx\{iE$-֫i 6aMpB9A*˂XKn0J~"ӲWjQʦ;=n[[Fq;SS|Ai)b~1!ȮO5{M֗W2HGU`VRW<׍=N6:!PsMtKo"Ac!ЊDvEk*n'# xnSib5;Ws2ԦӱgߩWrɘ' V4"vTSn\L&:]pL9TwzW'FnIΔt2{ִw׭ǓujdYKV7[cGP 5MPIb}G_lg1\4y rq\Jۚʤ$wL쬒)_"}"Wo`c 3sI1ƦR$"A=Sdž|ⶫ؎?ZjGE;1sx/5,d1]u6bAc+׾&x~{+f͋+7}E6ra]Ws*HXp4>kiOW9_n5H|I5Ӧqhyq:XP ~5_0厾s{+_qګЮԓ64F 9-KX泪[~pn0|E"d79DZi6+f%e m\ܿk+]: [wG<3Nq`خ,dAJ@x^qk#.uzrC?Gx6٥n]'v,TT{|pe_/mȮ̟)9mRj0r$ +Z\RjKvqQi^FotΚW^*c?:&; ZXq警7kfFO2X`N6^hVKtN7"XTB,NOIǂ W=VCc~,Ɍ򬔣{pڅ(fԘÁW>.k[7\Q|'yė\t)2o-+/3N:[Za:NRWռ|IKm쐅NcAbXY,L6ʌuOR-( }.i/#C,3q0Ѵ. )%o x[&7S4HK>9 [V28=Uu(cЮ kX<5Ŭ,+IqFrae1k.DA+fS!IJs]<}Ǿ*v$@9:JBy?jz\3.FH{թ$Ycf=J/A)+&`E9`{E y U9#2r23Uc`C8뎵\ƜF+̒)#QE÷ QF1\R"mN68%L`8u㚪.J9mrHy.l_v"ۀIWy0M=Yc*d.տc,{QEm K"×3Y4bM֦Vɳ\&jvLla{V-/$VQI~+Jv4 mnImVp҉'"\}6 LC w2۠4c T cCf8\]Xи&! 2[ SlS~T{e|* GJ-e%WV# ;RȞ\*P砪ZU[o1rqLFN n|zY%Tu[Gܲ Ɍo4TLсJRKV3XyԷc=ьpzcQ]wyշd:(汼׍"gv(JbBTF۾WOo PO\T1>l{BKpΤsMgv=KED^m*mWheCzel w0F\(mb}WK+k_2 VbjۜwC8dVcZ̠?j+hɝ4ޥA,$˖QӚ@31vt7& ^p '}*{K+"tFi+"Z› 9:j3&1p kl{wl?N G}ʦx_ZM$b]w闗еlp޻`ЉWV_Ɯ$yt`9j^(a<7$j yo+6U%R\F!U'*+Kbo61*@[ԟ<nS95 \PsRQM Ip`jׁ!{$s?X^gq9EuT@[e= {uyެsVfCBx!z{4|VŤ ZR[FOᆟ#.҃'8gG,3d W]vG'k~}ݟ]¢}jY7x8`OE\F|=.ǣ:ciػHl 䎔[kle}=rN!La,±\zxhGN*o} Jϩ͕7l3uSp2quq[%mw"ۨ?f*GJgb$]9Y㜐p+gIک=j-BYc,D*u$a4R3f+6jn/lYسs+.= `䚽kipXcn1VWSr]eV2wOK2*];V0Ux Q uYitrj̅ H[axHKH߶@&lk*Y-$vx"j%ՌpYdYa'>89]W0bQֵPInhrwԨSޡ9}:֍x%@9!ܽsW5$ڽ|jmFQH!!۲Fa(jc]Hݻ..*-%Wq\£RV34RYǦEd}Qksobby(9Sjg.o_!)A d{gnh4Վj=Ft!rM1[Y2i]i:ũ&YJ7_OV9|٥ARm{J^j"0CY8VR3 ahXB9 jiEgǰ.8ty5ݺesPh#Gf$ף-lW\fi+M`;mJl*qjpv93rܕkx1-ӫHIEmD b'] yyjpWr ;@5g\5]NMzEckڥ4Ee7#'2?:Μ12ߺw'k<`:.hd[-s)]Ee x5"jz넯Hhg*ωFw gNWvK)Ty^5)s% S+{KĶeZepеmɴa8뷜Tu/cZ~Ts~ !ɒ:E\|1|;v[Vw†6"iW'YJmhR\?#͛ÀnieaHiq.{. j+sip< :֯ 1L{ZqgRNG#xV2RVr\M  x_JĪx˭.c, ΪRW8ܬ4V@56jYlHFCp*hl3ҋˋ{Vjٱ m6Ǎl5l[꺔!I+]l.8[:R\tKُJ'LIM~%]%~пΡ_$0VL`tq7$ 5ۿ[0{nyO#Ϋb?5*\,R*dcqMx_ut<|s^p//w+ũh:N23r60n#i~*x3oˁ\Fkgi ۚY,lq[N0zݜt'7 k?Sb]rkp!U?6dsږp'aT VH-X!n0:~ui>fOb#^pW]5"k$h\k̖kFqm26^r̨xSZ&DcLhEB>Y^+ yp$@擢iS-ͼ)j:<, ]q͘\#@cXFoVt}bW[o٦4{J+(5[0]]X:H|IkaLXyGJıX(SiYrr-|4yQϢ"^jk0:+֦[2äXpa&Ads2hy%\fhilV\7fz%mdVh#)^2ѓVRݡY3Kv0Nk6@m!͓+5{YBy9Ͷڰy k[մUO=dbk-zh%nƝuuhЖ:U iFV&ړz~N3,Ȳ>rk%oX` ޲1&}sS+KqxvR<6SNO1?FvV]ԗ\iDI5iZS;$ Qt8zoFdAI.e`x[ƺQ4gξ#0 Vּ0ȶedu=_IgmUF Ib`U5G gg nA+ͼK 8+0ֵ̀t5uSv՝.:ɫO!?묥#VxwP2Cp͆oCfh 3G$j- g6u T%9EZ|Ra9sFУMMOkN%l&8*TԲUbh[Jz2?:TPm)I?ŀjz||r H(-#cߑQ8YE(׻RUI#IhvN!Gd=JɊM$n8p1Ŝސ ֊ҍұRJL/ls みV6mf pM3LM &PM$֚s)ǔHjzZ,Yָey Zt0#85zT}[ϐjݭ葿}Pf#FLunakc0j;-͎0+VWyfVR'E;.>yw#cUyeiԦ;X5-tqY_E ec2/5h%oqڔjZ7,g= ԗmnT݃mdRZrAk3VlұFD<[kFmIiwWUW2g;SW: [z: n|m:->$| FuG m "}\w^.,%RG1$z fKcTi~"Is .Kasmie Z=&ckQ98̴i"=$y1ZD G/Nukkb]v'/JF\&:!~">Ā@5kK<0`WQp\ qg$'xqC\cjj%g?T2i1 +wcL UJKa9Ϛcqbf\ck*: VQ>:,my&>C":Νx+Mag*S=שt02gBĨ;p$_g$k5ˆC4xuv $b_.)<: )[Inv{w{/%KE)RǂN&^KEdR! jF!u%k&*pIKRhHd$8׶'҄,xSnj!TVsm U:Fs9Oų'YYED$fv=Ac7(k 1A '{lPoe;i`?+ ]6,#5xu4xcx[7Y}Oa(BPiҌ׺EWw#iť!_=cY_Űfk eCqݙqes TthS#&£ xrKqC\ p{tW3 ٪~)~C5^c=V!@GL5sKnjFF"oؐd$sIZ2pei+P t'"9Š׾Mp8%XDfF 5JM;)!KYjNmlZFFB 0vY-S'pIa޲|O_21480drMk{:+Uh/٦r2>Oi`?4BPP*p7&񎇷6sm|w4_xS@/2H Gs^kzز}&.9)7Ճe8Xja]7/>Ӽ7[["k_NӴdg*8W/5dSy@Ӯ 9Wɚ͈5(ٳ̣cկf knd"&$vs^_u%ɒGRs [DbDk)+cEk9uu>9γik(te~\g(xnM, )k+disJ]i"c&+xz~}%VC]▕nl-H5xj!^{iPlX2[m\c""|>jJ@vx7@];sZ]ok=Q*6tjާ?kz5kNU|XbT\Z=7R{DG gsc(ED%14hCTcڴ +~2q^,WcWз)]9&?DeNZHt2ڍDNGpO{o \ڼW2ĒĉpguNG(qf+)lW[XRR\fSG_ &}u%''h^1x$ɮTm0[^ _G4n% G+K.`!ľyβC~m,K< -/H*Dh>4үb0w#8K3XrPoo; m \*[W@KvCyvOolmt@ZM(F*sxjٱ銸Y_ ZI cɺ;6Yh/eE?J]zK U7ʺ Mhr.{Sd]Iy(+r2`5].4 yo1Ui%0]i11^A#ҴYX#U(TҎ%fKw lºM.K7xgʹ+$.?jZHu*E_ǩC8Ó>V|qƥj3瞚k? [’j:m.,cP-UU]|7m9dyR'YH{V5tn1NO M>G XvD#U#J!{9}57mn4Z.6|5R.k &Qݼ]8Z6lFMg}x3ZQx+G%&XDWhC?Wl-QFZ KKs >V򛒺wF~ǗKY$ARV\u? 6#VDzz oi6A٠ŇyIZ$p.,D# R롤)&p^ Ԯt3AA5x6˹^1Pȯ= vfEe?2>ӧ+)9PE%d\SO?H|Y[C$ZCcQм9%.almYUJ%R#?Wd؍O3FFt}A3kZ%< g85KhYys\sk%lma'6:mo*? YuUPѼkm~$70EpJI({m VBVTwWpBsa\" <%3c,Dyi\"ƳF-tRi]qia닽ZۼԬ),wW}mu/`R0֕%NrqQ*i{ϩjz]+k=+ceHzhYғjeiQ*U#9 ޭCiie6D2Ka:Mq :}回2cbtVltm9Sw6M-*(%nOL)j5Pv>0XEAgV691WM J` iȏ;8Rt זp2zԶ0(v3uwamb"&nGB#a~8rsU'*JG@zSNF*č*$`ojX1A5reP0qO!왌6j\[ٙWNo29anj|Xr+O.RB{Vao]nҶ.^[h>#-7U7lEW32}U0㚟Km.!9=xI!QFe,czށeQ$[, Ee+Tz˹7=)a?b]ý7Nsm6v`*Ȥ*e QA8 KBmծف [MZ@I3xd)+s=m/Zq%~n.=|X[5߫[(bl~R_ca7k$RvI%eHܕN-SÕۃKk4MSZHAQA5ֆ&X1[+"6ҳnC#2[q.0RhqosKv.ٓf#s@8X#tfrLpMtZ}!WAr/y0I6J\Z&E9-f[7lf:1SK+'˰Qڻ\XCnI1|"ʖkwþ$`ǒ}*;w*ePO'aLs9NĪo 4@85z)Ч\ =k;T$3I'vmQ$g5e592euT^>zK[Gwdx5_k2k7VEhC$ FG*Ȟf;Z$xmT| khZzYaT9Qi^jʲyf9+F6ooj˚)Z J+^ME*6KkbHMJ@{716fCzx 1+Κ*:2ZdDގ@V N^gj.$ #ֺ9Ӎk>!0XK%ê;(aj/2ޡeg$5PJɄOd3Nub5݌WIg,dfV]}#nI+_S9Ҝ1ZRU)#; f7dROr)U$F*/.l!QI늫G4eD8qAs*$j88Y:YJCBȯ {bTs۹48Z3$Gݍj0lg*f5-;|ֲ36w㊚%OL[F ,` d"ߎ)h=r]o2OʌwM1$\hxS^ YJ&Vp{}rx~*/8GqCeT`*;/Ȝ#SWcV2vFŷo)bJӳ 1?.|iq!#gx~!~v9[~)=+w1x^&P{!, bT]jl}rOOV#]H,d%?>y88[SMPbӐw9Zu1V>zMi).[]g,o.?P\j {t=k m>EŬC1P_Y_Zi3=F Vtɺ^?Z9}lMu׶@D1Dk* +(nWf[h1DZ+!Whs8L_EٚmIcۋT(.8Eg7k&un,ՏY!}@H5~K+`` s:O(R9 T3k7рY Aڔ"tgQYJְbH֛ngny]&,3jqRGuo95MLdFA 8ǡ"śLՒfbz`yurc2T);E,?ub&HYmdͼl}1[K ֞uefIFz5(9xEYsCnR뚪F:gE&s,XZ6#5>fAr=CQmq{2j(K Z/ a"K9AIiTE6SOGycSRH sVVisۭ ZZf30?DbڵKA(iwDbqtk]$4m$ u~&l%!ձ]BHO'{qNQI.w mi'0HRk~+"^GQ8J2z3Z(6`ZVpv8'f6 \3uj1_M$ ̖ d2Ae6=TU3U'U:[b| '9¯=(8e- ?Ap !SX9:Zk`+7mDMܗ%1+2; )$}QWd$a@c# kC)RIriBܼC:M3~1h=X犏Eo'{Z i(ܚ5SQ_ nb\0 _4M>LrAGד{1k4DQ+41ӚLI^%"tv-QS:λ[J~U?g_4hl(ɸ `b1QQnt ^"E28)gX̎+)U#qzmn\ dmUZM1Kp*d,,5=KXbݫWiEKuir̝x" ֈ|&rN÷Ф;g@Gbt+-mBZEe5gq6͸8kM4g Ks%,;A" &_.Qu58b,9<tRJ5VWzj%v:-Ր"M7+FRxuo[7٬ n2Il<'K噷ݣ L&+КзռYA"ye*Zŗu-;NnޥK+(; a.zu1o<֊1;F;.f#?`Wݏ$݀J>/ok,9חiچ~)OtZw3(Qucx|L̒]=57ȒB~d4΅p,2͞޵w5tZTFj(6_Ʃg^ʮ9^wy[f#qYw-8kӺFޑx.BapOƷњkr+W%+R(@*4K.}MOt AM&PAx{ N+뚀#c}jM.@s҉2רBqJ$"WYsxne۝RM4QϏ֬E61%9MƩm& $x’qW^\c2A]_Yg[9%SJk27s9&WH]MLm?VIU? )Zx0G`Buk ai * N`>Pq3P׷S/JMrH^.g^KŖ{wZqġl<5+M#BBtVmVu(0FQ,Ҙm&qǜ Rs$sZIڢj͕92X ae95KR7bK{C)H`Qwi8MŠR ^n4hO'bJ|s=LD՝6`-unqPK[v>_3",C]jHElhwwyR4#yE5C'.B1!5(=)W!u#oL*cbq&oJE+Bsr ONDR"wCS\RSY0F0V_<1.Ry?ZxxF-O~X~sPudj/\\G2_AJ%/eVG9[R|xn)|?Z`:\1d|sKݺeҫ}%d@Ou%"խľH[MWUmuma|#-`7TSo&%:[x^n9g<7n!4=<@@RE5cAB9(zҬY$ƲMgk^ZGt  Z(LQ\A2o uq['QZ+A6o1#*QSoSPoLT#Z%GٮvveLT:nRC#5{^[?c&8'>߳rM2ʹU!\ ebV3}ͳZ$Wk.xb%llŸ2{*Vs6z7E啣cT-iɠY\ռ5]mh!=2&"&){NSYM{M5=cKȱXUe乀]lZ lڭhl͑d5?~SJW圜yY-τvf!T?\/5}2i1.*ҽgW :#?Jn ӌ%IN:}xT$;\#³]A1XuKJĿ;IU[yGD FGn?$|#m ofd*,Sh7nr~5|[$% ^*ڏĺ+tFMKWXEЃg[+:QX[xk1KԒR=+W֬p\8dfLln,QA2ϋ }ќf4MCF6۰nF'Q_.GCyyn̶8 75j Dڒ8?JTŌ96xN0.7Ќ".Y*eNڱsėV—x1]昷*i$4X#=5j ۽%`#=Z[RXSSSOCu n:^]B]lY?k5I6{l ձ?RԼY2C׭5(|,?V#݌ JҎɥʓ^ץun*i4?ƥao"Sք'dAүڌaeA )Di,ّnEUdᤞs>/ދB-VDϏ^s^i7Yo+7^͕taH2ZMjμ*9Y ~+}J̪Ih|6Kw=Z [qw[?CQi_ i*jԧ*| (Q _{QחUh)>Y^Ut.w27)װiC/lÓ&0C]k ~wuO.[3YcQs/a<>v ~v ZK2vNDV6Xp?d˨o岛U[;8_ݒ?>q62OgXYYʲW.zb++;+ ^l|7eyYXߣ]/6ӯ PzYEj6Zv8?G]:j\8Q^h: ibsץj^'fS}?2d7t?f ߩ'{em(N*#S6iשK#t潏FM5y֥x!1@tܖsZ {=jY#^z마᫃3U9gz7%m6z3!! \ad&ҾK$U1!TvVR/5K&&>r;Y.f-f1#ޤ{d &A,m%$Uʭu3Я44$^ִ?'+}mv8Z4C{h*[g ?:›:SLMxPM-yĤ-ZY VH@nn6ZΓNog+@N M,w٫4C$V'Rd`yhtxCڶصK=m6zƜ-r?Q&]vskk]>\mΫ[A[ib¤}JVL5;./MP v1yZQ qUL-Skе?jgӵyHjϗ6NP- آ{V̍m{m"*K~ |V׋F4rҸKk[|Һ0Pܦ?%UA.p[#'5u: qݮ>0iWIU8C~Xm4C)=6hdyT;nm-ۮe֡>k5WVќRʢ2R]YMq=$v8m'7VsfF95A [ zL$eoq]r?)2x8 7N@c %4.Ygxb0}x:IRٿ1maϾj=?8!+90sp:+oxvuMֲHŔ"$.C7aך--1_UwTnm4ۋBPΧcҶPZ1b'G~ a;++@J a@1Y?gO:U`T_>(xzveOok[vAWjlfYܹ25CМFX/TaI$ƬL+LVdG|ӺۖTp6pjyl9'k*5;C 4#3DSY[oUPvzRȊj+T(Ѳ䐌`:\܂Qi 9rrccgb*7o+pX7lnY#8!hC³lmAqje9J6] Wz.'eLdW; 1yǥd]]Hw47}ޅͶ; pF۳c,n*dKY Xƹ[h]ۣ,1n$Ƣ_'_Ӿ Yqaj|0ARqZ2$=iOEaBԊ7ݸq$IZ֎5 09Z[ 1AgdtBS2(09sgւ56av 229ؐN1 jʢMJm0T Fj[cw?Ҩ(#!lj?&K'k^f T7##oJt6}ीUSK%7\pX}jȤ9*Ãұ|B3/zX(d!*K\[<曧X&{^d A`*ww#$9~҉+&rIϽA`I$ֱG;4Qm_V܃9&[deKg)rZIؾin\+BH;R'gLE-!“Z[fJJvq3T-ܲ7HlOzv1b{Tt6Cʡ#OvxK{$Q1&e<m ާ;i:v3aUjxtf Y )& :3bU) reqMEɔ#%Ta\ .= ]YV#d0Zݵ6t'yJoUצ;Fpb5BM)zۙr40݇1s8=9e-k7y};Yj~,XSߊ STg5d|A rs{feܯJl=j90Taddq]0\^$2˙=^&Ctdy>n֥EGG5OMsXݑ#cI1]S 3Z^T'pQZY<3$w-4ӕt_7kBPV"WZ.b˃vclnzR6֤ԝՋh='ΈD8!-n !;,Z=zy#NwqL&4ƬKr@+ RQ;HsS?;x-AE4ݙ.m>cJ8f}{e *I銖3rfjq.=GҜ4Ԗ w9'Xӡ6řPOn_xsdXEp=jm晲6U{`SR&RK֪n|sSyzFI 6<0E AیV4Xq7j-m\ͷi3Cm5c5ս4Җ^{w.m- #9_2#m:V[j2Ź{Yn̫JQ^ay-@<Kp-ؒ#ެHJ.[X=5D6m 1\Gʏ*{$wn& ߹D\dsm:nB5\Ѭ5pг-c0GFO ԡE?㊕=.YW[>d2r8^($WQ7G5<ը,\ήRL Z.U׫F$RjFmrk:=m0oV'[N[ Oom4U]* !pd+*%HB`QS.NMlE~Vm̠t}6{rF2Udd_K`$yp$8u!r*ݬgi7s\zYsr9+Ic9c9"[IS&v3i&^sE":@cԌz|L (J,-&(vRW&V,Vb< }%֞9eǢW jvR=JtPx܇QV|̳lȪ2iݗќ8b]14RK! *jZTq%REhV fnk$YZގGV5eXm"kuvjGkUM ɱf g" ѱ݊Llw,~5oWfpnNbցL)OkB 8"֬)qM*o \vk{;r]JLӺk XwzG{Y#o\`U5tVcK7zj=ګ62c3gf[uU?y< fR LqOT5IS,۩Ek~'Ix"vEb=+-JfAp>'% rǭ]OaIw8mڧvt>5ז2qQj 0ϭ` בA>|p`ԭtc 3*iFEMuWL  zdXא2DTvqZTfs7N)XnNQ5.uVo yy~YLa*  d iWHtTtw8 V{LO[%պ}ZHF8:צr._2" +KgIb<}i;Z59uf%%֕lsU-Ɵ$f\uKDJtq1Զi+rID˴Ь= VԼO2)WM)DfB8-FM3IFcfe^V*я'>cݺwOs!n-}] _4 m6i/cn ,fpjl2aVCb2BQZPL^xk=Z&`fӯP^Dr2n|v7NȠTzJ]||-5ke -Ĝl_CeΣNޕIڕ)._sS[Z/b洓a8zZ+xYE7FU];=N?lxXYQӟ4hw+YlwA<͎C/\T:uq# cXcV:S`=>Rh q܀|%%y~ѶՑH-"Xsﮮ4OHGQ ӓlt#%8\7vDqFU5o ̃ץv,Y RyeO}RP5%};xqV\U_ [:D\^mLb$.)PVNisH)"jl. eZ ͤ'U-P &Q}9Cֱ)&Y"P3bn jpi|Ұ'5u&I9݅J|G:T٦ Ǧ*}՝lWPtۈ֦]>g hr?爥:ъ&%7{~(`'=GضeSsڬxfTxj Qr:Wͽ6;8 ZnӬH퉔_P9ElxXCNxzjGX@8_MrE˒W(qUXaI$8+$}д%|Ě3X.xkKiMq~r6fiz)*̇[DTs'pdS>h/܅<6ѩ:HG h~^pp3y -c )z)e(a$kz:%vLh>lԚ64nJdW6!d'֕<`'\ J|B;iXKD?yo?/ɃF_Mu+klAorEŭԈ[ӧTKeS5xkWhY'+oZ^\ȇI88K]mgXl-u=n+]Y6渡ۻY<ֶtoC$e\Ɀkr߉Cq 0EV 4ڥϱ|D޲y|YŦ|n3#F] /wFl~7vb >)v(k2 iD8EfmdqENSKgmb|7aXp9HBϵzb<\%֑@B=I5[C5Q([;zowaWoq6G@W@ ?Q\UyW `FJAAS \X;vq8IEm J}>Cb-JE 0>1]A1DDPk:N.@AMNJSdPՖWdr>:RjDk9nP3J-QH6T;m<`ETaj=9:\4ohV{MB7Vᆗ+q$ǫGUCYS /MӅϒm8>ڶTd2tl좸Wc|GlV| \jqG |Xu# T=}'QJ3=SډjF7oٜםiz΃{LH?t~%Qڗ/+ͥkWyfnZ tc°j BSfwZlQWjx^M CUO?$yZΦl=ޣ"m.v_]'"qlX kn-@P=k㲎hdW=rAyԍBZB'߹epX4MQnl 8⵾l0Hˣz[ޥMa1з60gX4e$s!' Mr:֩T]-&8%K_­Ne,4HOݓ[0ClX"c^AkqI147%"4ۏ0YRs\TOY[V\?i*Izɐ? ƺ?b{ Jr~z;E_oV- fNVVfGJqysկrd~rU( X-ԞN?*’DeU>gj.cgf?֯3. =1\/4rdVy5Nѝsn6m‘&5]kl̷595#$`$c( "ViγeA+ХB$ʑ[-o#';1Xu.SDa08Ε wk-K Ժ1fݾy~!/.5SzRk(r7FO4)rjL:;%,ErR;uL`ḫwRZ 1 $9+D2N|WI`XZ̘ibH[8M-ޥ"@;Q4b+]YjpU3u+~Qk ʆPOJ۶ +qm 56awoKSɚ[zw,ETt[]o/ކY"AT3]Geh@џ ʊݮdBRO#7BEiljoZf٢-H9G\8kg.X;Ճi:$ӌ.5MfvJ1o\Z^5ĢxF`lM04hђ |cwql15M U%15ˣ9kCώ7 zƦд{Hy+XCi ?\pnV;!~mr%d?* ;Mb5V$~) ۢ?^+:O2{{[xݖb3Sb[d\Zϙ)+IVP+5p*t8Ci`ZKs?.=6\$Ŗ3Ic$0[nM]nj.E*^5o]/dB~a$mp՛6ɓm^xOR5$SlL--Jd{ 5 {[@}R65gotqȣ|wI3'c1Tl϶V[?=cՋOAޤ2V7P%~zO4Я4 t8~E7mN&wOWd˺6 oRОEu ?:<FCI?!+5mՖ܎v4/iyp Xu#b Vȼ!eW$X5Їuy.m;a$ϯhQpڵ!lt,f1"U?֠NVr .V *=NR #Yw +5Q.HoNvk[LH̑rVY-:/;iO$:j{Twg> m1)#Eo,F(^/1gh퓜 S^=N /\{xǭgZMZPçKoG`$ -ʫ%5wKrW#mtk$bSq27Zseʷ:4=[=-,ugk>+cGXz?kK[+@LdIcpQbpxXtIjx%kIۭ_A&r6|=MZy:?zO~ ėiBvw|Z+htm\ȼjyÞoO?]EFnzG—9/9J3byL z0U'SxBobKkt_qxEMOE쥱~?eWZztAfqs(ӧRŻWx.wNxakCw,v2M+0nyU!b;o+؈DWB墱#4]m09BSq6O?`RvFwrۃ0BFf#-zWJΆUqҳY;"zQ 09ɫqYx;Gs4B|Q2MN`H"ʝ2VD61ӁHl& n;cISco( SxY79ҾX̭)<*=s\%#8 銛FTXe{CQSA1et,M嬙ji-'J[:^u Gp= +X V^S^Ih7%8ay횷*Ha݌LbٹN9&jN,(hKK=xj͔E&%PH^[BHbBPLkRx͓? ˕r:5r-qEY =y9M2m\3USvsX$ZS3r-^YK[nH :)c<=Ň{xQLdAm7 )kFIsEi@m|B `M6S*'-,jޥh H[r:Uw$o5V'hw X3qr3ʴF! }*\+)b?t *r"ƬvBiK}7T?c kQIwmxI ?*Q qzbv*JG'AsqeuU|UUxe9ɭy(.K`nV锝Ђ9 4jnkuFp28NrNkjIo1Qd7'י$uZME 2'#<ӵn ]MMrn8tRBB!EO7*' P$2ȢCV-8z<(ۜUA!0 }KMEhkjn&OScڣ %͉(pucIȸIEErs4mWv S\'q=jc T r񁚂m9 ŽDrD` uoZ;mf)0eU$ ʍqǦi]-J}҉̤ք@6 rjȠc)nLzU[8ܰ B#+f$VU MpiJw;w8CE;cR'ޔٛ˔b>shi%0Sf.+ZH N tJ$Z1AĶM2=kbf GC1RؓWQqufy@ u?ZĹd#vXcYޗRYă(htԇY*Wٞ8[id߱g9Rvp^Ɲw)9"dɌc{+ˏ}54[`T>|ɴ Kpq9t*j6I!F;U[M߻Z5Ã#q)maSZ~\茦eQ,ozge3M´[9P灃Gt[A̋gїe 핷Fyf4`s٢.Q]2+1IuCK+\JEmݸpZxp3$f͜sT;QwLӮ\&=lTy68 Zv GfM>UZ7BufJ}nTmg9;5b }jpꮤ]3ԕAUlTWZBF%xI6p j3<-tѩ嶞z u]6Vhf yk?E3|jrZGE?0'%֝[f{W!}->E o47rF+6") TGG4)6k& Ċ9ҟV[y#+b21RYInW{Ȟi8F}fwrT{uYIk)YgB8"U;Sv~S\nV4r\"QY- \q4F !:n-xoYw梶|Eߊi啌HB).40m3Cz䢬^MKĒSQS>-lVw/ȾYbsWvҜ杭mkkuN %)yt{iW+f@# ̑15L$˲robN1VȤʭOwyGu5ZC7$cS[5!fQu6e.[Xˍs3G֟h<J{n21Ս-c39itf<Cфuہ)hKDUr6d^/ل_mPbۣx~4B1Ri+COQod44{|PA93]5wVKuSbi\3i=c{qijv'KG^\Vv"kpÁuii%y UyoXm{'b7(2MY}Vvnf?Z|k 3@޻^urEf% RG'N &nJlĆ? hfG QCv#*sꔱOPQw9BRv8O\G%`VitE暀I>+v =2YarVɴ.D;pXCUKM},z}+f MB Pw. $O;Y;#kvױ)ӎjox p02?Oen{'h*-16j5ʥ#v.Búյ?gdEXJ֠[ߤn:EE }۽IRkt ul%Cͭ\ēZ:l7ˍBU8;WPouԃYYWњTˡEi :wg^J7 L&xiGM;^\QomNS͂܍+ѹnzU3\;y! t دh 3n;)ڣ8{&Df>*;"սTmN6S{&2gZ1xoL&F~ȪuRVh!qv廑XpkV/%]Fx!̎kymaLg5uD(0355"kJ($0dn-oʼp=CW5FZݸ`0GiBhQJzt؉x+]:Gѩ[d5~8fYڶW0*V8]GT刂@uEeiu4 AG@d{,y5%a}V<8tdC{HՊR6+EI1W9t$\8. -gdCʱ.I!^.'@!9$85?8!Qj%7Ė;m͎K=knٌVdV{9lz׫Cl\KvF6~4 GpEzuԞy.;,#^^pQ0ƶQfpj8]"o:㚎/ LM'I\sҴmmsb-v^:c#<;k I@&aҒaL%jֱ$؞h9&CN<6miL t1kQ@Y%$rc:r*\iT.H[8 &z^]ے?:5I6꫟U{+?9kn:U#kq7/r9Kk|0x5M<34lb&&+[$U$ypN:*=F{8ړXY 6tHsiKڀ8}ٮZ,VNGF݃S}6zU Z:zlM:OwWw1Bu\^_OnB]zE }#5ìl][8 2SY/M'XZ $U 'zVMnc4唌OY74S\?39ieEf/>̡@])#^EB6p'pF%Tmr 4VQ;f.m#Pd"+SjZdj20n6^_jvMJ|N:57sD_{=n%uq}X|Q(ek/E,"tw^ قD"čNr:ωk]J1(X9'6G*w5=2gH Q"9:ڵjN1Դ0nnחr[p{'2î=_K̰I*}K2 !qrRTuLG;95ǰ'#5L{ipm1–Ƨ7ZlmX)YCYil86;\s=R1J*(u=0DUu#?z4w6Ls+=r̄7bb0'Q72M{~ ymo".7bs5Ox,0q`1X-I.i?giwD~ Vl4˭6[h̛;_?|DH:+s{<,. UKRaC i=/P>*g^jZYΟ{,MUQdm4?nn4ͤ[[K;VF_B]gFdž el0+ү&ɡ'&45?A[w92Hj\;=f(.i[m>Yx%?+7Z|Q[ ۂi'jŧ^4_xf܌Tav{^5nGK\vni, SO{(]QFDifl.k>vXI-_Y8Wgi1KVC6޿x?'E[+ķuisWFj֦5FzΈ4>1v4& 5k)?ο2*غZzеc'4oK %pd=5wdG^o nzմd!FvI +_/Tr}5nA~C7bF`0z.w&Gr[ֶ+jY_DO!Y/dy ?,cW+%!ZC:xӹ.a7 +Mj*nt0ǖ R"Kgq qW|StxF7s2[8YcobOja9Wvsr2?2W؅<2 B[j2c L X*]z5Qt3TnT6ֹL~Ӏ9=#NJ׎ueX֎f&2:?C oZ bF )4| /'{VA/)XƊ%ӛWGMA%^ڥ6DҥczW_)S?M+4]T"9pp';Cζ4l28ڄChTvlvsxD3 Z!ʬ_'Qp!sU>rR&u˺s2 ̧3Wrܲ@\$KrM@v7̀")5VEus8=W>OM*7 tuR*vslIy$gkȥhXnZk3/ JK#J"I8wTcvh)1Z.ͨ{n:܉[0%v$N U-0I[n9mݪ̒H^6;k7_y`qBO`KЎ]NC횳g rlT'\BUbH@% f*(UyjqZR 5=G!_sPM-IVD6yOl 3U)_2o#";k} U+Yg Ӯ)ј1UeC,F:Ԣ3"aFx$M Q]DR3%F+ [̑$q^VMhW3D!U*OXF vl;و'xP qMF֥%UyǭR-b|6=\nUM- ȡ[vtf؜"I`8:mVs<`7)f2:"s,Bn??95KG03sɭkd@\AH9Y]jM&1P5iCbq] -XQl;`I9|W-^xf0H@qY>voǛ,ܦ$ C^5%߹NxkE9=.L9S)Ce Rߞ~ph#PYcWlehٮ]QN97JOUq9ϭY/V#SWW<ZsECwpƱgb/#os@N3֢fE9QNhc[?>Gr}JXv8 oNnwGޢUtmxCF:uN$hPp]5kmm@sո!+_ro:ii>_aGLV嵤jBPʱUs-hpTֳ~2&6XJ}qXBwyobߧ]HbHE0s[X"d8#xp~q62ƲnmwBtsEl[nf}LFO8̤ =Ԝ|իÅ*)V$,ZfY_uXw>j$- Q_R!FY /NsK/qs#""NϵWUqsTЄ孶(iUո*$g8nY3gq0id'CJ)e$7H犯e$ʒr T7:p3G)wXw&,U>cIAխ}]-v#tlLc}hyrmKdPu\V=sֺOA2H sbFBṾw&Խdxb*16J33ԗCdaLVc,n}=kaoSk*KhFģ:V Ť,K)8&5{ CJ+3ܱ5}cz wb+ Ph!d!|9y.gxʊʉTgiBN3izK<3|ۀ?ˆk{o7"4Eu>$B[Xڼ^[ՕAM5)˅jܭhw]Y$W16Ma67vPkLi"ҍ)9>WUIJ?8>rEΫIuFF\ ⫙"U g? { }&,LԜU4"؎ǸlT%gt)vijϓ*!'ݪk$wi:"-I&F9뺴0疗,kU{Wnr}UpiuZ@cXMGt7j"5+LЙM!+#F@5Y&9+ZZG3:*`H98mt7aee@y40L]?*9͹'yq8*zՇ֧ xaaa jz|_,sz(p}%jmF=+|I$w;"6w7Gv#R*;l=$0}MXm:ٔCc F;Or٩o^O9luL[Z;DwVz\H܈9D0ҼI#p{U+vܭۂi JOIfX$گmQ_!lN5˪jlY$V <Du,҇nJroO#iltT:Wܘ烚dծyXt;\R s#sEsNheܦ\ޣqr`1+? S)f֭%ҵSI:OR)&;nt2i|gՉ/$n$V*&<=VM't`;k[ad"; y1R9B>RwQGi3g,TAق+L+H-JXN:T7PzPkصoklX 'sZ1AFUzɷV HVlVm+5#?sLhN6PビPZj1pyZ}ؕ3ޭSnS0)}q'mdo᫄HnmlfHG$*%wfTH+b8Trm[ˡZ^$5$ r(Yv9艏2W3E,^Kۃn߮ Eyq \l3/Va~uiX2#O]Y꼕Ajƛ./w;FXVe3/e$(%xȥ.K̛( &E$ t0ymO4릗?ڋ1B:rMi7/8 ǚ{ƒ +}zH$&hwKmpr+ѭZc'TFx{RwUm܌OUhMeVp:_ i2\9+tt}fxe9Ԩ{9oZ!=*{ 5R/FN׽uU )<[E(eI8JV~!rNaWT~\X5΄v]l eӲW4EcBM9b)c>O;!QY猙Q dekB -9t:HeTrŜ2kpE0xQM6͎$Wd_Rm͓[fm+F8-a,:k8 B$pԗՊtb z~ۮXB֪x+5ZSO'u_BsN|7= qz;s^8H"5,)o㌞ujl1kSӼ74lWSZCmQ@@/\jJɏҰu}*um$ٹDM(D| qWԴ2!V~Z8Y)'m5Yv`CqN=єT9X-8@]̋;t+5eh٤]ЭffMZTk:R'a-SYWWcR,uiz-ȈI`S56!vXub+GaOMs׏XSj3\7EleSZn}pX.?qR'Dg*y968 ELTzx?⹹EU/vFSYۅ #˥970TRynkU3*:k\HL{4F{֩hcXT75!"@nBsJ;1{m!kf^=KF@5oz}ٚXBI-&LocYȹbu@źQJs2IIsguee{qv´尖яk+9+}"69qIqj)DosJ9rM-1=V d֦iRFbq@k5[I9GG]!WRܬ*55nzMHYlWJK l zk]f+gPCP#{^3E`PqwD1Y\夼*U7.st;JdnMf}zj)TtηݟԞ*ޡ{ ^(5ega!Xs8jbP,.b96"*M&DuJ$+b-,&JAzյ{-Q;-&ܯ"1a jZ4Np5\ ȮPAq*nt?$)bơҮ,l3bTi\;(õ4eG?0*މsMB;BX|v'GA4`Q㶔S{+3XӔ^Fj$zJu7 ?ֻFpjg yD\u#̥E<@Kƥuht[Y{}FWM<?Wh}Sc*5k顭,<Mk;gLEk/]6뇔3]Qܐ͟VG_E=kvzI4U#74*͹hDIO77l FWmX!33`WU8BQݜu%.Fg3qѓJՆ$Tix?Mp"h_]V}uK;ZSdPJ3pt6~1LvEmiH5v?0=4rH,kODb+Q=Op0j>*ME]jB'V6@1Vtˉݝ^ kWV͖K'Ҭ\rUyQ1ҫF[- O][,N+ ҮD9>Fl.dۣӡ[&sASKı0N' E3dp[\p|oi/,:s7sZǃTh i` = X:sNwlSXn'm( ^3W5Z #̘-Ǔ={hrum+D}먓KXjK]&٣FfoM-DNG'[k_ؼ}<K"@~}:8>-OHXrx5kgQN18qNլDŌ3g5i+!t]ҡm c$&g-nk\6VsbPHxy}0\JT8[($ɒ{cֳr7+RWBJgOҪfKl{+09 bZI2aAP\mIZV㑟k[5$UC]tudJX4 mDvJ7Yk-<(}_*6Ei[xijBm*R7u[Z[h @ZPWy|Aq8wXO.l8;"Kbʆ&`:3Uu)x;X]MݣB1exk\Z˴,J+ *wڥXSZ( JT9sT8.g4s*0P+R]7f7pV#Ӽ[彬xsՅh}ƸL ldVnIr#c󑊻 iI$aYڭyG)Qh,3~E 'r6`SĉH㢞+ZեbO̪NȩZh@q%*O1[:MW>\W^,f^qĦf yw}Jr1#NIYޣlA汧[[u󾭮xOsA|er?xUWSq UY{ӱUqr)GVW5'`R!cǗ OƼz\eٔwM> u5ArsEb&,-b{ؐ-rZGYkS< bƅZ(LnZyzڜk]ϦKN|x*ʷ}ib``E{pRDz72J:$ p_Jwr<\M[PMj77qcnK }8CGts"-kUO}GO|cWӒ7Nj>Qdn+1Z~Lj[HI^6iUkֱN@d֍P1=?,d“Ԛp 7ЁЯԧg"I2r/|MUlY;^H o*$(NQ@aIh[inXj9S&&O%mI76|ៜ4  * c<y&:u2GڭNWVC%SnąP9wjvb:p55<˼pzg%;6ӂ9wq스:-c LT={>Fidf؊Cc*ENZB,D&,CWO<&O9M u3WH pis'ޗ[U軌F9Ȯz@F*Zs{ ,coZ *V9XqzZC- 6v?6BX; 䚵DAq*av`䍟.ridqw4+宱*R$`xXMeƢ"qEWfX`nTփܝ j**v`ެG4k&p MSBCI]l7b:0 `ZkKUIAq2D15J/c6v2D\ujw0o,*9X{Ӿ8<5ZrƦFPT㊔B"Ƿp1Q*Yddحh(U,gYx52ZSi#T"*9&ȋ12.@ rF?18UGgʠZVkk%x>V +0w;kVQoRkyp{\\j3El\jk ,%I p}WU;&/$1[o I6ƹZԳ5YTn.ҳ-ÐrJjJXHMRKrHi"D(),Lk<3(BqIpANs@[zf$p(JPCP9*wJ7r;Ed٢)wpQs}lsuZ+[PFDҭokfb.OYOyTé$fO1'h鷆?{s]s#qںM#JU^_f>.* [P{`Wm@Hkt.C&0}MY};oeާ\#yզn+<ެ X)a?tGj嶵9 U&%I}n,Q,E}GHukY ڶ qKBK&ݬid,vVmƓ/"Rzd WTXb#XG.;KpTވ,mceTG=kQ8{]@XsjsՍrNVjyێHZlԑX5t4պ6CE~ j^ŵfi4JÃ[5)ͬ1Ύުk|xԶcLi6[ZH;f驽<:Q" cEIm9\ ۳wV'cTLV*0#56Ыkۅ07ZObB ]F]5&0A`x޵r]H]6ŴP%}u<BZfy[lgky zi9E(N+Wo.岰ꦪEdeSC*xR@۫&D;e(V5]Zt Į5 ̷vehR~EiF{7z Vktnav\Z[Uw|k9I]OSt_ Aia =EjOh뻭w.yj)y1e=2&խ1&֭ȞӢė_l*D;[ÝV^`"1UN*dνKrŤt@ԒRBD2uܱ΍ @ض+Ҵ2L9ۼ*FЅ㤛~gc jY Iy=RgݼWנE>y\8#4i(b3jb A<;Sw98IZ+MmvWW@jXԕKlt”mݖ瞕ZI;<&9 ;RtYBR弑)9jJI=km$Fk^wFrJM.kqӭyo4YViZ :PI-$aŗ+nWXtl{Pܮ&F :8^OOMu3B"4 ^% Onʒ ͏]ԙ7ݜn=?Én TK ۏH(Np)VN ‰-ex\`sR? 3Rqtd{ %ly1X^:7$ݻ Pm6X* ɔckfOMrh $[|qfmhMq2FR>e7W"9fOeN1rݝY]V6=aΤ?xVK,7wϒYQ[ޑKUiBԻ'/YFE^Ry5^<1= bjRJR4U*r*kٗt0R|恺5i$.mW渄]u=7PF_,+rr MNI;mN5aVhk6BGtZش49! zͶB9.IK}l@YC{olm]^ Gų猑;+/MEFyW5wGs&Ss$=|sp۹U-8tnrˊJ,k6XIXM"hgJsi1>\Vw\Vt;1ڦNr 5!D@Y Zh|uT95/kTzҶ-2zӳMy+37't57q147Wu 췳!nv0+&kN*5m~Ϻ"UKQ7WjmۣFNtPh r|jm:rA6Į?f-p qhT>h WڃȞȦQY5"7#+F3,Hji: vrjm&ܬ]Ȫi=nU'ʬ:}2kxA*Xg>jkkDrGˊ" !܌PȠU#r95+٨Y%/m {QzÚkj7LglлOܺ{=V@R59FsV] AZ(=nd8F+'"}^2nGV`Eyׅf\K4/~Ag`oQjF^TJ:Yd3u޲bTp}J|u:vs!_ ͥvˢuְQqfY1_1PIؘ*&OeKdqkVi=Y3N]")H٪} Wiшgyf5_.-6gX/VkνD*?V4?L]V'үYh\j9'$柵{^tG(YVEZ/ IrGJBGTlW<嬥_-8d?QK<(PݽΜ.5Q+/Q۹Y/( tw19rGJ՚+hUL29i*G\fn "Rm9֞+X7EjGe_{`{EzQV31{ HE׉x$*զL-_k ᳚7;k``QJ"':0IIВh1G&vv0wjHvBh!qZ{6;PdsV}V;s)isFCk Dk;Ȧ]VqYNjǚmE6aO§,HY 3TQ-jO^[k rLr^> l BXxR@æ[[(칷+SUsx/`v.x*̒ݥU~&۹+$SH1"Oy65(T9(ҭ֝~$2n=N9a(<]ht0VÎ;-m9C)$RfLz( [u\cnMsdR~T$`"` 'On,^- N- 87]ci>gk7x.AJA8W/. y=8Ͷ֕KCks̈?S-wM]OCVjo$zX\/ՇiТ.$#9*0F+t{FKq^dr7Rrޠڒ{n$:Vtݱ5#Oh:FG ь_&Dܗ B|1MWFhn%Mބ渹i E,HGtT'L0XYX5'5H^JH=f:L¾ʱC&A;+z=KNy|S\xA`YSr蒧5f.%ij?٭,Bf 2cta,+Gi_55x䶒=,p~P iK #jY_jIFIq[(ڌ'%u' OYܴ//sq֞/蚈i; MAz3UN 1jv_6֧omsK5^ZZHZf1T|IZO(*/#5yң*RW:y?ꐅ֮C1]֪O*RnҲ< VC.!HWE/Py+'R3U$j߉_Oi\M <uzȢ=+N5TJJtψu':H#_~+?ڳO4 &[E&&$pyUzM-)סNq>ִ}׳ps:xZN+T7k[Hnlm.bLpW|Zm.9'TfU5vKtbd++Sb*㸮8˙Hv đE.95MguwнĊ =Z&ȝN6=5F=А0#hzI8$+\&.hHqZB iKE`8k"I1Ɲ+މu7qI "$u{J?+qm[㠫bs)4PI%H|N*F%gxWkmx'!js{G_ERI4l]H۸x:qQ‘CCMTq-CNwIB+^^XlQqW&p>`w<[Crv㸢 dU\w$'7':qUmqvf3q2P*1?O9P0=qQN7J gZo fR$>X]izt㹅wF~lՏ-հp۲HpiO9dD :gT>P)N0VOSoz[qm7Bt[c޵`cUr1BQ^&JQԡ#m.0|#/QYDVA*T tcTN-#h-S=_L$PG[΄UM=JK#q z86S:Z;x$0oMɻ+W=ɷE0Gfr<OqwwuTԬFqiEv)˛D77)T0`RZRƄiQZFWf:j}:Z0 YM6a|o$*w Vb vНAPYrjْwkO U2sL%xPLwWM̮B!"BڜnF<ӎ# <)֨N`QvǢ%+CTɿ?5;P0Lb5NʱBK|ǟjv\oe-x[8_Aҝo`` M*!@jۅYIh>Nm M%nQֵ!YYZ(!PIU쏰'8Ushe=is;]THԆ/%݊_LQE{9;瑀L fpl℗QM&t~e$eӞ4C&$2OSYSEC.޵%/T=}*oCX d*p*6H;>jll mT5Ov}-%G@ jЙ$!=*]AB&KmϷW$BufTQH H5cD/JGϦ+.r0x_by]=̯3Z~'NEIPs,[bwhr;"Mpy%'9롷FHٟei9^Zs\$SiXAfC ڬ*c"oeG b5Fa0j.EBƽyLӵPf Y`yVcl,I~ɸas=iӓ.N)h;ILז=yiP^vb+n0sj.}E[mcNkSKiIn%edN-cXP휖sʱU&[Þ޴E7FŝV$sqP]A^Vs#Da]ZӗAsj` V'\Obʀ 2f3 +A-6 4l0 mCVFp1гW.GQY8ylִCPՋ`d>tݐ}vI.ź:VnjTFƁ,>c9_C*yּ0O2XI n!NKcɎ榱4.< ᳺ8.sm9@a AVȷnfvMiR&#OAi[6B<ȡPsTvw^"Ьd4~4dz"@+XlCu+ǭuE -Xk=#aS+)/chNڥsЙ#\yKj1L: rv=O#1! Dx&>R~^ᇿQ:qE9Ƨ02m[9$oeZoxqqm4*&tV4,r:{5R +{2[$[%ֆZ5cԼ9[d'*GU'* 6rդ]_elS)%b] ^mI!#!W\wʜdGUXM+lb*&@e$6sBUQ咿14;F$drv4"lHjav6#n2hԋO8R1Xm/ycdS|i Ejm22i[t qԞM\Eq nnܙrrrzyPf)%5*Ll t3͎IiknR|,jt9hӒm7cAy3;F!7\vD@Tl"vk6J 7QSΥ2\'T"[^NN-kg}2פk170|ck+״MLjd2?J:w*o#a񶺗y|97 Gcnw,ʊG]ee_U~bCYb*\6KF#1oQJN槐;r]w:*w6+H##Ǵ?ax[ˤeKs S.̫J:Ʊ%KxT sakMIF#}kF}}=9,r:N-me9+ZOs 5)7Qi_-_#S[|kM:Rg91p숫9w:%gj/=uaZI*c UR~Gbf1SRvP1T3u.Y_g_ѣGqcp3+[nϳ]NkEFLu=nx{Gd)T5618`ER$krrGeht돝]XP 0QtQe\ФwG M$O\ &}amX}0sZIԘEoQO"IVU$1 ʛ[QhTV+j׀Z"+{NhDu0A~d$}RD⹑06mr /~A cT-~B@Fz9!{G-f *U,3s"cs05aiYuK˴W'"mn$-s{vB3Z)SSVFEX#SVt+pc\x~BػIP7VicU-+)Z9=9WEkfyziלPZ䎯fuse6`[VZI6qKߏN*K=NKZĖ0s+nc%WiI̹z[i#S\ld:~rް*J۹8^Q^]XGUy#M{?ʩC~&6}#9L6FnWsu<;}4ߺկA<~5yr`s*HuO!؁jL}͙rHҜS\aok9@[˜05Er|\>gNzWam8 /r VSsI -G\at$j{-VѷyvP*3N2;G,r}._?%u0;Zj e}pci2HcjE*4F\tnd Y]GFkOSXWy{'٦t?K{Dl,s^ss"ik*@ݐs<:Jܓ=ZRnCd"I`-m$wɯ?ҵa,@S4V'ʋ:rɦ[_,GKc"E-axQ7PܖB_}jyGLdn0LcixXZuwMƥX5KqZ꺨 -"175h7$K |Vl twA O;Tjrw|V:q$3]#$4̋Ш1tJ@^s!T;ZOAP{YT;c@|+#4NEf_X_(3Z }~0T= Q'fXųr&s?wmGt&*E8bZ[˵˕0X7_õtZj18%/l hv6?;kzuo+X%.3 z?-G̮x¥A npg{]ߥ>[G|c 'L2{]SVV̩Z}]CFĽpX蚀I"CV::2LU&Hҡ;ZוNǷejv#kI,uxI}zxz8K$V\z*]QzYJjJD~ԿM:8(5.2"-OYc[U`dY^%Vi ^69!ݚSv* 3>iaȮYIj0(^H揬k0:N2cJ쭡{$}x?T Jqؒyj$Jb\ter6.g%r8k.:>: mNV\dM&ybʰDžutUfz%qֿK[}*"srq]4&;~ku8ƕ?hܯJR{;+kFI-od3僑]shY: Y_jwi qZJ}\RV|9Z *euT~x7ųhP3\ `nO?S?4ky q\)VuoCBzy8n Vms SJт8zo:cam3VOt []0+|k:[%*A"[c,@\kIG#~yi/<4ta/}غ67Bs!QISySiI 5Q6imc_ a[YZ3P@b8I񞯧2^xvH5GSYt 'n( ~tTïrBzv^?ڵ\]FSeZZ\s4kyo (⑻,:/՜6Qa{$$}jYß-Ozl~g#J~{ZJC<[jc[pZſoͧ=YP1Rx^y1"Q^xclPܪ*[sk{ou+I \ֲukM6}Ep+ ɢ`xO_/Aծ&U)F._3Qs^Y#DhqߟƩ]% OGb3[lEp*QcЮbBMIlKU|ciR5 tb7GYQ2 fj~3;my*m#@!YS uOI#`j>- {A% #(oβR2mTmŮo~(EcdlH+ WG7Ǚ և&ْ+kKM^!Z~Wwh:_k0#zWJBUpRi? }M6I #q~O0$c jV=ީO%ۙd/uV:[*uRQחa}z_Kw}lw 湅iHl'̻}QڰHMrz2ZJrY yUv(=j4}`A䚩SvkGte@Os9Tm<d @X6zs3)[wbԄь|4׺K! 08JĽGl2Ż0GRfԛ {U&IV^s]Fq +Pw%gc7V4sYS%ޥvpZBnH|c9Xi˜@5ND);'*ElXޕ`e_{h^'7Oj6Ѷm Žǭ#_G'$sFzVv*?/N`䢝ѭM hvS<~5R6|=2iK}Ԯ&i'sKNgg;=E>TR Ԝm@!>cCg#smQ%>RJ"qXMVxĀ(*@䚷,!p.<syTfI+ح6BY0IPmeAb'9n<: Sqpm6$U9yef|U[+xxy[Gm Ժ@۶7 'oQ"0$U-]ފjH@K1q_ݱiCU6F $R1֪j "[# 4H'sVk OLV4Xĥ[b&om!RZp%ǩYI2 ۺ+gndxD~JҹWP+RS59nk6W3r6~MTwl҉`wn':?,3CDS,d^+# 70*D-P2F2E$`0l}j՚؆͒'nμd#*#v*U֎)5-)Ě2LeIn:Sdn8b6hŋ)Jp`ގ `Vm9#We*bb;`Uǹ2عvXD7)9̬O@N8$*6h]ĂM9=gƱݔI|hB1\g=OkM9'ٙlYCnH;&܊235zIEHfIWpdi#۸@m /WAg 1XɻlLbBsG÷[q&d`-kMvˑY:}6΢-^,&ܲsk9;rfa2nj5NLuC^ZIYJeE?tWIOo;h&iI"cvAh%rn®N_;F SZ)nfe`}+ K! >sY9H53b坎s߭GceT񚻨D1]WNx4ڹ+<TDfKQ[F<DŽ0KR3|c>FImö(,5^"l,a9]qzZmI{}t@f 9TSC5Pamëwʭj38~+)&r[V8W^a[i's;[v#ޚ˶B V卢 țج}B-He$KW*z?=7%zmLƤdEh $rLOcx'*̺~VM,yJ@*bOT tW4s5tٛBsT&DkpNrFq]Nd]q\Ts~e dwr*b!A 1+'=9q&r6=*d[;ϯzk]Ol<ZI԰$XVEp}zV$NBSBʐ3]/tx-<,npV.J5T`157+uU]{Ox*ƌA4o8IW_΅yQ1[o!5iOH۩NY@yy.;Yr:fyzd k(-3KFxU )XT,\iM cTsIdF08%+SZ$2ƅsXVPI/uXVn_rgsfg &1[IC7'f)n`W WWE@ _=x57uPm$Rj dR}w56RwjkqiB`_1NDrdp mv#sfGs$bG~L~UoСKe w=ރ5B) WO&⢻#beGn0!Q!>I@#":q[e۠p`4DF?D $}+V=Oa%^ՙ~B5G@\GnyϨri6.֭U\#f,?%9^ d۩Fv:mRCGF8*qqR 3vZK:Zl?q֫KuUHmtec͊ϩC.HTpsKf#gjf"v![!>Qϙ)SWEQ~c2Bf{TfSfAsPmel:毼i{m+k R֑9ײ5~ϘD iuU1|Xn?-->qՉ75XAcRzTAΟM=P!&eIxuvmyڼ2u"Nۼ`moCi%{.p{J;{8XO\H63I~qTx˫Iez).] ot% æW Hyr\R>I1w-%aPmcck\%(q_0b&qtR89'*^u}&[)OLɫ5{ |WzQz{k;l3dl^^bؑcxڇI$u^\1|}k9^ӉTW.ƹhK` L̛[I *5hFOP=wν^+uA+ӑTr=3 miG̘[+D-ԦkB mVv*)qYS;#F#E]$p8 gkk\]{F;W!VиPoݗ.gоUCK@|͸/sd5 :]1NZ(qyy2"Yl[Q$ѶCYlvpj5Ȓ7%C-i~JI4JG+f`uwiNMv9̫zVI5u7}IykBOܖ@X*S>^A_iPڴ-Ԓ#Mch ^g/?Zsx~G~qn8YUFQ\2hYs/d~qNtM*Ϸ["y~ˤ3՝?Y?t$+`h;ԭ+?`UQ!" _:. W:K{ǫVBǜ :qN6DeS _+߹WuY" 0*tV]k:bDE@x>軉";*xWD]+xՊ9M[s3}I_8uGdgiڸs.xEu^5Pt 7ҽJ'&V[[Y#'XOKyo<-e]6E`98*ۉ〯XZt&޷6*cYIZL%JJ^Fmf_5c̈́Xן&({3V5|%-'Q5nb*'{,m>A5(PƪAa7-&uC=1LV-^+5su$d*{Zv HI7wEqn0HJjZ#Zӊm};~iDb ܼQsc}9̗ c$kCm#f^ĵc:R4%W{`k^+2EtwWz\*wP 5_ fylb6sԪJ3Ivejxq*J?##ӣR}ޘ3toQXE<$s*Sڹ^.M<9p?>kKi#ljRY9.9t_%Wfq}kyҜiB:9W֑pKJV1ƸU͊85h8Ab9Ԫ_=&w%$m>.us#Y%KKXFy&ԬSoCT 1I1-RD0Z͒.=fR *ޟ[[.:9k # N*=+[W1pfªW2XԝCpүx{T㘁s-aeP?5%40K5mͩKM$txJc ݎ?:QR$m5[m>Ռ2XIMj'Pi,<\4cUk\9E*dQG#+m%o,:qb7O$(Sz9ԝE~To[MlsLzҵt$=Jמl"_01"*𧆴_(,Z~g\ ֍TY5ͿԒ[yɅP+2^k44n㚋I!|å^,^&0rrSoa~uړ U zu&ۀ^C\[_ N?uA{N!k~1?fad(k9amQ`7-5cgQ{Ǝ,u;a撫Kr!iEex/-/T[k*ӒNQm/՜%GL+7JabGGɭ9l˫OT74I;FN^`ԩhk'N.ܘI"5 zNxznJ.&t6"-y @\oAY3]^s|TVh,mmԨKpe7USVqpM0n&lYZ.#j n>$m b2?wV-Z D{sTN+?$]Jﳺ=U4Ij{G(m@YS5斾+<;05i^9bi 3sP4J2aYI?=ej߼er|+/$֦{is -vH8˖c}*u:j2! ZÚmf9d?QZJiYs9Vc]fC+&SqvhCcsW-Azlwj(ATm-?:AV:~V)*55-=v]d+]NNF91qcި> 4P$Hӭom{G~@?a9JveÒ ͙)d d;ΩjKL4qyat>{D`wΠUL i'c_q(^܊: pTs MPFB9Zwk1[y-Xʷ<&k8%e DM%@fŢoE>*r6F~Z<圲ƷJђR]v2)72~'TѮ'=֛qxG f'mVPLȿ,p?Pyc~'+|JYAVrS8u~YGQ׶m 6Ar-K=ՅN( )i<|ׯzHߩ:/x^.(f!lH8\^+սfm'*tb{N̔%R[K($M4y"&? Nm< BOm)o^VTvට Wtk)`Vï]:n|M|@~=VS-cbGߨu_^H~5Ȉm!llʝ )I^Kuʮ&֏r,>ߪܗP8Qs+_T{{ US U0ڣp銊7vJ%(cgú"I/鼊}9f{j'vѢ Hj rG5("@l8`o I8*]^ՋnPCc֝c;W ;2A>2׭ #cn-z@r7uTLUYUo/ kv*Q2-G ex9zVAgG2f9dbZP#v9jlo7x;xm@8˖lMM{Zdo*V"{ͱp]I9 Q]$89 s@V)ư2)/v3rEnG8$T~5X]]*C'>fؚ\ U,|+zң٣rB2=+'U"o6m 85biw i@\WZƭ&PiGqs"Mh*y/bBJv5$" EacEߗj5nQ 2jv$C,9@#dYfyRO5qV2Lx;B&=h'w?1=I ;s֥鹠_LN~[H Ky2!QNsYuf@zSKM j'~|;۴qMkn1ڪzԂO%Llr1v5U- bg5vE8.X>RcgTޤ4V.ùa=yc)LT+)\tɩ$|Ͷff]턺af2dde&3S.d U}=zȞYש..]Z½k [ΑsSY#BVXi"s3n2m87lxE5I#i-g/3ypۙeY@Nk-4h\`q+yM;Xqrin5& hEpH@^+̓GydձW}l͛5T ݌3MIĄʊ>,pZ*RHGz cʁYȸs5bt̮T{E-0Fŏf'wZnJm/=qPˡ\Rn[d$o.2@= RF=Qzz%=Os8,?ƲQ6-xF(A8'+oڄirP |@GzͅiLVFPzzS>,[MAn6w͙J(%2T&DƔw2 >B*pC0qTeuse.NF8°ob>AȮFd["mr$ҵ*-- L7nzѓh0Biވc5;*~$ ֧TnO&ElŐ +׮ :<j#vS|9ÇbFxZnY\ޓ^Lݔ*[A)CȪV&|cE,`Y#X*wF`K*Ӎٕ_iGnMʬAmܜU GDmpfxR_*G& )$4n6 :3ʃ=8-)+#X;Ieq '};W)t{b0)9kd H6akRk_0j>aPFs]~&`:Lq>m0HG}E*q{#'QNWq7k![-+],HUͶ$ *lv52%\Dya}K\ωsۆxˤ* Ů. J4@Mo?rۘIή X[ET/X]mٖ r&@":1[ SU&h^v$յ?p9u2^v wtKBGa$]2QH6oKR)| qrO\~5i^n.+X75.BpOq?*jfw-Urح>=k/ңG2 U")$x72e:VPw1OSR0ki rvElh m@0 0k45U3 p^1n#ʹ+IDT:ն _G^(l Ski8T\7(V"ۏ-u]ee-qcm"2:ʵ$%JzM>U!\EYh>u9bcPFPW]#[CkUk>^z]nZ߻1c\k-nf+TiάMչQ-cb8"Mcͣ4ضRys2?"e`!V"#tާ/dGe\pRV|)C(1H z^.XH9$+Z+PcNpqs?k Nz6qִ>Opַ5@HCҖ-V H=T#_ i񪲙<QWM[rǫ V֢IS\V +O=*gVfiN7"lAT.S/beu,N=w5Zyb~M:u%}LkNRBC)lN]=d9–ֺ ⺋ txBҴ枌0VGvv"HO| < bz "Ƀi+gQKtcؘܴ"%u*[8S#c5KͧI=ꝕ֗dSNJƪrc2<;K;vzV\:6O5KS[ Qݞ]ҹ%z* GUn}x{yU K\$͜{_.UHe9RQw`ܥ>6)24qcm {a2H:nQ_OI5<"Yh60U:I&pW݇})5!?cn:q [+>]Wؙ;5Jšr$/'5M-ȃdm-'1@}Izf~%yS OOƻ"s6Lh021#b'BrG5j' y=vs%d Dy_y+r6k_37mTܛ-ίa̯1cinN110"t?Jmd* a'G ¬ FQcm4ņ,­'Vzyݥ\;ĸlhcS]ӺWhXvy˽@FGPTҬx4EwF㝪0k.L@PT5KIFIjYRFm~x U i;C'R6MxFH\2e85w^;7:uE=\^мE :Vg:vr9(TN0ON;Rwy';UBƷ!XlT~!S̓_O#Eg3qtthŃjȮMӭ * 0^Lז^K]1\F𳜚MiCg{&G-[b)b#8OSlk'w7~@Tw95iz7(iu]BKf$W'5Egt)[7U.1kpNdoo^w _j1U$)x^xɘjws~zu8CjZZmKHb6i֑w!:6䓊d{}Rf!D%ZJ_i.o(hM0vxAӬ>l,ָ _V1mD>M|_MuqXF5iY<4%YÔB1|ƥDB'o3S= n"}oHp5Mˏa jՎ>zކͧlܩ{GuR캭ř=|?63[Qyɮ JIٸT:0X`CMwμlkȃND\ V5kr tw=Yv Ԕ#UXS[qSF߈ bl ci6Z|9P6cf"(HҔ%%g'cĚW2`UxC <]-IR@y56l豒NNVU록zh#>[ ps@ONd3=ςff <7%UNi.,ֳG_Y}E!UYHT[~V2AN+| o ods[ɠ q'y1mo449xgb rI5|)nSҶnN@GJb3+ղ?k$̋Ŕt?RA.y?WŮTe+JO#S9cW:'qJIh]p2I)W +Ҏ+;d@(_Fs8u6֚|$b9!aLu0wHE?:/#JSq11B8Q}/RQ>R D 栰mccK n[5q-)FiG?sI-E5,XaGܟ)ӌz;^`~bsƪwA16O?"MZti\!J20"NEZu ;4pǔq]\7rE/"cqT5+׌QYT cY'`IZ}WJON#,R z+ '|:7y2/j.KNÂ@檪]UFѿey Nzlbb-ΰF;yI2k_jچv$V$\9ü|I>: FV7qC/)*ӂ*ZftTR-;\_i"O^p矯z}x\YI!~6,W$ptMuAcuh-Y䗮$ d#,I0+yh$(iyWt$r4띏n+cH&+nܩ 6d-yjd g)u< @sOʶ%t9Pv"Ź"?@ #t.Lq`ח~yU nCO< kޓGeLdyUun )NʮYkfbP%<纕+G Ok:v}LgWRs;IAZ|NG$eR +'?|eo:-4Ӻѷ&rU7e1Ln%IcՔmt9KOĶ1]NwRo2,w)VΫD泆;f0+t!v1u4$ηB.~ͩ\GOx5LNy]ST6F>x}ѶyXaכdzoEwjr V V'S ˺%݆]du1=;>iֱɸ1\̣qKB^>i(Ƅ2*bjh EsWjuujX uKrx0C%Y=NmEegϙ*kn`ˀSʸm?"oƴ;+E%rSkW|#Śv!?ZM91H?ZoQyp6(IxݳR9J7f8.e+#{2Ƨw`Kjo@Y^GoL,e2jV|}nbW"oXTTsMrvq7Gcq?n$׭cco+?Za͞Xc7㝷 º`KME6 ԟVpcs'J%y>C~<FOmηv$Vhy9ks']0֯odrI>dM ewD{7s`AZzeQjF}H%jtїRH;OjGJ㯯֡]29vi-pcm#*Li6#=M nyJ2b [E#ɗ9՟j#V{5gqZM3'^P"0<7ζNԖJ1@Xm0z55`lU;[R"%FV$pj:IBv;J]4CkrsVMm e+3JSr 2qYwv "sZ7*-s)t]e?vv֨E/\`lqU5 $ҪGon% ¬X5 4 4&A}.eX d3X̋<*9ý/9#`fuQ݊,|1WR`TPU&HVY#8A~[N)IXc ivqR\܈if\dV F'Y%fxfEGK&3ܻd,d=[ʧ0z&Pskv C\bi莚HŘFi>1=ysU6J ޵(iL`t5f-V5ُ85KQsZ+t:sZh#M͒j_*؅lԚfqiFNA*q/>q)$$AxL/ck+iym8zINOzk6%Vc1ڪ-SY"BB8U;9gU\cb`@/&3y1-SN nY U71|ʹ~Z8iam<@-ž٦̥sM1,82ڻRcRT澕]eRݚh6 Xymq]FUqk9ԓ89=RLS}[Afdrαueo<*O5ewyG՝ʲdXv)+]A$6#=NGSQ2yՋF榕RKrUN{t%;7BiGeuQ @Ḥ.ι>e܀x=-*۹9윆XjǼ$ZCJěR|U9ibs!qO1F3ְ wtҴ$=URnq,/RڹўrXi"Uds~06o.#[$2٫75:j󟈲/ ;T.GJ‹iVpwf6E̦=qg:4a2a=*Χog,~`: F<`k&S.𨼜kwTn J{3mqPfy}*χB-14q}j;")6\AjJ6нIO:|Z,R3lޕޝ @GxW]fY^[GAXTSGDf.\:`IDnk˾8_ZKV%s^ Rs{9"GR xoT{aGlVjO0ĸFznAM=ѕ,1Mj]J4 19>GdT^0SzL&@ %<3^ft-*^cF*Ѩ%j6O1^1W~rTp:nn.S<[0h}c}RMP򭴑a8=MsJb.56d9K6jDn=4}e-[ 7{}@rD8=E6Ï^l-%8dG^;<$G)>S lrqwL2I?W@T&J污h=CF y8 z[#0*;;6)B` =2P:>% 57Ytq2^u}n7k8kCnouO֜N1m9\tۜ4<$0VxCO0(*̵FQ5*( qPVl۔_ i1rtKi0Adkz\ Xw1żȧV/VnA(+&6H͎˹7"ȅSXZ`3xoiӊ %楬Ho(Md2ZL^)~ٮsW\b axf%Ū)j mkxPծQ:x+w]qwr VnO*,`iXjSVJ(Ij.E̘-ri#F0AQgpGZܺի]>Q MS"yzEvI5ʞZ24Lmd48ZM/$p[lzDeR8OO֊عPy <0 0:#8XrE_%AI *zUyl"dܚ#۸d=ogErLR3 `3Qiqԅ3]քI4b=XxQkV8 / kf[H7]h !#-gaK,F U4:Ѻs^_9KQ ﵋b'L@^唌@iKs 8Mj[EC2Ei*Z"+NKN6TY gJ+dO]&L pBkMjY$XwUrFQbOGs:g^cvL^yRsv:K̄Z0q`3R^=M3VR8Έ޾$-ψ0cY7sIK'q5Ri#ٵ-B(rH1XZiG͑moW4K)a5i'} :)AZqhsfk >s}X1cR/*~5躏1qFSJ4_$JR[/ x{~!0:#:2HIo{#%R>[0LIeojCI4I Y#ʦn *vTZכmcf lche`:\,$[@siL lCo[d(qG瓙ʶ3+ϮYŴnjϊdw!LTMSg%i/-ui Ap%Dk n84h[6 H?'*T,1#T7W]W q.?0@|?h۷*͝ΧEsluabA\߂ȫy,HSjPځ2gspjP@釅O;cYG ˘[sSkoj;eBsyuC~d*z2+EqUB8CEmzƣ* $Cos\_|}8GuF*?vķ@Co ?dR8U*'(iWFM/n.[";hY8@Rb{$T6^&` ܔ O |f ٹ m좾(ܭ+-䚄JH@\Z gnt=*k}W\U'Э-fzc5QdWnc&:=dggVEψ&-HF14{#o29*w(s97P[ɾ8B1&]~| (jXcsUAQc?gkR%dZ.ؿw.a#G=Z3{=:bbAzE(sY}^е?vz,Ffr ,"KO0j㴋{;YC $\t9myF9ftsmNϿ|]? UXs]WM&y_Dދ)ZuFR3*C5-97RN/i$ Gi?jG>Ѥ^\0+nKKIeU$#"X8Eb8SR{}F :/Y4s&G9ӤitSQ99YjZxJTa2y0 `{'Zi2ͧh0rISxdFߡUeXa&'@cL oOA\2۳8$>'5zu#zԬ ukUBN~f|Z/yծe[mgqv3\Sr5VN[SפlG.Q\/0͸pqc{PV15kz\)|I5JoG jsw9SQ?9aӒ:zS v+B=y m`Bla[ӚKLs\jZejl/ǩ=EMh@v6yʤ56 Y y;jPq)\~5ewR<@u'?x\6C_-lh7;ՐZH4ՏF6qSw>_ x_^sy})Z!\k4mTѿ|/1IpNtיJ\ֱZgjV[8u΍^[)E[ BQON3YI0Rpz"JPtA6u4Q>HVh\(qVm(M@]r}Jl֮ixEq;TKWcPVW_qR^Yd"tZe rIoukjEN2r?* ;JM߲;tx4{Dl:gXZv;" wܝ+Qn(U s??>܂jv ^rtl)FMRki ؘƚmB5xK]RpH6+ ,"KpQ⺧՝DV-ikϫ:R|Ck%n(PZx.pk@R{x$`w杤OTk c!ssrg{+oo(=7_!r_Rc\Wu°^'VI?c5|Xu@GR7XUbϡBw'ctgN܍JHFrm䙄z* =/T_>XhlgN6fvsU >b.]UG\ZlwBx"l~T K[TIcV*ÞyH!TB;$ GshdsX'x[ZY&[sOyڬp"cp"GcIrr񗺋vۚ:hG/DJ 7c|6:9:wvm /n8}.3zzUym;5ݢ\4΄cB?,U/EweXGVi<򋱖 }f5 5pcg]Md@̜Z3^jX*5ŚrUsGm<(]]Hլ5_h!PEk*,T_Sp'g}J8퉄Ҋ"'Udۻo..O;jHٝʾq >յ[ۋ_1XCӸ5-h1)n2zy}FD! _O(/fVSdi[s:p~Pr*e{D/@6}.[@pMiq)sVJnڛ2-OpCH*jH;WdpҞVeU,VLGJjcJ๷ ! Ɲicr)q+afD56v*7ss)8[[o^1'O0U7&UӯaYxV]e8h9O9U^T@Q,l*j"۳OP2\}IqEQN(4TH py5oIlu p)v讂d(G/.I6)eVSm1f KmĒǑbN撕$dC#q*HWs fP`޳'{m=vfXVFs[HX܅~$χXy:ҕK"á s chz:Ưj:z*Uˊ" k+kg0F9T\[=r5ʨa_+«&N6DM\hd1IA뷎ԱڼNȧ~x(Fْ{[K H"9 w'5"gnT7~R7wOq6L ,`YLk%HǜwA/^3OA c$6&QZEp?u4rFlޢ|aަ{w{ B;4gr$A^r-m~nK&{sҝ+,90l<X72$*ә#'/k ýRPz5l I#&@9b{2Ŵ k6&PCd]P˜K$jdT7`)GWbѪǾ@j]R7m0#l0=D: )Sҥ]GsWF7)UA݃Zڲ9!gs"/<[+Dkz~U^gOQ\ H9bz6Hm6NG^CXG Y7tm~5RCCXL(% q޺-;-j\pR?o<=x'YZ TT%ŌU$wW\ٕPD&1VRB`cA1= ^۲DšN5XmqXw$6fFL װӍISI3&[8%˩vn3MXS5gr;X 95FvwU[1]s`1'z sگƦO|+*z%3rq0LU{UlSKH>eq[q n'rDQVǭCt[l&IJZBX댊;ܵCck B'n xN@nFFrj(3oŸr%Zmx7ڼ\#*ݐp Ì`/Ҝ5.xT%]&j7os q#9$V߇fkv8DGnOSqn*5:AQGsHH#޽^ԼIhH38azW+]"8 ,=Ҝu3)7khd^< 25;) eSֲonF,6{ V:Cij|+ٻW: ci#$V5Ȗ.$hqi>1Jc7n{ŝeƵyۘJ"GW5w]G 9=sgFڃfD K )+|{XLaw!\P˕[~.jLpk -żAz;t&kZ5U$ߡ{ =E pjfL)$\Ztirj.z֬rk ̕V,8%u}yZ^to5#ʷLZ".J}N!= +$s1VoW. "Y3[ɒ[)zd$/lʆ<*-GW3ѻck:ez{w4%b1W2%b(LcZBr[*;D d ͩNqY9<ۘ\akyߥKmNsڜ(J,TQ}gd wbzަ|0gv9` r9.ʳkO!bo#ܑaFBl 0iŮ'v^HOn-#1(^24{fjSfKzaكOJqϾ-QGxeqyoDXBa$ֻ=yA. {SfO$jf rT]hB6ެKY9/WB\ J7?'8?v>:=wL*H,ܪc8MfRoAyR0 BF-0;KohY2YLç?Z}ٱo9#9_^+FgCiQ+[&5"ެt%mʩh^xOD2M(#HNop@* <ۘL{V1S``wT'ӵkZ<=GDi-.n'[v|MGS۝R#),:n sZEhVND5[JL,F[5bJѲV==9~]8IDi|zLU5`)@kjopUPPti}6 N2GJYE)FrMse04w-HO yvmƾU6&aWLCNmV2Q|ѹ#O3t\!?uW2yaz*Y-2Gtӑ MivJ7ºXdԶ3 kZ8*Ԍ5֤ P{Wh<.Jjx|:ԋCNw3![*Vw2gGq+AmƥFe&5K"_j.Tֺ 7R,%s&VAJZs|ƉDˑu&6ӡ'^+num&83! :5᥻?5]r.ǥ7P˪}qmݧa8#&v[q(+TDpE8JzdڬW5ZJ74[Y3Ѷ]ćiʇnX"C`3b_FuhrvGϨfNzda?$.ǁW_JmǕ|I2^[@]HuDA䴟ΑI<"".w[fX$=PX ִVGώ:RNӐH[z.ڇx$b>+BOqkubVXƵmiXFmsKxTK[O`ͼ<~Ui72gPdV#又$i8g]/[H M`R?' o.k"Z]n[IQ괫Kplj%Q|oC OimqVjY > Z6̃ͱv_R.t&]&B{ 8Mٕ)w91ECVZ ٬kJG3ۜuYuyZĶvo+I΂Mr+\( kov&KʶfԻ?i.غ15\Mof6K2UWZ-K8r/ {jG> akwdy%M:5u+I4@씿+ׇyˁ\X*ncd-T l '%BEoF̧'$$IȊ)n>["|wq(k@<4OZ tpi Y:e9Ί'̯2^ETf"xixdSǦ[9-s,dTSZnE~;kS yJ- k S85.cy2 oPƲC]3|>%'ՏMb6T5=[O ~h(b1(KS_ijty'2ctX5 CrFx(rJK)$PWW %# *yӖ|BH\G*#f;QqA'pt M!#PdTҗ"0ĒHl&EۦG^F+kɢGJ`0m^+ ъkڜ*wz]΢|NCTr+n'x"sWe~95Uxb0UɮyMir^u23@vp& n)oNֻHNk.yvmSd"S::)lBb[F@8/iֱl[=5>?^lDt"B?uusH֌tGՙ1\u-zçY8]1ʾkf/'׳ц6-k[n춰>qY?UnWwB:VΩ<,B,|=eU^iQ(=Vh!-@֬~>T lR,%9v+Nڠ]NQ= 5gQZ3źKWs]Nդ;ZРxĿb9.{yl`9iuF%:'J2 }9'#֭d/ٗWēTϢnYT8'kD.:NmhnYJr-V%rXb#"+M9ukgܶ h􌈓84]!g9:Eg ՛f@yE?f"& )=Q, {iۏҳu{Oyp׌I"h[wG*m[VQyL5S7e̩´/?vex|1_Cy-Dž~\͎?¨[:ۥEyw'jrpJJ3nקxF4Aa6pPkKk0 8Ey8$W4M%g#mvYN2R]j~ݖF5j>))܂G?zMFݢaUtBbIkJueKC(ɥO#:Fc6cO9 ֧Q#0^܄)1W,l@f'Vt:Pg}k;ԏ%y ~UjσJݢXX$ӇDG8u}.tRpZ#d 9W^еeBaZ,U}4bYlZBZ3sXgbMM/|C i7L׽ťyԚrC@?:(э;u< i>6oBQ寕yLq^YZimӮWD*{-,ZY K ߕZzUżt؎kag<[^ZJǫ0P)o3wiqWzWjdgN|9v#3},M%=NN]}!lr ۆ7VqWh|˷l`* "$@^!7ği4mEy||Ln/0q}iSCY5s:ʲߒI]\6睲s:QNӼ7j& G>S6zݦ-uCqnx8[+PSMFw(@ҵq֛Nx֌]+/'xZRЀ/R0 [mo(󬯭&ycd.;JٯQ}g~#5f M*ҝ ӆ!~zA%֮4ˇf aĞ.I5 3Ġ)ko;:ĚQYbq '% XG\[i##޴xJPW{!_7Mu= ~0@gt9n__.I^cn{bs+;6Z+c~Reg]Zp=鑙P*t6; gּ(dn[;yc- \$L(GJa[?z~5,00nV>W%cƐ0>GK2|29X(Uҡ ĬR=TؤG^򎊼d 1HFI8\boIrxSg8`W;3[m1Q^ie3){Ԛs-Y|;8E9`{ݞCo#R[))ku ]B$O}Q:\ Ɯ^fdkEb HW9=X+cTZPŎfOqz E3{T&`-i|{0iC`d`jv;e{lm-=`3ՋdH M}v!2ieXď2Wvh})`qhD6UUc*EthHdgTqWV5±]DӶb3)8ٞA7M'sp*'vѣQ=^e e\w,Tn[2#a_,[{ҦZ9kL'Ӛ޲y,O,-u)]( G%-^b2`s&qI䲣;@=vcbŹ&QoReS/n{sF{o*F0ǜUH9a1PԯcFbÎjdj {NbFzIRd@ǟio;ef8N4H;kKd(i[LJy=~|pp1ip cpeD+A~6T sZpoiq)6fiJɩ-JZm?+&[eP< +"Y<2[vZȱ}Fa2"lwEܙ^NzD T,ϡ,}lw5PܽymuRe$RVJ‹+}`MsCP§#HPjifSwRX~c?X[BI^F+R%A(=OPs#n\(D#ojaWfd#ܬvV+VFl&إmǂAr4gw9V\+* Rq6mV<$Je=jVHẙ-Y7sVܖK{fmS` yeOz*\~=M%I1qک=,nbywĻTO֠o~ɨ,y`5$[&*zp*űq/!J J,>N\uf{[i11 \tx.8]ҡB9v u9N$F.g1=@G'xJT8T,M]hm@YG\m3 ڱw2F߼W3杬z5Hբ󳟼bNq䁂o~9]KP.d:6ڱ;JdQz Q,\cER׭E* qZZ;s&u$ElZJgnC*+u",0:Z-$/ f]mDƾ?JqzխWȊ(7m;vyVFTR+WU7%Ma(um"EM,ػpsU2{)A"gիy[:BU2e"͆\qSRy6HEVGuʹ9 \*eó1<- ] %emwzYڣAaBH`kv"$McT9d[y#7J$3SA: ӌR64:KIcE"EKg6 =E%ԛ6ɮ̉ j>UEhKtRpE in:qm<X]9L`>a'=*\/T9gc_K@YT.:tQ(C\gVUW*H,Q]֧G[^48/ *Ԍk>^kwS,Z,Rd ˱\\V:dE$J"|c& Z#xSƕ}۴7ɵ1\+^uOpҬfRH5FVh940e@xZSy#u{rXFo{s]^Y'tVfGvlVGm2GՉJ^M[mvg.ٯ#]8K`N- 늳d\VJGԣ .sk%{[nmQrGaTkw`d[=6(4?9~3t-6y Sy{sctsV8LBu5 d47X숥JW*ZR=?ݓmƅEtMjZuV[q(:q$Ί/^%a =zV`zmms*3dӜFQeY}%+;KKak÷y< 辵w[_Bpk)MyckhXpH` ۱SQiιïJBf ֜e)hG//֦^v\F~±vqUo::K]:RH\K35ƟN\۴@5ZVq,רP?[SSȂUn XD]ɗQx?JמϕT:$؏?t89t2_ۗ -Yˡ^Ie0mvNqԕ^_{b b՛+l295hsToMWKwy~)Iqsi4]XQv2%ksmw<-z|Ě1/k[)!gi3:dx' $n^oBt4ՄAaF?RJP*ΛwO:W)h@5uO)4a] Z8GoeꚥdQ1$u,;0E֓ir/%sҺqZJDXkĩw|춲?8`9Ի^Vk"ۑu=OX~#49rfacɬ{I$:-O 9?h>k8F+yh*꬟&nY Z:oƲ|A[Yf5Z7ny|>HXsuUaXyI]+^\F+K:xJ.LMnbNՍQ3 Ty]Vut6|/⤎yug+ 5 w8o4*ĬZ?oZ<=&w)̰lb*JjV-/#.!,:y5[0\0L8zKM*pMvzpEC3Y*zosG.o'k~$M.;bD8!a~9733vʑZZk%|Y+q**QS)NiHo楹Gg;J [kM\ߌI&FVAr+zJ4ߡC\>4["al o9cD𾸰%faO2&^cx?z,f^݁XTi.~'BH_Z[L!g^5 T1W΋Q8+5_"&Sm8+j1sW+Zwfx[}*U^-+4w5i3칰w~j[aᑸQ)N2Ch{7iv4:MkK~ x\Oެ0 Y񄋈csҕ:{֝z\g0 )P ؚ[ HU^qCQ(i/bL(M19w U86s>Xf?j8$c&OW-56ʬDʄr"]BWKy}kI~ir*jti*1Tӹ>K͗S&>UX]LZlZ\,W3i>9QZO5(6ٍ FgdvrY(#q ݔP? 6k/o@qTʒ^#HJ Ug= Ά:VO)kb+;^63X_;1r (l:_F*2HM$jY4o 8%Mf꺯mnRf*K4"Ew j$aܪʒjUٶCL֮Izgqrd^ fhFan0Ք5Q,W6Q\K"#vjM&.<ёIS: e9cV^;/-H`o;ߥsuXF:US{zߩ ͤP'W47Kxz$Y'YAMqYH\~O[iUdeuRtݛSUKC+Vf{0VoyMmb`X̐ݹ1ҝ額yĖ[Xz8/2$=ƍJ3i"(dzg'KϓK_#:q{̗U9 !iCId;E8 %u=mefո\ͨ0C=t%467t*n$+syi#Z0<iElKEH.s^qiaC0"$F$"RJU3++v2HN/ ρ sM9)&~xkQו5)nx飳ywio'5*kTSd בX+c C'\j/yu1/ rLimMs/,5Y(K"k\B@:PktK x<_Lh_Ju%d޲Zq64nvy";p+%ܒ%ݮw?XЗT;IQH0u}: qG=EzR2uVv:=VBQW<ʗoo#&6QǷPRIu\X2{f;sWXWJYg}jl|Bv3a9{$RӔ-m|JvΠ`鴁Qk^2Hಊ?bw\,:1VZ5냚r7yj(Wro":\28 I|wͺވ z#KL o/'-1r+IQh{?rhӡ60N|+*,(pj'FaҜ%iQw27tH$sTYQ 3s xl:KۃVV*Әu GY^ʢw7v(ن? &K;Wx{H.WAi ,6,c9lnϡioΗ44Ij-rk~C0'pC^Y^fkxrr?n#DJO3U 4= b*zNT57F qz҉JFኩw єգ+z~r-cN|tS$-&[ 5t kÚeVB?hz٠YߞLQgssI9F &a&#[VWhH'mppٟ2-&ʜT 2L8]> 92~ ͺ84#<]q.2@! 1:5sypĩ#r?_j-V$S8| ֞,7FZW#+utgc2Q-̺x:}t;^c]%$4,jw3^5|@.[dSnO=B[: E:{&VX-f$~TӋ{Ϗ`x漡Gf1?6G_Ʋn2Fz.xcım:msIw]bnS_zԖ֙l~c'^h=Ӱ%^g dhxZFOrl) Kw`AEG*\Z,u㝮yk 8\L 㚭sm)dqDUݝF FTӹ?_i?2:|x*M;taښcB? #A#9f}\iyۊɾZ\1(n7(¾>tx9"m7P7fyJ_"hcDU"&x Uzl5³,;-SKFx, 5wobCpzWDk]{;4EѾ fޡLWzt7NAsı[{?& aO}ukPig\ɭh@W&|ZZ[6e Y8(M.Li$.FFT@@́Pk8^27yTj#ҵ[[Kuy2!!g4igʀd~uzdžn4x[tM|ZΗxeyb9"@1Qw^xJ+K?G㗎|e[Z(lOp-,snnsW4 ;ב9k'{wSMFеC<`bd%2B0p8N:ZH|B|hDc&d}kҹ^rZ-o]-3a3YL1E(b),AV'33BX:Vu*ڔ-ċt]wbrȮr5k5f=ShcU'Jq=0zΚ9a@Irj)0nN:rmFmί[X{Sa@-ڈXI8# 54kp%|UK˓mwd7ub>cdK ܱ' qo 5:=3j9rP㚿Ek~D K6+x{mijdw'9AraR<.1۴5KPٻz2`:ŗQL;qzpWA'}"fW GSP51GzU_).!|H#For{TҬj&ǿ&o݂yJ&4KB è 6M@jGld*pW #Aic Y9J ;Vgcmtg!pqֵf!s 5T,liJ+*0܅sv fY$ijD,P+I,s6#U$Ktsޚ$6KqY]}8Mcj Tu4PеqvbwQqGz)vn4-7J jDZMҟ5&Wz"$q뎵_LqҴQC٦<9p cܐ娌8u +"uUo6 MbOr)nơlP٥UZ3N^]y=p .ΞyLLŘsYF)Xc}%[sYʣ##0>Z҂Mvr(.Z@8r;Uݢ%$5dXB}oͷ6P}+.ubF:fpI>K5-qG@kaF)k9O]ZkiȨxhұq+W}|3c&DLO]h.T:c - n#?h TidZ WewrgTqUcX^w:e8G3Z }.s2In,1EsW9&xBm9,>69l.#^yaDZLՙ|ip[y~4"X=K@`sqy!\k61^72ʎ&n$,WavjO ;\i{U@RGk]L#^_2ݘ$ʾɮ/"| lr9g;ŐÖx\0OLf%w+JSt[c׊P4SRqQW$\[ڝSEqO]J$"JIu \FT2=^4ujݷH& iP9%36NIۼj^q(ho? ۍs+ǓA1a^nC]c̻!hܛ>G^ U1صRE`T3˞+M"B7zRtὍUG=/sӴffruknt#^o- ntʹH(։i冂IG9 8tfVfI5L|qOHY&VfMElS9Tad,ze){YI#t¡jIտ>,,7c&0pVNYj-Jҷ׏ܴrsFaP&[IXLu+V79TR*͎ Wiy{gnS@FOXvO972V+̈́ {t(+6o^FS_FdZgNfP汔bfuuc7.s =𧈺c6z7Ų pŪg @/y-ܺd$*WApxH#urg4PQGjPgՍXHKY1I?K|=ii]zl/oưsjv4%w'D+hvۧ8q~#5˹ ocҙ",;Y*>F>V9:ʥz̳:drFƮiLn841nٴg咶4R6h8r+YI\4v5IV"HjvI>Yoi~@ImGS4^fatAHOID\˖hi5.]DR[{|y8g]_imVU6_I0wH*(nRuXIud S? y#Ձ[VШ76aS5l:~2O[?.a wI).E@ qp=\%$.MDH`9Z}՜A,dZжKYXnvEsw~4 ]>79_V4O~2UxJ*5օer0Un|j#&!:'4_j(d#J׼G#Ŧdt ҥx]9.H'm%ĊG|^%<%b"E٩^W!cJI|6WAʻ|#c1\4{HBы<Opq%dwH5UA+&wچhGNFyf$ >6cuՔ0_—{/2ҫVR=Եkj\" ^FM8@" o_*}+H-P /nXI ]*'rֽbs.?ҏ \G9K''1*W^EaՔ1I5Sfc'˪.kVt Bv q^-yoP:Weakp;/LVD>{ (h-,Pi[ /R)+;9g"]CNDa01[j$,rO/VU|(wE-oYxx7̓CqpROe]xHy[ xպ]g -c95/ 9k[ sVM6?=9Հ80uiicQ+E޳3eZ+ax'W!vֱޮWaoYL$K$NuXGGѕ(|t:NG|A┟lr[%n(] TڜVD)gn %0[۶9*++^KoLpA*kǺj Ym%avA7ˈȌIF2?ƹ.gyu,]8.Zze}c.[zLkP9 W_CpIOJ͚H@8C |ױvp?lmN]|HmIԚH.0ҳQV-r:u SVq$Ҷkx ];NԠ+cKRvVcv;Lc}"x=.v>,|maYhd<\,N8WSM";n^qWJOB#=|] Xz=Ö^_i] 8nwfw pA;(sJT݊cGXrzpw0@՛Bkd*f:wYqNey SԿK F݃֩]i0,Cz7ZK^uT<}?cDm?$`dJ s֮ڥSj!bPjp@P:Uz$cM"?+XbTi:TI d8z#D\̣cu= {WV71,wpmnW"Kee9\ΒcL8ꋆ+e-Q-HXp6֢k|VLw5w96HJg浖'< zVV[\ܧUkBK Ia*GpČ'(,ESe#6Ob}b\1sf{sϟ.F&2拕-6,dp$X5v!bJsjxQH~EQS.{ݕ]5ɩi3{nS;+p1\~{1YkH!<ВƱJ/Wsu+['B^ڲI/];ؑ+Nq\1YN*;i cuVH+F"mDF,u(JXH4aWWLST"l\ծu7rո,%R[i"?oeL\Lᄎ-;KXH7#+mSXǷK"A@!Һ=$=R򪶺'ѷss+K7OlID|+SzrV&[I,WR`;/jkw͉w>'.q&Ʊ~P+UXc곌SIT\rv9]/WeII'u~*>Fs\泭K&RDHPUR8#jtѫγX4[Y66; q[[9R ְ#? =jJӃ-MQykמb|k^;o[PY@I ޝ*+QVº;mA䈾Gȼuq)3T ϼ̫0٨$tN+R6=0CaZT3M4pd|VDYsJ|5age TVߺΗR,; H4"W(**?x{V6\#Ұ;8]~˪H$nEhut ` 6CY'8+!Zfb3Ҩ 돂MIjf\ %d:,Wk||=f 6TFK?YR1 ݜ@kgnyU  D`3ZZoQ勢AsKk&Z~Aon<^k5ۢ=Ct;FK8T$z)ɻIܯ>uy<|>[:'r" JOATe)cJMKY,2ir`[CobέYpifHppȮYDO a :Vg$41LJi8U*4qna#SZsx&%d{Iks—gF$#'K GKbV/#$ UtVxayc#Y!Tj"]7V^e-ьTyŤ.ֵtgF(PUX*)$L˜k3GVm'i-Kve]MPdBOUN*>J$wj2F۽}͒$UH61[*DU/>$)&[jΛ!q==OVEF:\ KG Qa6΢}u$$c7D,lf۽(#j8*KnmVL^rɹ7!V ]΍^Ŵ)㙡HZ H 8UVE$ Q䞻mcfd\UfF;1xsLX1We!M+ 闩Mr5%4gڷ. 2s=k/ɻv&GRy'ȍZF ef 8ҬG} ۑ{U#yFqwj>f06:})џe89},vЙ'u5spl8 J[1[kwtYhjH|̫4cHz%{ хKZpO j9Y,.q+pw7sǭ L.TYYU_+Ԟ+ya"}ϵ]0Bh%%sڧ0;F^? &ՌH<~4laW8g$ڹQm OjI5XC۪2Zִ""Uz[B/FozhtF\imU@j#Q:.S[768?{$6n6G?DDj9Y>$n\bS`utk*k 5&%cm,C;19p4dp 8RYc ܫ:8ӌZw{9%tN೐t6%vV;1e%13^,SP2| /\6C椖("}BX z|\^dduk Dv'>;κKИGW=k,m@=!ZΪغYXmhWV oaCq4b4NqZ&'USb}+Kmnk 3ٛgs"VT%{K#J$ ­kEo0@x)mKF2_1lVYVB+RzXb{AR4*Nbi_,&zD x>kojvv\yj!Uo[Iab,p1ҳ挾3hsGHSKdd`(ïj_hñN0({_`Y,62]ȣ_~W^ Gɟʻo=uzs]qJ Xu-c:Xm¨):f.ݡ+U^ss\5#17@Oz;i&gzԕSz,kP7GPz{W .pecd;)8ڼmkeyk ]PZ;k{s cG;\w5YBPEih4FrώP]sH5IE5[ZMP=֋iv>Z84kU`Ѥm!>dͥhKKؑiI5M [( AITIQͥZ.('>ֱe 2G42([^-(Jd;ZTHҖ}L*XWv,Fu#5\_`*/@Qoc–흄*49q5&2Χ@PM,rrўG+DWfi0nn_Gg4Q[jU&eXqXTly2nڐǂ:(>fx#qLA/,xXZj޿?U$*s[NU^&ƃ@V'qbONk֬Pң=e=$]'Fj(&0/u} V$eILX7cfT]䛖9۞uKޓ+bkUF}dc'K"("#MgHGȿ_,^ $eGj͖#Q"B1K[h*YѶ^b^e6:WW,ŔgT|`U{dX7w3M{Bx"+6>P^2Ïʹ/_#鈃kǦu]rŏEA1ePArÜEt8{HGs)j{&7e1Ֆ:j*ͨ Á^ Ƀ%T 5+=Oyif|GdHY%~@?PCeXոR4'ht8䍠}'I -EIK[g'56#lsտY0-Hld5 u`x·'+]pn-Q nG}jESgCө=_tjkw_#4-V-Oe 9~%)@5ͯm ?in^! /J槅QwU3W$yq8Y*,kY%Zf2 DyXG5 1LRS_j~#F'eb" ᦵoC̭;Xxro$\Zi*b?Ͻz֏cǨ氵he 5TUҭ9ݳdRYUl5 _ `-dF^EG$eO:VYڎ{ia Wm4mv<dGՓ9SxHXmuD~"ٸd<0U-tb=n١`qVwMEI`=Ny8Pe&\NOvַ&iq3 sXڍjӤB}b'`UIF(~1s[^MjV҂8 k2()fU˶ҝߺXgٙ1Em(# j8O|uזs^[Ϙ~Fׯb,w H-uf/;I١QÚEdCi"n7UYkFXtZ$8v5KWu,0p8+@pxnN:4%HNkG, "Vd.?ӶX];$ z4āUuŲI<M#HF8*tp[ Fx"Ʒ2d}1"BىItyeg (u*+3UnAZ4«8W$_$.'=>D&g}Qխxͮ}֭ewuR>Ů5[QЦ+#TwUQbSZ¶FһgCoN 6\#;?qbBeB9YsnVP6rqXZΨ~p!Bmj!şDYi0y)n3p;m؆᳓[Mn+j9[S tM*xx]6ӔZIiNB'e :/xrJGpCfVd}Ҽ&=~|l;ki`UJyt꺷-2&1sq\Z;un8H;Mi[ܴVc3EhqVdʢ݋ڵ/'3XeC~/Zl\]e'n_*+Divo @8¾j}1_Ci/|o|jG+q’s3U"A?Z͖Q>BX繤ԸKfhșty=`\y 8{R-=6ZH$&์K[7SRe "/o:ȣVWКX6ַ<2aRKm=d=$ZvZBӕĈO4 <ްGٴ=kV϶}Q,WVK޸JJn0 QX@v=*$t^Amئ:Z.HPM^@dm稫6P«=+)]-MKv hĀIl5MK0*tF9$ mkw٥rjױmixY@U9%Oo)MͼaG qYڴ 3&:c'-ۜҺMiGSK-$FKysAPHx^+=Z̖?tv82RFrFiNdWd֣4Փ=$wqg$ #Q+޴,%_ߌ1%f)奌}NE. qVk'UOw]"[!$c7l NwSkeAv*^ !#3RF0YGQZvt#Ux)E_ME/SS_jQtX{[1pz0ʙc{С{ֳ1/l9$bPpn`{tn#@+p:UZ3NkSGIm0X ,ׁ\6K|pAC[7Dŏ>R] ÓhuSY- 9'{WIkI2in-MlS ݣe"7p܊3\„88J]YW,:hq<8 Mrfy%3 \OA[I 7^0LSYHk>VJ1Q1KcK5sGe$dmuW,13W<>'-*دgR> B#Is(IJCk[w,b%pv tGN|=jɱ=7|jʠڟ[aϷ5NxGqj$N;0c%\8r"SX"7#w:=b~$^1ӒXKcTt`$9ZԖO3^6^U@qj/'VPt2uH۽d!pbu`W㊚ Y0H1[ltMFWcF +%O#ni~ԗF@"-Vyr[,?*fT0+*.)3Z4Yg#5n^@$aЕZ;+٤>n+9TQѣjYt7Ve|IaS;Tڴ 1e۰$c*k:69*zSCy|sm?RY^6wc5-Z  5%`?C?g4qr8 (&3 KFgS/5O6$9Pk=1H+#=V\u|VZXZnJlmMH 4+hzTEsJH s,Unvux/v\.WF2ܮ U-IuzNE }TV {yֵ=BՅYr&Xzϋ5I -4 gabyhe<\][|HO\qNgVN akȴ?i٘ ҽYUIy.2Rʤ 6KLu=2< 'A-*49F:<#86_i *2axyW,[%rF3xNo<Ζ@VI$L0Ed|;}G.FG 2ïqVMx⾚nFf/(aJņlk}NGq ڸ3,/,s^їI sWEi >VJ:zCRǗSߥy"2)8cuz3(O‚&6K{rM,rt-ҮxVYuVE6ʿḰ EtZime̡fOiRyT^m77r/:@`Zf$y={S4XZ6V1nF:]ejam>mfZswmΣs==.șKʃʖ . #kjZ#IPp POFl SN+D̤oBvϹqaVU(ܰһK hhvP0^C~0=GSOzQfZ$LRF;gm*J`tV֣O3ڲ [T# ۛ8+YM7o[mA |-F]5Kol4oS!|V<3XRV UsV|6ֲ6Ce<YWJqFT8zӴRBޭGAEkb ʍ3L@ uN0zW ®1ne(jq ?wrx 8*~aֺ*hwTs)9r&8˙JI#66K3ŇD]NzXg֮mJ:=^dIr9U}qPJƯvq5^Q rO"V3Mݏa u?JzITT'.b1W~xN`cĬ;QI=;g)XQyC[j2O#`l犠I֟ )jPSU1rkMvbI^(pTH9&i6-q@2j9zEۣio!dA)ͨN)=HŻ }ur' sڹ@4xkdr;U d 7c82Pr0X,G  Evw\㡬j?(CqUmHl5FDp4PdI$zn6m G|JK%43Etu{$UMqӚY6sSjݐ/$ubs m䓌ְQqji*yr\/w)6L&u8߰g6R.DddbZsuvvrK#`g7-Qd2} Ƃ.:7Vht ⫕Vbg؊Y̴gW6+fln' z]Fޕq ;#a늡w<ΰ1ڇvɊ5 D7f}IJ$Q@ko$=XyhX6=UHwP# wR"C#q8<՛GVw##mҪVԙMV)! Gv$Y:&47\zuUjzl촛|^7+j:S][~}V]՚ W&1#jhRg?ˆ.IJ1i9Jǒ+ı?OU.QW 2]Np{\,*Ȑ TFOWgOHmvCTs  e@5ZCe7ևviem ^eeްne,A>UF9^Ȓ+qy1G5)̝K k(1E~|-*1YoW,x ;̶%K3' T KB=;mv /*=OY\;֬QDᔨ^F+ŨYsu&"hpcxb"kQK]RI]'e3@jR95.Q^lB)ݱ1j}lлyd'C[ Y Zl asXgU6W%Ϧ:U-} `WE(7y7zRm 9dv*xPƒAQr9'u~#94ʉ(fZ% 8lݜOiM{٦Y9O݋) 泞 %g=Uwv$k~[{MNW;;jy෸;Gj´h{0#ZDs5]+ٖF.;݃Sd/SYL$V,̅`s,>UkĖȲQjh4K$ݪv&Qqq%ҵr:ASE2莖寱2lH : On,ǟ1Ok"y!XBxlvm Ԯi5oFI>3`Yff9>bWk},F@ VF5$orV^{T: 9='Vt>wx\;B#s-ûWd$vVhK>Wl jFWcVmW,>t-uR;XF<ǝ} 5ktQx3z5xĚ g5˓VNc7H٬-vF_ :{}3cMfޢBO,Fkh7kIŻ+R@P7&{vL;zc޲&hĬ2p+,Ep_k.FEE6753 (ՍxsЊ|Hq8 2s7jy>Y^!SE:ǞBݸER ,B;ǽhڸS41e è[6. 3cƹ1MAvXU:ӭ"նȓ8Tچm ^)_}jeZRM'&˷7>T(~e*#qNѫ`o$E<WںGaLLk2G# 隥idqZA[E8EnHsΣzO]In7Jx>\^R4Iad Q'0,@i !gyM6:HxRwgpP0:drn کkw!`(>ZS\2ug~Zks2M6ۄ뛫9]C CaO2.eҫ׳*j|khWSYF$X~nU|Sӥþ7݉V]>!h;׽q3u]5$uIԩ}=Ψ\O#(y_GFu L>F RKQ<~%"!,RLd7coL^xVUi%KT>Vr-K"JJϚWt:U5{g46|3ZoJ qaj5XIOJI4p{VWzu!-;{ƆD:fconI;K$B#imBܰPzT&ޤ2 CG)sA.-Hճ5++EG4@׭}sƩYhn[YqxW[׸q[q j=HYr 'N֨zRj)^rU{U8W4խciE8\jϘ[4s)c= ܱz)g"G~*1Yvb]v=F8II# /q(Ԃ<[>q lZ]>ڙx]Ɵy!q֡ }彪e͹EatT5#(9xYr :ߌִPg{{k5xYZG^~&=kГC+}l~Aow۹I'V=ZХBv9 [懜~UeYyk9 qV)HxiN{Y{;xlՒ="F>T s=ǝ,xuqnJF)Ƨdµ6%Z8q,ʛdz*ZO.9.vguMgP{mQ}LBK׿ڌZw6~ufYs(' [iRLdc1iYF+is z2f-|IDRkHvzdcZm0LIje"Y?wqqVmGfb@b/4br.Mm2j[jnKLfBё,+^;jMu5A>38gf#reSQZCAS6 Z4;}a4+2HZ6:^$2t;F`Kv`5+V%tnuM4J$r:ρmQAUYc ի̕(hr7)H O[m#>O&R. t2yc-lh*}=z%jW\b]K+ V;-XkTqZ"RXZٵnS2ثj-%V uoj~{Xaa _r=ͧvl @֛)I{95ҀBGRI\D|gV# =>DجYh >ؔDN:~th%NM45Q9U;>9?c# mp00B3~:dkUi+F}m dXВg}V{NƓ殞4kޛIQoru_;gF8IRه`1zfa4k]Ibɭ.q U}2;ʭ{;9 D$baFjΗj܀1MF%{&[˦LqS;M>KZگ MMTzw%ҞBt`h̙19Y-άX]6Gޣm.>dvݍi[{t%'ɜ1c+uE2ē6U-nç"R8^F+)ɝ4iUD)bY6vנ5Х\1|ROK\9Vܻ-4qXq[,sFp =k[K6v\@Q)&akH-FR_KccE>lwDX2`U6{d\r9j[挘`<ivwL'BW9 [<@ oEk\ە`Oz޵*E\zױE14JoӣNr=1Ra}AK:y+(m/_?sY:uךQOR/vgROT`Ǧpv1Ly>$ =6|AR=cIPXI.qV۷%ʎ"!붴pP:2+sQY4مI'7%1-{=A* :1 ?EqFm9vw(0+6Lօٍ9I-6+vR?3` /+=SU*G,?LּS /Q/Ec*k蟳w:xGU?tU2}X#-#['JRBJ9b$g 0EWu_揠,'9Xi~j3O1ap"b99ɯnuiSw9sIiwۣם9j)/D oDWo#ݘ hg 5d˝c3u7YG?zǭjQaLvH5NWmrcآ t1 q"^\qzVTL^8qAxWbKohO Z{+GsĈx+SOt_LmL|+T)r'$߄#:Y[d"ZsEh*9QOt@_n\*?ؙ2(P\QEpFN C^xF p=F}r:cQ0kfIdڱ`Fp/m ȐQYd+%jY- c f 8Y`O#c2(Uv݌2fU1KpːAj'f:Տ,4Y0QԾס_$5R_.pyޔb"DsU5j8;7,XvwPw?QN<5'&"rȦ5`ZG$VC[`Rp aNnu ՛WRIM:VuM6e =h%iw #m̬Y=5){P"S51xa\=: #+ "ﱛN:2}. c$\A,7OhpX0X O[)GHKhdӳ560=Z5\A 7Fy5ݛƣKC}LIGf^)FGJ{{qI,ϘԾ87r#9\y_9ː؎Z̨v;39nFS-Sv%utId U@usSWM {( O]HZ\s*9]).YTz4PrY[zشD{c6[1#w?Jl&0$-OAUm";t^ɧs)5)J$eYǖcq/l ǩ'V{523+xjԏ٤E )dH4lO('fOy#Az egbKqUkx5$ 5pnڽG+nf0Ǘ<65+(\hl$, ʕ$Uoc>[ep0cک^F,/QO=iԹwZé0ْuci<Q+; ]?Wa9^QCz @mbnVnxϒzϓӶ 'e3~qٿmŀѹ*[me;GnrK`JrvHc+]}  ]`wԀ=Nzo>?.r1ެ-Ǚ=n8uKVZt#InlgE$`lǮ-pz6)jhcOʬZކX8kӝ]lF$Sֳ䬢k.UՍ4忒~bsT?ʳ;O&լfR?0D1֭3M9Y$ k}k;j ,$.Xv?iim4{qW<9Zy"g VL+GfvJWn6ymSi睹ip@[v,smucUi^%U!AVἒ"e $tֹ*+[S/o5^Fbz . ~@SzQTMd;9&o9FQE`.rH>!<k?gֱ-kmPv,}+p܈0+ ѫkUsGg趺Uh|!1Z֠d#dֻ[@|ר.s$6hͽ#RPF\枉*5kO3!ލ%'KREU-!V߈tvq: }k:òj14!9JQ{qjZĘiXձHi%+ϮV!HR"? h3mQ((TvEM2hVV"}D6r6Ll%@kHMhxoQJ+Ec:td2*<QDzU+/$w?{6އ BUHEY?ė_J;rWQMa*D Aϫֵy=jg6q?M}Z;)j$9[HϸyYH>FoA{Ez:7F:HdqJcmYOa:dq5wqo,hfNkN:V 7Uk[XܘLaMi:1WefV'Ozf݄VHݵ\:Mێ4Jmr[ԥ'w.nG[H˚ז)hctk=Fr%t*L<҇NwbUVWoڽ{3rlYDӕv0/#^qNZG@+F旞[BIvKFnJ},H|(DTfWk%aONVݷE@@z1JL79iFn1xQ|E `;jQ 7>z@YOf9WwR-yQr,|w$Qck?y4ׯG L<ԗYm 鷶*^";(KIH dַNZ#+^?7ZQ'7?IVQNhةB<7qPV ]4X|Q' cYC$<|DjJr^2f-7N*thSunCza0\ߛ=)t^C{V0UmrҼ-dr 60&C웫H?Ƽ=m+"WIpL(:QUZ%=2.bITIЫ^U&{mg穓5Zᕯ<֊4t^2vt>?h4۲˭d?geud_Wz|W5eKO;٥9XpuFHh/jK+oPkJR=Bs+;Ul̀5cPp\Nۏ5is"7Oc4 oT2Qrk~O\Y@88C_3 .r6/%r\掷UoGBʻbv$uR+|Yvfl:7ayIGȩ5[6F`z(qRJ|zC=V#Rk_;) s6Eyڄ٣c`wZ"=Ġ F2&w sFyn}pk֖ $xḑ?0s^Q e'ObkRzԹߪŃ_jipVV5fK}j^ t/\%f'޼kWQGP~1<)l&G{sRkSנ"cNdU 嘳a62xfN$f5U'+?n-4w,jҖz9앙k6kteX,YFFp[ׂ[A+ <;yH{Y`\gcp)-? ~x?LHqfzX]FQi~NBBj6%_H?nS?JյCڋǸtVҸ7*k0r;[T G=Q\&a1w7svXd;WMg}iZ+2d~b-C\tsSBWKxue܉g?SY0rF~g ֺ{\sAGj^k5d۔Z1 tHuM|-!us5[뺴D1$[3jj0z*Qj.U7ކf`LDXBԼbrGn;#8=ߋt7fV=rfjj˩,vvr@50}xy^_-1e#W1~{6nMnSkFsMD=?GKBc&G9~⭶M?M&Lc{4T)!=P74ѩAY ֜֞F׍5˛0gM;:Up0{W&oE*|kKm1{ ϪFa'TBЗ>Tut\̓$ "TNEmsL:uIHFGCZ˦yF[i(kyбSG2G.6|Nli"2ʁ݇HY\J oٍe:wٗNEM/x=]>ZO'# 0Kulj;m jI砣]ywH1#IsϟkqU}H]ː8Dɉ>+-J]7u> ye0ΥNGy!Qor o=RK3\[vaGry?gw*CtڼGw AYNKFtA-lIoYJi?y G׊\y{{:uGO$-0H>Te)gN4\G&ѣ-^ .i- 67Sh;J}OEa ɥZ۠=*41\Uf+;ݛ*V,{Xu{mi#qWG7f)Ej3rQ_:}5)>kc eHPn!MsկSIZ'oeH5S%1Le dO(IExTu}XqRe;$y8<wٲqVϥ.A-fX񆋨鱶#:] BV.r0xV߈!5ҵ֧Es;mm0RuvˍʵG963hGwE$f9Ia7FݵTv4QEHcrx$0muK0r9Zfh1늩_h2{!~}LdڇQ3pnk'eV6,2?ZF,EvVFM%3V\gUeC&*+*W|;)[I2-z3Qi,FUںVR|C鞵;S*V3ӌsL5ҜC)feGCXLYr@ymV޴Zd)GZ5˚d04*'ֳu;(Kۜb $֦0VԷ&&ZH{WK ,%id ghhW"+Q5ucNi_yR1޴b@+-a;" r)2fɑ&ܙTBv<}jZnvm59[_K(ɯt{aC'78L<x!EhI,K0YudΕ=uP+RK kFBHqON+MIpW (Q$b;X] !]AՐ;xg[,va(%05^ ^6ŅWێyojiʑ'62NJt#szVV 3ɮ5E,|9a,[SJe%d.~,xLk[uwN6O?Jd }kϯjlNQ7p{W5e瓓Ӵ-}NiT=44e"K&eX?Ɋ͚Ο"NVe$E빡E53YZΠrsɒIJ# w,~%å\!rixZ  bF)9=v A4ngx8;t6rm"suQϊ.E@;Rݠ UEC%ϥJJԱ:eydcC@?/L܉YW=)B*guS R|f夒;s:VU U~ PqE&m6;^Fpk:"]oۛ,oLWu4Ff#*[t~ ciT )i'*K'[ٝWmF'Zdd"sjv.FWՉXuP$WhXP>b8>lG/dVlڦMI#-bG#)<ɱG˴㚷L"Vc)g cHlܫ*SKqlX,p6Z6 @Sit!KA29gVS$uHc0Þ*y&_#9Jm43l}DY\iIe!S9Nq sXĥH,Gҝ{+v6w5U;ZѵɈ(|۫ߢ"3*~TYƓ3gp9(N\bX3IIIs(Xl#P[;<-\ үʞݕS|"孃]ف U{j֗<O9ZB+JԬlAAo ߿0~\9~v5JѺ˻) /*A::xR  ̱Yę<[Cm'ynt\yr*9̩`8P8sK9iCv`皇 lnRb/qc-a2`2?ZD #jNvS*]̭k)0TBNGfLG@nZ\J̷8eǧz PsroKBHzY$09{EO])|a< $ 5t&wZ1A#nzܼmXd ]_dyq ?c^ilҳ(^Tx/z`hWT4HH \wa:&ں4HфVFSޝq8$y{A#ұἈ!I`1VÆCTI5{h*yϽ_v6rvՂ[{UKoBSҔ^餢6w$Kw=y҃vKx|zP%k$ڿ2:f]OnVJ/K=慕͙U>4R W̙"bsڹy&8u$;[BVmM[ =;՘u;LjqW!+ HPqknDe޹h&HRB~^B8(¶9YУ¥Gh&W2Rwdk$|Sl.Z_%%sߎk 7{}A<6屛%hڿ1ZHeB ިZ|O,8Vk+&sX٫7e SV829B-Kgn}kUl }[+Kd˔e6,K&ߛgY:f<䞢%Y2cܚ+g-V)3a"5&+݆\?JxѼAUJ5]W4um+X Y3՘:mʕbA5ZO#[1cRfbŁ;KvU$D椬{cQJvr.yjLмlJ3V,R0DrH\cUuq%kn}婙Z!Agr{Vu*%dEkj /Uc# ,lhe.frVRi2(e5w>OU~e/ٝ!M84F-6i/Q&Ԝ.up00s:hTEcT>60u #?Z_ƞM&fmN5sRmn5 輭ܯTgjZ[Ko3\+ JFnLԮ6284\+It^\c'6vZAfѭ` nulfELbbtI:ޠIѮ IA[]GF;ԗ馬Chw od`(-ݤ+'TR8'Z6s`t,9OuDCqZ*vI+]c}#_G2=!\n+AT&ҀMTWBRI|>ɖ&Sޫ˦NoU$QFqY0Ԥ}* c>*8_FuFԤ|#袪j>mRy/Zm=w-Z3xgJǎQU\{4Y9&Rm{u_Z^#y~v%pjjFwe+N<:)Sh6-S' .5Ipmd$̵IHFA灊ֽn^GHlA~*9n41 yZkrN.ݙZ麋M?.[S3=5v+rF:nVGa/rMr^|imlF1:+OY&r[-m ̣ Im1|Uf𾵜;[Ex~\[Ms(Tj|/U' !=ݫ%X`V1| vB=`ڛ2--D(wiUCoűֵ+MJ$Vm~6?B+teĥn |mXfbnub?*ۏ-eÎpsQOö˲Ϙ G 'xZZGKN85ΙAheAj}͖Q V1$kNpۖ;%RRVFί}LM9C\ڥOt3&%y\PT.qݏZjNܬn1N$ :|j5^WfBcO`*q'q*峓 U$a7OR#èc«q)xcBp'A*n֌B8rf8鷭TV][ ٳ"9`u}$MO?(\eЙF6t[KHхoCDAmt},҃ jTyuG>L]d{BkὍuN+Tyڏm\Jx칫nC&K68qVA3 `ÎLJoI5t Y!p w~u55=.s:ge~UX鷊 Y3&֨Zm"rii ᤏ(FmVj9t#IeC)-Ыv~mu7Q%,2`^d(-6LEըs4Ҏ^9쐟s-s:*-(Mv`7lpjdo-? lw+RLCnN2NkC[ң,Q̯خjVSz?# @1l@^3UD73n1 s?W!'yG5NvVB:[T\x HǙ̫@s]J/a5&mb\TcmZUi=pH,͝1k^K8nk6mF8I[{X\-kOܥ{j%aH^k i $rsg5{Nbpc;9mXG#wUdPABi~f`Ln#)2[VvxMA% qn6ǿh<)AE^Rw JL6.?cR$zPorj퍜ZVk`kKJv. r0jSG|f3&<9<Ӷ'8鶃c!Le_zD e#rlHcRR˃ ش)e]G`)Ԕ"Y QjKcD6Z&1S~Hih0SS/ِҴԴf_.$ҩAqpSMM-ɜ(׎V̟zVqĻ~3Žk>Rٹd 3Z]cv*͔~eOsPĢ#ozv8y3VYcLx "F$4n7v A>'k隡㜮+JIA&HbU٘Z?"@օ,aBX$gj"vN\B=!d*\ZJ \鷚\2v#Vvp3J2\6,MZϧ>|J=Z'wrsROnl*mJ.R9Bp]zRJtvs|yz r.'z+1o3"C11A'#rQXGÎC3 ˩Y@(Rf5+Aj麍VTэVRh}I\(NY%ЏV a%ɐF)cyrjq8hܞ3Ov ]AXakD(շԞCe︷sf~i^bOT>"hc\js;)%̄V:j%v+2s9wiZ$ݰ2&ij&|UZk1qJ皯+B8gSTgK\dnռ-[0Syg|SkQDEt;.:W6+Fup#m~S^\\EriO}jn~Q b>(cf>gf_]* \Fۈfc6[ Fu_^?Z)tXs':jsu 2ō6▌ʫ\ 5V B֓OXO*ٵ𵇘1…=[mC}-yyu_:XgHѯ"y̙5aMwFy$qtH",q|~5|yV0Nvmǩȥeg\iRQcӭt6z_x\ ihVfʣ#q*qYʮd߼819o*_ʘfbvVGtHkc!.za2MיZHE[je*ǎkӵ@ ~JZd=4aLsEm/ιegF 9;/ʲևج T?FP+fK;؉!=5%oE TkkBjҷs-܈m]LU][w۫,]P p@#lYzUW1\Z>wȫB8K/2PuɧS' " H. 8.ŹdѵR x(Z}yVj͏nV`֒Ɠ_׺<Wi1Ȓl Ժ,Fzb붗N}yzqUo-BS[\d2ʴuVfr0tR[<6HkVYU+ y@rzDLPtO֭~ɴaÉq5[tk\Ԏ k6fB7_­Ox 02 \Σੵ 7Jʳ5k|жt"CƜֲ)W/v$Ѡoj%wj;C7kɸc$W Q7S!,uwޡn$$G̸dP:~E9ҍEMŰ}K{&c/"ά!iSd΢OK֣z|!DN7DܚU-ՋӫetQo\ 6ס!O?Z>4XQ"zᘊߋI;^Έ9 :u.?]?*?foCxI,nOG/lȲOV#:U]OO#38:`)ԪTI6); L[]~bЛ]->X OB%.-eRȯ-oۛgwO*K8hH;K)9KKTyi8*M7>($k8 MVbp2C]Q r@\Z9U`pþU20nOJ߸5Ug ֡X3*lw\~ϗDY²( ѹ8HMרU@%͉ڥp mܫuA x5R.J$#75`o3WnN=&\TScmxLQN rSU)Z[Yv#*JԚ}{$0`lhQ`xb1[NVi4y֥2}AM!XpR̵| ʹ+N\eizP"VQ@V18F*kxo9"֥4pɶ݈sQCs#+lrAn!JJCw :g~ 2QqnYSg8IL {Hxl$jp1w M*iǔNBx gwA $x9$`ՄK7gkrр EmFeǛ 84Kz穪P?X>ZZYMswZmDRs-RD)/u[Nx|zsJa0@䜴4ZjdkͲ1CՆ +,$vjo#kdc<ֵqQ~eM*TĖW*A+B_<յ0{9ZWa jiiw784mB.~c׬p]]E-±黩7Mc֥㹗,M"1t Ehyߖ(Cy8pTJmNWh|78ugS iD:ykMv5FlHB>ELOLh,U($`&̖?~^ա9늪TPOZ`~RsXKTu);Xns:旣C2FNqX.:J=էke tS-I1%"`/׌UF6bb4V唷 BJF1{^Xتz݀0R[}E bNJڳG+KmBwDo\U!)W_'֝`$PsUȭs!@WB2,o@H[w,F+Q%][ odՔjV45Ĥ1{?f+r-* =zy ʩg_4\jOH"T^'2/++5U$V۹8Oٶ'ڸ诨GT<\g"l0CsRYZIq1%,zvmbKQ*zaos5?t?kTD2uCoj}+9mjW>̩ v:i %ĄtJeCgKy'8]iR d|sӔwڅ6-&xc5QSd`Ć%som-Ո*̓\3iuw6V<7c8V;#A$s1RTd8ɫVFRnjg7kjm^t 2p޵4iD:ESsA] mQ$ >LzU/k#X'٤R;MPB8>kM"E5h*6$؃zW6!@֨Ѽ}su؂O.v܆8Y+c 8f;>ODŒQ'C,r q:GSI8aI^lY2Т1IV)V{pTMfy]AFM4WVoR 3YWøݻzӒ[uG8ihypK8̠"\jM9l2%Љ$CP j׈bڪ^;!x=iF)ٲDա"O圎mi_FB|Ì/5jH3_'&z%vRv "]䛟\vjʘitz~TǾ#ihæ_G!p *fבTHOV6s\GK%g}ıU_4:UDJ;[)^g큊-ZBc ]묘=+:~~!+ޒ"xbΪu$S^)e5GKW=ć2JUO K8]A#5 c8ը#Ѯ[ G#*ֺBɕ5*MdZxZЩoB lt w3j{hWA $ŭ&aƲ+ҸojȺbֶJV{Flt~ 6.C*\akRҮ%khqn&+9XOJĞB[S"b CV@3Q1MmF-N:+IvvxMgůx|qKmb8k۾wyg~G(:I){MxX IOr[r='#twyZvs3jK> ~ ]ki6HFfpzΩ{w#w"Dc5mh&>ûo> +DDzB4 m݁=0X.%:qO|";Ve>;,z7 j6W~%@Jkľ7hʾRݬq<y5 i˸r9kH[0O.5C "񦢟v8#\VsPͤ$a =i8)u)JxW0qQEAs=Ō;{ދXܶ0M J&-7o&rP08ZPHT&}]!J+rR{m*嶩p TօnB[WBi7'ee"X/ݸɷVb|Ú[[RTþ=jؤ 5i_@s|6\jw$E$~rOkt#s۔li\k7)rO f*Fۋ,l>X#U/  4_ޗ*ekmF6R̘Qtz_Pk)^ML@:/ipK4aݤkΣ%0I;gN7s`!U;_NhO񥅤{m4ϙ}G,:Ж7쮵YղtUyֆ/f9.Ojs9[ ?v-O`ئ)9;4Alu %IAYCۋK;k mG3$m6nZ8WtĕZ=B1y?ΕFh\xJZpQ-*{:^}d5 o.omT #JD"ՔM1Z y]ې1Vm 6݌z8[4jM՛)8oE/kg;BasPA}NٿsSX] uL oc-Eiei+)Kᕑ.eLvzVzUg?lZWV|R[(mrcbYZCXum?ԱiZM%QO%&gܰh#c TVޱp_IeF*dmT$[fOӤCD+ɠ}9@6;Zho<ƸsSsiѴu5 \cL5s-U!Wb$.4VO[+m} #Z*}QI{7Yu [M&P.EawX# <?@sֱE'O9>ѣgoS֮GxA6<8VktJ&O',p)9ֆE2'-a)-nO<3HAhO\TXըۻ`mn~d$Vq. ؼ#T$[\[c5=2-"\$8q&%ϗ=NkYZ00{W0Mjy pqKSkDeol0Z8ՓsZvwufQaCQecr'Tu9E w%'sZYb$W3[^_QKvf=ޫy=ZNVESnJSMSm~n{iR@LsWIn{K}۫ nv3R ݳ)y`FJ2Ozt]:EIni`йm4kRF!? /q%'aI뚂[DW9/Jwk)*U!){͛enѤqxv91E`\jsq S lՆj$1fᙡ0\[Z_ļ#LH"i$?LbIQ^qJrڭ̄;ZaRc#ܞ2/v Ё47uICbQIikq Xݹ\Wni^ mT+5y;AhDíX |+nXI21n֯jZ ݾFܚM :d*rɟϏXIy{x5yY4lw9 W7iOSY ۼ]؜Juh]9! CG:zHFکiK im_}3T3w D8N V7\U mcҗ"l$>nj֗AɔԒMo5Aair2GVv#E/5 &1A|WW7|c!\T^\ ][89G$i]1WRKChVSV$0wI՛]S fP?Cs{YL6*1~eǗv5VNnbrj ͥ :EPiTr?A7 eoG,'AC]ԵˋRb^}QdmXgzJ4OZ\0 0[oX]m„cq\qIt*ZZ5kiwijҧ(H@|ոjyw0`STNvLkH]3у֍ܖPiI$Byj2: 5!mV_5pd<Ňn:Vfu";Lr @?q&RЇ2,\Cj+nrJkԦ{d{{Nqkohwwcϵ #Wѥ,J1SYJr9+ӭ]5f QsZ<[Il 5:>%;B\T#R(klW ϵQ6v!u>~qhnu;]%4[L5ӋeXǦMU̒i_k-:v:~6@EZuvg#ֵr&9gLT1m@{(qSRwKN*zr~5iTO*.#Ӥ[\_)1E[,y0 PrzNagHGT1H_ҩxT8`Xs{2]-(Ɋ|jZL 1bZm<#9S< 7V{fh⻫4CwP_7PFqVtDp3ZX:ŧcά۝],05ibzWHӨl8cs]HPrv75jZgvBQ6(Jjbh|J g#ޭ$\PCn2(8+L_Cb\ @=qXsZl;#c'?(7f\3Vr8[oqe聥XG 31i~;@`FFv r%b=+`}}[yk&5)k=$ oNN֑JqoV§ )<! #+v'pﺟssz\F{ZJ"49Q'yf՟i:;Q`(֔p Y gGj\ѩ<~m&J$J݇줖Cه5|US ,LYs#iEFj/fM$2vնԚSef~]>]Uq*)a'^7q]7>o7uj.]n"Au~qLKOˢ];ȷiFӏ:U۸R%9]{ gYre }+&CsL#IjK(񌞕F{?3s*|>FՑ2]Ĥv)Nqlmt}pOb,-|ʹl_5[wS}BD|Q隡{QzgJV=(Rjo}M [,uJW23\At9qH%SeV2:\Vnd<qQҐ" 8=*\$M H7K,m7sU>dL=J fR Yrr{鵸質X:Wd;SIuotZV_1-H?t7ɮwFP$kfw I|ՕHթ[SRIoFͻ]Ĩʼn#~}j-(Q5vG=ZWW9KX ^ư&X9'#ҵu] J;PNlݑ|?n4ޒ`ĥC?xW\职7t\ZsLRzNJMEUSR(u*9sQޗC!<[eۻ=U&l!Y{e5FA5i LK'cMevh éJrjwk2vyv>8UHe_zbŒ+-YEU5]G ؆љ7ǓEI-ʹ胥nhYBmاTڞXF ygwֺ}.W%@棆EI2ڳ-fQY )&rVWj62Cα7,_]kN 2U/;X'cZi61gJI܂fYWx1 ֆH^2^hѷBݭ>p[(xdE %GcY>'iEӝVdq:U!M3BI  / 8qu.Kq:Vn)\ztscqNkiw\wRSv۹$[XɷvKrG47.-CujpW;H֗]Dupqj``1oWi8SJTII-FԖ'Fu#fC0NzֆeqQ9]\ڎo#9@a`p9z64`FqZ%v5eIrꊷ4-zd$R6ߎI5M^wr9ݾU4.+5t9[QRٍ'$`c.5gҵ`8)ǣ#$KʜjyS/x,|`QiʥP*#A%s$\ e&,NOj :ؽ"1Xwn&%rO*c+g;[rk;+˶u8f8_+٭&O I*ȑ'Ȁ\Vln%ȧPBH*K2͕ҧ%Y<jhܱQܕw3R @ON:Vv \ KxNIt=JxEƝtkfÕ88sYW񅍉-=n_isٲ|VUʒq4jFO:u=aʕnk V((*`d3aȳ+6V38(Ju( n,sX۬dnpU6gl=-T(6ڰa TT7YiDO8'VuSjɖLtb<ʆXa-Jtn -4td7˟j_\\n- ;c6Io0v~Q;[5$oY%r= M*8|ZIt"Z;KXu~Ypr6юcvCK*RFiO-Β$6)DnHZůL@~ڰ~!j\krAk, pHHTތKnchĈ1f锻kOKyS}˃ֺ TnjUܱQHWZ;Lpҹag[JK.25Ed{c簕c-]}+Fӻ]ŗMG:~Bu3hC9k t-vU6#G)K[T\1y(vZx-xk#S$*q"fvdc(/igxz;e'͘*j/vFi@ s!Xثڄ6a2zW mJ;d#}$Z joor~m&:cEb\j(gr&\&t֕5h:,!FMkGL䏌̃kAgrG\T3qE_hNɟ7hȷК8tiQHxUe 黵Y|Q<8^qКIZFQ<=!ZxA:U8B?ܾ1Q̊4d}=ȸM`^\.uB6-.&G[®4ٝLKK[yg0+zre \#,3vc?5Vg:\ qLw QZdĺER} .0\Kvc3`|O9.獰U>ȅ)'vtw 0oRqTo㼐ެY\Jg:٤=0šd-Q%[ߞ41#g9XKn8Gn1kb' .ch7 L!<9F_瞡NXTgV=>lj_iko@٬ IR"S믇ZҶ-N9mu%&lRţxL "q_+]c^)tTfL2.Gs@後N}fjeq0L <گ$֜lQ%[ieh('ئ'O=K4l3u"E$~:+-J#gdlU+pL0*'8>n.Mwոba儜 %Px+:?>GHIq $$si<%O3ڥ0O9ZHDl85;isP+cZ#;mj%+ڢAPv]`; nb ke5&ڱz| V:sSCi4ngJVݍ5|$6p?mXz*皊Ó櫕>ʥH5-( ¸n Ҳ-XB_ Xc5<7x4qޒGuqvF6O_ ڌ1 v UM7ځ[3V^<+][f4uLY3QuS Xc1\Cd-5i^"V!G]hz^*)`2iT٫m+̇N$G#PިAFA l|9jȳ| mi֫ڰC)XHoc<Ö/c!?v:l: cWYdH_.7Z(|wp*%VۇqW[{֔:]԰lx:ӵQmnV?!%{Ukq/r1Mԥ'J)n<;4(uqU[÷I?t >"hDNd#@XUxI:lLv,.kwjU[)7c W'p=eNjIu̿5uN1Ƌ9JHH<,_\ocAa[z4_1T-ipќgW+^|YİIPEC4Y I#/ 'Ƴ3veZ{!^U5iL Ç+ f[ѡ$= j Bۗq TVzU[s+U;32ʜlyGN7n#Xo@kF=<QOBݪu7sk] $)ƣPա) "aB̠_DdzV"|'σz޴]W[6W8潎?$8<sM8& ֨1EC)FΊe5/_ b+v@>uSJʭpS۷FP\`OS9GMVi{z|d`nsV"cH7'gih7 P[xL 5M~n+>kmtF3oG׋,u.; }fCث8!1⦏@`#sqWpn"KSpi4fM@@>j[89xַo,%trDV?k3?Z49괚Y 5)sjm+<^)#Ѵ>d4>7zae.LZ=UhTkr<7HӕoZӔƨH3O\Vx"sB9<'?h' S% dGhJ]0y属븞>*+*HԠ6,`~yf JO.&X#3UO{=*c֯RZcÿh-q$cF|-;w&% K0kLw]^Zt&V~)j :_ZnjZ6<#vb*j6XFyrc˴h4I^(# i]χLi18qT`%YOwNKOU1Iwاh듩i@CeI^LTʖiR7iu'Q60!,90?O-GٌuK[K;>W8yU[qmirmm#WԢj&?e=u Ȳ0[ߋ{ 8+h &[ВE@ <J5b]u5vգl#N1YaLᔓ/J' ZI9i3ҽfPBX%e6gV Ixk*x ĪzN9]*Uo{$kZ,/RDmc޲n3* `I Pd ȩg,/q%ebb\i4mH3?JVY؆8uP@bVm1=bgX .O[{5vX-NqIj6Iq#y徳 ͜rKYnGB9WKݖ>@@clE3ݒG"V;ܱɊ۾b5qRwRK]=CAבwkF] kq[[| $Ӗ;UL+8Zv|F-2+G rnC 'q7LdC >Oi fT ;U,j@ \C3h9*;SxQ uݖ to`1-gO~ǡZSW[r댔/CS}S:t oi/Oݰ-N)D:u_(èvu/DOE;+8'vY[6^-B9{f>jqs99ֹMFK] NJGEyt ϼJ$H AƈW{ĺƃ-4 }ÓmǑ!6E!2IBt8y:s\&D[9ddG|M;P-,0O^㏈Z_cg%cXo5YSQ:i]>lG5oIp2kJ LbsX^!#lέ#9#ֹw% ;zg4oX;؀T?7^´n'SQnֻTHM m kRTg|wsZNL`}xy;#IhjeW\`rk*POu-0KU2.Y(֯i(*Z?kuzd!aڨ[ؘܖ~cҴ ƨ~m@#WNWrXogCpEq8n.C86O$paxN/Xۤa{s91I cEO8$WW42nv'VVfPzVa]ddvIlRP06H^2N'wb΄`#k&6ƭeIULz~fC9#Ю+3BZ8lrܬ,5b#S=G`XFGRzqY&v~݃+VJ噤}H/'@.#f/l5R+G&FpOt}=5RQZH)5!|6+MqL6Wy@[ZKnqW֪.DD=`T ܃09gmmK_b*S]lSQ ÒG4(Y6kmŷ6ry [@oSXѮ@Zo9=S6C'KH#VVgldqC#d>ƛ JzwGH̊f'l2ȸ`NNkj3 )sO"j휕ɔzc=+ir1=j!P;U-Inק5-5kt$w 5n5xB]ck/xǭbhqr,Չ]^pemm,h5xiZ\̅"P]BsKKX@*9->HĒNMU^Gw<}*c&ծihܽ5Ó˅/-g]N[yܤ{T1]2܅An ]n`s,3P\j#y/+%iHV3* KřEgvvDAHܼ/na#-UV_(q./d71ƊB\4XF\c|e0I+:I7;lMuf>ɫ2fpیզx@s\,DbnI4HIc\Lw]f ?xzmb6;UW0+m3IRkN~V ބM%zI[P;)ֳm@)Rle}j۳`2n]ɍ;PfOF2Mi۴1M RH$j]=wsTԗ*%o"6)즛5ԭ"yj6ZL-80u֧K\tl[szVKd[Eg320VZϙDW&vE :6&lE-A*tܘݫ$dź`G'bɅsZwV+@hEx[%|0Vr:-|ԊwvZʤ5z,<2 cbbXdt$+XS5 u1V`(axIZv.SjƢ79fMY\nQixQOҮDmN[ѓGQu/Uq:!aA9'mm4%U d 5CISOrxw/8ҳ᳆<WMb7]_zd ô39QPx* v+ء3a#.k7\u6!K&w -X 彍a;Qy`{+1}AE@ Ҹԣi(ٮW) ט6e_J-VQC|Exd4߼ #5B8}cꨭ$[ҠY8[pd QnUt\ٽ [H%VP:ô9RcLb0~\Uψs΢X34hۇghS[ƞT-^!&Tn̺W!lJº2M3s#̱LV-q <(rMY3.G?ċq*b,1.5ȺUrHʻ_$1ˏ+\R-CFFJ\}Ve&;xC{oSK*ꖲDF`2: >'KO\f8'sQ'yr:k5cXNz *9y +. l7֖dIIo5+JKdvzpSNzC3OvKg2F09Q,+r~?Jm1߹^Ҵt-^/E¹t3+}QslFb8 r(DUCI*$;d,d9\sMIv܃ .2 {bOȶb>dґbǩN:mG]F ɍ'LN2m!wU4d$ΧF=LBcZ?;I?n::ڻJvTԞHhw1+Y u jZԞh;H=3Xk{P7Bx<(R*,q05>=*hÜ'I> C [8ʹŌIdR3Z3fKp?T2F{B̤m$RG,wLz8d/ >£oR wІ'aRQ?)&4Ma֧M$ٞ@&N{p.zWW>?Rќ! 5Ifr^Jsֆ$^m =j. j}uj+y$tb0*UAy!JCSJ#iXC) fZM#֌)y<9j-Bq#rgȹY[1<]‘pᢹu=]y [B%z)lLOLAad ׿zH0^.ve"&޳T (QO- d#a]$q5Vv%4e'+ljֲƇu+f%H?4Sr͟\JJ;CZ'*o"#U:RŚٮoj&0F|h2[ɑsTu';A]n8ZvF60y>S q\rzT88ʅKh[2q '48<Ęo̯5aÖ g9רGOhڝʑk^V+y7%r\w9_UC?::=60 ؞$~+ٔsIK0=w Q5-͇woHTYRY F@GJ|ڐ_ʇ&=V,<[tbT ` JxUJH{Щn -K=Ryiq?{{ z&h-BMn)Z|ӗf)KLq!F0:t4ǵ 1f# kӌ'$?5oe'}by>KVL03#ν!xn Z_yX%c 9 $9k1q4PJ؋öv'[X՜ WV)9I[Ub7dcICn:ܴsELO}g=2-sCL-kB-*H-+ac.k>V.ԤN[:tq!||Ȫ.g)L. [x 2pƒ&3,"լC(&O,84E5+ȕ8 q6y?=,:Nrӹ6ouXcNz.r+FҸ/x$`kƠc*'XthT$-x}.,#UH\jz4p0QBr8zK6^v,OjFm+<'ԕꚵsɦlJLα`܌1};/Ҷ8Kb&Cx`Qq"(޵)wtE=B#E8G=]SReȑP$Q7m٤#{RK۫zEܹ'H^A'ҲE-2mP1Y_Vm|y}*8ATݰ[ؠ\Λ {y@$}9чEF1N:řJ|뒦Ի EtvA56Ui<Za"`E8tb+R uyZ}>1!SVx̳fc&*=D64Q?6?JSt:N+eJv絑rwиfZ=+iy+H-]_ f`QZyg,FkOf%(CXaWxVI\ ֧4&L$ ].B wh$)==eV {ƱՒ\C?\3PuקIM>8;qW4K8ks#`hnE睙.{{Wνkj\e-~lVEF=v]n4+XS+-Z4+WaװȫHRD)6k5 lU#'ev2zzRܺx[JY<Vq`򸦣mQ'#zn B/C ry[ K`Ag,SI]lfţ٢0=rj q}ptہU,.UQO3;Gi7±lT8V9j)E\ޛ;٦ܹ*MѾi! nh>%9VSOoHD!97jr񟛚|^us?&WtQ85[?h;;kF){3ݜUOH,Fvc5qk[&Q~m&- E&{3~U4 8?]]3Nm;ƺ cY[0jm=q Z+w<-H|++lʹMr FV52riJ nQNEV h5 c#7GnZ1 5i 5є91V>cڥ9FF5&fIOSvb;NZAUdXz6sBj }ΔZ8i\'Z1o3_ʌ,7^1&زޡ+#O/|9G.8vX~UiDT\4j1 7))*][}?ݮA'wi^G::Ӟ"+RKOh}/#eZE֕psG>ٺ9Z=6t u$-6kӋDkNb LmqTJʳ=sba޲MQ)F?+qJRVLRr׍j g\>q[l'IwKZH^`z";WZ|h#U΄܌dO\;* ?o,F&5iZh*t2wcJ:̩VS֍K"i^$d&zɯOԼɭLV{|mc|R<6RRID?*ڔiNQ5jU%Nzߦ_xqcspӝ}kʼuRh)8?Z{__xk\P6mUW =3fbs\F֊h`1J˲;گ^f,sO^?.0sַ,lb}ͫVb5xPG, _IzX\zbؘU ~LtF!\] sּjUR\f[+J5b8JTvY[tF6 wi8c)lr[=0r1ڷb/Pt9 vv2ɔjzr̡nO;.5Z*)Q#rHnNi23Z(aSp=KfЂ3av1<֕4BMW3U*`Kfm[zTte}Bͽ rB`I;6.yj;hAf>fEdE|bm0n՛4`ss]؇sJb,EP8 Zӕe8{.8p 1ZM{rlqY6hp>91;Q;=S5am'|g9pm;rX[LnsֹąHzi+2ӗL/B*y-QI8.i;t{6bvrqX: 29aZѥϖiqo-aa +[yLxwX#O- 'bx Js|f2S̹X!bkqd \W;6PI8tCG$ q'5}VĈ0zDoZͽ%Î9k}7*Ual]$c 9RɲD},Ok5a⯫֩ZL,nYvLYe*'<@Ʌ䊊 M?U{sJB tnV{IcSÚ)trH k{HE!۽pN4N.uq#33gh@F]vBNJ(a{Σ ף W8gI^&Kmz`H {WCWilZɛM9f@'gk>VƬ0He$gU+eFsf[WS 9&s.Q'$zV|[$6%!VN 3 w(L,H+^:U1)Va-wgs*1]l3cq)|*9SMZL{Xs C ", "W42B֛&)f1q''QZ_U~Ԛv28l N/flHTZa%׭FrR}UE2c5* jk>H  -B% .s%` 9'Ӡ9ا$KPBHW;Jc,ؒ9[B,iaBvQM@z [9(Y1SmAk܃ڶDK:"ުZܣm ƄY`c#~}jճn1S䰬uHi8S\][ PoUq+DEBv՟fp3Q8>UԚi$$N=(/ysnT`M8Բ4ZQ;,#ILbex\r)M;uU+of[EI<+qԵiEQ0@5F卡n>R%.ٕTh@7"AL=iAsb=f OӵWX I4ۍm*r,קwOqVtY`Cji\]#1 ߭u7TveH$\)NqPm]P "IHI;(D[֯$XpQt늉VKT$gGP|r[Q :Au3*Zf5t^};Ȑss |znCj؃RU0A,$c9i $sTK8&l(vާ6pӷjʪl};F l|eXgˤ)Rlci=d(?Vg؈e/>Q+o\\G&yP}pMTTvSME}v8*q[Z>l$*O TZql8d\[֭<%'5&(ܪ$kczz> %Iޱu6«s2C/3P&nwqw+"LI+1!|0ekhi,$*zC[ge3uXg#b11aS*=;֤0v;q&g1SdЕ=ngj,2d754Y *ߑ'RC3$%%;rJW"q/ٌO3UQ;tzۼ@s,cEq[q2qwFQ~MLZLR2~{=&I֢V5d\5&Ad9+;y;YzJA}'֪ZHTܚҲٿ;bx桩'{jSGv{8*fHfBA=*Zi՘/9wd_VUh#Jc?Z K.6ྵa_sjoCR]FICQ]81#xwl$7SMp/1D c8ɬnpsƲ5]"<x+?\2j6ѧ3\̡ 3mZM?x[Ҽtp <ҺvZIku2FzUls VӖ2|7HH@'+TnKōՊ9衭n9 }gJFѝ^m $e%\M#8/5]-p =q[Zb\'; +8kjǝrGr3]W~W K gzqn"BHl57.E|_.r}]xhg];}V饺O lsW^P,)BV-m+GXM '櫩rK<\9 3YPȶ2\ĀX9;rحlȔlѰHUWoW|k3`dےWWx4spܑA=n%Y&i7әc"rR\2!9g5 du393;V%y䅆ϗtT,|ktV-xqR;*=1akiJ1VZ*m D%,k/U;qnvĬ6K_*$r=z,à ֦r喻N<ѷSբf7w31$kPܶPڴ.t?/<SUP`A9c^ܴv,98^P\DA!>j;`خ[iI4ΏG:fvyCA'훰]<4y;ڋh>pLaXq4BN>67!Qx'+2W{$WBrc y=F|<.J~eZ!_䌺7z{F68*]ƹL~s')UMOw'cRes) W*Uy<9B})n&k6ddp䆨10 5>Ze1;y +69(@$C>dEntַ C*vpQԜmm^zԮBǶ+NNb(N@.BƸIc֩P&:^3Zs"ytZcdyʊH듊Kq#2*MdT'uXIU:ɞ2OQk8i$ޖ$ :ల\ѼIbM;jRV3-bcȳƄ.&@ˆQѬvtEyymCM{f54Zzxo.ڸh %èZM{9UKjOZTխ TQ^cmu;p<ݏ!RuH#'_!R\xp8 o 8RM 4R[uldv瞵NX!PH1Vg7x^+-GRi kk +sI 7 peb#̫jzb0or(֕n U[hdF;y@Y=jziI)ƒŨF~'4jJ SNޙΕK+D&xEdj6:!-!OBʈKfd{l'FNnVc1L5M6-3dzWi.j-Ѷ9ZD2W)&z*#{o";ڿпW '$ilXHZ1KH܅!5<>b_,UJkIkr6!_.rT7#A&b8shZ(_"Ǣ4fYjxŠCGռqpmaC-]#gHK096sxj Ku 3T IH2&;l:1 v֏m0TsU[ib{`{;KMRXUDi쏏AW$C\cY643c!jv*ۮ-܁иZ񥢮>qXڷmb ؈XwκY]FCv6MI>X)"J^ey>tr\btmcNᣕ|zZڐ󰓹}BEr1Gzudwd߻6~ oݑմJ9 b#2K\ǎzT8'7U+G[&m20S OAmn?xm0yoj1 ^*94odNR|>dAZtK%WlwoveVmGqesT8cjn-V@,%y d5lh <pHay ʥKQ?l4iP$ylG %ׂChorٮ49ep|OO¯ANAR`b*\62ocͮ'HCj~-nY~s517`3+נq|4M,O g*LԚpK6kjB|.e !YЙ>ԃDL \;)YH)|Ba~1PĹWAkҤyweIJtvir.Xywsk4(=*Ķqce1^e6"矸*9G JX"IFvRaU2'}468ڞ[qZ9eӔ햭FLv"ff$BBئI{4dyT@sV"([̧&I1 Qۺhl5KexWL}\6XFVz;n[^&VSqVl-"goV-6jVg}FV'bRݑ SZ >\Y -56Fִl> 9=z 874XUKOe'*GOƪj>,q^dzT5ÝqU nyB@nXlN.yrG-yat<k~[;=*^CދͣE%oCjYH }f_ls֭Yנ{Lz vJz:ϝ^/'DfExZCe{ $U+e+7ݥ_#e-cPV+a*crus:LY+Th&`It}Ni6:wmQ-3GN z4 F~p*IQd2=[WSK+y~$0JGb idq#^q\)T5-Rħ>Oh*Wco nf3X+I$=ڛQ`#d]6 C!ãShڱң;de4kXwb94h|ء3ճz 3U;AS$٬R~HӒivf`{iw1'ȷ Ӂqiq.$k7)%.̵u9+N6#m6\ⴴ%H~QqMI7iaSRK2mu+OAZIYGHW>έ~^+bw_f/7 3|xVqQ$!фet]?J-1Ch]$W;O#p∤޸$$8>[=MZrȓOCԶIuUb+M[f {`̏+sT3TҖF&M1A+bpq!c0W!_JO=}m{z7NMmwiuǸULVsd)w`) !"1P V`Q 3C7IzSΔꯎjj+ev/$gfvգLHݷ$Km$6fݧbqOxCWٹԥUIһ r=6LLrKEVwN}m#cxT]N,J7#5{XGJ\gl5;h^o,Dgߥ[ItZ[A3rZ?\!&mݜVd4[T;lznkD8Y CuVʅkM~m!{ruU 5(Kk"KƜ.yb8 ^[뗱4hg IoW+2WyaaY/(UP5惧@ (?ʲ:˙Bg,M>=NZ;{Sh_y7`J Mo?-Zݤ.*{-z򥙓;Yu+:42߃5aE{u;w%N3i@[HqRC FSb;P<8юh?Jfp@im>[ͶmVuf+1=\]+G-;ɢB% $jǟR3U<5v/`KΕIBJΟܣsFJYd G,^v: `JUeЭ7i YVX|=J2gmrcX#jGq$,K?jA5ks5zcVlAZ9aֹSNOY&UM6v[W%ݤHJٹ!gh@U=>Rb&q.]=LjOkMi5L, s*zeX:gE0GR]Zfi~%F-۲K=ݫ pY5tDzZw>.8Җ= @*H:K+.-%լ ^wr}f{ҝḐn6/Wjo h̨*TJU)Ueckoq&:JhPpIa_~*3j3>rrI=}=~,Ol^`qO*Be- sQ)*%k*YޥHCCYV*OJйu" xrY4̧V \T Հ}P g"icN17ڒv|sɬ:nzq޺o\abzcw9ϙwS6hLm=s\B5kpZ3 +*4)A8TN)1*1Ջ"ʈ=jE@Vʄ*դ[j q?)THk構0ee>RUJCHp>LѴ3uWi!XR;,.8,0Ip ej@zZ"vg\`5w*sCD>]P֥"dB 5`۳A)5421A۴m M2HV#5!y\#)W'.wNEzt)ޫKַ-ĂEaRћaW{UPvXSnaN@=LY.>:Vyk&`YQH$= e^ Oq'VryY/ jVwS1 iۋpX֒osdAɾfMd!8?5bEw=MCW x;T*.[FmȁR@85~f08fYLFI؎^R\f f.kSqr*)|-?n銯c{!5i+0NGJ̪ w%ܙXp;~5NHxy䐠Agyc-v5P M-B"9NiBaI%!3U-j  ʮjޭ+rϏ\M@ j5V#_ze`c+HI4M3*є'*C>\ާWPĎS$πu%˱S_xp+ =d`:׿YTmAU9n`\0[Q&؆p3Ycջd0l .ќb)Hsǭ*]mݵ-ך[c޵J9V{bbZ6&.O_ΪBp`Tb')ޮ]7ɂ1s Ħ97o#8QP֥ ) V A-W,R}C[/w桭ˑ~ںmfA'"Bтz溣{Zp|UM+PEs!a3֨\" "{zm֮$xF8攡CNR& [4RԞ[yKyr9RH0M7'&:[T;KG51rFMM}`Pwlt- t8Ӽl d:k\ YC r}+^;a7T[ɒAz4&0l9+@W5xE+ nafxLKkFq҅?rn.6,gQYdɻ[8F,OV^k[hH7wjvB6+ E'M({Kno6`ku\#o$!)MtBȧ$JR'8JXru(-Qf-SݸQm>K!|xqQ\B6  edl!'rzֱI"[XյrzZ|35v#ިƉGB `9Dt8s=HC)a ;y#jq )\s֛BnbNq[4wJqPw&GK[j[1 zT~ ؍]?4R5b5SzbOK0B>URNB.J>n`xЬ@8Zj\|)eѭDis`\V8ɮ;>H5(OCտ*WwhGSUATrS`l;[4Gһҍ}=1%0X1]t4; F;OװBܱ31}h]4#X 4洍TyFU~pY>{Y%bc 05nɱ6^,I呧2Wqb[Os&qVKSM?LtJSqj֛n)&է_3$0-j~_­܎*ſeoj.n>nzxM[ԥ+($rPٛǴ;OfOrC ?Zd8?g}IZ'rl#櫶ݪ Hزu`BH)%bƠWUҥ(0[5#^[e]ޔ^rՑw7dԬ5IT 9Wn'PqZJ>C8nÔZ;]9A8麰ṱ4DRGғe$`=>1ӆ#XS&ZNwn 1WN:#]WKzYQ['i/ݶxU]pZ-z4HV, >;Uv^iO w>e̗.z!7oBKbä`8V4! spGBW5f3H =Z\FcN0lܓ!*x'ԭ`ۡkyj;j)NGmրYsWEجqּB20W:"=8T&"g$0jƿ.mXcz-KWo\4HՍ029Ud֚D۴8MC۲k#kΖٛ`R qU죽I{j 3?o6>4JS 009$Vich4upn'ի]ZḼ <6F3I~5FGg~]1ᚔbX0UnXJ c[p^=/qhxMu4hy8eKv]{y1nV+ Zcz23[&3 1r2ohc8#4۝!&q5~Qci8ʞw @0;9osHNKbmJHr^ݕ!Z$e#쬭de : ,v0'Vg^?WL4 xs\>2 Hn*iC"ՔS6;~Ʃ6b4GN"y\[זŇrǮBHm4:\8vZ]u-i/[I*ԑ!CkĚ|kn9\ Ͻ5%8IFSA%g" WzÚHَ!PrS}UyC'$TƔԹWzd7pBs)bJ51ȌN~k A60>nr3X٧ʖ>%Rܣ0=Ԍ ss|zjV.?:dhLJ? ZKkcLW6 I/]XK+<ŭErZu{-U#W;G2OdK+xvVWtKUJbHY-18:K;m^%Bcsy%6b@GXəX|=cU}Y/mtj'zq'ԚbFE(DERyv,`vQ7p͞xɭ}8h$\r?*pݙtX_ Hjʹ% K仴mx+pjUԮhdmZęvLag[]:,xsY1> fmp21?J֒+V:9qGv$"qӂ b[I]*D6kF.N!#MveRcb5C_1kX6\j2|yq* @+*)ٳ9({$z*/Uqa=H+&˭+$H1ⳓ*)<"p=ޮZ[J`G8&D 3V!'m5+I:dd{ŞA e$c !UHS2ߎII7c't}ZYwѩ8U푾WDd1OtԷW yX""Ժ5)߉qtgY9;F?pNb&bt=9;T5ա'w%cv]6/6yVum68\ۂ@ʆZF+u+ij^oqW] uZ曱Z;ښ#(*&o9JxPhdFMt:^r-b nM?̗)^O‡dzΟ@ǯsS[v>Ae;nц6a>Q52(jU)]FyotD) CasV+N)GRu=0*I# @?@EMJW5q~&=9ִ!_NhUgf1U=WSiUO \ɫCCʜVd6+}&R,/ M~ɸy1[pOu]t[NWgJV_3{"q\Lq^^ŧۙQ$* +Yɍ6~3pOcti3uxk_hR|%`En0  ը73}wFrUP Hj5Oj{9n?~b%u3_yZ| I4ҏF=+U1du&"ݜ-qWai\UURuT%cMGVXl1sT%V[GTMf4sm>^*irQvr9aZZZg{u~O=l4(uA?x.ERv2gΦfj9htiz~y{bjwyl㑆{\Lq1H:>w{24qnpJBcs VRJ)e0 %̱ѭIĒrn-؞|[}>k}@pKk:Mɝ R-68ml|//V-}cIyUAoS4iSYzn̲̒ߔ~˨Qf^խjv죥`]o7+Xw ~cj@s*:-Lކ-kwE I:U!K>΃E!*1TޅFړꮑDb)\Vlg+0{Z6Fk2VtCVie76[V]tO*$qzUFVGϵ_@W I%gs8; VD #[:;CmndA^ TE,dkUÈH#aOL8lk,LF-WFc)[#S gzBXL .~u+oAJ\˙gw9FfywQ.3qZڵ،$ݸ؊kVe9ՊH v}*<ڪEUb[Q⦭KS_ho%1`w3ZdRF8VG QOޒDЛN! 5~J񒌻 ģ\ebN8ĻF8ӭhLTc)+"Aml*Zv8؝J&XzT'Sm=ܹ O&@LZFO7l <`+Y1)jLcjmF=j,CāRYͧ6dW(ۓ[ mJaZ[d)kO(VX\ҧr1+(7 O5~g2Oz۟LshQk'B3E~<̪#}QZ7etg)Y410myeep&~XaCn9]jM9eukIιՌcʑx*x?+F᥹@NKe݌2<*W;U];z G/ta)s(#ȀW4o乕ՎyӲρW 4OK9Ԝ-ΗlnXSTb19?d˅8n2irk($ePdǎ0jWk#_! 9[(S9o 2BɴӇzWZB쯀2jIaU η4m*T2JR:t,3ogu^Gf#G(i* 5ʖn }ꇍ4[68UQ (XRSkUvuHQ֕[ |Ӓ1V,WR"Muws!'V]LmI,o!A_-m&￉5 RiB y4it!&\F3׵^EswvR22UNe- WnI=2jŵnQƠq~RRnn#aǵL4w0?3DZDQ"(I58 -"թmHɆsWg!  J{,KbӊZ IxWI#lAtE2كf<Qc?pR zmNx ݶ/$F'<ڂ-IL=)#czGvTi~eprFn۲GG5§V 9E?X3smQ6=i]Zc$Emj@ 9[+-t[hFYA\m!Dr[9f:Y#δTb>iܞk녉^y^k0#=3LЯe =@c)5 %)rK;KeȪyYϛ3^g;1n w&xGM]~sGZ<lWiEJAڳʛ][Iyc+Tg9dĞ\@rGzy,6cp?[4J¶b%70,4D}bÜYaqH>Q{ tqPJMuH,4X*5 媉B׫PL;if(RsO)n C(vWF3!8L=ʒ6cS/ln?`+r6~NU8qXw<|ᮾ-2aSPNy8tu0jNs-Dm4ݎ*>^X=oE#Qmhڃ&g<_,lĎxdҭڷuUJX&[5/7&km:kQe'5.'wP*ŎImc55f"ѮT* [tWQ zX6[7-F֒vi' k-2w-hjY _O YHGɮ,nc&0Q8e{S=8]<u7tQ#}2*եI߽c*7PV'HE9-⪿̬iwgM6n܁H늕ِBZ,:b<6S>oez ܝm9ңv(JRIưcţ+`8W`gEmçҦKcpw(jg6洣Q64cWu$mΣxm\8i~eI ٧˰ѓ*#2ɈWcOP&+#X2I}@Zue8$ *1ZksYiθ79liph<y|N ^z>pGn?S(4Mu1x!1R"E$* Lj.WYś\֛fu9ZFOP٩^1SC3l[S]4ZWjVv}:f*?:і,i+ݫВ/`VuhJK_\<@䊿a-64yevQ?fMm;$w)M\] \]|DR$Q%};KBX DgcgBaRg/.Ș\둚!LM(8MF s]vmc"Iy^.dV@MLw+|WS/K{tF? vIBq:z&v(;֙L|#vZyQF,+ y]#uS5JVtrJ̫>gˎ8 kH&r\莍cq~~mHb}MD1V&'ﳘKhѮ;rjƻco&Fy\ d2pc"ɟE"mhBkXĵE孬3VUF`mv1 ZE0^4NnVHl7k-M"֥Y DHYpjhK˩Xr?8j#x;[ bR~ pOUr^mN=j!_83P [ %57 tp#BI!9-Ҵ^:1Pcqv1Rvi{ ߽KtI۸䴆eN2=OZ,ǍtZI]9ޘ*J֞BsЎh>BO^IB_$.Ѹg`)i +J[³smݻX7:ٜؐK9M'r+j79g@#B6*3MզWiIqڞy;2H[>⺝j+r"I1ŏU]?czq]Vpǝ:ty&_":RUst^?j~xxx ܧ\Or iN2MU%RK<3VDwwl\rdC+kK=Dtj<{I/Jզb yu=iHt8<Z3^F\`Bhm<ӥ(q.Τx@J}xH=n eJ JW<ٍwƲ*QWfגH+hId%|yܹtCig͊|:G_9%kN/y;OUA\x4e|ѱ Hۓʠ][}UKK _V]Pg7k_#]ֲJВjĶ}^cekp~tjxoIqrqҦ&ޞm%tx^Sh uwTnv 9w:g`q[ڷ1[QrN=N8Z[p\p.O 01]ꥎ z"F틋ezgqтk:6f𓃺[IHeUH_zsT.3]"X[IlU&ASƛ2_!& XSF75J'YAZ@U,&Xqίz|6@I5%ŽaprqֳXutm*syNByvC SYsAvO," zm*Ljd !B;1eS41;}%)J 5jԈ^6@~Jq5䴠OznySWѨxb$rpHUrna{ZBHYAiREjc8dt\״b$]$ cݩkfE'}>xѤf\ flqՉcMG$rOzYne[rW~zҔO_(8M{~hCupnFUb񑻨\ZKɌ9W a /RR]5  y[V!{v6He*ڻ!$cMJZi]w lYk ՗K_jX"*ޔgt[Wv14/>C N":֙G͸r3O/LB6vڮU>Ѵsi׭I`VSp+6bmv/-w3G2bNÀ*e戡oHXe)v\VrmCVOޕVnu= 9,^ϖ*t˩;UIQV 16kJ]*k|zUh1CҚqk@WOB{;U $gG#}j!˝8RְvDRZAv˞TdQZ4ؕGEi80տʭ>fF+M-MұE%Q j=F+2bWWI)bGn݅7\i.QTQަUՙe$&AT㊣y:P 9naMVcg^X|ª?ޔjH,̶LrOqT+w(6=FM6yby*ǁ6rbNITW4p|Xٌpw`m*k2 'OqI 0Z2XɟΦ sںݣfưvn{2Áۇ-j GQZ28=jcZVdSZeqZ^z$i +Y3rj-/e+d'{50hX<|خEKAd46-=e_s 9\>U(kM87f2 +.ڈyGAH Ԫ jݵU"۷޲y6w.U%Ӡ jNnBSe[j\Nw AI 13tr4M[/ .T8TӑPc8p9]ӵĄD\K[fVɌ9u(I/$J0pނfݻ'fWb6=)7e%s%7yW!S[VC$*1\?mh +au*^:ӏs66G㊖,.O#;ݳ}j,ЌgiE*Wj~dISiۻ4d2/2\inBJ RwU9_C5(x9֜$х,89Uu)LFثQ$y[aS9]Zq>e5CȷeAbsXa#E#H5kZ"RoBքNW` -WɁ _[}3&[ZMWcYRꦧL i=ʙb;2HhjtIJ s5i.9na4;:I44nՊH@ާV )ݣ*kשJI>ڲG,Y$nmJkMkY&y-Ɨ%.k+ W#gZ i`}bi v5)Y- *j6­j|#ս"{i4}CO.69V*xak,zC3 u$}Jcc_;F!DA^Z|Vv26FHS|zu?nxHUvڳSwq>!O]g2v\ߎ.൵o:0=)GfOEUQҴWqZL AZq,;KnsQ"OWcon\Τw5UCD\(*H+ӛBhJȓJ# 7്ƣfUNƺt?Kj \e;7݅Imy[BFn۞47a3_J-Y,%׭X]pWX+t+IURץ,Gv5T]3WM%[Xc*:Jd UCdsFۑJ!CkuAG, 1WslLc =s~g#VIt6lmi"rΕfĶsP5}vt"K7S]m; bB+g)6¬!Jdp_+d+[MSlq7cHnR(LS%KȈ 5ѽ 7N*9jmb]C aDaf?֢ѵl*&Oֺbd Q ٹZʷ@0ݎZERH5}G@$h;&j&+G{ | a nkx jܻ1hoF] w+9Px5vա0y&H 1E }g7n䐙 '3R15qZD%V]}*>_Udyho 񯹫 ~i>4CPjՔ3jڶa86f Ќ"t ۳ɑjIzF6dz)KW8R9vCZ6IOPb9uɤWX^mpzY5Uٜ`޶V^I| CWK,*!m.>^O;9"9b{cܠ*Qyenr8!4Ǎ[|i0( ;fGDy B}9VY,1D!P2"?j?k7:[{ɪmhZ܀ c5Z_{ $`¢n8qvCfD>vermCVmo4m|H44ں1FhMʨ㨪N B [,nHQ0+>}J BsB Q~+`d֍qt&-l2 $7 )„ǭXh-)TЩxSK6gVW%/F_),j5ELk +\0˱`j֔uړJHuIVm?m.pkm$<eHГЗ$1E2G^HZeFL W~u= l-#%5Lm9>*0Wy!FmiUըppx V*]GЭAT FMK! RFxFBFsLN?Us+%cZv #)z`<pOJ,Uu.G\J G}2ƽ[iKB7/5b`X:483X&2H*̢XHUb?,p6 qkxR0m{D8y"gT itV0.9kF'LD'(E a\zJn.K@9kb+Q72/\(]>VdYΝFeʤ6AS,.:р}5z7f7r+r6T-o ey:9so wYjv )!ߓ^ugad enYZQ@C˚[:XAܱڭpwkI6v3ŌTԤME?#\y3z\,G{޲.,M䌎ܑTGERNֵ($㞭IY+1wXgjs[[ͧa.t!e1M?7R˽/ZqN:  "ϑc IewG4m8+q&#:Dvx4;%Rv˰?c=j+0{([48Lr*z$*v'r^:zr_5bՁ̋jK-\ >15iYJy/ƚ(2 bz|*UT֥Y+r=+N{l**RWP4LVV ܌ՐÀ]7t w*Tm1h;)s;^NDQwz`fQT6Wo l i\P *ijÌ5ح+OFa">8&AmtE)|\VFXcⱤ[i_#3U;4SĤ$T|N6vm59u?f_,cQsK˶5[lt(Tway=eg;+&kcOk8Gsq&ᏟYṀoVB3jɩ$ fl `[$?)9k- Ci@7LqK+qGJ&j:T36b]uی?,p#ŞzsEkQNeW6 = ~QAI̎TUŪsoٴVhXg"BLDwW[z єW7_SiDUf#NAq:F+WQmC De#5 Q|vu )-N-]CZ 98֤ ̦08XFQqsvk m?MQ#%x:Zgd屎:(tY:ʒ(G|x4x! LոX#c5Z}@)Hu5%)t*ʮfD ,Ƚ-x@858b"|d+7pc.u{ɛ6QF\sU>N V=lj1 kĽǘCZ:lQue:Rξ% '26E?.ub8oD(pO9Wz/q [PaW uRŶNCsi#'ĺE0xszg}<=+r]%KNVM*hsi1ۓNjZ):*};Yhk!"pi&5ԯkz#JBé upcIlKÏW4k{E;IMꚕd$fA37R2?) <#%VE+8v=9Pt*Ztw}3B_Hv|+4W.385*-僕"Է*iڥx*~VP3lxzhK$zFm>DbsI'iC[or ug-%ҩҌyb R Ȩi̷OJݚtf)$*y!j⌤4YW=GYӠԫk@t@wQZV%@RGlg֣I;xyKu9)J8ޜ^i>\()pQ`5[F-qX>(ͨ;RNrѿέxS\-ukZL0k縂%(+Ss}\8Rvi%` RgLΫ|Wnh>'#Nb]=} YoZ rGR ^~nA UN v{k?xV3҃Rиc+UNZeZR% MtkedܫUwQ>gU40 nH^jNؚu1Y\еJTrG5, glx[x:+VE@\~uSV6(ڤ{؈$gY&kv}B'KLlKFMixsǚR7P-eS(WFi{f FV6no`8W=2D0CR-Pu֏QbolUdjCS<Z?T]ӕn#Q5sy86.\thгy+0㹐jo<̿c;x5Hh2Jo x?wn^0=fz_Z(aQj~!0ɛW\|\<2+<R0sc^{{lER3v ]^! . /3~6Ρk,w7&U`jBz}zŚfn D 3τu^#ZU#pv=<:>湫m8҄Gl$\ FIb$ \͌s[KjK,n՟D*?{l籬c'{1:iCi#A3=֖"AC5}l^@3[.`gVVq]ܚ2j{-՛0n:t5ᅁ`i6.\ ̼-9p]e/Nz~ɸ-s7ckQ7YB\r+1Ɓ0s]\%My7ơ|@xָfsV[8Kӥg\*Zvo(=hXբ@0?z'4DF)WQvBVa.l)QZ페#a>й#j&eIԲe^Yyl8|܀M3O[; ,zم-9 s]KWUuU|sV[aXfUY /P2Njě OWvbjbP q:+DږWuWs淥4֤rRX34ʸZfoq|,j330FRx)A6>U: bDld4F&.O*U+`'511L|bJI*&EDqi/L6À6[|c&uRFy[KM3Uk$ߌ+VU>[{[$%Inۣ'Apk:|OVf ҹ-mcUMlj*~`=*iFp"3Yz;rЅ~;H2z}+9%kF7E[cH  g[qȱ#q>]+p[w<1阺5[g,Vu"u%.P\hr@|ݤ)&"Isε8 3H,N*UddC~б]#pj3~]nqq*&ݧZ}RZV@@n21ZV1y5V;\P䁜)'ie2qXڌ.AS5wO}4a ԥJqz\4ZjĀzcx1B.x54E[J+&|UHZ4LJJXjetoq鲩Ҁg9`U XHWk21\= άs+fM^IG#g'hxb4(|$bmic34|BRKGD0K^bܪ$U!MU9ţF"cqTycgxcޝwl-L zQet(Zh`+Nz]L k&݋ QƊ6Z0ݔm?:!&2b8a(7˞ f^RQT^*HJXf;bjX_,s޵W3m)Y .SexW(cSGQ3w:[I#ăMY݊t+$qKnZDPpB?SєBXɍ<͒+ݳ3j/o.V]_+\mc 1dRPk~UN0̣&ݎLi.G ,;Ai18c}kDe3"e,ڏUlr4=)$m%B(a0")' v]FdEaI$*5bg1 8ȭUURjF.e<`7տ*9ArY9H\:4$gk)-t x1c2ƣa(EyRwlds(=jm BȨIu撒ZI웼 2NlDoR5+gUaW.7kKR[K{T0NcOLNF"]Q䦞cskŅ$w4aMq$\1i zzVF-ݾbnUlW&6+ 6~| f٤]]x`vhیՋkȍBdVbTg\hv)BŶ?Ɯ{66oA⣒+Yk{3tMFD|WkskOhȪHiS!D(NOSV~ ][k>#Kmv0:ҒiZHޏRK q*:zUѹzlLPsgOZYm2nʎƻ M;΂1ʥO* #OgȴծYm|{կ{6O;6"'?hh:XdL qY,ԯy~jC WZŸ)vXn7#31# W6tHY“שKwY#ݸ _zQՓ4̟$N.$Tg\N<5O, a\ˬJw!n]12&NKCn(|Î}#HKm1nb%%oS\+huHY6(3^ד ʹJ\z'wZrFf}PO\!a{Th"X9*Z15mfkxN0T˒uVdXC3NDi]ȩtJC`>^ɭYSVQkn$*ij3I5 KD~ˑ6+9A͡(ɀHK;ԒƬ$V\Sn` 9sŸ#J\DRQj-]B?yot\Qu6ܼYk @ u]'G-X{3.5F'k-Ey-%r}+I|G % [yR{4s5Q~ȀAqXԃ_m5F}BIepO\ NyֶF ֆښL3\˞Lxd3Fk(?c⥱&PHYm̱5L'< qOB+~~$tPUx֑R8=v9I;6:\⁤&hqN9QJʝP9TI+`%]$gAasZ9,.T"sE7Pܲ~'4'/]Y{w#ay5[$R?2.3sIkkİNC ꜩ1uMc!adNZ3:Wzl4ȹe:kX;LvZ-ԍk<򵕢&9^#dcԱjR`}5ӯ/BXՈ둊kQn1Wʺ-g>{"Gz|Jmuk=P`pqֵ,Q l2S\2<'"ܑVmk܏S^.av6 +vWQ/qޤ5V󸵋~q;W>uwij䎕fG9Tni&쑃Q\VŽ D2`S].*!+8jȅ-ԋ|+U'sY(-jrk vToؖ WikB9bZJ;q۵2.׹5QۜpW{˩W[kH'>[>ڴbU ^.G`*[ {+J8UBX9浮%EhC"tM[rCvw&Rw\>fBF,YUX$ƨp z ^M@ilg/f&LJӍ=AUT֠°D^U -^_k3[yZ,{?θcrv95pz,R-{d߄"ʉAɪ Ko$OO-yEs,pL0!14B>wUyb]& X=,38ZiSgf`%fNj<=@uTO!V*pyӢuǞ}s]&i˴N܂k ,]YD5ω̱2Z[F;w4{ZPzS*IDQZTR2VKk㋳ o>Xs[G]@G(+yx!W!#yzUЩ9/xޝz'MaⶸR⬦j˵@>m@۪^Bi]T.'\4)({dk>rUF7DKSijvmgUwLlcYھ aO$6*xr6isRGK ]#/ESM;JUڵ3B rwⶴjzThʑK8w85ZtҌkКő>k猩9 [K8[iQ(ӣGCW4ȕ0GJa=(_gL$Z"Ѯ#lC@Mh) ~W4uGDcem̕QIJyM n>Ox/5(cʻGƜ/= N+I!0[Phl Fd$kw#qZ ݑiHUdVze[+q$=f\Q*IƦ"#N>dȫ둑LӤ-N^?V; rz՝7Jq{•Y7QщKBFD$ƹ=+€CKe;;kcr4yzg/ uPLXԻ~7Vm8¯MyBAʥb_+7xFrugm21ǡ9Q/"K%#+I)$ TAQ:D_ڣjm*N.1e-U/5&ltb%c!~KYc7p1II98rFrEqiW6˹5g}#Nx8T+"F6##ӥlk7:nVi8r5:}d05"F%P{AW7wj/+yzBG5OZ6d`\Y'-#ꥋ& .tMr4 ^ܚsnh$k4#.r1kR[:<&2涥C zzJDíiXMcdf^3F##a&s(W<Z{ =*͜ ܮ3m`G, 1ou5+XE Y!FܑޑV$'*4A3UI9Y RoFjbr(1y"yʸGqUK& ЃNj-v6ұ#k=\Ԛm%.q=jͬrisK1#Hs*Eh@;y<.Kɀw`q43uJV46`R$ jА21eE򞝫U)Z4ӿ2dKpv\J}vyugyLǯYrxGo/p{x8ԧͤ4FUjk!`eR)2jTtn IxʃtEJIp u $o3'=M_=? EMҴ̕E'b_Ԭ٤ #,; ȉHz[QNK '%lY85E3IaRH\o.B3wڜ$k՘;.IWt+|#[Gt`䊷UEh`fy|mcwۼG5Vz] 4-Ԩ6AXTk?B^^QB0SW,3:ɨ>PVIhG!>E8x:F<ˇ(;2~Qh,Lg ҟZ@͜sNƙo4JnzU] ѣ/@懊sx`O)vphZK#0Ga^`Xg(V;֗)7VҒ0CBmٔ9n}W[՜޷? 1 "0*HHs\X{s8Jrɳʮ\7␃*5cL{HcqHi6z|m߷^+>šLY+"}jN_3ҦeDT  vŤp2rVz,X[y$R9Ik? buR֛HP((ѳHs[ve^1I8IX]"0 59ntʌUw*K鱝 Gވ%N&ǧJ{ 1.uuU~aξ#TlvrVͶK=k.hq3GЕ^+ͯ󤴅_"9@2M7W%[=8k~E 2(x6y% }lڕ?9iS]$ıKC,`„s+ 5ikt`? ոCo4+"vp$ ֲJiz5 F$&+Ök~e:4qbXzԍ?u?ڥ'4-ZdZ78eroOTQ)y$+޲tkQ;b̠ݚF̚OtY >j˃w:+B ;CM,Hf\ :˦ Y_Zjab:жhMm7j]O_Gny?8ȁBש6H.Y8,3WUY_AJ8WEKwb@sz~dA FVBC*7VSLԍ>tIlO$*`+*TgV5]p´gO K*|Q6pR+)9t~6{{y!;AzugmHv2|}s]զ[Cf\mRRRBQ|?4~$ʿ-uklĄt.?eE}E)p;[1s3W!kUkn+jա9Ik塥zPQkEޫ0]k=|? )d_Z݅ڌݘ>ǥ~be9ɑV_-E-ٛ(èEի4G~ [E$P7~|=͹O eo@=2kzRⅢ>B?咕j^J&}lOVi(60&|[5O_.6+o.[3Wp5椰$9ԚҴR{jukeGo4g(3Zq(Iџߴw|<Wt+拀 _|TӬ!؛V! ׄ?+@νQ hIcO?u/[)MVg[q*ZޭФ3 :?κnG,%V _~stsM«k=u)N)oө|]Zog;:u8 Iwh\ ?56E2oC0LIM% ୊7UiSvK MTeB[uU=k>9a 3;9$Ω7||GG"9 {T;$?mZ&ڬjş3'5 CVMIO1# ͚o%&%$*(|31988iAZWry澪e_NMtlp$5>4A 3%Ɨvǂ>`D5.:ժ#δ1f`0bp9gt5GJ8Uqs2ĪO8jUB;>Ưy`!@|~#*isrdygeLF:LI8%Î|H©=aeVodB/82=k%Ü]R8mY*.## 'vr9jwJ:2'֨"T,YOJғ1,5 JŔ8[6j6n`ca纏' ̤N}jDlX<(_ =5yUY7`-hFp2Fi `gӷr f#8BF1VXj lb,l閭};AUfzލ>}a;[Zgz瓟Z-Q`w$YňJlYeڱ3EmPm,q]ExG#W隣Pdo)?JrnI"%k(@]AKnnjG[uĊN~c}5+ҹ[zl; ƬiwIDp1 e[^yb|V&&bT;;V):Aj>ۖR>FP7 t "=y- /tN6-ėˀmAYPjWډK;t"5j_HcK._5+3o SG_Ʃ%^J&blZG$\[JԞ!r/֬pD- N>ESU5ͨ03펫/}2ۺTXxQ<29 :/5 f̅9tC3i*rk-̼S!p?(jKf\*8O ̗2TnUR$zJr8{KL1G&7]/.fCSWx7( D'o:׹xwKo |7$uF$t5R0?%EEgrOK6g {W,|Qwٗ>^`k($5܀b] <#J1ѶkiOX;#BOڢUx3rovWhb1Q%wQ?7Vћ:*X"f830>Z']4'= /#9aMO@A@Yr;[A2cv=M6,0\;p{֌:e۝=;[iǥJ8(9hpjZh_HߟzK"9l{xu{)'N)btIМv s.*$u7NTվt*)Uv Pa`~VƟE$㩨?S#8[66ӆj}:GfCՌe\ۣq5r'?$fb9Cz)OY#ghQ+&Nuet;9 B]Y卛ΐ&j[~GC~lS涗65R&hivc6ýePz֣b%_ہMcUe']k90˞h=Wβ֮V #Ukn=)錚5.7cn5ǎp9=;ll1X· n=SDŽn9̌ԛ^I_,N5 : 1DWt h8gA4]V NDfSU]P*kx.."֮sqeqK n+ơƨ"tmJ;Oh70>^7z|\9,EWTiJ,DXJ[4E 0>sl m#cˊ +n`O|VZFCv⹧}a4.Jk|Ü^N#]؛aXZφhu#YJUݛh1Q_235YRY󮁼+vr!qh8GFyR-#q#'TmJ-Hۧ5Yw>)+vBIq꧉um[$9FqRh>,yn[n N|;q=UoXqMӊ^박Wz76ƻwt95rmwKyt?Z'IuuT@OY1;zWњΫ徟2xMEлThb=j-a[3AqWgQO Ԥ1([,Cy2& N?*,4OX Eq62V&̫,JG-ls\~&@^b1Ik'qֵb"@4) 837fkeo(FubBUepFjSz=F+R `c+: 3R~n>5?;ekM Rg3wj8ʉjT tg?2[B ,;KH2i..7J8ʝL<b$ GY~ vEz 3>`C#k83<‘(H; J+,tie&YzrǤm 7x6:nܠ6xl{v2;TZYˋp"*~,5AD%أ _0ėzfmTtңq{hkiG OCy*}*厓!HZ .ÈԞ=d”RF0#-g KءCԊ1*esVeT )Km,lQLliXɭ;_<-WLJ'lKDˎ,/0{@XW #>y_i7D=+;V*z-B~h$vFoo,#<5s]H-.d:xaT"&|SL>Wk~!XylpxM}* fb2J5+)Sԫ)+96hُ$ⷴR2-j'`gijrƸԃ'4+:zEU:&*ȭ=cL5mA8\JԊ=Nh˽j'*<$9 r'lJ/z'iVՍŚc1LCVmRKW#BZ O4xR~'+{U/`vI#tv:b!GD#R覬dDdF>!-9^j.o1K,NNUԣǾ{Þg79_ 0ՠ4Ƕ+o `׈A㊏Nqt\-ӓc(tTq* `BXeG %O?ݨ5?Zy>`ݞp{RR%aNs>x10 αr֤ o?1?δ4?1P3i5B+[XƜ1>BI!aХBڤ_20Pq(lLQGzv rPʩNsT ]l5}0n$jؓ!X^o , UمIbZ_xLu4||5_q=ĹIȮ8]M o6cqJKgb}HɉgGefO5؞+-m8^`;"Ek(Жv<;9Eo+3w Et>I-aSGT^Yې6EAo}yqs>7KH`Ȩ:hќ-!k?pv~fk1p% ^hZLqJc5@iPeke^2_] yFgb#֩?7j ֛yT5[iAu0R7piYsS+cۃm5H?rc5]TB8,ZHJ@Fk'VVV+ؤkN/ʗ@1V߹#pG9n3[`_2D뷑RAtr+y*pqPk6QZLa nx~fC336$b&nBY#5~VlmAo.OK߬ Gi]!g25j[|t! f/u:9ZuMeԊvQ;YDU-tt_ljcUA^GY6Ek)#rmk#9'ԹԬ-y@tjbϦj%~S)*AmOx>g$1,zԱk$ \)^. jQE:JEka,wSǏHA;kX(,\{{bLډt~d#wJokk΁ Go*L,Su qU.|M2TFs +}+۸~\12!Yg.g<`)l;)dؖ+GY=CyAը&av F88?H!dqІQ7Vk48߽E EeURњބ{]M8Whw*y)ntOܽ;OԢZrV"cK?NW·|7h> DFy>LnPz-_VdS+7R w".wiLddC5e\:1!Zdmx7)WmW@XxE3 bi $ЃNmuX2E4LXsEɀUc'8ކOM+76>iHD3Z%{H-a+sj8Ch}B'uwMXM-z3Elc![Mg)x|mw^I B͙11GWu6m"pj8tm!5PImL Cή_ ddz YQOJxEAWQD6`buqʹpC≮kŠ=hŝ7@d?&4Z Bp *%KTܖ9+{}x)rѢq5~T5mMtMWUcmD)+F"T4n3<343fm"+/o2(˟8'XţFВH:a5j4-I1l+L&rF{ֵdFAjمyw1/j'%Ž?MMٲMGCVA)դ5^îeLs$~ni2Ƴ%C 1Jlt}NMںskgy #Ҹm29}.&ѵ;+Qv:%GK͵͸U 0珻 TOrJ:\:mj`xtpeT5{<a]W=TWN1Z,NW^ylj%.GnN1T',P^Pr0C:Oǚ8 u6%ÒQF:C/JKW<^wB붱rUq{[I xh3ȘX~X_0+0<'c#7:Wg?x>k6jTvy7l+o6N;mt+5ׄR-VLXμ/zB\Sic+iU*еaS>ksº6a[׎Oٖ&ѓˑTCP4ͪc5,kōXd0}ev O㓃W[UR}X@H;j71xC"2 ih0#I+sIjg V9 rѴ=⭲#ʒ*mXʢ^:S2Bʃޡ6fI H9ǭdihv8jy^WFYAe#F;*-6jex }3P|ꛎ{Rk2yh~CA Tu9^fz =W9A&Kȧ ~'t$\~5cm0sYrI=k3kltʢ{Q01Uu?l@1k^}ta pyn%@g{B"l" NJg5;Ď{]_42:p};tBhRe]99hU+1T]n$~5,Nmb5.L9]*7fNVLmn#pqng HݐzS4c٭TOaQ:̻5ěp8f2 9&KQ+L 2e2 Gy{j%뱴=̙ݻx=O"QF4L@?++6vK$pֵgnkbFwo8g'&p*ݱW5`ݟ$sǻ$dִ➌KL㨫KlG!sUo?+fdݜEf''^h$ ǥiK,ҫH]G5!$3ںShL"޵9$Т֬nʑl2sږ4-Оޕ#ِ $جMf3 dBՑif N nVlNSJE,`NrM-9 QEIh\`_fUn@9` [0ؒE[V[k\#w{h"j#ď4ezv pG9o"^֫JI\Bφ.mj=cMY-ֽERBAo02+KՏTU"\ٜ}ߙM"g`4̖|y'W`ʍ ^Ux`M+T㡌=Rfam>dHܚbԤ䪨LKmg".3N޸Ip0MI9,cEV oJkF% ==6VS%RSЈcl$" /NEVzjXhi c%د/,^+nminLBwo[D`o$Eu,k+"eB{VIg`YJ|M5DE>HvglxwD]bϥZѮ&hpdx!q@xpp~NL$Ohk^t!ձ޷t]T[gE^EXГױp?8=8Jr\Ͽbb)zi,19*G4Nj+ UTqޛV᱌JץxP1Ҵ<(Wn 3ںZ\IȄ' 'ָ֡Q`+Z);²sxDn'֡T}UbX0R8ȪV.} 01[23@k+X/4f8&iqnH䜒{IEԊh ma"EnW@s>3&0\4Zc#rђP˲ gp9DړM"pz B"԰ ڨxlnUոh۵ݦ qo ɭ =`J?0CODvÓ=?8 R 1CMPN[ktnPQ1FQyh{md3H %P"I\wؤ;U(:j%%5\o3cSmmf9e"7qYՑ)$9u[yaA8<7BP`F8$e4r66*!nIF<*7iu-V@@seqOm.;N_ŎEGm}V+VkOmI$s]Fūxbɷǹן\[R\P"GNiw3'8pFGzi׭au"*,dj1^zp[gNQH,sGzЬGzg"lmч,:6*b}kcc7*1Z\eG)gF2洎ev>: , *:;LwF8k[JQvG0Q<+>H?<ƯGtV1oxrpS"' 26vt VY߯/N-ˣRKdmk6^! :Pu67)-1Ʊ+ e8Am닀^Ryƍ%e*.N t5fZrs/l57nA)#x3Hd֎+|DBW \v[Wij(Q#:1twM4mkBeXvZ046,P(qs!< kZGuɺ@ګG] #$wSG44p$VN&m*ER y2Em׾y bt YJɚl^3GPg>EYCE!j_Zg8/ʩ̙G#T>dƹ'dr:Ã"{C?>{VF\r=ZM_EjOiX LhAFZ@q]VG.ርGCZӏ32S٫VAq;ScdH漦T֠fh0x,oIpT*0SGu=d&*֋QVB{75.ywcÒi  -בQ?~6eKM{{}o= Sź\[1P=s] R$&qC/iA8Jp6!?g]F:d ~#ha TG݇l]8wX썲`aӋR̠F +&FSڵ=D3=V2xtΘCVfN_3"nM::;@bǣVa |gRvITJ1 o|*Ԛ>mGPa 8aoQM3jY3!m|bSG`߃ZW&-Rmi?B(nb)Dnɳ.3׭_䢖b8;ԒBۺ="'[l "_\ӧْxn*@1 9Y8jZ %\|;xTלV$ڥĄC_P^ hW25Q2*Vn)GTmii+i&n$GޱIaU>dr 1޹Ui(uOYmUI55 ;+Hh2}iӥ`7^·~9jMZ2kYbSX՝뉙G`N {QfNpŁf3M,G8删Xmۚ+=X 6Y6_GE+/p*h0Z׿Mu,xU[ ZՊ |& M&?+v㸦\*(kT-d qY¬[c? @Z6:jU(U4B`6 kM؛>L3$ⰝI8ѥ<:H mP8!@Ҵm6ԷY\N[hl7z&GBA.fϲ0Z|:$V/fFX&bA V&O+HƥOF$hu燹[_R/Sj^H!RNѼ)~!J95GZlZtRj~YTn &p;գgMjeͭQ;#45.y$¸V2,)kDg ۂЂj&`m*ѱW TdHJ+֥ԩn=dŧ\/xORIZVicrjJe(E;4Ae۩yk[hT2@8p_jK3 rGLԹ*0R%h *ȇ ‡=Z ePPJ lT{椸N[=xJHVMЅ=:З2.If9j%NEV(#jIr{.uKxeV{|<$햮!7FJE BRDr#U’qIyq</@i{+fM,»#*;\[ɗbQ`9-Qc>]#њt$'浭|I; Oftqf^doJ:pjG.Y\=uoi<絻mxViԣ4de{]fdFVoW,*c5B,ˏC#k9"_qQW#JV.4ś20cUVhm݊5:C: \}g ݅MUH&WM~$nY~=j-x5ounfBN:WUYVlbQrJm J7[rP|A.S{֜4&r< %JZFx 1s)IC-KtrD ?m~&lȎۖtIA>oX/O9;EcR%D鄪Eh]๏6^m`GZ:G<``3[eKrC-d r+/uh͢KXߑ^ܲ;r&d2;vQC!V(rH]𾙰=O*VD}J߼yB2#ʸp$T[jFO׭áiqDn?ShlN8gOdl56$%K98ǕɮnMoojq(}ao} oA`;$Ms2x2I?v|RM{ԒF- +z$Qڹ5O#-t+)Y^SuSRWS^Zb~Wգ':KUr];F0~QɬMKߤMgEVYGluhxy/(=ΘXt3KY'I@:e KRVnE.T'ynqjNgy30卒'ڴ!pԠ DFY!F2Ɏj՚Z6Y^Ivw/;r`k6+^L#[sYH'ފmRtTd)鍣P+q7c;V\ַ1REE喬q/3C䞵V&'XUG֨bDĴ{g07lrP_yjyC' hhcp*ZmlNkJ܌5WW.-ϼ`dII=1Y&m[ e'WR|p_-A1 Ƭb`鹤w8Hʰ4iw޼3d;?Zm%M7);اi4ysޕtoZ#WNHcxV}kZweJ-BXRۓZDVcYam?ޔ=dUZl8g:El7D!sPiw"0!~cӊVGR1kf9)=,.6}|}jթ"b Gia4 giQFW(4+s* + *{ =kq% V;u&`NZ,jʝ/WU99I?՛<]fa;LZOc*1NNkRu7.^T\٤ ;pZwy Ptw.B}W\ m j"n ҍyFC߇5' Un>Ov]Ϗvb*ydw~a&1kxR|-x Ҽe c`)&?=3Om+U[Io/UH@jQ9_PYSmR-'/JQ{cͱ|W|B֧mA^OCt!Y39aq̽>I3wz*]"<һ.zc1Zj_Cd1?k]NhƯU5:huMı(vP 'zhWҞ&3\ٍ! H[.܀:sTg7Wq8޴kW~brk*.K35lpYxF2V.TX[NkT#$]<:Vwe,9rch^t -Dž$cҸ:ֻ bpT u]$HrҟU L9Zfe[YbvpySr5RQ!_6-W\ w*ڻm#E*?fSNyҍD(8Y[*. sz}* F{yC6eTr'=b^:m&y֕gv* =OznoG5t *j\I6w,$L>0BMF裮[=c q5 lW @Io08995vU6n淚q$f5,!g;>^lʈ'Fۊg5Ya@h;{RnhӂJOSchE"pMy-Tlr}廒Kan]%+C)wWvJ-JRkpɞzף7䶳RG) ر]۟#޺#MUzӯW";{(M"j2J>Bkd<+[IŃ'}uF'iSjM8E)Yr#8!.|:_e1 =:ƹdLceMS{#{*W?"v; 8M`=kжEIf.:gޝ_Ld+*܇77Lj>m!c:hBMpRk?Ls4HU]KXF"R׽afcdZN `B\ 6Xbj+@ARkԞX qzTiI#GiD3Ijmڼ/ln]{?홖GJqQ{R5-Kz)UCN{U4?99Un}p{U8 rOnִiAXIjxN[?Y^巙d+;WG/T]OP "1; hd3mܱ܎3I! sV#/M6!SDX3K+~/Ha)+YbFƿ/ S*],n#>0ޥc1Sv/!fYs=j7N Z4!:s"ז؛V 1Y:>Ӆ˱PckVpȽsEx8ąN0j ?ǝ:oo"e .q E{3zs!{kzw@Z WasHЂj`+3N0@=EVF,Ls!%9PIn¬ʴЋJ0qެZ]kë[jsp.݋ԃZ"H|L2?ZNIyTs} |#Է1h2}kB5NJ9{>+j0?޺yf;oίKFT߶*%YÒV|AlqU#rTGtdKd>^Kʞxv k(e1`DEFW;9);=B_]Kpdb#gqN)oЯbp )i lYՄU\=:Sm584{~A)$2[w nN 5U_MUȱE::@yԝɌTSSBYg$?v>6㹬[f V_Q'\#3Qdesy瀵VY-C,MiW>*Vu(ۡ4t=S"Qmcss|݇\##56g5yu9RdERV@p7 ո!7,C dsrChrN. E|؉Yib+6IQ ^zSĶX-q=+W/msNrfcMZCļ9mC,Kc=i_HkD*Gg*/O.$or]Ucz= õ>qZ>ӏOPt 1P%$C ÏZ+FtKzSܑPN^5 v5-vɦn9u_Ls1#9l6Hz]B,¡xRzpM-#a{)7vr6:0Τէb?suu6*Y|;TO]Qo dQo-_\x^5cCR-]g5:}){Ha_@K H\W:  !qH;Kr7v+Ζ;GF?ʢi늩^y*(`3Uk֕II8fTe KRi֨s Wמ>TyQ)4I&h,5 + ƴ$ΊQViWiXy>հ9qMHn~y!_Oݾ?Zr^鿵uvKq JF+|bRةQL񮩴2c4ؕ 7+^Sq皝͒$esX`J|W[_e3Y *8Br:Qq˥܎sUDdܮ+7Eh# MJFV׺0^뵑uѶҭqTakr+Ȉ>G=sw= "7F(!&( 8TbLV>wFn&1Qi%ԘT#KRz WUAEĒ@O]VtTb&=ZFW%J cYմ.:e[{` '9|aNz-]km>~K9#:ZKH((?jOm> Ssi5jiHyӼqEUŪ9_2ZHmk;RsVu G΋3Hޔ߳tu\hۻԵx!I[Z|G}}dlCTDڰA6ņvbN6"}_(%lŽ#MujխՈ ֛{q8Ү%dx4dVr 1@F@#/+kF\脁&:/~8 #<|8SZ4ȝJU%b!uP늉apD'Qng 37na+Kڂ &2z6UDnp Ldf ] \%Xf:{Ơ>'ozOD9:Rg>/ "Sfu=:fX"o}Ձn=qCt\)O2j|rElEִ$R8 s:U>M]fmKJulG$m vQ1֫?u YE=ҕ;(y45g"kZ1.KHNꭷoe-|O YKNÜZXN9ISm*x/`2MkzI` u#ɲaFFz 3q0\4;5:oG-.d,k`h1$j3e#*za6+AW+ж;ֳtmj𦒍33cjf~ϤST˘cY?իM>lSupyÏqWhwe<ԹOhɲ+tiiOqQk(!psEjَ[L OOc:Tޢn4-A@Y3[Kp|$bS]{={O9zGή4}xE]ů t$CFĴF>'y݅YŗϜThX/ 9+z"0"짰jy['j듑^{k]ť>M_W`B:ƴ(.ںm^D}c8>)~*çks8;-&k{W%qRAWx 0dR}O˥iv-^t:E n<1S98\4Uy5+rkc RrYja 69yu{)e;W{hNϜjNmUXtwҭNZާ^eW8p7\_큓Y/ cK^G6'Ajbb95%rƃwNpPҪ\ߴTlN9\]ÍAEcIZ~;皻Eg3洑ݤ靌y9ɪq);= Eg]i0HӚVcTuLҵ05é!,Z.VRуfh 5Czuoy&v8-\6jPqc`:UEm }4즽RiKGiD}Ei[0*jx^]c^ơYZAɼ!U8b3YOfk)zݶ!{KRFxh#3CEe:D:Ws:e3J~ 4$:,?lUN:#5Mu=Fmس5OB5&GL0KTgGI] xS+9*\­vN^ȓC2ŴN<֠69Ƽ:35FT<]hcE-os.?/Z;7S# ֏YbuRpj8',0d#xJ[-#+۽@Q86>n 7zOesumrP=j<1\d⤂Fwqߥ\[Z➤q,%KOZ]+թ*XK㯭Mc9 ڧqZL.Ч*Ut'p5 i<}j} |Erp2q4R"L:x|`֤! nRfjt,O˽ sO SaC" f2I-4d<"$UbJ&1ާQŔ{8+n8$K,$xgv~pqINێ?ȏf"l>fQ*v>v3-0g$5_j5/!=oqܙ6@[ۨ&CRFh:b&nG#*aT=}ka ݼ3юMhi7k"lctf4>y) Ś1kH\ ePsBr z^ե5*B"Q-QPbaں;MA~eı[#R(e= QpWǷ G-+^Q(t\zYQkXԞMY{p*%9: kԟ݆ Yi @,%.c=C6" PsUQѝmfaN $l-b<EhOfa%YrέxM^ZҢKBa\DWVKHʅ_oC'&n>UQkUN.;(ͷvǔPOBTp PE*p*p[ReϹc+Z4qP5Ҭ7rF>ʽSkp v{YD*<Ȓ3='IH\zYUU:.Ԗ  I+%;M=JoZk`yb(9ȭ#QY L'%8PSR%tۇtéiqh\W60e'_ї<]nid|=kN6P1k(O죡I|Cm.=.h3-ͼCr+ޖ2.J3ƥJx:v_3q (H#JXш$/i+nŃD9UmOXyx-Ҕ*EN:Kpm*PHD 6&¥#B ,V567|,;!rנ3}C^Sk#Gfq;;hR;{zּF;DC'奕X/N%ƴoE}6NhPK<[}@'2Et=+2w?ֲy$/a466kQ5-aќ¹}_KH!F`UV2#JQX!踥g7oGx.dq]mksus5˵OJI"۬ӗ-v&׺eVl|]tcֱ.nSO5\,Ƥ SVEҟf'Pn8ܽ1Flpmإ@n HBY5y]t;Uf@JGx*-JE9#)ˎ_:%h6ԊF.Yr+B0cJQ*79̸@\;MQLOi* _MBs9]tK+\$O$u5 韾|b5Acy=A*y*xúU␨AҰ.Tͽ%h|S%YRO@*eM8Is$t>3EJH>Xvs: ,{V;;[3)tC[Ylo*BeIZӇfrr;RXe*y8]Qrۺ{חoxfmؐ>hZU[sjql)t+T˚īsuj(,x#ޱ]2kŻ/#=b4ӤTӔmYu&};6nݢe@I'aκqZ5knwKDOz 7My-k?vwd7,*ަh&Gk:F)n J!ģHF!;< ƿY 7v1cZqX鰫ʆE]1JgkÙEzIu(i|y[y$(b\ڨi7ڭqSzMpv.Ft S3Wksť}oeW3ҳ-%63UBX'Vy709⻩Ӵlr98wE6Q&~c 3lU1[;B!UBz g*~~PzV4Ir''gc4QFȱX fc F~ }io$5hMQ؜I9EEՒ: nVn1QR9Md>70RvGiٙ@\`TFMq5ei%2[}W5jCyh}pkZ FؔMi8SzMα"<|ڹwM:G*xxWGr,vy37%˜-ڳ(6UIB3Qnn)dq5_I/q}\~sYzokPdgkZ^Zd6w:iLb<&c86蚘.xs]nE"EMr\@=>9i۲*x+x,\LDG=̣=ςc B9@˷=kF)`$ gJ[/ڹe2z֫FXö)7\0*ĞR0YfUޯV~jNۄ[2Wrba* %p$|9i$xi謒o-GB.USzְQdMVY,PB.ՕGZa}6U,0UOzǽ[{UN5e&54ZybedqYuDmb* a;L\ $ebqCm ;5"-gե`qd1{>")62fqN$4c1T8/KSGt=,AQ9jqi2:lخBV  d5oD#/こY\i6qvzZW #j#ɱ"Fqk{n^YKBSĬ=+ZX6^*&y©TfrI kk+ۥ_H,A }jٞw]w^*Ķm$ۂG79x9hެqo~+6mBaK+}U%봌ԓݘd[%`?"N^,5#WfZ]~A&cV-%s %\$ EkpZM'7YDkYFkQ|e饃Y4מX?`Z.ћt }Pu_--.lͳT)%f9哨QsE\PबqtZ.A56Umqް[$C`cTDso'V|kCRғ5`6h挷jdt@+ HkfNn#lw [(|,ưܕ \U㧢ۍ_Z5-3NsR$p;g~- JZ*`W1M*Ms~i)jlb[$cźFTSV䵱%v}Ӧ|{[]1IrENGY- Ov,YoX. PI c@8֪[GI?o.u+>ڨ$Ea~ky*;;exH揫ꌖ*סmxO(|;VKxbUYawkkn>卙+>;IXZ՛섀gީtFo֩M%٘Z TBVv؏JM1%ZyZ(8Q/XjZh7In1|ڍmlW&4Ja#9PMq܎+G߽? Wrm#,r/_Z|2۞Fn=kҴ2&rV.7F5S6R.*\ZmF# ŹPɶK;WԼմ`nFS:DʞcV Wd)Sj,䔪ј7X[?u^UnvXt m"b\rvg]tiRzES_CӽAVj^9BcijCxҰuG\BJPmXӽxwǷ W27 uzGa =^?em_oM*\J󥄊z1mM?<AG}^_j0= _HfkKOݷsP&:xbbe䃀Ұu J29#C%;dx^anfT0sQDIuk Fm2Hji^DLBMDwTZI{Zeoyy5Wd'kǎ0qT؈݈4C Q|,׋V:#BelfY۪a^\k%|HF{*xUtR^lNc}K@&{2VLV>lBe(qk 2#~b9Bщ$iJ5=QIo)ktI754Ml 蜐'+G\i7^n*#3ckE{RSoMn{t2+H>A,5w#óC F 3?ޯtɣ,FxnMVǵ䧚p8b6 Ʀk{M+Rح+%ܩ5 60۳8g[hx5<1Z{JoV"n-:p0a^k޹翵mi7xg꧄g'a_"94IfS|=+)0fxQxVpS# C-:ⷡddSԜד*`f\7L\psYktZfmOL3V,ʕxN;W IdpGԉHʓsYT%ރ,-Aӛ?#;?ky1^ pGnU2B H"v /2Epqs[Y8Myjlhr1k+N''՜߻5c5]2+ɋ/o3j+27dݻՋN$X8sZhɤY>Zn$8"їkv=R(k,^wuQ+.88%'k(BwZve{r⹫L*жkV/xm5fu^hzi =eTof {/kX s[V%Ԕ!@TyRWΨקzGqr|Rsjf299ɪaG"Ub}x!xFw瓩i+CXƝExJԩu GwEdEXHۮ XY5kFt2z:5_*vdUJԭCnWE, ydZV ȭ}1! `vcU<*ZCNwJC;0X5I.n|b/e֩-oQ,q>YGX#јĞ`=Z \kIT(ݳA'"HZsC+S&3—!׽nb!t" @O0sjxrJ*)t#5.%r:ҽPж VHPR3檆*+fg<#ݣ-u#pz#m(Zfg}Aۭ>]\UJd-$Ch6EZ+x3 6k ?kWSX{L-?8?^ǜӟXY,E,ZL.{FxYgp!vLB qϹ:l'>_]kHe95IvCף^ߪu%tJ?8Dp1ŠV|=BqIUe[hovynAeE+jgn`sVόi68VݳFZrk[#UOE&uϪ_"E+¸?Ҵs8 aX-U<+5)NoRÓP@f&L9]AQτ^HjV+ ̝[?VE<նX{U+IaI?xXOYFSTjN2zq -{~jJU<8_98zӣxJo厩ܳ2ŷ槀zw]xvF+;QAV÷2xΦi>brGzWjFe[b3|Qp1qQ<5E5&ß梙n!#Ya uwmPcSD%b4&>a9AU/Dx"Fr N E8Eplzf~TY!CC̷0:=֌r3o ~zӒSDG953[gƤLО.Ty5d'['IE$xnL֩,0dlS,T^m̧pi,u*v&msSKoC5RT%ꗚܯٍA9[8Ogje`OA#'=4Mلvn݌j#&Q[QYB51D-oecC!o4n#q,^.3#.81! wD.H+J総qLIJ!]m&H\,G5bb\Tu+`DZKԞZ_Ċ]BTI#~FqsL1a5`GEv꫎pk;tff |JkimB8̮֎,0f;x$jaGg` wrhC73;YoqDqRz־B|sf $8ԅ=BlW9'YFRb1=EU]JʍWqNknS!PJXy֣-T1D6rs Q>Nzv 'U!zsv$!@ pq[P[b;Ւ"cx|qˣLnV {椆P vN@rVqQ|uilGvG=gsy*e3x-4TK֔kl*sjխ0 Z`6힕vmcpd:[=Jհmh{i" 8cT҉^ sC¿fgΈȘ6:sZBTMuO6ea 8ULq$NfIuq {{VV͸0BUFoTO=[_Jg'r/0%9sj;(8v~yj\JOc^Ђt.2B>umRƌVzѨ6*5t7I]#E8F t%Yڜ>}Abx2|AtNg6#+B7 g#R JFSt(zEkysi+^tJ+MOB33 sk#s} eskVݷ3yC; ֖iB&znN ,!sB^6eqm=Įlv knCTso.En0c*EĞ{&,ִwaJϕ>FJ68KyĬtsAXV+\52+|~\ݹ#N^TYp׊#2,r+ M)ȭ;y+GQ޹Q2\F=Jː|kcD1$2+SGCϐbUyd+]Zڜ߆j / G5[M6"l5V֨nD`\Vu x 1uTIM1/-c0e, $dH$ݲKF=T⫗ZLSiG졗`Px5n][tr%XTqֲk+)7*DbHlg\'y!li`E:rQDJ q?'&H?hZ6ܞ{K9iF6KEo,:uGcFܛT>i'eiON+q2ʽz2ͲXRtҜt3s:W'*ޮd+F9Zς[dWv [4X-$i|J]hP\4Fa]$S6jX޵c5%2I= [/yGJ>o"@ƍOMpWoJɭ I$ШWr|wvF`T*s4(ҲqVfy ewz IA^3s;ѐ<w5qEi^TnidvtmCTI|RvWDXi;Yܣ}1K `>&+v4`ӊj3fMú+ZVɕL5Mt>Hz8]g\ 3(Nel+$ 75]E%x1rkY,}k{MR[uŻJUF0@wSP]UAMVuVOrD)ukY^Ƨ'*;Fj7P\бtT2wWBӀkY`K_^),08W5[uh$g^yb+kMon$rq[ƍ*k2J4/k"鶻ć-j~ZjKs*Iv:w%e$u&BٖpئEҭs++YKGp X:.Gj˕囨eR?R:+>f7e_x* 9t %\2ʌX2jav9/1dǁrSg;82;)>1]V2]OR e,N".O0\2s@pN,r8\@ ::W^sA wdj7I_یy 㑜ӵ-moom4"|zRRʃz֋%Z}~G_xd,N|wo,` `<㊞/ dU<ɿ\c!ҼCguV Wpt\Eb71l$8>JKXJxjE'cc>HN)_Bi".3ҹ˷$(|9A^#&-дK ^١S֐F;jo<;rNjW);X0z#\+AEWs;JeFEGǨiۂø*Ŭ"o83Wlf ǮF*K`o;E% 5OȦBDvāAԚbGLixnxe$;g2kO-Xwav2TcMʉR:Tfy猵|P="F6s^vn; ϼ4V$KU9ޜ[;zi#T2g5џ&vs#(jWVJz%LK,pjz7$H=AjXFn[ RxkDad4{K'FPè@$E>AM .e lx cTEBJNZix|ohh:#ex}+Yf>K,gޙkW"K9i&rq.{Z8=LUzmc5dc-E[kMJ)|% [b$mU%VxXr4SA0DUlbqW%X)(%FO9 SI ȁw@\ٷ$R'UdM/TwFuL(keD-fh m֬5G7{m%v$ˉ沔sY*qi2p*KxÓܞxVу$'>0c=f稖LXg# n5T'nO.Ɯ^=<c׭g󻷖#m9!~6j7t4K4ÎUgRy+Ì)5z4Lx6*W+^)e 2ҧ<˟Suq,cicmsY"K:񂽏5e@ 5k qnQ(Hk97tF6;tMeV>X ոe*|⧻g1(d^9O9!>Wwf;J1ӊdx3]_*2j]P[ɮX㫇rZ3dmsj?k,1NN+y;ID!ҷXor7]}UmEHpï\~uY"100ԿjG+/NTpъI3}xFR A$־4^4C\ҥR TsO[QPzu1FBXZxv)PWId$a42C|Y}rS|sv>^:4$n^.u9[)RC13M\fZ,`0^]5Fќ:1 zUVRb&zM>h5<$ 2;U vz}ð#qJTԘM-b_ISvSm#QuqDlG ,r+9ak83bF*k2H2GiyT;kqOK ƒr~XP!'ENՎ&V'up=vMZ3IktM֥X9ۃN}jP &qɦ*" JM+ɭ =ӈquF} X18Yَס5\nqc z B %g| ܎xk&2Cxw9qԮ?*~/ڢ(m>[Dc }}S^ z{.REnWWZƒ=R cR>8FQ $]lm*1^n-Y|V4l&vp%*Y #e=a݋|5-,8OVԯi'҂X|@:u}b,9] :MVjQN5qvWz"(L j;N;t5Z+qZS35@T>å@٩,[ b:Z2qg#hYrZwv{P+} Xb8+7VE8U7oMZ fQ:)Mrږ$V)X׶0nRB gONs]+)FZ$d||5nlSE;!ԤVv ^m `#k_ *Os=ʫ)Vj#2+ͭCqo0 @}}0qV5a wasұ^uV&ҲJVV 3`i@ ~cU^9~h# -2[akJVYЫkХ^@lf8mΤ9=/1#!aenԲ#s9ⰍiGu!h 1"H1pOE^1rjE$(w϶[HCʁ֦2ܳ<^[X L6m9iIۛs;"Ϛ{W[Ȯ 4zTmo'jQp3]txUWYWR3ǜ;#zW?tpcVDŽ$x&tsOgY&(=NRvjMM2zcl9S`1Eq9%%R"R*U.#!XcCna/!)jDTM{+3Giڑ 1L=\j1.!=+_Uy[V-: rL'Wk/l}jJbä鞆O4ɍUcҦSQ(+7i4sG#u,q#6ڳRN2t4 *q\*]t+ ǓBel`kT[Z`YV:r9# +>m.0 f>pK(%sf/"%ld)srv-1\zV:HKsu-6 `QAu'޴=`Or5Ҽ#uvjZ[;h1S?{ki YQg"Bɹ\P**ϷRITrCmVnhIV|Um>9V,EBFq3Ӝ!ToUlZBJ<2$\px3r95> 'DS>.QF>}fQ? z>7AjwsrU*AzHH4pF޵3lswzl`ijo38=k)m kZ8/56 Vo-"gX؜v?Zٳgp1ci bL)8ZVi+1RcB~H'=*?ȦycqN>ma"*٘G#ɑT\.]ui&% YH+YA aぎ"&H8˳\ޡosyPo暫}$.XXk1ao7OY-;]# n +y蓶3޽7j(N1USV"ߙΪn:zͶ| nP)5^ S"xv;ˉNcDmCUt(Iʞ 8kbKD7.gcHS(zZrζZYvmS^2qIn) ZPO:L<'Ul0~Xp;x'kvV^ddekGIJoxV n]cZg=M`xye$|!W]Y2{J5kN/VyΦ[jLDv:qD׆Ҩ"c3]x d3C'pCץmҗQFWn7._<2&o yZ ţ>2{ԞѢY6HzdtJk:*Z:ޥgE(8&h\Y H֡N9 =:5mfk{cgΖ/5y'ExAftD<\‘[1kV(r.:5I 벝7L4a!߀ vB4G;@j鼳nT10U!7 ^ r;ZKAZb/˃W<#4P*\uv', }*o'knppqCsKcT{=!xv ~`{wpˌ8Zq.,҆v-U{qY Ǝ{[ނx~i4C&MWH>L0j-YtׅΤr?]a[97VjWǕKbƯ0&Q.=+[L)l>o+F@pP<vh6̠"InFgjb+LY^/ Voѥ|3 ϸY|Iy!O%o VToN R8uՋJZEبҍ :~T={='k m5xtsZV-orX= JZ G€t;4+SǶ8=\U#JxhY]Zujw]e"PT-&{d-YI#9&0Q5pkyHc''c H>,m-,`l`е5<[h0\JS#9WoSGQ~dح9 }^A.O=HWat8R֥aʏ'Sʥ*ٴqW-VqF.Ґzpq^ggB1̺|(@(iMd<2m̴&Ѝ҂?f퐘9c޻;,l au *MՓ"!-"7E%Vtܲa ~e4`vX)nSHb'g%:$U䲳2y$ =a?",X&Hػjɚ)S^*˸-erWQc;[>c *ԧhꆧ)nXC:cŶ2rWLXWi?Q5J`ӊi::]Ԅ:G>X4K/K]wM/gsEbIԌbft"K$Zkؐd=>X~X{zTw]khKc'RkHkpGOI=;F#ˌzoA 9**{5hz$d՝]wBGYZNz77S!ݖ,9;N8Y1urXقA9Qm')w+NԦ'ly֢R~]LƝDc"l8)hzd,w1\ #\} 5m/c yGkWz1I6~hعE;"p:d>/ M,:팊G'mg lqZ8M{*t{(acRoj1իhe?D*H|$֗hk 휷!i]`OJ JQfn|=0lĮUi6=4F?`iW #i=6rcR0 =\29fhdz اC$m J 6rs2rkbNP. ՛Dh3<2*)m (n~TB݉nne- E l-! P;g%i#[X)YX=+RMr%$Sm(eh U[bFw:].vov;d֝ny@wvwVSuEGDqϦڻ-؟\S$GSB>lXXY$B(8 xXy>VxkUԔ)0k:x ջkHUT +xR'|!U?zEkY>IB*[vn"i;q;`d Op*=ɑ5.|}qSbAUݢSRDgD{Vvewo[eFS^Q88Dk4"(]:6A*;Wʑ6j x|7SRY 9ϭFd!Űx=N8Tnv&˸1ʣ!KHןEe1ltd"W}'R2QGC,AW廹?6<⣽ϟ wcp0@Pi<92#\Vch4ҷT)} '-av/JH`gUid6U>WY"1Hfi+ c;;}1U.lFrj5{|,AK$PAjn+2VٕeYA8ϵI,^SUe˗ ji<Ϡ厬&[XBYU*׻"5c<|by&`g>/Kw5$3 wg*b:3Kyo j ǥgΪm5n)\DgHŽXo+!/YI 2+v&yیMN.,)A{7ñd5v7J>{kpşRj aP*eZ@ޤc8I%²yp>%^}2qshs{[v#) +;kox6CsB i2 ;'vQm=:lis@1FhPRT}5Fk*!=i3n;RմɧIl&h6k[MGw)TMFsW vҟ =Y pđYeRb?>\ky]b; 9m!.Kw r zt1mS<=h8#~uqi9s8P= \cO;_"EEWG}Όzk*;Ji\/jqٍJ-۔Z@CuVLC$/qnlyU(dyaN9f6Jndr0#Lwjkxt7Otfx؏+|#]qiV{=c"z)C5^W1yH˖XE\vu;VՎWQ%G]* kG_IfduǸt7-eUX߃UDͥ Ȟ+ݷgTs̐#c9\tWxdV뱳Q&ۙhVoT˫N)ѻ3|%)Ʌh@բai8 UzIZgYLHH9 %մye \ ɧKXOй6`椆u8y[5ZCHq.9C⧞½oiG=;VM$Cc z*ܦOjzj9IY/q(MʦOCs?fVm#W4hP+(=iEI;qJLWVwdž{+ <6Br͌w;㧆4|:ybp?Q^]5SFxզ>%?a;*^k8+4;:7-jW繟OB k!xŅ(lWV6aQ˫"iq YZG~Jpvnn氵H}&n݀}k;M^lAb' >bI)ŇoZ93h[\ "L3\摫HiZ410KRTӍ'ıųJ$:Hk֛]`VFw-ʅfkvTJ.\-1z{WjZ j.hVcֽ Ldc ;XڦF(WRMr\"Ab{*}\G3p\T%>,Es,OWeuIyY# k*PH,Ž늝VtT-v:[",|0PÏam߼;2D$gi<8ja p;Q˗[)b"M۽ dB--lxJmXln9+.=Yx^QQi7c%Mm$Vڐs!!1ջv4rrqXk"Y4WH㊚v@~5V.wQM "R9ϭi[Dxbb*K ,mju,xٔ㯼s30^"Ob{nggg_ǵu0mUL$qК Ǧq]k5RM%pDq^-¸8Ph-{Ö Lm##E}ݑydk/(EEVK(Jq1Vu 7ȻUsI=SR[ԩ6+Hf'$} M;דIpjΠ$ x1}O rz-TcVvn\w(W&_0-{%] &Ց,eޖ *ʘ #.Ctqވ/뗔d$|jYnԚ6L#ORHfv˞8-&qơT+ű*[k>,{XdbNȧyP3Npk d{yn>@B$ \cօfccҭVQzʔt{A&=XaCYMdh!JRF6Tgf`)ƆȻ$- *WpyoiMA8\RNɝ[ǕۈP 'tB0YH^[̱֠fU-#)r r!- WqZ Z ^IWti5 0:M?M`|\0,P7ZibOB"KeC05VcgnnCZ)f\ YwC2dVynv.~d)o{30 ƥ#R\;+JҹSE\O GRqw+rb0j3C"βղtbޭ$WV鑾ĠCҰ4l=V2Yk{}h⇦q^GBm#c:f87sf&鳸T>= {VE"_z'`kpT$wga%( J7)%mZ37H 4gpի{]ND.oi#7[+]RUG! dA az]gv;cjrXW7圽[iofgDuPsCU5m,fOZ}Ŀؓ0}CVҒiXKHk¬^Wa 5\V2Mw֧ 4`T~,QfpM)Y(d;- ĚoؤzIi! &cjE}Q$Q: HnX%Gzc-Ͳ\`{S~\;JeBy>k;HeB TYYbcۅ[Cyl݇<ДTn.o+$/>̱yLnwy,1(_-V[Ģ6UWo" DnɐRlv*5U84uqޠ"v!Pec45D6;v⨫ 4~G#51اUJ){=Mi}y>lz qP5wOcr1ҕ4ǖAenzk.@>Ձ4'̸;2ǥZC7$nLPccbT4ڳ2'o73.Iir6ȊsR0l8 _j Ku-I-oLpz!U_c\ϖ̣v4ɍɤ>dwuPGaHw=jX=Uk-٭ qsNkp:υ&͓QT$Ta-I$D9R0pyNk-+'RV,}= 54>nrL+ֻ͓IAAv{g?bm2`5?AcbOlZi̫1ѭbA4Һ{AjsUZХK]Hwem"F+Bð4߽F9y#H`jčqj˞rܴ{UȹԬ#eP8-by<,l vV ܮlF+EcY5!CMK# 3ǖM>#@=v&ժG&t䗻Ne87;XY)OZ[{V>jH"@ڟݻTj1Z2NN#J;{L5ǔzk^& o#kKôO+dkJj ^='O(oc u`U.lic&ӵɲuvc/tVƔjW=M7I.4$rze|9pycqޭAVn;CKk= 4M #& QfLsɤS( A<krg{R۫b8$$t9Ơ8lsZ6mpz{eߵg7BC6=V 01ݪ_KԎ8,VL`rwuqi24V&v̭A":|V 6UU5ڝ/Mcm_zsi2.<1p]0Zjc[ $? 'qQU-A]x_J!#|uYtwܓoV9]Xƚ WuqV_?ȑJȭn%N's e\jصUd,Ҵ$ '84jq.x|qֲ"Hc!ʂ}+NH POqXhSLx9ȨM!B*d#l 9RW<$jUqe*ș[j)N ²cpIC27w*%g!dBD@1U@YJn1FHѝzIjO\9tyc6:0_1>Bha0=x $Zkm29VB\dV 4J,e{#մb]e;6Jٴ\aJޛ*q֫= Vr壒W;;[(pkOwڠ!x/(}H*VưROs$H sUq GnSlxXzMC ㎂Z\u0 KGo(rw`SH,BV֯IѬ]ʫ} |;fWhBKVQ`a#p,[}4/܌+‘sG3IӠga4$\$rjhؓ;}6c4g=rN+^Ź$~= SSrN1\v5X;-Lo e'[TT2799b7{M#IB1^*\.Wpzeq?֭gaz5cvqz֐g4Zr'jxeǥuKqBGhTKe[߉4 -raNt`sUn,wZ[V!%Wq[ bs0AVޖO$L]팑t+GFZ,TG-*?fJu;2xxynUdFrMct,g9f`b\Nx?kXd8=$7չ5@k_]ZW!qUCC+ŭ{F*. DQ1#dQr*wK`wFבê];s֭)3tаbozl#IT[# Ҹo57۾.#sZG -9TQw:>YH 0Q^g{(qZLeGU'M#RmɮJ֯G5,h995Zm6)9=u#n78MBY\D xz+|6mb?.s%DwU:SѠedzEҾƍƷ0ёg*"&%Bhu]D̂9iVQGB;wEGsNvW,=%eJɜUIͥ\b;x=6ֱA{חfQI{ǘ}AnF%U*eth R+$IHqY/XBvS7.1AJ6j\BSWтi&ռp#?Uh2F*#\dVuΩ0̐ȸ`V!wDF k (6z5>bi)#n").A sW["K9;ӑjD37J}Lr:b4X:|{.a֑-uS^TncVw*zpަN{ ~5)ҖFHn0RV7Tؾ1LV|9(I@BwZ7 j+בYXtՠl0A$ۡɬۨLZ̬ٛ[$;FҶa*H6e'bޣ֯Ġǜ:n7sXF\y 2:*H"{՞H x\`TgOq,?,3qPp$+!\WGtҨ> c!%2…M*6b (#=+VHsURfxFsJXKhB:I=3HM2(۬qzqMU? )ov${\@#WBj*&^092_1G_h)aW d-S襮)z%դ;Xg}G-.a]އ\ĊO{%T d&&Im.}aϷjeCW."HqcCY$ ePjN׹g9I)Q@H[5[xpwq80Nӎk'FwW@j}Nn\mviYǀ[rZʹļR.EMi8*]GZue 1\imSjQTlFo t'/Z@:sռ%=1\i5~ ghoR͢8 G("OMe 8J ܰ+rېC'-Ihr-8$*|}#i/ WiѮ- է/9^]Nm Q,v0s_ckgm X6:+yJ?|s"n6 2{ț J#5c*$}NF&Gz֑k% W5[f|:e"r5Z G}('f̐$TFq#E^K}~#BTrͻY .6ur c W&LzWGr $`O OrۛE]sV\=hHV\KiH s(rRWDvgN\7!dhzdH2 kR|1=cqƎwVfY s8梉淺SaaD'37_K,BfBhKv]9iaL=do$(lx&q xEyx|R:xn7Z O,y~lS\o-mv^JPSU{[ѤȤzOx:4ԢYY0hS30995k+-U>堙c氍%eciT:<)tZ܅erV w.2 I=s\I0{ViO92F+HÔU.H"k"3>y(8[࿞%Lo'Gigy ]̠ R㠥 9H|9wujҢyq*l<ڹ=_Su?y:nYB2ZMI7`. *Ww:V}кpmI3Mo$')^CZ.1"=iB2[yz&@?1#1uْ%]O{U9Y0+%>Ʋ|E>J37/J`EEHדܚ5o##rm(I2ռR^HKMW]>6Мs֖Q]4ֈI^r~\ty%kk4[Xt .ATQ%M]xA0HN=84}3RN򔦢H<ڣy`ڬkw۬ }Eaj?ǽ[|V182(e$4.$Y7 "2:bkZd(L`eiWsv^FJAۃZQW:!EKX6QA 8vbEw77\m,ˊ\&A8M9ZˤJMݔ灏l԰*\?2/d9+bÅf;֮m AH[OiY$#%7h戉`Of(^nf=.k;IYs\Y$qU?8T5}^Db>f*YҌ_* wF~f8@+1? a d&^>\~n{ƪv낋VLG ZZeȆsyaڢӤ]998#Q$W3NwJ)KZzhn$0Ga3TݵLt=kKQ[h>Y<z|E?b5>V"'}^O)UǓGz޻CJLq$C,󭵻H̄ k+o2 ,z1\axvR&2E\5kdmQU v}|oth$α.jʒfT{& !`;>n!#iځ^JO޵o&nD+n- Ҳeg{Uj{299'q o,w=:V ZW{"( lL>_ Hy_*.zZX[lM^m'.qJf6hQGoHcIm\OARk$NVd4 3?JQKKU7FʡnGLWyyW'h`YCl;y<3wu9IؖcsM]oDKr07\Xb,}r2I`PHl*gheuRNN=is7+Pqt籂V5cKuKfSAR+28Գƛ\ \y>\C9JF^پXzi%J @ˑl!9MB+ "nsY{NtK>_z'rUܣ ٬uW- _bYNM?2B=AqV)\zSM cjP=k+i=eoR}+xTƜt&ܙEhAibH2)"\9hlFj-*~WGZ.-UqM%M31ʆ3d5ǐ F[v;.gajngȫ[:m) xU¶ӜQZF:3OXo&R{RkJpr:mqYa9ju8g[=Mn)/Kf\(6 YϪ7w\NG"KyœjAn0*6.q(e9aUe]s z8( >NoH8*_簦qyrG#qH2fn\kzbRS tHSUllU <:9`[>E>$hA=vTʳ. n:gٶA18gAr ;;s\SZ%vg9:ՆIU=3J ȉ>Wd+cGi UfD=*V73&-tXZ19I\R=jzz ɘq{$g՟wk"!ZH˼[:AmrީiXy5JSL3:mu LڪJmƬx1j嵍I޵Z?ZCy05S޼Å8%gcamJi[>h)5N{ ,$FYh =2Z.٪ tݑ m[LV>c p7.H޹^2)}o%rLg)[Ojm=DW:.4TiHHvHqNKMoW:V9Y Es&8& A:\J/wa{Vto;I5[PpR4xCbj@8EZIdDMtk~`ֵm5Gּܷ٭uX~oHH8;immXHI^:OT[%F+RT|ּvX3[8Jҵס\¨왭ZPEF0s^OkK@ǭjxP9Г\¶ʬt #L QZqpYVd@2dJZ\SnI,*?5Ͷx c |0::ȘVJ[9=*+t )k lY0 QBV= riw`*;b9Z מZ<*e=(uEFz=BqךeJYi{+ ޤW#`xTsݰk{wfb>LnIMܫ؎}k'}id3o,draZD Д'PF@$'|Rw8g-\#09BLg,:5߻1"\*-h&5CuT9}+#ӭG pN ki+G|vzkq΍Ki喑!VU]b'`*Y"?Zx=P.t-:+MheF`cSխ?UgjV!ϵO:_,205eom$y?NhDQZP >fg8Q]^jHOuFʹu"WE8mjxe:-Yq'+n x\ocV=wm:HO& Tq=.jO8y,{qZ1%e <.o"au-Mm*l 3IJɧԒM0:j1 L!%mo1գ,wU88ҕXι`Y*J]wfEH%E~yDikDqHT%1QlGrE:ݬ\,xZXH5GKU+}Sפ0 8xه_qzU%gX> CA- T$F5g٘ ki`UP u(`zTlPf#MIcEzU9ཐWE- v+u)'82{J͞;=x,}3P^R"~zi PI]IS5Y^H"~@`54t~F2x'&K}a=evz*JAYA޵L{UycN 5p7+U6rbbD~X=zUf{h;3{I ۫=OJꐕdE7,yOe`nK25\{`qj<$Vv jl'x.ojt; lU ;^O嫑F>XONn]0I ٪S\G+Fjgx0=jX6$qo4@\ #UhG'*)hpG<ҏP=sSy( "I+H@|WrXn(xV'm:SSу-zCSyT 5ݥ˶ JaWpZ̗[qY7.\J{L[{TG+Cr(z\2*Ïʘz"F$¡N[ӊW~VlqEۍ ͌\^JnwխL7 GLnMx3U65GQwXtfζ&WfXׇԌ$8,縴%L>`_5c7'j1KX+;W zWABrL`UCSfAZF l՞o8/@V'-+'T)fV2zw[2g[<1^񀳰$z Ι7Zu k>3q26gi[~tEiB*3%2/vc]hk;85^m~L=smM+%oݳѾԎ{񭧸E'WA[-$koCԤ;nɔ:bZ:ެ&] P2)S޲ybcYUj]M&ьj!9lSX5~`;V~lau{M&yP8S/jÓ-CX&qN[Y^'f%q[sˤZg$U;M)Ic+FmZxHIsA>\y[׮ZIt)A>iI9*͆%nURzVyhb:5)ѽz(5zqL5'Q.x5~Zp  Y`9qMLRTݓgaKXv,:WG,f36^Iq5Fc2zm =O>|Ę^_n +,f+4'לW[e}b&*3YiU,Csk?ePj^؟DGm/;^խ `=2zkoS }k+Ay^ JcJgjnh|%eBjpVeRc _ZuʤW,sKVXў|/axeXP28 \W#`qp+Mt#T85WNB3* 걲Ó^ed`|b0*{&*pwV @@ FmjΡRS&=$j%ێk M$=3I,ʹ@kjBJ+sy$w!א8I%e"J0o3KV`01(-l]d2 DE ^G/#zW7:ܼ]Cۏz{'Ԍ \b-I1,\4oL<+VXc(kFX񟚱5hȜ54mɬfe&+/O8axK,^Qw :G▒VXKvKX@^I=]j/Fs2=,`9[=+ 楎Hr ٿLgS8i򵡽|o,\2-tMqA n7xd Ʊi%Ǖ<*5 TZі<@2ȷ@[ӟJBlc>O\*qV'ذ8X t嶆*m-FXānKCbJԸ.4.eZ嘔o¹=%ƴ"b6:)G%$R[t")u|uCR.XQ{)}S-´DaNE9Y=N*DjRp3 9WuVKe䓒kZ&@-X&njnCQMٜkRyFDWo!k 9)ۑ>,\pkpT29*+Drx6Nd2Lm'k[F07QN$2GՋb~s[_ gEʠOsʤy*4|u!2#9 k%ĦLh <溿VD9DZ{X9sMY6sM"т3[zd;%ӟ¬Z_2wq xLCs1])jZDP߱Eo/b2 x̅ä @0GAgX!p0rz m"K q(M7ڹRJiF쩠*o3HpONXt`U%S?W+][K$\Զ&$ jƥmKO&_tl`R/[ Uv*AYZM7R{6{-nIZJ.pztݰ]x=2iu&kH!2flJ˴>i#̏sixbZ&3#*%0ij587c\b]@"\qq\֓X6Ҽ)uRn$ō#nɡ!vnR9 V =9SWs)SOfs_eVAztsԑw>s_*tkxKn?QA7;b ^Slz{$sb1Xu7Fn+ xX-h;`#瘌*[:W?=^:N=]*Zweyuk%)zOqopսg62u&ck&Z-oo) #'ԚH}N86k i#HaqIros[SAn฻i\I#qWs.[>V@GU?vcbE wlj\O8A]7GǦ+JQ܁Fs&'$>EH$S1b՗CH֦[w}.TK#:`\e`&}r-=Ƨe""&,YٹqPjԻp;Kg[HU"5.?h֖I{˴*>'skIŭFIrr}T7jLW7Lbz]ZlrrGt̡M*$͞4 Nc[6PYWa*劵K>4"B@ V7PI>衷=6!"HuBVDb86<SΉrɐU7dt{Y@ Z6:Q@G52] cA=ÍB^0MM,qR`5BW'fT}Qȿ,4hWUCZfslK;zbo6GZY̽RЂqM)DkQWU O`kRE'kT5ovpG.(S4m凮+avm!vW/?*+6+7I)lp^1d Hq18&Kxg=9r(T;\Ykc+hP&=3O*$P˝EP㸨NpREfj+VRh\ؿ"REiQS=9 ty[[k)"k#Z2~$PE gQMke#?U7g͔52ip(H?V_X7+c6ŕl[6gQ9&L\~'46,0k9U# Ti2JUX(%l rE\khTluc+i%IiFx=NL V ː:5Y;OUb#[B4౎*TuUơf̠cU{f͌pxW'!Hz@y|Uͷ4ڌ4p9нZ%TQ5#Eq]L:!岒w }jSٲeEGK.Ɯ簬{yA)s涅6YHo~*`\*7fMg3QF[2r u+XsH# P;It= n-e@8vRWƱFwRM qUH))BW:m:r',P#3!a#r[R31⫄j7Lh|;S;EUI¨V& E) /^kJ+5vSwZ劒{QoFFϜ "AJ\n&11b`GutQ0k3OsQָ]C#jV2rMJ$_)l֣KEF569/c-u>nߣu=6J{y=ɭp7S?\_\knGj?H=dh0,{0eRi#B94eq#¯[闐<=kYB7TseΥgZFj.{=~FTL71{u4x;.h[]:nLfN8 %D%E𲝶c%™%G5~ =V&Lg5[T?6̏O@0UKTںH&J;Qo>a`1cX]t' "q*HYd]8r6SI/*x5)v[nb#r .]è5%0\a^;LbܶS=QU-Ax!f+ZQ0Ji:#r)=MI$l;qY$`N{Ҩ:m2Um];UY1ҹ*eep12?Z0qe.o۝sj|Wbj0[\ l /Mj%5y#dPz !EYn3Qu[z:B+ڽhU, 2=r++q/mIJ+.:j¦66Yor1SC)XޫHp35D,@)Ani/y٢0_OXJJ`ոcTa&ݠl1IԛʟV3g)2ZŎ}nTcj QJJ>FnWdR+Uh4dMO&ԜGɢE ~=k:t/ uM٫w01HB#>jZj0sCǚ}kntGb4&sIaun%֕r#1{5KD_;՚>y ƳMFɫ ld %n8CG !%bs5ZyT9/dɨmeQ.;0j_2/Auw5< mUbdzW0[E.f>+^tv;d9ZLq\050Xz 1*N ef$oN-:I v*=j.{yI_ZZnl{bUU@;$7RA#ڪ27 nΧ'"NؒŜm-KugY #lrU&cnÌVVXNM&XGiI$Ejɿ6QPsY2Qn yi]FF~떧Ur4#n6Pnv|*;+2cvo7[(ޣ4Y=:iyDbʤLռ);*8K,U=U<$^sc V;0PՖ!-]5f+dLEc%Ra٠aLjp+8ٺѭZ|E:$H.PJZV!ʵFٍmwraP=RskDl'X3|Ɏ0ƵVa199>,XgLjߡЦmF3t_*s&dWua̅(-RT d rinb$%#cdvi./ARp1m>nT-+FUcݛi hFhILɒ15ݵ33Zeq#H1m}AOщ_Ay\I$Vq"X j6VFO٨E/5_f$bm[B z՟3\ QNj_s`+nPKwU9W3g>28zӦ yrQR QMiTYAyavHz+:xsy:5?#UE"Y˕%sQpɒ+Zr lG7ǻ ;Uqg*W{ g~I $*[Vե'k5iݜt5, ̭»%rH犥W_tҕ<30WRq%wlFnuP?2'])iji$srd})ؑS?(X vSWƼͫvv3.ۋX?Z|7K V=6yleÆ>OA2/YӠ!}?0P‘C-tN4L&~*Wf^]&=2e[vtshtBiЁbg%k~3Z>|ȥp:6FkJTu TBFP\@i#] w X'Yc%fz-R#)Oĺ!zLdvb11"aܤoR5*qrZ<_ >ҭ"r {X?^KؗzŔWԖȑu ;k^`# s.3?>'ց5~0gfLm]u]ޢkŋw`v4l13[FV.bk8;8`84"'V¢QlX!y@LD婽4)j4SUA'QTFKomJ%URLcVegFy4$*nbx`7RÚ\Z˵i5OSq5CwVfT޲t~EQflTjV5thAv/F*^3q4jvO#2^kQxĀApOy sv|+ui"W'u|el#i>h}hmտcvd7ޑ TgxF^#"կ+#$+<̜&×'rjIVhjmrrѓgsr課%ͼRD-4嵸mrXVՔVY*qLհl`#j#^#NMs1{AlۉRk"Y<fm8'&Yc'98M(hK|HX[UX1=[r^5T<IBskqJw1jo ۃҬ}/_, BFXϰ?ETZ7+t9}K' !A}jtCMZCk58Z:ib;#K`cwF0jhY+JX3ʥ vQZ\otc,bcAu}mҡmHdrcdC|e+Z9ԜqDN o"$CzVGI H=tyCΜΙ{9%ɹě"Pg͟ZKJ|,1]љYڤpT0; cs]߽#@AB$F WMjW{-̭, $v+1aDvr>܄NN u2^R_0ָlIq]߄ }?z:yk DtI.uMϵGX{VD]ZIRuelk 0d?)=5I?eSCU#e43|`$'/;ʤ4LIS j@eL=(B㓚iS|Ggasl.u˂O Um6IQK~fjVe@!i_i9^(ƒj۵uHXFgkj$P4Kx5xifSYЅǵu:}呰Rvf]|郣B2 ?z{b2T{W mqhU.=rR6p3ORw$CZԘh7&TH®юָkYt>gbc"YGz6?+3` 瞄Z6m9-a|QJv[ZKibTKY"<c'gKKZ1p{VPHڜefYʥ7igHQԌ6H&yNʖJBI-w@_oznZ&'x$e\ u-zL2 p(]j.&{u>9*h.dz5G'aV:WdJpW#'h29QșYj$x`iq9TUmh]F1Dw7*xW[e,,L*EI qjrjRp@GQo[里 :gZ-4B|(lp1V=ަrG]!k 0HִtF1.85$1S9;3hoB!(^6\ /!ny 4[[犵i32ۭs:{h͝:6Iխ F,vs-l1ffEH%sd _ar $@bX!㭌gvk{v cRTqCmԱW]FG f8k5Xb`OBGO*̇5bޘ&Ieb}HzeczCzջr0^=&ANq\9^7Zhs&PkBM@F1OZx{<>XeߞhzKPZ#Bqmk uWLRqpkמ1":_3ћ+[A8-LG`Bⵢ8"yִ+4l!ROs4˫YqH56۸f^P ]86շ1ole@LU t0#{儠 C~F8s]9FIcᤶ.; A|`׭ {$[d~nJcbʖ hL" [/&Ibn)dsT^ecNpM]2%}VgZDJ\ 1 2!^wvp yv #l7JsmW%/AuM@U =`iwoskŬ@+l8^-I&q,3dv8RVrk>c4ټE`VLqz"H`MV\홷7=IF1vVTH035H SZC^ىaX^ 6BkGДز!$u'ZM{Ѹe }\":0OOqW#\.1Tk we`ѿ.d66,AXZB".:cҲ$(q9 owI]6ɧ(eҢ/qF@R{\z"䞽EMR`~8ΎDɶ| aG4Gsﯦ*RDp7m=FURd^Yڰ#dgqkhA3]ӌQ8dqǥm f3=2;SLjd=y8Sw{2d}EuB%RJMaîy5W"$/4ibrFsXYzc:WDzr0|ܜ rqe#%: c3WKqӭ*{;LX5(UC޹{/µt `x,xIJ'D znR~L/5Hi71㏖Z^ńr1֜`NWvԁpe~;R4ڴi1}Kрv9*o ѤCӘǖPQ&K9xe.H+e8ddvjsjZKگnUrmI7QM5L {1L 3QGRd S(SqJu"ͭ#"ukDm'"x|3콪:Ͳ2qЁֹ%COtu"u/VNAbׯdt!09-Sj3'3YJNƩ۝\ ӽ$)I,{.kB|=MF.uF78Wa1<ҠyOcٮKHnWԡ渏>SS잣u,/fAhJIG׊ke5zS·R8 K s4 lAMfW wde횫[y;snk#IMy1͏$6Aҵ{YPT0㓌֠`˕*qiu9'VMUTc՘o-$\oV =HR`j"ч[ՙua~\Y=9+nk4m^)I-b"5YD?`sS},vdװHٚX:SIab?'[97o;y˨*֙ I)\n6LQDd\)J:e;Dp2+K=ǝMab\cwG!O\(ҋiQxn=Vrܶ<|VF' znKIH%Y2zZQAGnNJqj7a8q3[N9GҦVnh_\5@zV'nX8]{ G5*TzXK};R¡;NA=+d}EU$~`V}̝ÖYc2ӝY}*J+`--w`qMM`LzfX`$N3=+HB3]k{c<pCyɆf8~+!ȮH0M01vRvѬiҪ{3|:j!q-EչwR[® 9f|ğSCS:9ycڴ!r9d_C8ت B:;%8&ymCnF3ɮFFQAV[+ÌgNP%Ջ#nys=U͹{ֲ<cj fQ8'Y#5-nWYt霓]MOqB4X~G_4kV|pGEHMۖ\|\Q5Jc&br*_oX*U\qvd :5 v뺢D [k.N3oTA9T`tҪ,,z*H0|J9i̬is"ۯ#bx5' Y:jg7c;}W%AҲ7y5$rOjъky##=s\=-qnjTQ%Gٴ3oލUtO"60v^$P8ysHJMZp!H9$R9]*yU+( .Ƶi-$x{*ET\c64I-^xvxxp1ӯtդtjp8TR&]kJnOݚ2_4ݗ]XxݧfJTZ9 zuxA+=|'kӑL@{Rֺ#v%A{.# TRԲ U˜cKcԚqd_qtR3QN5b]\sZ h]zU'JiޜWPUi"m.zޫl6REgVTȬ@+bѤBERMf:dOi#_JHQ[8'jLOCQ*#-%+z&֑H#ߞЯ?Z) Uyn0>]Ny-gjJ62iF{8CϨ4Ci*k7Z)u3(\~jvL!l$tɫ} .ƪ1{o|6 r9+Vmb+?2gUZ_0whčiIJKۻ nhj2 s:VAuJZ޶0mN٧YC?#jo饖0ys]4!wMpo#8&4[xQn&bP@Vlr*Ezt'/PFP.G4wF  x$FV 3*徉{tᵞE5'ʮa:n*cAq$P{_ P~xL&[3dw>2 \yш W٧e[!nm l=/Jd>{KWJN%AOɐK qsU|A8WcHKky-PѸڮA"<ב,=JU9g8;MN n,y ,JdgWX)ȖQ^FWіwaV@"n|[v kkZ\ o<^ӑkN)r䵌_*:kZ!QI[zlly>#t6zd9ؙRlY4ﴰ"WBdQ"S;(ȳ/̽u+bޤ&pBU޺]n^!RX7H.p4RW[);-y'W iTHʃӞWJ8q<5isDERov$H㍔V%!AWbݘNV NW9N)#pS=}P@'%IҴˋf]/k!PZW .ħx2#(B<آca.κkClI.Fj&A@9ZoǜTkӕ5 &\ 6i1)|ʥ%V#jQ7oy5˳+yq+#[6ڹ'\){w${{R"Mn\?3Ʌkğchg zFk*e02 @X9uA\8hlE7"U%5 c A'izҧRU[(`N@S&ɴQʪ+8WȹAnN44˕l@zSSi)*3J])CWM 1-)CM6ͪNrVxr R\GG91 {][H~R"Vac0bQxzI8Z$TMt]W^67\xԺ-њ]ޭIg5ք>sj9U2*ْk?,3Z:jMk)g`mqsY[\ps޴q++I[CSv:29c%Mj\K h6N޹.eGFL=k.TL|x'q:WU\$]!&d9&X/~e_6Ň!5utyInˣ9B9ɮ6ɍāgNQe-cpAI{``fFTxuwY< W4e-Juudnl]c9йXɦ_\D4lr~nBdEZZjZ5fMEYm<.K:fydS RCgy <] %C_Ʊ%)$~2]|}`xx$P-Da Dy +Tԭ1I`=;/x^/a#ƪL3nUcE[gJn.qYmsL=R+tv\G$zi)'4jtq81&|10kQD4P7a\̷|Z k^Fql66ZwQI-B;)lCY]=>k"Csճ$zeAH=JEuB]ɓ=c;B 4ɼ\HHݏkxIb3Y[Ioelo?95ZMt~T%.I_|U[k:cZR7Qd |6S\JS^s[ZX%qᣌ֭؉w.FOp1A!e6`Cf F~S\*8)-(yO.EP m4g"iP[:u)?u9s8o ;Q\ -뚧UZdwJ&| 8$hN;M#=zTr+n)`keQ.`7\tEY#~Q<}z-BKT34h.žb m޸I@d횉T\4r3o1$uK%ҵM $S!մ'2`1օ(5~B=O"fZɪ)AdivAqv'>خg[])W/3DY~HL# 1y.5N_$\ҋu`q2UFld⢴eڻg@J{lւZK U8x覗Sѳ`WD`0S [_gm¦Aj]t3ޗ9 ,ɗwҦGYq]%Őqgjt]&pcaC̀{V̠XsKwiÄ )'g"MZLk9e^15jq+ɷZxBN<^%&H'"T5Nc֧X탌T.2:+ݦe'z(2 է4ڳ&Qt$$n .t۳V^*}G?*'֥BhFrkG89"RG4KتpEF5F?4N{Zt_%EԷ F1 1GVv\sҴ"+RޕNlE:>sbX;]]1ܼ 5/'xh"Hyýa:qzD+5SmNy!U9@Ƀ}IftZۗBX`Vw%?~8HԤтr/ZK]QMtvqdt&n@]O5 jNVV9 e#>iڰu [#CUs(b ]Y9HbΝzZݶ| >g$qƆK8={mYT1ֹj Վud jUx1#9Ƞ7A\ܱz&W;iLS`o=iq|qs-PzO4Z 8>f^{Z|i[ Re{D +pz:ddz>%)o~ +VoTS"˞}juu Ww+![n}jνlVWF.Z 9/ӆExc62IԼ$nMw #_0z"j'(TfT'e+@v9"8ʌW>L}֤q) 5OtjfOGlt"d$7W4Ϻ ӡǯj)%{Dk>$B9e'.G\_Wt@ܿnYhZ&|b jɐAˀD@v;{x5"j S3}3O1iVfn?R_lRj&Msf "ebSVKsfj-nC1#Vi#9+"h @BץHCqְV =oY߉3Zhb CrHws/ֹkW8 1jrMkT5un_C)؁5,+nJtbjS13uLGsRːISW4zHb aɪiN;}x 6OZ8MrJXK%%^Lw[^ʹp{{>h0'ҭi],x~hzxzN L728a *{,y9=+V n9&NĚF\N -bD5}op3屍?n kOiJW6냊[xx7lva JQO}FHF 3JT%/"dnH`YDvqڞ)RJ7#=kN,m/:5ͼ1KКҔ~4ts mApR=p)ϭ]/ܵ;dH=)a Fe^%Y_k0;E=pMu&-KcOF"ײj܄R7qs{xKbk)f4f63&DVa]pTN;I֞)Gc*w, ROJjmoXXr Mrv1*NMRW鷑2VM)"0k'H^jd,@ (ֆ_Xdi`O8"ȌadR}57PA ztAswѬm _*ʲulgqOm(E>[L1)ܜyUMbXCƵ]0#9muY$@W| AGSOa 4Jpj4Jѻ eVc؊vQ[#V.X@8PGor#gQFMv3lmYk"xVT>0ZK(UܠTzu*Eś/L5r8dz4nF( qEa[EFOC') e$5 6+R˷%G=Ua]]þ'9:]lե l$㝫޼Fѷ>-ͳ:t9u JCо01PkbEI.Gz,i6`VpSZj\R^s'OxlKF@xiEv ZՔ ޏP$gB;h-V~U%FbfIX֘w`2==*bmZ$"$#\xu6̫:tN[F3ܯEkI+]e?4g ]m*zn*, =j͐V)wP柳{\hoǥ­xwniMB dz$8S.VsI[\H彻}z N^A麪Guw nsakJo tז 1^SwWJpS 룷sUSMGaOZ~rwwgJQ\\В4=.kU>T D }?*tWM `5u+$ bz󊽮yjs{ #Vt5j%KE #_L$:g3M*|QR!eu 0\!>u+(a˖U C0HDYp8k4]읙_4o\pxe>֊Ob*2""vf9V 0jdr?4A1Xٌc &<'p:Ώ}o&mɌR1V3cr"K햢Fsl'Ni\҉.rv}V,0om, 6ΦSlNb~! @YMڃ;qS8l!!v=)wX9*䊭G?tMs>6r0rzkKTHmIzzUuay|{l @IqH3ҥN }Z(ш/ֳuSMPJ/{d/eɤ%a" 5tj>XǚLu=gd3%Iǭx[$yi$3Y~`$U57xҕ8GކRnjJ }5Z$V#"qn+mCuaMU̱8RRtՠͽgc{KjVb8zלj0ԓTdC O xk[ӱdc&jQi)2N3֪jtT%#5lt=)˒A- Ȯ. )f 0x'=i. l!'ezJtZIt-?cl'>I|}CW6Ƥ6 o$;ϰ'BF%t|$Jn$)C*{Ek~)<'u MENxjgox讍jwBUAX 8pBWfE'$ 9]=-gcW?'Ѫ?m0-, pOOʹ{5i-CnYS9۠׌9c'>{"0SKdbYٔFR<`8tk*dI!Jײ/Z ! +ln!UV]ߞxu%-VtSj +xTڳ|"nW`Qp$F'c5n] \t6Hj*.7t j@I ο&q5PI=s K/I%QF u#w$7塑H?ezwߍnd\K\ƅsz=uiZ7͌) tl?x۵qD8TP9ZmHĠ9q]4JZWGRI~z>ǝC\8' 61r+F։ " s158$U[ٳu!IUC)*1Y%YGZVpˀrOZEycarkcv_;Ϋ]m95 \(IG6mdH7=Mz淋OPvg/|V5*(٣|Pr35wwbycJ5Yk$Ēp? ْdVHUΒ搜g'd̯Đb$̰ܼDnktfN3=sXrG1ƱNKz4Aꍽ(c:y@r(0 Z~p9ƧҞPdU.Il˂i<(*EVXRDž0}kiŒ\:[2[?GsXrKtj/3r].<79wA}1" 5t_f{KI$vŎ?*7b%ukأQ$գ+&dX*4B>9ޮ 2wjF`Lz}9 Ew(f̌WO=kP=85z+o!*㏭KrC;M*6$w5robׄHl6 e2Dԕ7Kmv![O36Q1m%_SEHFXΫl@&q[4R1|0;tKHr1zKǁCƈN1=p88BΚGJӕHJIYnnLM;L>*&XfAttV;lE8F{ԖԕڣjSQfn3޺SqA?Zi xnߍei^2Cv>$nD< o$$+j֔v,NJ)[2QC[˫g`h&RCq]4*X4 $܏Z Y %$L~7=}i **Λj:V﵊ 瓞ROC6{[E}J8Hi84v% &ӴF9%p0\)nJ)b7QC.Xh·HzPrvj׃RLY+Ңt`:R]8iڢB/zpjmZաzs^=Iyjj>ϲF`!*8C;[m1,w+*aC.7V ,<,Z)+cxXTÁՏFVGGVlpWL Rk"H}UHRR \VV:>6o~;OsU٦Zm"67 zeg |Àr)S3#4'ʑwwƀ,J{K}N\b)a3 >?)]$k08Efz&e/{.t dT0$eWRSCiLs")N+ ʵɳsuIiWn\n^v_2g zُVȪMÌͨcqJkԖ@ynpjciP[Zx4ho&q${ Sh||REqm#EҒ|+E~2 m8x1(hmL *iCR HѩMJJlˏ5 {V}Wr$zZj̃x'ӽ>[{8cPgrA'kK榴ZVOb=VNtDt_Z'jX&9JM"ÊІ`b5_ \{'#8qQk8 ̾mLiF*#9EkgB:5;]ލzG9EZ3C͚gj.ʶ=7$1miYj<0=8T%湖ؘ38xlda7.0r*8ӜRF95t)S֚vZF'Q&v2n]Z*F? i -¯ 4JOKFs.Yk3Csֹ95]f. ͎r2sT Jʔgs@oTԪDY p}P$t|ARڑ%M虧rB9 sҪ@IVc!lK2[IZfVp0zo#ڿ17Zu$ڭ E oUqhhy=v z 6R 2NY$EVgiETfa[6WVgk GJY מӖxNw18Ռx\+sѭ?u=׽U} `; @:akD)M[Xgs!z{:S:#w,zf[^+f0w+:RA 8[4e%mizpr; ;¼sHEŽEŎ=j;Ts],X3UMݢQ,YzVM###,$zՉRMiIu \Ts]#yKX Q4nL^ OP #uP>nh D2tsYZ#;WrJb&6pO>ի6$OųvЀ#U+P3ZO(uɤ:.'vC +=RAE^Z4gSJ,7\T~^sל[6" Ya\V5PS2ky6a*ż!Wl յ&Y=jUtՖw Ρ@ W {Fn=ִZ)C6 "fPfqӚJLkva7Ǯ:cdِB{Ej% 3Q\iJsw3{ؚmlg,2ϏV",m$Ӕ }sTg^Cj+&b܇QBH8"rsW9*^T;!m<ktΈVb28N14pQDm޹=*ۚI@.=Ҫ6wҥx/ g8$;Xw( 9}͸K^[D@!H5=s=j,˹*00Orvye(j rcm)}{?zpHu#ðg?vziJs0^qZz$<9I#Iq!I?Jgr}LӲӝK}NMh $E#T qTtd$j.0+Ӯ ̨;b,Ps1#( /ͫ "; ܺnEbI=s9;1zT֓DRZ (zd q zc8K 9vzX w}˕.k$\ao^ݕasu:AWni. @!aW]l$IO㧸h۴TXn֦o$9"#s+8IZE3ZHps# yFW\Ec@iJJ&Њ]4GY:r#] $y=Nj\GGLժve*WO3$Oww'+tRU>ҜnJJAr3)25t9xfi1eyY3Bݺ+kFVyW:Ӯ $uKNបiinY 7m >V\<ԫ%9=An,SZ"qSq|mW-&|O8"JвHu+1VZ FjK`^8}sQ*aX 6OzޣJ*OXݩ39UFm8h<#Z܊+0{|k**x㚗ZoԿgO}ZR,m=ѽjՖa#ф$|X`w"sڴ7-quφ`5Q2Z-6['y!g$i vZsYV|ԧ$za{R&pOzQZ̕wOD l~.=ݑ!OcNcIJ㸮m6`:5MϒcZFjFd8{qFN^:E>=[ErI#'hV#1YKH M: X.-W/\ǖc(um#ZR0CThkn0YhۭRZZv,x ) lQ-l5 GnKoÅ݌UMJT J[ּXuiGcSX TvXD߼CiXˑیMw" p\$`J58-y2I8i{9[WVD]r"kXR)OiGSֱlc"js')=9Z=ڹ1aEFjRKwvP\8sP`i-]rFZTwNȊ:Gϙe&Q;`gb+q.pF95 RX혗?.{i:^mnԤAȫisJ~Lcy28J*pSmbccUk"d~Ir%:Ok-3c7H,ej!-00ISTf׸GrpPHաx|C–ziv:o AZ)>%mQ҅9Y \|M~И똹mZT4(R:~#R-.t\3N]ڻrYq|ݴy/Vd"5z.!`#_@[vw3¯%֋?k7Λq-Q[иUeh߹GK} -f @kNMU n> 1\_߱J/g/zVNz͇4_\sErhQ2Rj͋ȥR(7a֬in5y k#¿ z]XxcO3!o5~注 ,p#Һcգ{ hI95cػVa}+ĺ:tV >c{W) 7D$2vJU1ƺ=6HDHQ=1ڸTRo,jTfu휩5aB7pkwxG>+7%pW+ h돕[GWwKZ͢q+Lq^'JJ>hy~'iqF.ǯJ\w\qدM4[~: mكv#yj)NGQ^:PQc#jm-ݢQ{yncRS=ePsN֒B 85v%$r>'=4\ D%;5Yc/JYy,,G)*iǧ$#rWJԈv])$1x>%.㑸"83:桳Ի?ʡF.ټ(͸'Hh7u}jШ|3`W5q[?˝YZu5E𸨖Wf+|AGZ-Oj@w ]oNkvBEiԿ؂i(r+iPj*ڜ-W"2Jİd!5 9'֟2bC SHtqרem{YԳ>++  T !qw(U$΃BE4`<뼠IXeAۥqt)ɭ~Q^ _#]>4]1p5ypdMZ(JܲZvmH% ci]/]8K pKsφn3\Ed=pzYM*)\-~d;rIk2|&FlOQwM @\LUd&IsSJz7:hm$ N6zԶXYqjfWW-(]9ScU"'WZ9A ;\#7 Ҥ"߸„^{; Zi ^J㛞0MsSFx%9,,u(-(~]>kHH`v5K7cX+sN8Hrlz FF dp}k-n-5m~2 Z5KY%xX˻)s:Mݛ:[Bp:VqsL9V- 4y:tK6ͦ4}o -տ.Hp-)p4mW0ۡ}"#5wކ'G{;\#z /)x^2kƴڭ + „SU YgTR=[ֲtyhDݽnf|6O"HLn(鞙NNMr2:+WOٿ:n:q:(6VT 0՘cR(v⾒XccB";H0YU…;V-mߴ{gE, juMEj:YHqTR|f cG)"bqEXک#9J{Zixk]x+>#aE桓%X~7Э{JJte?4-92Lij0&חO2kQgmjvWsZe zj]}捽C6cPw=JRٓoCk lWsLHbv]%bDi׈1$SҨhNvukmzѾ \L:K(&}3]aZ2 kA$вԵHV:a5h@[;kڤ`gcuFK[[ Q&^`K%F$͡y5Љ80F0{U+GLv`+Rm3m-V`u5Twq!Z)XĞo3dݸ-& `s:fiAgH0F*7PI口N44.r7>!m}ҟmw8nw#^ʌsoVZL.So@zx'19Kqk &X?2#iho܅R]a֞1s%,pBӿ*ɖ pȟq)UC.:IPkX z=WGc $&Yn\/ԍaVeе4VQ>qtlKeo˅YbF>aS\xzBJxq iی7LR_j[9i{՛&$O9kჼ:dUuE-Tj7A* }=+S߃:UKrH +n?1,c m)Y@Dv)6`&t4zTowȖ^RMn?CЊ.S=z`v_A'h̷SC旎|:V72mx7۞W`h6guzҽ-Vu֚P=nf#[t1=Q*6[d   hԆ /O*iv2:֞)d߼8x\6G4񯫨#{L}"3<2QFh/[y 9aV0J%9.`:T4ʓcѬPx`ߍ]ؠ 0`karVWR{hk3AGwΝ٤T$Nm0r$t)ٺixB ^ lFbcOO/lˣ2oU)4;erROڝ0:ҳ$&܏cc0jYw~Uf즶He%Ė{,\qsLܶPҧH,qEvAUc'b87:VB<9Jӆg1y{)E8lfjS}S1UW_yr oKH͞έS gԨ5"tujo_ܫ6OV#Ar9CD8SWu4dץ)SKFӔ .ߊs?Pkz)qd2OZT1ӦkjUhJ9/aO֮Zc6zzBO&U :f&1tV/lč_rί<ص A랂9HuFf2nNx&ThfXkNlIּ `n{֕a?(e:ҝ^m7k \r:f :C^u ֮$v6\õzC~Y.B fjp6<֊8]WjbsJ]0ib*eqcpCIŮ[O@WUı1N d9>i" X jvlϕ5_(RW! WGTw4Cҵ ٙM #,֚tČ:q^kt5!pxR#O>]O4k[5e$T:uTc-B@sPLQˀ mqMhNl䣵DIVct@"bBENmPpF([XyXt#[ e{ t3X 2ި=#[ "clZզ@1O0jo7Y\8DK0銷 x* sChV]i42GǵH3!{ S,D }kJ]h('lygLe];]s(9":Bxަ8J=nrzSYI<퍌KH,T;U]\iV(Eb/ sң`Ϊ|S qgi?f;3^*pE6;by#ӌ%r(N$< =+U:-Y2-V/EIl-jĐH!ƳU*Cmy#wtW+JtaNR:?Ri.19srΕ9Vy[w`2M]E/XqJY?NC}jQZ(|^&6aq֥g\REcC!SjŋHc+8qe XJ\0~vr#)%%bna9=ꎡ ݞԐT݁f1[BPO1/#F5̧b \'z&a1nU"9jSv8i̙ly85fӼۭ穩"Lb[tZ(Kco1)H*Ƒ#gַűDP ҮdJm(ȍ; {AU?\rj1ruqa,)z|BNkIԯw5zX8-H3U"cE3YԣN➐;rX07_GyN͇Tm %dys6ʯ@-B |Kck}BA?ZoNZHTEztvSH[p21M44Rx{dV TYNL)Uͼr" EW=[E?# dp5S5A]~Y>n8-I$u9Ym$`4 V ZkRV ni#*wSjPPuc+=BAqaUnBPؼ1E- Ud8 "On=|YZf03G7Yʊv0n+!> J2_ NFG2;h t`_,b34`y%Bi{e$+КYPNcBq4nq犟wfSLd`sRAr¹iB6*,8.q[1ٽʰ$3,!Cv jH0޵#wbi91&v1٤E$F"s۽gȖmGc ޥT‹q_lɸ4Ot8S͝Ǘ:pM><TFQoF0m5[ں ໶ 2T+$g#cVH'= !&ժ#f+xqvñ_JH6iK: 趴Zru\uJ@aִtFI#V>O-'g#͝5*0aNrVmX;~"-#5w:>u=RŘ5ۘn<ħwvœdf1՜qifxu0TEOwBJFZt.ZO,I7 f7Ǫk.Hǣ`V|wqQZI?zWk]2 ,=*b%ٲFQxc2ې-cRr>=/;rм/ q} O Ѵyq^ o. [,ZŽe 6a&]XZ_1'NP1ovNC<7> ׮,Ԥ~jÌYENtʝ.^^[X&wZM0Owwfuuxk<Ǡʋ%ǖ q_gLb);7UVN_PmR: . oF9a^8ɧ1<^o[XUp2k~խăaF =}kSj}G g'$z]bB?ר#84m88}E_WhӦȌ^0֝,-7%85ZM15 oFI,ckJIP1#5xM,HY>F,nu;@>?½ rnJ 뮦NNu"WgyjvA|t+^;܋V`W)wO߈ui[fu!71X=~,_Nx:M_D`Ȍ^qe7EKn U:~ǛxVtY!SҺCBl4ϑ̸8\ҘWM7xz]2%gEMXTȻِ>fy't|Ci rFGְt]Xj 7jŝ7^ )FT|K缑IOH\V>FIKಞeG9kݞsԯ7zƛ$d]]k&YbOz^{B[*wk~J [qOOIl'ԙ<Հd~u-Lj,|ؽW ooy!X9`tlb-wk}lFWwڴ(ےEK7C^Ucx:+>5Vxz,+2X'c&MdTz:7m,0$W[d%]y94LnmOKDn3mJ=TXB3Gr{.}5nq޾QSVD4VV,SxC˶,#h\ٌ=3] ŵWZ1\c>gnV6P[֟#)b3/SO*rE5f\ 3ڹ nӕղqH_jfx:v68N~jtoF;st{;E]@Y.Uǭute-1TJ-.#:E$\urk0;zάlu҃i6ǐFj9-XamKV8՗,OCͤm p޸*M;D]0#-fjJlf;hcTUTV߼?WU6*@nf&~%܈A*!Y/KeӦq<~ye<J|Ldd5Uv޽gjvĒj>Y䞧jr *s}j C×&%rM`SZ/^us?嶀m,O|\Tgxzӕݵ%h9"N2A%'m ^N( c9᯦l4K5Gٱ*25 l25`#Z1ki{Gc-pSl񎕥gy1խQdBgjuX9Jܶxl,cGgjsK]cxeƺ(bq3&4ww $#8׏.H݂sXTZ30Rݚʄ3`MtªP*9> ̆\3븹=OMEhZv@+Ǜ1Ώ,nB ]xfA gRGjK1zV^[gԹYrAk. W-tJBۧYԭOJW%LwZDR -Y.$`yNG\i܆lbt$M՘%$Zӫ;jsԣmL7[!AϨLƀ]ۛI&[j=f& ٔac=NSΏVvGV%*z*|iT$FAGj(G5FY.3c @$xpvЕ&jxziakdȳGPkSHF+bTCJܦ1,ܓ%l]+Fvq5reU(xef~i)j6щr[(v\-F%XDxخ6o@Gb:;w5.b\i7]mh6|k>h[v<נg n(Q簦)nD7!cJRo'μwzBq'>Ծ\8Ȏ5ϰ_dA?NDI?,tPb+xp @ }bTqPp{|ʼn3x<')mكϐ!%BVrTwYّy뙑 `{U#7FS:\d GJY_DG"ICVk*x;r[bl+I> [[:a6,~MBHf$vRi=P:s|5#\SEW7Q8k]VI[F,C|I|9 }z \e:޳nOfkʗBxVPhݢ !\z$upfs9-e=|> Ytki8"wSjj2.WcC?hKRF=6qe'&WJru˸E꨼?jnbqט'R zU~~kP꨸h ډ,bVh>YmJ[l/j†R1fxT' eLRV/ڹ%mY);tkYe?=Aj}%$zYrq*z#M{NuN:I8cGl0>GLyqbxKS[\8[c@+My-IY\aUuZEbSi.NQxuvQ?Щ>jI:F'#SИ&7ЧuIjdɡb(sjDžm%`nR{mBw$2xyBT-mPMHt`e85TXL2kwE{l) $Iw6Jb8GƼImuIIWcMaHެg(jT)^].1r#R!<ֺ:kndp p)&f9oI-T([]ZeJxuor"˧7߳ԍjsWҵrn9ʭQ0Xl$5 |i#@XtAcj$tHؘZV܌GZrZ2}_NUAR!zR+@WԿg˭̱cL{\w=MtY.:sVRJc-vXGNMtw-2,͌}j_pp9:T)&ej8Kf_-q"8p1+cOېֱNFvAP +{ V5 ӫXt]tz1 l#5Ū U?;c=[rk/뙶;OndWsCXN(-\C1v"fÙ`w4A} $JZ+![vKFPM bL1Ucn @IEgJBOcT) vFZ 8\d8 >޵pEj;`1}jnAqkU\: kZI`9~/\qmkުr#8d`qU;  NR1Neҩ7`{Ve{UnO)Ҝ 냊ֈEAB@ث%~Ymj .oL v<=֗"7WҘGR;jupVV>mYP9'y8{ջgv#|\X6  O>* ^2KU{bɤQ^e,DsMc=:մǥr)j caA3#֢XJwOSt9*v>k2yccڲ\27Ze0dҶTTla9aSL*7 uiyo0>W2mo6!i Ԫ0ǞZV[ᷩ *Na9CML=)i3a:d u93jJ1 Eo1=k?jcv1]An5Lɭv|M:*>\מ2ċJKfP[c2@ kTDU."<lRSI,^>l l2w5JтR9w;s#R>Ԫ2;lae^٩$dqwQ&z6+RXwdt5ΛЄM'r)G'dgtigSUN30kos>-o΀V8Z*ɸ`qnU^z75c4HwWpܿ^#V"%UA'wl[sL O , Z&>_=c"xYAc*EK!鍵Z)[<1uf܎^*^*Or1W%H$sO0gD]49#ܷN8xh!GggXZMˍM:'Zag ێR(mi UL䓎=b$Y]hZ͉@A-*qr>We\KyYA )oH_Z<{T_Keǯja 7I XHŲj$fwmLzHG*8`@BD\g֦T3E%H32|iG5~pZ< `ǁOخxc@}j2viWsD@;Jե:mJik`3:݄#8zy7`z{RiG#qɌ'dj^F :# Rzr3$RAT"Y61Ja7N.4'$)SquXV<F`Ϩ*uf.QJ6d (?9&O7 >]/X#<~4aTc /F51S\K3 îڒpӽc]\yY:I8N"9SҞ"3S\ WັYXJ#h (Vt oҲ._0p{VnVہ&KFh-q 8#H<=Yv#tD(N2)|,#V Ip)y§Eć^UH`wvㅮTֱ P3Yƍݭʯ}bǂCaRɋsPH1WTTjxo3JuX`ǹWGԅd j# 潓z䢠ܰ⢆J%dkREK P=p ^76}@O5WNPgz!Z޾4uSL^u>()xǨ& =R˹PA:1sX1 haQPzWiڝyr OkpSו\ٸ;B\rgkIdH\3q=+3|Ӊ%851:\n4p=w8O:]Ů:N0+!+B5s0f4rǏº>{s`ץ9EEsu:3:Z~ڄ2 T擧Dj^hc zj, dCg**ST7CZe[HΣ~#P#\wvi.{5]V=sYO)W=ӫgRsJ FBaVR2\Mq[k8 uōF V#x1Q>d)崏ut}ԛ;0G ןñ'+ޱ|A>rr1W4W(f9 ?(N/|KZ6#i~>)>i4$^kVk51ʕG FjpVTOImĈBHzrkuĒJz{i4.E=?*:m#xm+#5Bq𭧕ynp9"!<J '#Wbw~KRyJ߶wg o45Xz_SemYr2i柲rz2 ~7Z5C1t[:$^E3 MB(]$ jhgi Bwzg5Ҭat@ Pt4?t6k[ۀYq<L5|MkJY#s;Ua챓@$TZfK4++;K[n*[vּI֙DJ uY)mJ5'qFcJk[LDN3s^k-3UԡS]ɵdUI`[`d?w׾$!,d.k,ztLl#2x۞Kɥ\T'?z0䗒%ŶQ1}<5ͦ]&x<v?ŽMāGUVהxSZdk&z==+Y}꺆]^1y5kƳoVZ\oՉ^oZՄ#]\uYMi>0.幐ow×1K.2uBD _桖Yrn8Ifc KJ.B"f%9T:M9"$52pO8D"wBB*݅-ֱݏ,Vat?`u'$b#+z3_Keܞ3Zڴpi^KW9ὑf Q]'t{Kd5,5p9kB00i=hvU6ΥjS\k [*mdGzVj4)i'd[^0Gj|;Te巑 `씍ԺV=ap{V'k%gl]Э. :OܪUʶ= , |֣ݘl-,tbX,6;W$J4=Nwdi®Vz¥Tm~aE4ܒzU?QImZ´t#Kl^Y"*kt7LQ[J`?ZU[›Pn5BpQJ1V4#B7']CQ,x"I==+MmB1(W1Dz~|ȝ]}Ӄں 'MI&F0I\nrlf3L56ܩ6rKmQ<&\ȋs>~f'gA<Av<. sVj:0kAs?u=W{}t9~VŶ.a`;Nz{XЕHRZLgi^٭:Q-MxI{o#vGA\Z[R9efji{Ҭ8htm>I!hUӄUe*[cIQݼa~$Q5e |+gMK7]hjKm`@S޷C*$+t8 Z!+O- ʹ!sW)j_g$%9{gY\w!vݹsMYou!wuc^)ǓmQ1qq՛p V#pհeP嘶xvYan]; 0+:ӘE,;2%1< <zeKT615NSrFyA'8$Hrˡt s_CerfpsO]ۉ"_+! :4m86$W Nw,HMBFw]ۗkGKdVD%j͡E:\ ]D?$(|@9QWeFwV_ّJu"$ѝ7iϧjhcvVvv%$،Ƴ prw|W{ؙ;|3-2[@a$j׎#us 4ۛp6k_mzzx(٦bKs!#;cKz1+L+1Wl|[l i=?" `qXir[[t@a-%8u؇nG08 \Hz9eGe,xؘZ}܎>BAΚƉz+1aɓӞ+ZPGq 1Rxf%0A7t7䍰uudh2RpJ;]R[vJZKMf8m)YWdqʔ3-$ʎqy{bV_|Vjpr靵jGi+f3we8RCi|LR+(=*mEG#I#/ 8(Rul}.Q8؟dֲf(Zd]*PTڶ`Qr>X4*AϹ"ZlmE- EjHSm= W lrB U$G+kFe[| :ո纑N#Nq߳qc>1z0:u>[S/͸UB=ivX j# U `hۓT%DMIjR;2zc5n9'`>v k|0jtКuz6tq6_&G%>g5y$+'Uݚ&똞 JCG.i\mĞ֨]Y˕2׃\k` &\C"+z(3wc]NZ\M ;;PHFVFoq#Z#Z^䕀ćj#h_bj 3ԖϜwrt8ɭhQcЊ+pmg̗o8fM4g -e-dI KFQ5a匁:Mۃ=(Ub1͑+*>bRH p?xVӔ&U _f BOv5˰iP\ IӧuEOx O'ޡc]ӢA91xm "5qD UFUxP;ΉC}[˥c~>\3շ5aq&ga$g5$6ny[q\~ ]:NAJ^4(Q7QɢZ6g,ZU!)jjpaiRԵm -"TNJyT۹=DjOc.mq M%7}Nj{cH鞔Gj3?c܏( `bEC!zR$N>N;U.u+rFh%~e)&^@#MwH}`~&`Ɖ@4XXF*ycXSԌI0T6(K)8om*3V$wJqjGTmeIJm .?ߖ@8˞ ^ʏ\4-V3LvCmI j]N][83ZV'waY'cW7fiz|z%9o,lfON*#WLrRvWEw(ۦI4GЌp|VXe%UՓGUtY:u:sM :1*vS-Z8#J9|Q*z'i$Y}F)-?=2kU//g8U6w`ҧ m.$tZu{q]T݆1,\>(:hB\Vùxl-:!jUlUE'RWqK7E\q>sЌb{UĞF M.m]8+c" fzӕ\uu옓뚯-N`1WG֞"x5jdأn͘oLׯ!eup*10C*39sS:TE Fu[`њc^E<pH2@Iq 8M:^谖&,9EgOMUAlU l`L[olm늯kZ?+ ib0˴NVml 85҂#v+R1 \:jCKݍzԑ\: 4EO\`ICYwVw) ;Kdz\bL$SZQK cen8kH*?6u9):)HhҲgkj#c'ƴm,@r iM}+t:!4եԤy+9*Q}FxP{TS WI)Gy[G֙Ԩ>5e`VS*MɡFLdN)jOnn94Y'޲nnɢryT#QCljpuӭ=u 7C"bR|5afu#iG.5[՝T[ԑA`W%9-?!@uCUZgfuUuҫ=-:z) uC:|wsG&N-bP9J2:ކwNW8 ZWRF-}u-rnΛN9;}}iڄL>qäˌ6G^Bq`+'E_@&z l)#Tk\8HXFitMSL9l6qU2FڧBt沍øMI{ȡ}(?w {J==WhI$[eƶuٜh2#$`8-U= m6j֝7[\o'1nY hɧ۫|^FNjKtiX{F5Rn':Vtӳ@]FkT)gl[U-LEp@Wgv?rkf8<1G^:V+(= $/ ?*Ƒ˘n#-֧ }RՔ'ж5 ";vZfWXH$߽+@EA$NSWfi}sW&UnMg' Ҫ9i61DZT0g1R𫱤qjy5 Fx)> ץK2=jŵ>X##EG=9L<@_A}.5G*6:gu\H!21T+zUZ.ǁ&Cp|Ҳج&NBqV`r3i:Jd*p7d?gTS≀_ Ll٭\7i0^ԖQ{VENBjdo.-.6)`)C/8ޯ8v =rR[kwtD9cen/Fhj+H(F\t[Ń&G&t?;A3ZBNp^.OB zՍ7Y02:jE/qq:ƻ(1WVVAMzjB OFB2'k/rt-b'+KAGK|;qȟ#ʶ+2vY&g@2Esd'i&g4Xuzh=.ad2{O7\|Kɑ׭VK㔕TnqU;3V]%d^Xɻ(8?CC(2RztiC,ScVM'R\z2c"qs$w+!PmaJeƩTpVr̆p{kZhI$MƺlM,Q> }Ꙓߗ,Gaeb(lPP "4{KgLvIkBY8N1SBU [ W+*}SM&%ר*kmacnßʳiOUa &KMFa)s\@,?x[u4of3Zz«-AgAc^kN_rs5fX50䳑 t_l#m's:43[OKȸɷyF3+Nqke{\Bv1b{5-Χ,gd7+|.zGKPIPMzou>˂(Q#\W:#.IzԡUA Ǻs ҰgE|(%zW[11W` cA\GK#85Ԝ"UTt1aF2+BH\ t -Fpq\XdIv=`l&m2|BZ5)+XdS1M: ےIo x<HR:+A֒Zw8h֖P?R%%ak wjNTW~4%+,=ZuH'B-i5zx;{[ 󗷸|2=xU6)@G\*%ёMIN mVP˜)-0wnZմ̚TG5bY_Npy 2rBaۯ*2{ע&Ŕyb~AXd~|so/zª];)t䚉'[\HEUҸg}\iGhڢg*q匮33ѳn/ݙ*=k7R$\}ns)X Ajb5y7Z›uѮ"4W,'D T-޺X$qDZF)&a,©8[65'xxDƭ&ַ'_&u Ok-c=IaJ{#fZ҅Vݑ6o+txE`ו nVHS'qZ6ntP>JܺAj\ D66(pU<\#D.2O p872\plyRO{~3O&߱Vlj,9$ԏӯ =j/z,$hjޫJqW/E%o/\êteKd3;Uӯ,;*tƍsk.[a1UIH=*̞.0P8,:ƹ]cI)c Y6:=DY5Ruҝ&35`I煵'XY~4h]Fg=o xgOP Leቧ )+Ift@;vv!\IZ<+l03 Fkׂ^V ɚ2r5yղ~z&ʐhm%<ԶJ?:? [ Ȯ @[m1S$hhƗJY#,L&**jǑΥG8sn<7jV~[㪚MK(~tizg4Be=qBSZ*Zo঱6gɢ׌1i]$s|;^mF3%Ţ3*M݉u~$t,V_uNMiY=Эbko+d$oU ҴY-XRfr͔6œX15m<=i>-FVҝ`ګӞ^:Ồ9ȏ\x6&9A6mR.Jvg? N'W5Xk 51ֶu \oU\+_tLW kJ0r˗Cڣ)ZiU,T[0: q`*^5ៈW{-z"9k?|BPGݸ׽yn$"jVGE|4z\bo/ .[e&HՈ~LxHmԀLʸE2+^+,L`]- ([EHh{+?\׌ekv-"5R+x^#IE8a> $SxLWmF7v lϊ_f4&HW*_>/kə%:sĞ*Z4ci;#'ƾ,ҼtqUNIo?u fieI_/#|͎Nk®^96˚Ѷ16z2zqJp#CU=~ 4i,4:t 0<5]Ԗ< G͖.T1X?g/0-x<J©P.U5G4=oOi1#b[]JBL$RwڹO`L}.& v:g ٭F Kr?TCkj7X+ #OyeoF1\{ftOG-OZ ܴ7/e&< sW|9r .fL.k߼gfUM;=+9;ݳu ,apz1Lӭʈv߅pO8*Yݓ{E<7d|DZG 5m6Jjn)u9\]E+ q>ZkvHsڷ?e60x Ζʎzd…#0䚽ef t-ڰ+T2Mj 3Q{Ir=ͥxad'55֤&5 we"X 9E]NΦ W*߇ k[z͍۳lqA9"s1Qhbo#y&8QYwӗr)'Vi ,{{Ӭiy7ȧ'FoCJcf;\/Z:"2Jǖ+w`r|́9d3At5a)cӦt,$ ǵm翃 ¸>C0+^dO۝&1y;E666XMebX Ҧ2*[JYڒ~@80ί,yl ֪|.V;iS5tPZv?W*rz|9AL@KÌ\߈-$exx7IP2sz#/K v5?5\zW]jݍR7ccuC,Gs1z}jtj;A>g@ @Ι F'G*Hi=5g+0O ߎz\0A]5*}4Վk`@A>.˜< OAVЫTE52]FRHtnRsמatOf<u9"єzqT9qG,>iĥ-n[rHuhUBON՜DA ßSlFx5+ \"i5ABEץ3')!$Un-5vZJ6cv)u$zr_gF\'4f P)vuyBEY}B'm>瑨\bjmu"^Ǝ[FWZ mZ6wJǮ p^$(֤7hmjn(j;C(aOLzW V]\yY\irJf2ofHdUărq~R+}Jd#rjՎĪcoZms7%wO,6clu5jѶ9?jI4E# FT:.bd֠a(afAvF7Ĭs}JId܎7ARE$8F=kz[52JGlcSў]:f[)_ 1[!06 ScӮ"QJnZ2hLAk1 5bi!\ ֈAqֳkM#}Gcq 9zطd}le*LR̍5h%Z{H-IA>T~JNZ塼`*"c*# ѳaRd#>RM)TˎF*ݞ6695~-^ɔ˚=Hy*Kh3kyLƐ)P9,2kR[W$f^HE&GQUt{H=mǙFO\TZJؤrv|ݚgquo1XYA$JZf)joXDZ'*cWʀHY֒1I3WNn֙v3HѰb:O\S }P8&ܦ⪇'5h#Vvڕ mu5m_+GCW"{aq'J_ehߺ$9+AQѧ-9փZQdSS%>k'TV䒻k[iPp͌5{5s#+ZUSeR-GSxYI#kNyk2wc[)t1UeK&f*>h-]Lzy!L$~QS :ig=Or31QҜusw'yG^WI^:F2;/z))w_jCZ~X?o@Z:WD}L*Jg4h":!p -DI;dz3Z :{֞Q=3ҹn%_z|U&SWRCv$8b>Tx"66j,:]7^{80o^a.>h[1\\$H#$wji.T>цaRm̝){WFPZ9S&^Gud7Zʏ敃cviSe]i}(ډ#cǓΐ2*'ZάZZKFQvfwZ6mg'l՘^z8V`@phci1ıq֑aP)ּ2*B)`Ϧ*շ)-F)>2V͎XKd8)m{vrkTFW/tZi"zi:c ztH bgb$iO85Rh-lhZ4ۍ2iX IqM@c屁ڢ1t{6j5` :bm0d഑zֺ W<ӱZ(y?I#iZǺ>f#Nۨ@RԆM%4m@x{ o`=3֫JPoRF(J5dQңF2h,$ҫ޶o"օ[U3+ ,N^KTT ~I&"UfV`q֟}q-;k_}ɴc-[D[hP_=Dρک]$ \dqG&8/gtVmB -i'DQic'Ȗak'Ws+K#1ZM-i%n% ͉@sU5pxA?zkF{lͨyhQU=.(B?q |IJ:XV7ffd}E)B*go!fvdH1֭ˋ RKFO,xHN( sּ٣+ws%Fojh14ң|\5[YsU}9#M\u&Z6#NMucEy#)8ߐ(`G&xmYE6kf ynvV=BEZ2FM9_{vJ!˵{S*K\I,@+FF@ʉc?.954b&II] m>F+Ě?c6\ImD֬uO늗\kT[|K_\TWw9oq:z.c 늎D)=͘+du֯]͜)q{ %9SJbFXqꍹݬ]Ry9+IxV.c<1RG'=kcL9]=Mc.dw:4h] Yt qO76MkãjWqajzZœ/y؉>We۹Cv)dA힘Bd]6r8uwH*傝˅X^iX(Kyc$NYl̍=OEAY $Uu77䄰84F%.fi"K T1:m6pc^q?flGe߆8|ؒXtQp3S|ѵEFjvEeh\%`SLѬ$ >+6/McY ݕqPe|t tqR|v_s V:Kp?vp>묁8+UP 2>Y$~vE k]1ݏ x"'D qfUīՍLƺC/:Q#%'So?Cѕ:NU$z7sRH'vNg,֯bLm@J9Qs(9iWPc>ef5ZǕK:vo%NH9 w5O<;(f\򪃩RLFǯuI6`=}뢥Ib%yFaՔdbw<Jlu3ed.0M4W!/NG5Y5e+IǕ2]EA#<} %,sfnbyOto I)Kkd_ K*3/3rmjsgS,:ⲵfGouk|oq$~J 3$t?C){J󗾙nXfax?m\BhI Hp[+Wb+e=e6QvKS>&ΐcÀ8'^%[Ǒo]YZ4E98G/'s>3G™z?&YS+i4[pjz9yOZ]H嗥M9.%Qs3`FO_zNQszj5}x[=Ev\7*{Y ]1ֽŬ-]ӓ޹_gKt \'Si/]zN*qI.@߂zSJo8lW@n`vp0ա=<o s!7df֡ )cͮl,(X94[DH`sLn팼vn8ȣdDvܫJOC)ѴSe]2KiڻO\whK#Uj/1X?`X}_r[v^;Up)6'XXV4:oo`8.{֎Ii9]EXG=n9%b%u|'*^Gu%~m۶Z]B) RQu]R͛u S2Vĩo*Hu]e8xsZŃ1Z7^*7(YGrj\Ƥ߻'.iz U;,ʮ,2v[kLch?uަܯhf$/!tNGjdXN{~{yAkiUvs҄u [4Y0pY\صnI)H'OBWlm u~{\Y`5,`ҏ ^MjG$T%-d#ZVzV"VN}A4\l)kjt"gnw*1ޑPʾ-/s01 W-_ݴVv2"p:㈧Urwu)Z\ɣ֏i ^Uq]־AMaȭ*}3IVV$ŠUǖqԺux-4ڝ*pȭ ek%sq,<|*ٝ)+v ik͖+ Ehبb*lsmk{{a@ Ui}8TG6IQ:ֱuKy6~hʆr$bA$OC.=KTG<&&9oEWjzg5+ 1%ֿR{U.ouBH`A,pz7ûO k]wwڱcJx<GVV&w]>K)/]o ,JM~ H?3 .j>#4xa ph61Oϕe+5AyR]~AT@yCK!ͭەGڠuNs3ϹT+дqmr@#s\y7I%BW}GNϞ|M\l}&Ōbe8}3ZnOK..&S8SeH$Fd &Ю8F v^\2䃔ٓ-Ƨ,hm8 ctҶI=pk3xSBKg峴 ʌ3cR1- ]>Vg1]zGc 0* No7kF6_j(>Qr= YnuBHr>I$[_)F]䖶WIU>r̆Vwq͂#_j ocI=dIVbmx&U>]$ УIti$=Y6n-T^-m2_M2UYU k" 2-Vךcvm0j6msպQLIi-ѐS[$L]_q}lx$$\յFj;r&ti;½Wus\6RHHU=w׷b'w%DTɭHu`%RT!{G>nT[1#?TSII"FH%0խ{uzܝ7Le܌ Գ'ϴ Ydb%.]7LWK%v*qkRԴ1,eU~2j⫈NbI ڲ 9 H#SKs&jo<frcZ҉.9 rk2I!1lb0''mMvZI'mIjJm|uU,GݸcI>Bo'&W!~mA˻>^3(#$zحЕ28$`*#;FZy#*CjÀg5&F:"#8Յ@G1WRF>:rHSҚxB݃C@1sL*v4'w}Y d#t"iDHvVmYG ³X&!rA vw!ht\=+d**8W93ʠHV7*SX+ѵ8:bBV׺5Y<2bXFe5Xª2Ƶ5sM.kc  n[5,j #7+ܭh Mub VͺvRuI-$ݮ`>JVT[ rsң xh8\ r?/5Dqϵ7ȹpe/=*nѤ57k=*MqL5m8* #4"&dv;}[Odđ6rROLi&,T׽m5#k"Eڂ۰ zo>:䞇v*3hpʤڎy[VGF%Tg叨[0xbDtn,ڡV[MQ)-:|n[9ި岍̲1թ%.T3چޜ oBIk۳6%S[ɉFODdgT>oS P2#ı?1i A*X\|Gj 5RVMo4d J³R>[2!^r~w0ǽ2Hm%OOm+Ǧi'- iEyk9>Ol $VHm"d!Pz5 )0ɐ<;U[d#BEC-u Zޮ20JӴHS^Zn4nC[4L-6lԒ4ʄ,jd"aJ[]]#z3A= .=.KI{hr#sg˼ W;}X5ezG旴 $*16AdVV^BҺUH9[q93 ێMX_ֵ[L`[GEBmfڸQZ2@ HnZ!<Xb$cڹZݚSRJ1yeT}kGx*wP:3HQڛkG]\=F<@+E՛3T]8bYT9޵lCq:WH<x:U[6 kR hJWG/؎Z:efYku~YpRS ~Mb Ɗ76H6.X;b>u@ĞRzQQHe>36Hkp@ ӓާJ<k\To%ѫt fF dy2ߝHmz?iQ5)U*Fs%>_ӧK<Ӗĺ֒6bY0sF95:&G,Oz-¤xNkd*̪xzViҖh¦GRH_kr9 r16iJzs֚2Fi!x"-IV|[\!xWhAtsZ0{ִyZ.;zʨ7l\VG1.qWlGNj4E§2CH0}+iǽ@R4aUNZ U,v;GM#lsaȮP4i,:%g]>$BV}ư鏒b:+= D\_l:=VJ6'-1\ QiwF8kkLtw1U5sXzRPWy͗v^BS]0Ev7ȯ'P-ԗ5ZJfgw幧R0c4і c/~f[TZ"K=&ҰUXجV s+8DmjuYCI1]qV7fuƬ[j6D<ېXu.DHI6Yh"<}d6iosWFfHc8ɥn$|@8O<3~uY 0;p[5^Ko6mnlOKudT}fUݼ^My ZZh&RMX1OerV'k$,w r@sDN`ȩQ}?i'tE+o_oMY {W3c zrk^kր- sҝ+4i \ⶐnt)|dv륙snhۜLn?-sʖdfξinTTVS%mZ$iJ6~1)u#M6RGN:A$"5 .W#5GFM2Ij=q 2wZO(p YpFBa=kСNsu=WZlip>\»xBXǥ|~sqUo2MsXbsm3䇼>?mAfFh=Ukv%B0"=m2kCy3ISSd{_@Wm|K(PU=O97e>y0ez>|3ky)wrr$1GeׇIuu)PҐ9Ũ˜H1Pf[8K@ԒeIu}~r;Tg}QQit%ˏr+v-Dg} :r,JHU`WtC\ __"˜_CIrIf5+'婨*.ڟ cպqz4Z4:]>{k|KRMֺOݵR3kt+.Rfut'ΰԈJx$)ՠE%{۸̲;/j-,@r\omw9WI&$ڼEuMKGZiv,+]Z~hm%ՊD$8W};@9 xhiv7\S+&qq e{ԥ*rKIN 4ZQnQ,BW yܱP^d4K;MyZq}.MK '.sxdqNW2 =͆[I {J~JJrvҍ:K)gQ}sMa `qԚ4epjI!:JzҒzH\՝=5 iV2ǝ̾b[% ^m\ev Rd.n.3W5uOĬc8iu)WrzUJ>3oWG,$ڕe6:͒n@1\y9R9z ]#qnSԯtx$<J22IUVg"ݽyX`SGT}{]ȅU@8VދmB+YfͦlbܣEqQCXο2p2cyy(7goJ_1$c"9o*SzIjn6k~Otrn+ߊ,b!9ɯ<(`IIF)bu ,y Nz{m;Po#pj[_sy~&n};GYkJP1-!a֟Z}֌^r;^@i֪̓0Wχs-ByqkC^Fpd n\&Ӡ-OԵM.abAM; .<[ḌXoaA%*>5tyD;(f5ygZ٢tCmm0Sj}[V+o<8e6U8›שmQ 橨mzk|3 /bK J9 ||rqu/-[ZƖGQ 4%lUGRuo%ܔyXAZ]CEIL׭TС,l KKÑZ?kseL`pATl&hGG1LsֽúY0:~>]o S3 Zi:|IX*wTjseQ,l4\߁D z]ӴMX$mGKqsyri W_&G-κ90ZtVjO 8>W")xdDXKcna&lWО[\j6?iHoz&%]>FFǙ$yWğ.-Čd{~ubKq8w+.;{աTXkԧ{;8/6=:-,Z6ƹ_.L=6j2s2HQa"D͹AX dӡK gpI?ZjJ\/ݓLuǰ$ա텇=t2W+qZZƤS=WڝRze'h p)}Mc:RNƾ/mtnrcAOq$L=+$vNTi6 Ns}m R9yu[YZ Ht$/SɘǫcRn:TG{ף$ɵ=9pT18٬g/emb3ך(8uR*k%5{-Uu XzԚ}֡U+$DJM唘 $)alr;Y`S/5+h6Jv*IQDsִl\rrXcϴ-9qW%kY **qm+*4v 8&(Ժ팍+?#'^|9asY)"_)YY,{ ASH/PR*"`4i"pb[ޭ&d`曳8&wr8P6Q5_81EEsLUX`[FIh(k)fFW¹{=*Bl6{U%X̬>NKwhw" dU st1p3=x8] ].Mm,޵ ƔQGrb# EQW4[3F$m'VRzxI="@N2WZ69;"kW"2%cZ gTOUc`$*B*1\je"II/V@kP37UQ#6ʭ`:>_]dX e$ 1NF 2 |dZOMrH׫|0]U)ըi: 1Z;Uq-55F 8-SJb@mTfRL̊è?: KnrMW 9VXepCI`@jK{f%eHF$RK"@u7N=j =+OSJX"g+ԞzkC@ݍI_j~AIsYTg}M.62 _#ko7Al ,ܶOJhP\0vݓZ$ݜw]O<)ٞ2IuہY,Ry`D"{GH9*Wqh4%'$JȀ;zĀhYZC)ϓ*tsUwBlnj]-0@?޺MaI "|Ti5Xƭ[IN#> h$v .XwwL0 ~< 2N$w\e3,ۂqڮ\߽cڸ8mc(PŽ+2)S[xl7o+%"Goeq4&+(͉cRmN1jU^Jѝɥ#h#6p+lϜ0R֐\)|1T'*i^ LE7$Q ^Ia-8D5,hA8ZKl0ȢZ]ZVecHS hv;}Z! )ݓ(-P4g1 lFSZ4W>W{WIUKlS[-ܨڕt #h[ve>jx&O75}6FCh`}jC]1*#٩<<ϰVٜؼ''$A!$ d'8 58fX\0xv7PsU^zRs6iTo25 Uxq\^Rwd##q9YIjCvcn5!w!98gCtFR/ )#iFG}խIz?Z/B}z#BT{k6suEs xrs.Nj[ⷓOѺeތ̨3D\$&ܻK/sMI {mp%F*Q~S޴Qv Fkc. ӊCdsӚvJ5jKmb-Ń!;5-T~[zlnLg>JI,֗3E;VmauҼ C*)#Kk-zWƆknm¤TQi|=2y"iᢐ{+N%8cmf^ŋ V[x$j5ѫu&V #ͲnNjD7U` ?Lˀ=9Mc=]S`T:خC7c9/5ԓ]ydDG(O+lqs7&~FuܦEt-c#TԬy]D 2jEq\rkLIiacWm f8ǜ:䊚E};H:1֒1I Zw]NZH.yͿPPNkNy"):sSAs P}3Uͧ4)C1c4? pw=oݖb=j7k~E==i3wxI'V`n?q38R#$qүYKǀY(^.+TGiaE榝Б%/㩭{ u#_A#]_/v_ *$2e{V 9 w| iyVϠU?jH -Yo#|J݉\ICu_lF";uޤX6]T/6H)ʣ,O>kq}#mScp}Q$#MTcҵ nگ[Gہ==m>ŷ{+0`0 7+0Ĥ4mg\޵qJC1Ǵ:h.T{xkq̹H-CDd>:Pl8QWʣP[d8e)ZS"UؓBBgj}TL<X;bDqI,~1=keؗM4zl=ju?#ísh W>]Fpc֥{\#Z662HVou Q1r7sDRI$V='{3u⮞e<_DKȁbfLcՕz}[f/ Rij]QngܝQxrIUٻa|}xFu=sPA0c#_J;}dϔUs)W3G2^>8`ZGֶK 0]T9\mqeS5BVIC?D2Wp & -d||fM-%p绍{%ג@=j u'DoGnmkǠKwq+V$z|:Ā3F Kkb$uj$icR:em2Y.0x:ZA' #0THVF9a I6v 8muf9i#adѶ͛1nUv\ݰėGa T֖q$dw&kdܞYƇTk G,]sWӬ"o.3HTn}ԇ)F򫐢3khWya=KsS[ivyDv0k@hA∧ٶƤaJ-Pw1D ֪^]];:UHЀOZ3O%+ǰPr~O<ԁSVզ* uL75,:ݴERNROڦY{" 8[}6Q]❡^hG6yT+eE)ː3ֲؐ5};TˢY?Z-kdAVl$Y]IqDkӵ&i(v[˺Smƭ}F m Nqֺ %P=z[-XWp sW)ԫ+߻G>i1Ƅj iۣrKH\(ΘNtWf}b0vxT Tz4nY6ySDp؟ht;&}8 *:KحbRR{Ҹe.ay"A(Io ʬo&GEְ:(X1߳0O@ UKչG[(hxr[E3nyũ# nw*JqwFJߡ: ZEC$Tկ\W*?3^ϴKU!U(-t=7Tt6Z <-i7C}WIIyIj`FVRuyJ\[&o%䎷~ ѯnFp.WKxWÚEizכ^IlYk kʷfsXʽi;WnY73l:UBW(ם.}ᚷtu(ɎI$<}+7X7T2#Z:T'vfDlhmw*?UVIӑA m[HBjzFG+?ExNM=w j@»+OHYZ]etVAqg6^&s,><&T%]Anye4MƪM5ݻDx{ƞ%,$7S<;-@A)c'~N|Ӵ &p OkebHq=M^NdZ/3F~YMoG[nko|ӖrkµYfW<+OKbu3Jn2MoS=Ƨ|QֹFӕb ѴnzdsRx~_ͷ GzrŨK)$xJXL\.Ujze%1Z~̭#6q^io@et?Zg\Mw0y+iSQ6RkHCV)<džX1Ԛ+c^[\X2y5R0F3>+ڍN\O5ZjV9V`3zOƍSu/ "'a\^ա#;$#קKF.M_^۲aa0.p@xL~c&'tzTZ/.omQYqǽlQڴ%֞vn{KxUB?]X|->SmXγ[ X:ӥX. UXcζ|?srQIWiyDqK<QѦqԭ>Kǒ7is,[.હfI]5͍Φ_kddbu]J\ѹ涍$h:'# &N3sY0BƵ&Y&EݏsJZ]J¶]ZOG,uF-G'mμacFOX֥#nGZ2tַ5+˜ lm-](,rɀY^O&HHIqSjpqYκpMٞ[.¤x]&1JKGQJJX$3aN? 'w2cu*9sʠxM+"Ƀ9zעjŵ-z }ֻndnIE:M G:OFQWzg",\qXZ-kYp3Iˆ*7Pt3Ztx9f]D ю+t-\h$6ѓw2x$OqVV/MCBi\t08,هgW"kNȧ+ ^7[55ԣ _RPtv"u0G;jaf]t$Pb9o\r#R9%\d1<7!i %F ٭܀[ʱwk7xV(Tiѕo[ l㵒6*4%x X6¤1ss]N;zTչmBO~:g*J35iXq&x#}:) ݦ\ܑ+v~QV*z>oR?k'QuI9 7G`dۘCixWh;S])XKk~[|ݳ1^^حH!3;`$jx^ִ1^Qq]\onS[98GVʜ$|Z~'0x `;G^+{Uki<.AW#]y/'yf~N1]ږ)$0*atmڍ>.v sV-x\tK}k~ `2k++~g/a;__[;z (Zr(sXm~A1xc8Qi뜷Kds'5WS5.ʼvYW6pU[wZk2zt`^6So|2q {8Fo܁s]iy15Xh[̭kŽŸMt/=Gf뛩v` 6@|f0dgW-eoboy4x=dCt<-6l^( ^x➿Dw-H_pjf8⁾BAWJkgׄx=_/sR!֧Amol_iehld)lzm:|CLC٢mI%+үIч?5jm?Tioxᗁ5-_So3c~3~ҿ?Gy݌)!/u#?/t9mVr+˰qN;K>γ$Cs0YO @$o]x2pfh`WEm{Jo5ռ/^zӣe 1M 3,`GLWk;\3|R^ܴANr5^vI5x\ #/"]V"yC$mC2n {Ke*9\߭9(#Ҙ ߑi-)CJ1wrG; cpgXD ;ԊzsOBe5>Hi?LS$ K]A͡PU!iD*oH黽Qb'zز^c \4r;_e°gr:XU`Av1Ǡ*W;8RI!q~ar&ۥPAbꐤ3+\D{1dLaZӕ݉TqOz#q'5vNFj4ānG˚+Iiq"6qyJ6dYF H,̣nzn(1B#*jHR($UHVmdIdmG49+ л[00PkW3\D#QWm-RҳǍǵRgA+R͸bɵAxUհ@8歴h%. RE@7!I|$w9MM C9>.хctifbigA:?2=˔VT8Rn!p u>kߍgU6EF=Q]KW ll@aQڣkdX$d)*cuAӞf8FW2}j]Aݭ;t8nSҧA97(δao!sҫu8!AZƇ01O gGzGC^P!z-;QW-L@5Z3B,}ξqDk0+p&F}*[diWQmIl/J`2ƿin C=`eclvH.7 u#1{RE2!'pɥ(hmwɷcAkJ`0O|ޭAds\ӦSM;$4jnkZ0:%I=IE/%hؒ֝2dJrjh.7L@.|?5^铡AB?u8 mb$H[P&X-'Hٙ:0/Gnk5Us#a0XɭNA'l maNXs+cx 3Nky8SM8-A \sձ!.}WF|5qZ0j34'J@"(Ջk{wM:۪ _\3ӥO-ͣIun/0]9`UGgr{d0;Um2M Lw#㶴RbM@O+Lyg ,8hzɨeH7u$Sbۓn*wv2m)Smtdկɓ>֙8o':N/NؕNqw%[6剆y9jiq pj1ĤG_EA x@M[GgAZVǑJӲ՚L,n [EFDAwnF 4̀K(C5'`HsAMIuf;- *Tp*rnOz؟M`REyFGhbG+'8wp 2=*ŵx{g&Ff巏fP(VӞ,%_2,[0hc~],.^L8'*Vީ]KD1lNzlv)ߵev+ f,aޫ'֡'f涌;ׯTW!mrkZeU#+95"ی{j ]d#-W*,OSոFQmonϩ6kAGp"$jEͅbq#`j=wUɒOb?*- b⡎'QlGRH5ffIG-;TCݪrJQL183؄ 'U]XdSz0#6]Q`/_J=cS:gD|@8R x>Oե~X)̀qL/=#cLmr׀`E!]oC*/5b ,"mNSE>:-bR/h˞+j@kZ6Og=XT5͵ejsV_^j 4{WS泮?d85 IBi1cb䳳Sȫz7,yzVD>bIWfh浴 \Ǒdcˏ"VbEp_zf\ըk(b *ph"I5*r]\:+*7P ۱ɮ %JbYb@G?6 *R7pHJ)jqoKM۴Nk>b#I6zI8sQ#FߴqժQnPvGZa+!`P"2};^]觹婡j8é?/V1zÅCբz~)oq 4[H敬/R:FD-J:05Z(n}ʸ4TeuS<o!DjIv#,l #|;FysQ:V 82!#*1I,Xm.$љݽZ8.!fϛfUHFH>]iqKkiZirdzvAq1T$C'5*4䬙nEe%SnO\5́!"nCZ3hl&\IdqYظXm 3i6-2'*pJ^Y>Y&(iHQ_]HVe(Z$c5.8'X fjIq\j[cݓVdwO>׾(:LG4}uG:~նLia!UWbryäyf_[j+&֕#_R_óĪ5@F6 񿆼C,E# "q:ԕ8sr8ƴy~S$z(XkwnYO^yQlTcƹf;W(dF1Bq+Vt#R sç,DMt~#" *V^NI?VsZkԵBY>^4۷+rPbOVQ -" L1U䶹Tr{l -867TEJr8bz[ϱ,[K닻UO!I4]_0bh嗭{!vшMq#>ٮW[6.mSV9r=ͦҴ(Y,EH9:7 ȯgJִyX \x'm.Ytcꘊ853, JNUATr]E9A*f^0MKdj2 &d,0B7u9'`U1Q<79%ӹbU񑓊5I^q1 v2YMlr^ <qUY̒<+54jԋV&(YJ{F>,[)'V$֓NT `rk1\##G QS]ΘUj2ўc DSecP2?*M4 y\3[e[_\K`y- *xrC6ny qU/9eQX}&շ5gTƥ;]*rk!uy18\qQjKo®3%:P26:[vJɣQU׵l-r<㦎۽l0U?Zwj4ÖjcSsqOFRzơi]_\h'W%g˷n1T2oW>!!=ɩ=FmJT4mq)^tWI_(݂3\xWFjCo1,M.dq֩TT(5'ZF}!T?δHI};ӂRK_#\,au8?U *p@y|a]ѥxV#&!fe> ">pԬIjiSJIV-U\7/&.G3? OKt6^yk~ f֮Qs63\x0}b?{iBc0}k yo4_+Ŏ) AJkC;?YGV-}iO^<ԺpOF-u=Oq;ܚ,Ys3۞#&C ,yv}kzy-8K͝[2_mmx1֧ûIr] ֳ੮\0k_kT+֒%gtbq>.Îs]]g.gY/Q-,`Ӹǵq9aέ&(z?m1 崍A|WɅ3]9|uCaC[lr{;Ӓ*TpkҾ!Im̸ODܫR0~u?BHݶSEҋR~{9Zi=XJ>O/5i=,[}7e湨c4,Wi_ X#~J_P<176V!a >~}__ oc?mECM4y {kO뷺2VC[?3Z|H7H-zz⼑%LGzx Rkޖ6x\2HȀ֝.M?3pI돭s4gˍ2XdsFesq|Pqi=6E)Z-/$f65];nܜ]EHk.?x/Ymt `p A*+vrjRRm[B~85)-ܩq=\5bg& JOzZTe#g$$_\fHpJqֽztzNȖb =J6'##=iA*ť 8Թ38 2\%xnf7U+=MV F20hZ+=BƠ 'qS-3?.-bl2FNj+vIL`(#֓ЫY S}3RבU_*ͪu)1n21=*nYAOzѸ+#\09_bl`,z *á*B+(5Xȥ߀q؛8]^R!75%d\4zwFx+6b1_9ȫjI6&8ckodm1( +Wm nìbdD;Oj/gݷ8]8ma[۩Ո[S5ʕh:b#{m͝-Yؕ?mtevChY_ Sjk<23֙uҠTs~(i= ,^h$ FF ҳ@m̮GA޺l"43"Yɥj<ɻ2qzmwQ@jXRbJ֣- nA*ۡIߵeB-i}jXq+3JILNvSdPbQ#RzƯ#Xy$bs޳;<]\*uKj.~SW@6W8]!Ú"I/'nA9a'W=H֛vk[xᐍ 4 1-z "$TEإQUÙ+ j4'>cBH h Hа#5!.? f?:ϻ5Rɦ-x2jx\;E(ʷN{UaI0(i*nH[=I԰ڻCvnj*֓e.gvqLrHZOkڄcҫc{T*8RGr8cI$ [sLFyGzM/H͞k9SSWC$$>rwĚiPcONlCY;;vS%stm̥* IF+C^Bm-$ZD%Õuaw8Q2ҭI[ww%f(8^3Xv%C9Lݕ)+I :R7F9mX5v g Sp8U: %4 ר,<'4(UB:W{V!^v2kA+{e<$mWzFs($QnAVðp2G:]r+6h#3ʁ$YW؏$z~Ւvd-PCL{}@ An(Y+UYmu)60M.KP4Wp H:4ad#iʝI9]#yܵbxQ,|=,3kjrMF~a[%WW[m'N}pX|N:* jQxJ |:i>ߓK{m̧Z@lRt㊹1fqCTj;2Dx姕3Aҭџ1J]Iz fkַ")c>,늡l=ݛx]p=wdMFI]-\!bM&QtImR>Шn[3>=E1ozb!5ou8׷Hc\UΕb=ehmM,'B7`EL 1 ʨGvZ2f8e-OJ8lq4V{!Ijњ0^;`կ좱|q+ŎPZXpQka*OWc&arZQ\~' Az|AIqQS+=xxEjγ2>-2Bs\ŖIWsձN2)'VZ6g*T㻹6LjF*ʹ6pAm4<ɹB bJjOsWL{mc({TQTl Ӯ*_ V WaQUiJNڽM9#Ж#R?P,;T^:㩥tqhBź T]wZLq'Jع+qܤf㨬ۻ }jpGvC)%{UXƣ[$1Ͻb]֪<1C>I5-nuL F8SJ8>'/5.M@|_"8MW(3ЦC:'?yb{K'v˿Xm^Y|y{ )'Fl'$(+`y8,[ԝH752׍ĒaӚR_hюɞ/TRS ȯ?,]vJ3,;JUwnK[6nLThf1337΄ d.hᏥ;2 y=jI>x=lig([fgnē=i'meIяI< >b=穁i b \;ZZV]LNHnՅWmt[8\hhejrsdIr ZFnt5FHV%;G:V~侖9hRRCyVO$t*CH5*6uDNٲV(Gsޤ@( qM[FP?֫l1;UYϷJjV>PPj7hǭMmmr;wwmDzĹU 7_¥BŒ9⚶b0=Q\&O~9;ٲW7!A=*3>U^ĩ IY$o(8EfBߙFfTV]+y v㺕q+K7gLv$c7[?fٚMZ8%*y z+6p95N6ϗ )9ܯ1J E`3߃WĒ"{+}B2io鍵qoMMVclwߡbIK #` ,jkp{֪2yt8\*qUN!ౌ|슫銶 `G!z^9 ūZF[;skR[c%{Va-PҸZ>"T"6R{^wPmT4Rs>wZZv2ɭ82rx#1F܊ݸ=RIXQ[˸l5,̛V c9mWiGj7s_g>}hIQ~f.E2c SbDsUN:T`{s5dD9"#,ְ`l9y,M6bdG3sԅUI;&>5'U@Lۏ3h#ߚ,uy8CHEi:2jv:YF(f q>EsxwS?zΣ؞oM$;n=-Ǥ$o3ՉXk8 źX+ `I.TghlUqrI0GW}.LehA3J-fORU!KaQ[cQu-ڣboV3LKmWNM;O‡GjmQ1$`:W4u]\v{2ў)AJYprc- Ia914IH׵hY9@UFӁ^Tڼ&ӈenmsI⒍zӴ;q3\+qƾj:.AݓpŖVV)ojߎ~)}/np_<38#mc+aJVzq &/ح s\vf[j#kH3YwW7jU־HFP9R=RfOmr1+6;4qZQѯD짟G ,L1^#*/R A#cjZ5E 8! \A;Kag)ٰs=tgovZS=4LOGZ7)#3߽kxKXЫ -\֛5SZqI62U35{U(_i[~%/2O5w۬yI8 BK {Vl3OyƷGJ"I,qa1+Rƪ hkCk@#l ^[IWb*oZ,u )q[Z{^i鶶jp&''cH Ræɷ+zfVHvonU/&0IR.Њ8g\ޛvJ a7H'[KE!X0HTj#r.Sլv2;/՝;EV[quke17&N;q]A]sӭ);t:/zd]2(|46;6ןj̰swO685jZ-Hҥ{ͥ]Y(T] :Ի47ޡF@d4IKQMqI/rVGO&BSZϥig{* a2Y D[(rWKǓ'*ϚOMe2NLv趚\.s:7$+VVa,eqW5J%ׇ(J><;{m*"nDepHm;HЬWڊd'| -61 0I񥦢$3 6+qPnم)HSҸݷ32 8=*>AEf@8d =峎8pgR Ȥv: TLltѓի~vg'O|Vzz6Xmι>5;!%c|>\OtR)ŧOr\4G)ɮ#O.Y4.ם~q"H_1 1F7UӔ>\V^yqyF;?t诧Zs'_VGY!6|N:?"=w ҒK95 3m0Ar;ë}Ѭ6?Aڨj~z5wvSFbBvX-#JeۀXdKY.Ċ ڨN}"€M6[bsE 1=H'@FRk[ V ƨe$VS>Uڈ;~sPNVIf]7l#$#:՛^HWZ𷇦ԵH"Y@s=|evr}#9 I< 7 Ґ-,T ޹&\+@l zUQĖ L+=&f1RĒҳ;֥hIFw+[s) 1HqKl K OS݃zgntcMdpq[d_W+)XWPIP S&#}Hb)w).U%[bSj\fS=a 1uVίDM2w'f\3*=hؿk'`u8m8^Gfx07, |qp根O,|\ONt#bqk$BrQVxNtA%&H# Z"%`В?Z_ *(bsP}:h{z۸[ֳnƖD9-~\%ڮZRA4!b\NޒF吶wnRW'o-qĮYI&$;ԚI@FۂOZQġ ZN:ZXdfmqcx}18TpAzI[69Us1I ^:j((8.cq/ yec\5ޓ\kKIBF\ -K-l'wf` q[ԫN4<㡱opW;Im̈́2H\eط_S\wR!B=AJ$kR5bW/-_a;F4EtG {'U)jilԶD75=rOzkѱEB}=6Q֌:]RryMk$*L | sғrl˛lɐ:T݅F8#Ef$T,&<:mfs{/CxJmZK;\*H+o$u5"~Aҫ-\x`S^G50=sRP7ۭSi9y;Dմ=(-Ҹ\`Zo cj6)J7%֣ 9f~a 1DV`xKgP6sլ]Ny EO{$.c:cSDA6*˴u龌#QuFkœ4\TgSFwQIv^~@v_c.(D^#qң*L0:dPdRjL8@0;\&[,a9,+;|k5 p'X[)fi0mGegs2&Aiç*DHEvZB=sY:G!Hw @H43d21z a4]"HOj3K$c5a @[zQm%rkHԛD(2w\SrZVEAޮvh[psg47;òj\qFzd=o^PiV>y4k` G|hvi~-˨Z Kar8=wq. ad b(XalZ m~_@\j=Y6jap%ҋӜ)(٬鮮ްAc8ǡVڔRJ6{B)hpSݶ /:R˨ƜGR1OuHOpiwI6r\cjcvɞmF_:κ;rsܚ}9h`*+u(/ʍ*g%szvϭvVMZ0q+9")=z<5MF$y505i cX2wȥ { % p0 H#y#algԡ#$չht9$j6%\Fx+W MT䝮qN~hJ`ucVuQU] )Rp}Fv)+~L4ɫqSңf F\j=f`$O:gְ,Ks#W&ۜY&4$NX\<&TRK,qF1Ru:̮$q@qc_[EW{c?7{o$ײlǥ]R:T1Ky洡&KS< -Jv cr{Ggܢ ˖Osd!k$7 d܄>m[HCsTM,Q9#R N VNPp E^UPϟAֲ@H7ZeoHPwpj]-Dݓe;yfn#vX뻡 B}^6afӍ.jC+gJT,W隭mew6Jh4RmC*][)NT0Z]ЭXУV -$ee"o'{xpS!m܌e8ڇ on5ao٣ǔ8۶SNewO4RfXrs< 9$r㜞i'5&vM6X8AHX ;QTBzuD`wry9)nʕXFK *s$jổ^y\K3#Z*H aÕH9ni"5jm@ΊðrKa)NBIIy_JX44ܢVgZuIlҢ6[wU]5B-k1G¨Č98Wk]zUk4B}IH4ōPKc90wyz?5sjΧЄUw=Z*;|a<4itPvN0E^=i`V]fZ3jH\62A暺 #< kp~:c?$2?e^Dk9cV5F\.&]c7w$Bgf&F^mskKǨN^bE : n5 *6l~jZjkwS¨!sYqEGx{Gkn`5\CxU6 J\$ZZ0^aNrũK&xG2~z^CjH@ǩs>{[ZxgTXQ1"dά5ҋvGkXCuqhN0$Wqfm6ؤvF!Q1^Z4*@X#v^e |X\<|[4zcZ| d X:Wx!2ċm3 \u0iI#1ڵVeԪR-x3.}okf(x G\ JRHJ趺- Q%2kˮ|=ZYyR냃^uh*r8;t:1u q(\*dr^?9ק&Y]E VჍyW궲iUo'W|3-;Dž`د*XzM]w=89hm{/ovCI^suZX<<ǭGS/5D88.^ƕ]їxL.>ͩ@`?Xg<'wl]e۟,7_jkk5FPG96dAA5F|*^wuera?!KA0F2zUVH'vqzLhpsEWAI'9qEKt]#סsᮛ[ %<_Z b$یnKRX@}* Vga"}/ Z/0 ?;va9Ti:gLiժZihΈ5s^}RcO]}mY )Y}J%&sgj;pNkRĂNdMȄ85608 yEhVQ=E$w"RH}vNaK `bj_;("[y񕤛˄J=)= ͔2ϲ nE1S aZP~o`|7JfRsFy'FxVyyf.p1_61xw>_B v\^0}E~{~Ӿ4|k\f2V?GiZեHw=+|BL=ڧRMkTii26SpŒV=ےw>݉mh`]ʀq5`b{lKi ]z]fy # FZ 48RkO\Lproj]nKGZ#Ȕ,kz/2n@ Vr+gB[ǰe v(hxR.A ЂybkXa=8❫10(^$ӖvGmNzz% >h GJC䩦Z)mTd =ZrtD ӜʪpH˞Ժ8S}Hw]Ȋ͓sXVg0~=+oM`!irdEњ;-%d PFHixFcx?5$:?w~ - L~j%b3[¿"!xZuAjBձֽMP NC>J"X}V%&#T祛 BҺG(w$q@]Ðz eGk[K$i\cmĞ+.0V.pLc))Iؒ;&Ax ֶ=pT탌Z|A'3a=,\w?imG0!W4p$kR-F ?ơD4S;RA}Vf^A]">IX*eXnImIrZ.`0lHy"GރcK&?t8^yq!81UB$##<Ack܋Ral!<QE o68I,Mǚ7kekX]1?/֯Z?Ȥh-we IեM`0wߠ.P5gsuR_j]}6Pzdl&f EKr|+O%J]&QXn5hrR~SěL_aQSXs8S"׏ c/s\C]e3sWf<8PzM)4=j ~{b,NЖ KpRgn{3_I>teFQGc*"<\L>"yojSҢtuƘ%}MC% 1'5ɼ&2ߝRɳŽpOz8JB@ ֩Vvk,j=v r,尻Zзvq()P0p"Ƨq8%GsŎ=+)Ai؊}}͟n^-3;e9dԾ`:VqQ[i3Nb/ʽzՄI\NGn+H>bwl2+VkKJG)o:CҬE3]kOs{Sޗv؄dzҢS۾zӎ,X)Jo=iG2luec(m\t5b EDpxG;LW\K"g-6;u||VJ11l3[ihs;mb޿/n6Uڳ46Vr>Fbk׈FR@y K&'-&{IʏsA%yycsRf-15' +;I]̱k1S2紜=V* [)k@c2\`hebB)v<Ց8~MhliܐAүq~6aC2J/cVuviHǘ&Ctդ'Z,Ùf<9#bKe\ApOԖSܜLa^Q3Zic!RzK-Cwfq8@sյwaN*FXÅEݟ=NyI?ZT#KSVW{f<~_ʻ3LT:S$*98I K6&c9pV}i7qTA|WovGvY|I& j8vQ_Ol)?+)a;dLmj̧)b-Cķ>Wl$ݎ 5v] 6r1>jNF=5BocK$FHipBLSL#[Uy7|C銗$eSMu$EWk=tc3[p+40 £p=Y.Y5OQ׭BL죚[= ^KdqQm;ɣXßkr޳Q~#]Z oOZ T߻+{$ќ*;-N~b3r -;Ψ<7|Vݎl$Y'Rr`5IyQ.3lr1 Y#@n1(\"8sC3(Triz% v "̮u=3]mEܮ: "@sRP֦1dL+fi \[i{Jet`4T6Xf'Baٗm_L7K"¾sK&8l@NrX$ ۥ0Z,UrM85 += +=6(e95,Ѫ(0uhb3UUd2H隨E%tdd21)'zVޙ'J0[ʇgk[N@<]Ԥ4fNpASZpč;#RN85jZ}+ FvK^TQYΊ 6Xe l>JU݌pejSO6RԻoֲD*%7lVbW]LF8چCgFe˷mEP9b0hgmѭ*Yne'z{j=0VRFd}-&̹eɮr&c}KUȞuvQ{i! 229ǥY$` n$ݫkMw?*UȒz|& H qUZAY}(@cOVŻ=Eֳ Sзi_y*<&Zk8Qn\imM4Ws^Ka+@æk"XHTnGs(*]"vV uz%͸oּ2 x{rYwRA겾#7\GUJXAfPz ẞ 殽Q ҵ:R\:IJcV+ؼvr~cTltAwjIx4% fwSswH𖔘%֍b|xKh1We2%JVgf$) }jwQOnqjv3!׭>KWsܴtbY#VO%Fk[Hȭո_Tld<'4}DCJe{8d}i?ș4s+825VMԥ%јRiPbuH$cca1j"ԓ1<%2H~ҫ_wXFmb{|[`I+'Xh=k>TU%ς>y_c+-$U#\[Hzd̷2POsj[Fuy=(Vnvʽᗅ%a=DnzU7>mk"bulc<$*lB;WxcGg7`; ߆}Q*<# p^u: pqɮn危!Hv*57coi4ggelw,3ɩ֬O>pFs?=d׊8Nxh7'+u P5BI<|ϚrimnDİNIºJ^&îXEBH;rݼ2##lRD˻u>hSc/ncPjO4rכOuGs+ծ#t<'"NŬ!h8g pjp*݊i6g9k7fi Bza)֨#Eۿ6AWT/z"1h<s2$2XӭZ˒AFӿOO52۳ֻ46?JְF g5'+3r aFN)r^ZX|mHdsOWr0PnjKs+\[H{)z˟T֎DU'tiWG1}2A=+3` [F[):ٸ=}kSlu&c~$n@`N9 ζol<})d#]"ΊF+I,A-#`//)d̗`#ԓ^SHQJVm+ 1SJfmI{\]S[A,@r:L`u&qԄy͋ma<T.#!3QXM?U^Mre/-61SԩR掇 ⇂ ̏Š/LT72C6TŜ1}O;KH]jb!IzR(hSOozt--E5~!Lc}PC\R̐#*!޳~/k6^g@a ΤΆNumS0K4ďSqWet%a’jlj:wIbk `V5:4JFQ$RꭊFʓCՖ\׈p͸kH!'#'},z4 ^M1$``*ƣ 6~NT9n+ӪGɭ.0 ;1wxe;1UJWGZ~o> ş>i}ꖳ}Jt]24R3,z }+RC+ZWKh^i%v]pY=uG<6zc=Iun ǏZᰊvۖ)F(s845U5{~&Ҍ])$i..%pv$n/;2x,u1 \Fܩ-g\qQr&fcHun3L6WbV۟J_ xJieV'qoRM-7=STT0Wl]+NOc@eq_Kˍ޼>t'*b&gxy_vAp$XX{ %DҦyTEfbq0\~4]g;NI# ݤKXJH 4spd9B9M[d[g$Zpk妑]u5+CJ2͌V ciQʞ!seFyL^v8V+[pii]GZJtϾi#nr2@Cڻ4* џAV sMFFA=);^ȋ/P\8n)IRsޢAݜⒸ&@ +Wni/ӵ;w.zqP٦HnKI5I] oyss,]NJO7%i+D[j1.vF*JҒO 4mh,LHҕ\g.3ȤtSwiXq͞xV!t?}" d9'',w*ǹp#9ȩYQcPzd2=jb6ʲJB})8tK(Hƭ ܺY9BwTC`j(@[+^d1(\1;+mU``ޛdv)u7JȪp{ vH-P]VH@{LGQ#S=k:)CNt:RIolŗk*,VS6c'^qmn"w0c1}NA=OSP< {TJ|HF#Ͼ I/G bE6۴g=;UtYnsˮZ+yE6''Iw.Rv(\bB*;HRy9 kIfRԗZ2#8M]9E+#4LFgFw/- otHpc\ԍ$̫V>E.[;fۭRl4BN{QpTjnQ3? ׺& ~o! {U; /?JodH@\ KzHϷjzۦV ڠ8J}/ Tjkl,zToM mB#=#i>F L˶7*]#j609"FW75vЙY+gtE!bѮ '?n72ΧZ^,zJodyO\`UƩpѢctmRzWLmm]I0o'>N\TerNӊWwc3U ƔG/lcKiJ;UFm,#W,n İnd֖EM;0cz TEHGjat᳎=+Fkܖ.2s͝4d9-|eMdqL=+糴p;\C-pٛ2<\93ީavT@&w|Z@ZFhT*ZX 1=*;7)8ev7>dIsaCt5W6-KF:gҼͪIgX7;+cyahskֿSEnOMkHt8r3W:vG ucWP'LQ{Woo@k6-$e X鱷u ǧj:ڴίc2e;eѤSӔV uc$p WϿ4l|A)HW펕)SA=:2䕎Oh*" Ux8D@?.A׳(FBͷ_^AIOމZd=MNۂc*Fdc'$+Or1*jwIV:a8֡$ ڬnb8iɜ )rxPUWn/r)#OV?Z7ԨDZS>HHkfu G25XzUW"m,b~~!|^9g7S5kt%bm)<V Hu⠺Q|nZ!5-Q'Ȫ1Ԛ|o8=Ҳ.b3U \cPV>g#XJl')`1cRZgeU%lcZ_:`Bc+7Y="+^L-4JmTmYxn3wɫ2\dhOlՋI.[%85lkua^9of-lCgܬB{⫴l^r݂ḦT0MsM앝Z\n$|p}[ŝAYpjo֟l [d g15D&Dt=Mh'vc)GTvܳ5<#fߕ TЗ2)Z6zNqqlon1V#3J2^5C_c@$RHqV#՟&/z k/$#cq &U%L]@:wB5b(nW'[ r:S3*7v=F3S _ciA/Gqk4خ7U<ۄqNȭj՘,.d$d5S(^ :t4tnHHb\*+yZ5V{G]*1Iȃ+M2im81`v 6e,sPXNd ]ʫfNZ$BM/zM:K$pyxt>O"چszƇu,z&ۮP}֊FլKF+[hћUk+dt:1P |4 Z-JisZGFRNhONKEnY=jh&fK-= ] n@%4w_3 "Bݲjfȳێibd,$+W^f1 jaR7O8,r3~!l 3I0%i#{R G(kV)GjFz ܿk&J q#&%gmȇ2*[F **ӵ~Ż=>[QܰjA#f([^!=cOřґfQiEumjzF+2O,z8oUcT2È".+>E.4@3 p2h`'ig~-C&r$Oc]($k"Fp9'qqf\;Dҵ#'9CnF#DyJM$"/ri~3jNWSnneGrh򬣌{mkhTI z VxrJξ՛m:x IW;4|F Ϸ$V#R7[$uݑ[[DvpBU6)pt5 'aj[M1RlI5%ݤ`u`s,#IZjP4tkKu-ocMjFhqx%vTm +m ķlڵqyb1n pOG8=8vՌN+4rHG\FɳcKޛqݛm}öqkeA[:Wzu>LO\(niD٭^)PaQ;?Zɞx<2H Z9t@ҁ_\̾# q%^SVmˠ,h,F8͑7S״$1<,ݥ 9T@=jԚBty!1 tȪ{u3FМ.*GBJg~op ~kOဖ^ۜg5cͷtv286;[[x#@3KuAS)+j4_= )zBy&QzWQi̲B2IYUgD\hTDK;`^ióWΞpDž+υRHY8iSVR=tVH,cc?McO-lЎWѺn$w5H䑚J,x؊գ/gZħ\l/0]Yl>nM*[2fgv-jhhEi^y*=zycejK078Mz5{KuUakn`f3DA 8_ fܓ^NeZ~քrL$hoeq߭*mk񞪲Al{NH*d$1k;Vƍ8$\TiOZo"qsJjYf-{rdWO[Ns @k'X5YRHX={dWsc$u`9yyduQi#I㜩*mfu,3+r&W$sƩ~jR3e(Lq?2+*oV*O]X NnsSC:FD&!ȣnҖS9ԊqP<ǚų]bV<.G5I\4rF}HU;Œe BdB5=],<q3&ZI8n\Zgn7' Obv*2H?ָ7PW̒&G$R0B5]*#dѕZ4")I#'í> .YC-+@9n@"A8,OZ F8'o)'d77N0`y&$ u3\–-7zq(-8+Gy#7њQ! socӻr4oZn6,~ns[Mpn'\s(JE:.Pao1n4g8+kYRqT6lO'(pqZ8RctZh,Sz&!tnK[<1 nDE2fWpwl }jp0Wݹs×Q#VFG;bpOTO˓k7PMRAMqƤܪFƝX7Er{f.C".q`U c8ϭc/’qY^Ozʼ9c} E3F"c^j\p3rs=+8.U̶T-^s )\1"9+g=+cX3JIEgOv$m#!xY$(ܩ851(`t+Mz #F.S)B+<ˍتڻzkZkccKfuYyNmnA&wCD0o9Y8z-ƭF3DH$JS!ù| Z:/ԭ]T F;kE!*+;0EڮV87O738՛UY|ƙ9`=}kRؙn&Aa%\8 =QE+:lmX;^|o6MĠ3^[ep#?/z$Heݎ vR|*5;NGl䊥 %\T,_ 7ͅgR:5KCgηHcoZy$7[ZiPM4NYI+HFMRv v5`H /&ZܼʠsAMsX7{y(v6썈$Jmaaf\5x cVwL?zFRFMԹXW;" k>mͰ[qu&C6z̼YqE9#mY %x}T 6xw$>fɜYDvoy ޡrGtV(#M`U K+HPG5a(Fsxrԝ{/0\LYGz|Gf2D(`^3*aSUX5+rdp8rz1M6܃"#$jx#]'ea0'+p/wis$&\5"9,3tcTq7M#ݐsE@15#È=|@͊ЂM`ng#aauHCgqU8r@Y+3gkhWCA"-QS nVڛ{- ̝2j&2Vԧ$SI$ujqD9$$DA#8v&oZ]pj8y`r}"e'"'d>a38隩x7~sFO5R$ jjNm4iq-S0i>֔UC5^q<6F4 SGE8Ř9F &협 c4%Zv.ӈ`ߝhWSIp6@0>>n_+T=iXE@wd} TU"7zU$HҌVU妆5,25QIP>fT-v@H#\^KO$<ҟlrZB]N—wыQ% jޥqPQf=k6BQd1$s1'ձcUfDv*䒳[? @q(o:^qP%qQܹ},1PUY#=)IZ{-@F\u~%|F6r܌ l5;X5d)py }kwyr?rpMP%~fndMi︧G]WVMFKh1qּjt!< {XmrzWr#8'\#h琢^xXhZ7fȤ!i*2*퓄ryk)mٓ \u1Im =f]du^IʤA|(cWuG|VQ䜰cSBO,á jڱS}GD 7QZ10PfQyϭY T##7V;}[Zb1ϧ1X4EC1XkF]obt5+ۛ8{JO%B ZB i -I!u'F6ت<"3B1LaW${Ռ@֢Ҥӹ esYFQm$Tp#=TtE19ǥM*xd[TM-r#(ֲ,4sn+r\P)pG g]v0k0Qɧk060t&8b)9^GgJtUe%A[ $tew2I-Iwj̦g6OLTʌz։B)bFHV3(+IQdq?>ڪx< X[,NN1KCF&bxɫ3ȢR$Ul rXT&kÝ۹٢6گHҴؒ/j b eޣ=:s*@aEy8DCBGg]DDp ]AceT6i>ldsH%XT+̩^5W)NK9݈xcZ_mܱ'n9_r$W@jv/ r3:al5VQeOֽNMi- E)XzfR-;Pe^9W%wάvk8֍wؚ^[Wu=Enn-E\rq^iIʶ{0B|6}Cp̼otWdeRpPqֽw6qԢyŮskr yR0kn="XC&gmxhPg-V,(zkb-mN5I[fi3>vSn+E2d$JKZ(+\;g\Iq#ŁG)`z[ry7ydqڣbZFz鷻3Ŕrz-m䅍8=yL,:Tv`j{.DaLJ9"00z Vu+r =ǥO*A=¬W_ñFwrL Px&4DRq:jZs=I5őаҭ@i:+"#vkp( v汹+Q޻+x1U/(xވT_dqQh~yv >1?kUsH"`3q5RubTEPnGQ֛YؐX֜i;B/ՍI @~m=KH m^.2Á5qfmn ?<ÔnFjYw'ّ6 0)x>.X Z^ѻ-X0fFMδ gU,ğWGi$1ڪȐ\^RsUt)n^R-M3ޙ$#Af?m= [y<1!]+p8wc՝w1GSx2fc䕘UmtvC#e8P*;8mM4O^*q "^2jlr#Hi)D%;(cOfIy kXCեg]A#2՚c0f PU3<=XatG&GFr25?J@XC4쉒\h Ƙ[!@#(\di1D q9I1_q`UƜBvHa[LIvFMt] Iֹ;mh/6;g[vrƫIТ֩)noXF@M^;h#{e zűl1 V}X뫻\"Rs{WF-TjZ5TdTQ 73u+ϕ#oLҠ{LWꯠ6 ㊃Om" F3M.]ךŝ2i~#؅"7\wC}6qL`=BiF|sT*}[5sWGxZT{pT~;(1+XZyi_5t-+:[!8#9'XXoݷsZ6N"tbMnTam绖b#'5l&1ojv.]rk~n܀G$umҺ9Bļ<)se2IX u5>b|kk-"A3T7v9g19Vw yqGحѷst]3 \NpiC>VPD`btYKs #ly[ v݈Ēsְu'3ZO*2C \\>񅭝N8.g-s,j;%&tE*qrֆFew?"/)l(s ֦6;*'bpկ7B9D[ 8rY VH z#S"ݺU:TLGaNEuGC 8(7i3 SI Y€G^S3 9'g987 dE3*:Ec6d GaPˬp`hm4ޫCV;o.S'ظ]cOTn;:n Vp[F2ˉ#`#elIUc g.+浧_dXhkyR2ʋ4LABX_UmLHy]Aufr 'BMjD>)bF3]?W2Xj4<ۣghNc$5C\\u^o)! v݌&E (^a4mS[E=qVZ#5K|Ǘ=_ :,X&ksF .'R9p Ax_&($b:zV޶B3.xW;7?8"wRwfγ\\$C ȪC]Hë3rIxA@4H!V;hKZ%8 u ?&:q\%v~Tni4$֌VW,][WU`Zt.krzf7B%SqzGGJlʝ<ҹ`IqTΧtёs=+NpȆ+8Xp.Tj뮧gmbE=|ɘ/15 ɏ 7+ rˎE=t˦]V4n.SxUbU 9Rk%QdzzƳцEfvWg=!ȃq*QSa?C;g BSx3^`mQ vFû3cM5kT4W]SѶ=m8\g |i$V+%Bdp+gmwH(%JקMPQԣUǘXrM}$cUjY˗Pq&ps^ie/.n%=l}J4'$U rkIRe%}'Nt9ʎOYח&eoEdV?+užI z»68y qknoE];>o R';_+SZմ_rZ Xڧ3UKI oN}LAqsx g^v"Wi'fUUI;mm ,HLl ^k̵Oj0jf;X؀z|g&ѭyFTpY%IqMIN%GYV҅y&k|#m?irdbu_)%,+]->ABz{ JoJϾDR6{(q8)lWˎgNϡT+9EPVSf\Bóbu!+35tnt[3щ<ǜR!%eth9?{_B sM+{ifRxx3D\]]&i10B3 Ig{ Wd'NU;_eU+Xm۳G'OZ1.c-H'uzW#UBJ69 lt(GMjj,!v+K@Z, w[i&`< kf,2ڔYh)Fɞp3zMVVim@bqW}9Tb\Ry~I&x(TC]x̎޻-A%%'ҼRK9-#q[V:jFp8fӊ5ۋv1\!ܮIc׌($OAZ~#I(sҰ+qznJ3"7;aeuh\˵aZӻZjVzלvkm(a8渝CPMbq5X]<| N9ɦֆʞOPqs ԖiKvj-bl Q#k;#jd)p'73nG#\)#f,DZ8x}]k"Eq"uw 8bkuh%ykS'k,TA.ެNx"Iad8cXZ&y-dPuT滩 \Z\X]n`G֧G4yT"tZtm[@#}Ey=y!^KK[[ 2wȯ0I{U*\շ!J;dh`rHէ{Iʪ QO[U8ϠW qӋ:ԍ[;{i>cc#xXd(bψrgvx-,4T12tRTYZg1>YI#~]JRzw6 #ְ$:a8^XN.H̕DEIV֯4;`bxWC 1^:]䕌ɥdM ]J8K$ےV=Jp[oUŇˈkV(E_= 9'V[Y帔c5SDKj2ۈ_JBkިeȥ+n_$l)z̿Y @=cZM'{Vk|<+}AB+X E*H#ޥYک#`w]^łBU[*8%}~IjFqpvЂ:㡩9@c#'5L!, c'랕4l>@;,'K<6vެx:U"0< cz`1ϥAx03RFoH$/PS10O#֞I19ughlpx!X# Inu{Tm<ޕ1ƣ3JbU G=_Yw#1,梻pr@轨S"՚8Tlm㩬y,wpbcil|zsDao1+w*Hm8ǥBK13׃ӻh\ (J=IuDϘM:ov*@e@ܜ14 TVM+Y[Bkrae@p ɭ2Z+O=2yzf,:p -tAȄw9Rd}8jG{˸lx4<튧@6I*;I+\uєlLGVYt9%K"j#Nh =R cS pz`F8j͘ T6448bp$c|\<+87Ϗ/=l( &ֱ7KC2ܜ ,qIɭ+'{+V%Ame1e%Y7ҝc=58g؊mzw!DgINV0KGj+ԐA*Mb3Lv >SVԾit;o買9f$^^.-4Fw78'$0=)3Eo$#qps\xunv0&WkrMzM;?*9{ޚ-_cS{:؂w6cdO'YvvM՗,ogE8*F5c:KSlN򲾇hGx/X\.萟7Z˝;2ys)H,תxJ~rǚ66!.'Sk9EE&ufr('Y4K|+lHYjq@0p Xk8̊zTFʄw'Z#-;!*)VGqRM|"z=y٭ NJr{O'k+#|xQA a5#P*GQeDF̭BX59nM92KcQH[eqYv#Zm$Vw{* ӎؤ;FJ$*6@T 2J28*M fΊ7P@:KBK~5\jNS~ebtƗvḙjp, eEvZ/Ų('Lxs쫓i;nYVKsyS\b͝uhU#nd\Fr^%ϽjΡ8oZH_ 4rcSEYfNzAm%ܨ=kFQLeʴ44iB K\id!J~@mV<[|DYQkҕаj8}H\dq%c(5ZȔ@*֬"X+H=$m\ƹ[$mRJ^sd-ޛmY6sJnc)Ù(D&O~E9n+XѤYN+Od^Gt8ǎqQv+vSJDY1-lr:sK꽵5Ż[ۉ[;cjp@ PqT(dVZv&p*tY @}r3ri(cS﵌@MnSmcS:zT>" ǵVҮDI*OL6qY?Ң5((?zF燮_&KUzVzqO3(NOYk3*vLV  8+m@9Uz[6rR}$hot8'Uf'_+CZ}1 1KaHpHs\4*, @ zd 5,zDQ0I<#Rn:h8M4bBzsK#m Ϟ>X'Y1L$x[gvM^8adnlu?Qկf/EtLH+ֳH–d^8vɽn>mj'vmD9pG\T..f\p)8ܷRV״ԍedu-K9&Xr a6ZB{f("FRks4QW77gLHiY?j7+ :,iOښ?7-}3闭A#p-V[ FCt ;5*^K^1# CoyۮbPw6⣶u\CA:cP'4A#}VI"!'gCj o&;ˋHU;uq۲|waP> Hva9rԛ7dB;j|dڄ&:]jIe{`f`H~ lgv+˕I*C̳\KLGo,hX0E~Ke㑚V+CUqԷZeqq!3ƺk,1ǁZjcktݹ Yri ng`GVrǎĵz 򂇰\ΫKpUyRzJNV<#iNÜv27NqLմ[(#/'ɮom>E/esIt7 QlVwVK¶\w7K(Dj)E8߉]$" `uDڝQ\_*1#7VKEt<nj}aH ^ӯiQ -N[ɤL%&H=kzxJOcxy2zfqǭvvLJ:qNҴ-,އvE[c\>b ڱM$QjڼXF13.g֬^Y٪D;tKuē9~N ko~#Ƒzcy oR4uF}>l>-ַّ yW1[V=5F"3Uh&#֩K@o4PZ{gEF5ϴ;5HnM1͉e6?/}f_E1wgV!rιdgB*.e8y*Hz(=4k@*̈93_Q[_$տhz^ky`[FTq=>lNx%ϋ!M?d3;ku3x?~dCׂX8ytrc'wHUjQO1:ԵZ|H!.7O1L's"/C3. 1eJ] 摳=Pdy75.KT+3[mp$W?܂k]F6/[Ɲ⅚0.R6=j:tF^Siz4yV:K)%{N;g;/m\"ZA53Cs6_iJFfRn2ќȸ%$ N=pksA/bѻ9 ֻ]SÖCX#B%EEo jVwMlwF֮=Az|?!n `Ҽur$uuKrd< Tezo4W(\xȁI#qu~Tgl^}E_}suq7亓XTG5xR;<10Ggnf5G)Un9sTg,jo& I]4)^\nǚ[,:?Jw8NC,N{9$=iv, +Ia%ﲣ_Ȳ [zu(l{U XI:b("=j-fuؒ+)vGuz7-(hSb*У#qԊ 6ot-h;dKm"; E46}JTwCD5k=EwY؍3Xi*Vg/гtiick+Qas S#V zU4@Xlߚӯћ6tJAKU\dSh:qWKy3e@Mq #OukB$jl[[=6^sn'I8dj> ˑbWkИz^xezסi# 6& 3Y #ة_| ַ|I(7QF954Zvl5[Ga_~ ݠ_:

R'iX_񦩤jV"h7!'_uƑZ>ѕ0ʸ)ԍ[I9US+)aSW&,^6:8]-IVL0@$T5^* +iE&2k"8c11WԵ7Ui鵸,ėrٕ1O Uo<z5gL­:kZv<}.DJdv;XgHl7\90%(P[:&VD8i^["5P 6lcv'{+i1ԁ nF .rco*u A8TQm;LB8Lwp+64?*HBzW( '"v ,niٖPL65:ךxF8[~+J5rGA[GeV>aּs欱189 jcK^IljzjA_^Yn|;P2zUje_,ֽ+eKvoެ5y}/g50JnqdaMVlaH-/A^\*9NhTޛdc8mkD|c5y(T iWT:Onc!kJ5[?$x؀cbM)ٷ8"z +9'JU8S4N@E?`NܦʒpNjjWZlzf5i"$rvK1J#$894.΀riv1 qۊɻ=Je ɜwHW=:fmmCX4# ZJYG=j$DەjDًM22.~lG_,pj2w #(z-٧ 9:t"4 ӕ*nEaM`͐x訕I9FHs}K ЎS<Fy/&w3UMDd N1i%}ȖiwA52.bP Jl+C5Kyc2#= Bw5?JNsvpyϵ+z GZIN"# 24pRV;@I?,rMOrG5֤d*z:y¨ 3vSԚ81rcdZE#8!!`qR1sQ2ffJ[ w7'S-€H>g,w\qU7sL Wf;j>`Z\{@eRbf J TZ.YmRX`UJ%ٌu#G`Sa\O'q Wur#n[{H|G* >%J.e1-)>`c0r+:]6SkċnJa'ҼZE2mMg(G QĞ |8na1Prq1bF3zBD*7nqI;1!It*y2jLp is&BiQI-h*c5+ 7OJ|ؓz=[Jbi"\jRϼ$E{pLIráklܸ=Gt}嵵.jĂN:)@w#aF5n̓ <{$M[f ;hX<GNj7 ʥF`㨪tdriXmY )P eiUW,B MiĻ %3Z~`܃U2O8NK9P{E69Y#J#N0q\pƫ\ X@uX]\Bji̙6џt vR0cKE,K#Ȁ; ӳ`pA}kvլ.YhRx73\m в9\W]lV[)%:!T BFQzm嘲H7` u4qܞp;ֿV=X6VխKq>S+X=pAUcnrSK JL^)PY>r\\\HGu#mTw-f5{Q{Y4%}%.7}驦K!qڱ**UTk_ٙ0%'=M2)rG2EF@&ⱄ6g*8/"#OAbZZC؉u`OOjUzJ*^% $ϒ0pjWn}k5*{K XcҰۉӇoMx<ȅ֍Vj5ov ⼖u:Dly@Wt8 @p$pqҧinwA\0*3zq=sϳiv9QТ=N޵2e,::ܚ|%Z{Fʍ܆{vz#PXmj:X=kOMfxVuQ; %ڭ-ñӿjȻԣ퇜ƥw*r*&gE$Ƅ$#RPEԭ%_=?!Q#Ī~ccFYSMA(]';Bv/;өEzبWR`U|K}VզE漯[."xG8=Etӣ jOYRҳ Ap9W[)ʳkRPn瞽EEwkm]r;=V&2CqU/ʓ&;jimy$'ǝ=v2V1$C1$zb4I,:GIf<ޔ 'vOJ.F>%mUq56.{W5-}kCLP|GPY-b%mP"P}?%dpj%fiFwc|SGlp@[z]^TܿC[ZI,¯.`1yNG5qzTq.%xVvּV;ɩTPg֬Sڬ vYhtMʪ\95̩4xqMkS)% #Ўkz]n&STU 8]hTj UUdns%=0qXwr$YW0O~GLӖ!F(Q ;U~Tg u eH@['<,笍bc4xZ.\q]0yg{@{RUbxu!շЭ2JQȱ֋XRM-0z֭1UhR#Ƚ"JNߗ5>sY3\$kc޳5aؑ"K֧JD+̀Ҩjzy.}{ bFsu< QG3]KLӿ^{'ݠݘYYy*"oZOK<1H,z#ZſqijX% ~)8dC3VC.V&#[sJdP ;֍~k+ X x普8B)~y+(ba]\<̛G\^Hv'#i"ՈPA޼J 2Qo5dkZ60nZޝ*єBz^I~b'5;]f0g@>fJk"ԑ@VKY;%id'tF eJfηyˈ+Mxjl{(*7)i4| ]^V9vDG'lSi?"ikN;O&,;`}jdTO*}roX(2\3*z48 w8Fؤ*FkRJ 8*7>}ɉ]j)4+x%FzV y\o[³)Z7ͫ99VBh!H;MZTWtn6q93JT3Hi$ rЎ$8+e\*8Cp[uK6^0dF#J3G9,y{1[Ly_6б[O H8hEi7+hb Fwtת  t[UޮTs}(UF9az/NYDdQnqMޥgt n+Go*dI4-`$>:UHodAɬ 9fv ѥHkN1\^I-wts>֬я9Aσ`> | ,M)PP@J\)¢QW6Ÿf92 lr9z<|[umXOv+ h՝=lB-ޕy$3L`)eVR5iZR,W&CmR-U3ɬx R8aKt? sHKۜ\Uq۔-;(&bkjɒ;2{Pf\gSHvFNmwsU/:LzcFfX_k."XJR58kFm]薦O_Ƴ.[T$. ==ξY\M[\vsO]WWVeC(ɩah3@g]=֭Vm$4E6vJ҈tӊǾ1#Kn dwRZy1 ׊ba& r8$܁##+s cT,8Ra+{#AO1ZEi23bݕUԭs[ͷk_U/ nXƪɥT{T6ۨ،xYn]'$OW(<z>^@28adzfڙ~],p"B8ҶtXqwB8Q~\\|Ao SYѢNmŐ7Ec,9mSVGeK/@A5~8u'C,T &v ZNRL6SԵ^H?5w&w) =r?V nnHc$hpK+EBK98zddUfԓMzO|mz\/$V'7{ "JN1cpu^v(WHx{dפZmJJ6.){*ii| [CtzvIt,xag܌|m.%i1=kӅJn)|RE9'yƟ"$=8Z77@XYڷn" *rrsQiSiZ2 z)2yV-66Sck#*%sG݋1Ռf^1ֺ}/]?A!V5,q|;HU11h>XY:;%]G"{6r2o)>V$@]}˜S}dg:N)K#+b}kJc6' :Tfuچ8@LkFqʐܠXh5Ž7\!3*-| , (5-;7B!U(̦f֕3ĖP0ZBrE`%Ƴ!#?;U멥+Ia^S uD3+ICP tZf_1Z0?G魎6Wwc98Vn%N><}.qr"_ƥM"y$+Ԭָ7R eLpue4an_|Ĵnde$[bsY/.p[HO8MZC=zս.r/thCIp1Bp'rUYXAmmoR*7e#ҵ4}1&&fVHd `⫖ 2(&AmiPǪb뚜.-d[kk&h0x-Jg^Kn@F)xj OA4;(Ƭ:#v qɨ[4fnrFib`Ij1_#m0ȧӆ/b~IY&j䰝&o$&2+˽R !jݪ+ʰBkf lI56 e*zJMMd|](x21dw9 "91[ƌRfr\چeu0؜Cq ^F9ҐZ]@dySzJQ3[*:ꌥ^OH; 7f0glA*Hn.{̦0d|Ň&jܗ9?`rK(͉㗠޿ʭFt T[65zJr,$F21\xF~POU"!UFz۳B':^$>swfM20wpH<([#ԚkO%X.A>xE81jTVQ<}r$6X{+㍈8Z c&u\S )(ů ]v;r舧%4Ԟzu08/& Yf25YgL0yS<.ǞFj"5aɥi%s1P0KdTALw,:HHg9Ob6c&GEIh rH{Ѓ$w $LTWSb$_(?NUV9^iZ4뚩|oZ[K/d6c@a e tis>+ciȐ)&s%}X]ۊ㓊U.94c3:jHg,2=*mr$wA9q=2 S.2p?,I1kHRed]b\}f T|9`WR,2s⛉gr6BqV ţrqe+`Ww%=i&+Kqي 1ʒs֢qJ OJm -А8GxnPH#h#N̘ݒ:Rm,}IbX,ZrX"~dnk&ye GZJrU$SA$\`jnQҤShp!LrIKnA#6A X sVXH˟JrfFܒ %m bǒL2fP09ͧhX{V#wQ6p#7%>#rǭN`wcZ-L-p.s3]<_t> tQ֮&:(VusNmZSfwI)Unjm.ӆ7Ŕ7 MMg97VY!a=N`Hb?*m T`Mj([0al<7"5YfXnN^ e;tU9=)bB{Tv)[yUʄg+Kpr{tVy%yR}(uOG+A$gzu$+1kl4d3%y+{[ 0r;ՔS]]xlhf&@k*J w>=m,Fʾf{d<3֪r܉E;$z #WWɪYJ2[3'.é䞜U\p=9`SZYA v{+/Lc׺|'\n$"862)rW~ ѮBҹ1kKnuB/=~זWPʟ#w*Cv|Ftմ_JvhcJ|i+ |J3喌kix+.<g{_yҬhV`q޲y˽Gz2RQ{]na LI!0zײ:Uoζ糈0ČO`*[M01WNV2濸A2 \qՊzn?G^Oz,[T$\j[PZQ<0 lt9$)WG(caT:[%HNN]1=Un`(_jjڐIKj+K{7\ 5YjeO'jvH>:%+>5à ozcJצ+)3S쭋4\]4:vESךgppU|{ZMac:՛+!IjX$֤{d.)bhmH/;@YCjH-~4'a@ D>!ùF? r¥r@sM'IR[\pOC611$/ { TNWF:MTRsJvgQisevEjP+#Z흞0@=OL; &=wb{rM#^a 3N*p7o3>p~KF $0=kO C?42~Vo3acLz 1n=k2_-\P<ČKu=j\TVl8$&N^՜դņueG9#EzImP0+}OIfU.HMsv3N͈Hoaz좴qoH#s\V19ROQۘ37\ rr@t\I/N8LO2CکW{4_K?)Njѷyd8xyaFWI ƻA:/Kj:IԖo' pQ޹s%;)%u: i6+*q2 ֥yr!I-/XHCVgLîJ+CXywoRNnF;\u'5*ІcfVF BW\.UuևLM6c-U.207].K!,,2+1/SFI?:FM#5]bU{vмm<~op.3U͠ B1޷eZ)MFrz}ɬhqlu3ĉ|KG>jEq_n3!u`Vx<:YWmpLKm6xָE?+?&TG@) `^ ʬv<ʹsqRn{~^ eخ W%O TV2XYJRr+Ӈ=Oz?s{'QǏ[1#˹,,x;z7O?US,+Zu!?cPoAm%U\ԎkNWLF\Wo{kdoHU]ŏMJ<QZ >>&vAnhen5%Aa+=DJ[|CQ|Fbhqr9cp*9l49V!K#I ?w`3$[7JON?QRBW&5 \ 56 R]=NqTplg4kY˟5wJ״+UVcWn!KKi)5jOۂ~URCjqI#cM'XT6{v#çIj*1ӷJvcr'9R1 aZb6h+KdoE2kin0VāJ# t[3!c澛3j;&~F@n8sTeQj|os9DKhWw@`y5$KEMZwѕP9:f&Hu dלx_tBNA5i.oF2b"t*7Uwլ1܏jA&CZOGrS]I[i[SզR2 hFU푝j|^VFB+o|*.`o/\VM5i+]U褙ݦ^GΗW$H⼏UVebAiC2X8 pMx tw;iS$OSdI6ه#qF`*ž@H\;6s9r;Gҵ}ĊQO[#@zT(8Ң20TD%y03nlnim V"dQ֞ĀKd5*i~aɤq$ R.HG68$J݇{ [Im =k:|Op0`~ށܒ/1x)99xZٚt6G ˋ*BwNQ+)p}:fBJ*H9ⴭbHp@qrv"1VBSRyd ؤZ:Jldt S00yUWУdc`O;wӭhO<(AYOcS"0R\e[=Z8ip~R2kt'U84ҿ7T8\І[rF`A8#n۱zhKnUYrj6ÁO-|d;VOQN6̡$?VrpyIO˺sSܫ婝lD Sz.r 7g5RZ!39Vʻ(8G4˩Xs&Dءm+}=]N)k8r+F Zu=+01ZKK4i Z+LW  ֡o)~PqfmyժkQ6'coR0sڨN%:)zlY sަNIh&Pw;7O*dUTr Up/zjJX[xnX1|WcUF*[׌Pt)d`F3[cX4\ƮN g'F %P\#i4j2A1ڈ- jW7\z}*U1}ءa'mJӜSF3+R&;f'-n#1ƨ]amN 80IY4[n#rT eҠA^FzOpPtW?)PMM8(:Saz"mwʧ^0!ILU u<.0{jيw dVl8y\=OzV0U*TӵVE>r\8b iD|㡮N:W,QՇ8{1e Ixk 8W`t%Q4P3zwZ R|WpBZٰ۹NxVMM+ƴ[NOhy%TC r4; Kº /K0"z̲eT+W7Ta3^lzpӆ궀}JXI]-ҹ5Eۓ"HlT`6OcY*KVk"O's4 }^#%-si6#1:0\./ (ʛfc$+:'u^ɬxT#,dGn#5Bl˪N)("Xg[iA )<?>-2ڟ 5ҜݹDIIYCt]եѮ8NCSE$+WL(rUͱo7k[M 7pPf<ڽzS?L^+1awr 'ռ<:0X=O0YI<'hؽ 6}Ԭ|7™xX>yv}+ȴ\2sVK(7.U4mlspZo;fV[SZwZ]x~zNNrdiI>RY:tDZeأ,zjO-z;H`9=@i\63Wailm[P#@NsWZ3Ni=A8Dƙ@ XLrOSTLm=.$E@*=L&6[HlpǭVDLWYb @6Q[m`Þa+{<[ٕ5<Gv3e+>˚ϖpnr:;Gd}MqẑksW|b;ۏZ+ŏ+08eؚ̙Sx^n_+WLK@+5oL?>Ke*2zPMrKM$ilTdRWxdNKq*Ju6S՝ @~Z1Jı LAO5xRxH8^Ii[dl'(ٞ^&%KhXd}~j!+-Tϛ#^XʆU﹗_}Y&@j͌η;cXr|r;TIkW0D@6#cxIHL BG& b\cjw%9c5fOGGKo%F7Ta⢸IP2@뚧uN^WE.~-"~Ӟ{u=dtjI~Fz20FdͽFg,1\uG$i㚳e4yq˿~hiͬbwVpɼڵ,݂2Eyj/,6g9pj% gfJIh:* xmb$gӊżծF`zc<ewFN).!r 0>k:Qo+IړGGڲH2skoCu6A+I ZE"mHRH^b08T׌yt OS| 3,s)|"?h>iX&k kM{w#^xDK@0|#ӪJV],=z<"5?4HQ ٳֽVuuԿLbk}֗yMǽvJߙWZ?v^Z] 3*ҖQԊ_^݌a#}EAռ:N22k|{ਿ cpFLң*yS`:92bē# ݱ|=.'36 a 뎵vy1+}=kh)^>GF 7V<qm%c<JܔKoXzt1Ĭ󶽌5m*UoSH*:{[LF n#oR5sm_?r*-'(:v(˗sÖNoct[u׊5dCmlT1͎=YRۭSMJ\VH5ԁx-B;p\ypB'8?2;ca8N^]T"]A[N2rz8 w5rHvRv^}l#f0YmL{f1F־k׮=LZZV#3H9%Sr滹S7V>t/|?umi_[c*fV#c"4yS'=zZSM#͖e;{ؿh-.Pr1`WazddRHv\p3Zu[Gukwlzt $Yg-aFx1]1yqʟ,ڊ4>QK̝pt> [C46$q]۠T㡣X=4v8E:}:ЍV<-j[-,gP85Nzc+,ycdI>pW:t T!34?ݣr3k0ڄKU ]5_Ɲ~lتN۞cR3J1&9r99ImBSS"hOB/g.t5 upADU(3j6:63]>qjA` ՝N]*XV9# \_$zl(JW3a6KZ:6WeFPvvW~TЙ-I]Jú-mw߅cᔜ݆䁇;W&-)mzѬWs[w_Dlz1kA<wa]B$Ԅ-ԅ OoΊՌp]cyߎԬdw-*~xcDUmFE kX_hv>I4sV圯M;uX5hkw(yB;͖2yu)iMk"`(}JM#Zxc`|ىn=j'vmg۸p=K`hVSZ5^rVǞ0 `S]Lcs֣N3Zl.ah1mY{Vޡ[Nj1{u9#$zҵˋږRn:֣$|ca<1PҥRTrj.t#C]w**|eB}*[2 ~\r\Է*NNs?Bzz.f;NWaM"c~6\ކԊE%t ++.gsڅgrE$F@a 2?J^X<`z6,Ұ١hU 8$Cg9vlE4 dsWPl63^mn#銋 T8Zʖqګշdy?Bۜ W8E0mqHoR@Cu-hXHgsYLz=+@Hd攵MX;Jg|U80u{g C)jqp)vڠgFˍG绲Y:ƚI>ϗL r4d(V,R,vUy^kzrvrD*xH5 w1YdzkRpμgޜ۱(kpEW@ l9 k6e}\nQԛa+[ U~LoҺcɺf'*qQ#7HJy98.4QK '{@9Ns՛y8ᇒF8>oAi&P[ <`vkrdbZJ}ݧwc}͊fXIq/a~g_VK;efk$2=s^!q$ +*>Yf p:ם<\r.T}xpMjׯ֬Z*x[dߔ b͕g%2G.x[6$1[3Mq9[e^\Gc@aԜpjfF%fq,a$=ח*GZɻi B|\,C8si _;fSs֛M+$ZQhКvUv2j rtw&[r: j/X{i-65J;KC(ޭ}_ yHuA!Kg=j}Iz Z$R YbqS\9 9Fj2Q~q+lzzo=aX#/#r{u'+1FZnXZ 4Znˏ$JDlW-@3!S6Us08&>CHPz+0st99nxr8]\kygʡGX+^ozŶn2k-|֒ХYpWoNy?Phؐų]ƹc]ž{'%L8k2IXxH1ts47 k>xxR4kʮ12>+[[\h{ǹ'KD}VhiqҗaFY%6.P$q[ߤdqBOC*fyO/DNuKK;W3,N#+g^k[kȪkiRxhJC4+$y = fȧz=ÀQ}Zg}Z)ImNV܉#t+vE:涐DcB))`8Ec*l{o:lZAbx5M]R}@{0N2McRұJ6NIhbB5Z%HA1Z~[z{xxBO]¼ɺO->Um; 9G:ll4+V& +_WY6V*U1CTSytaye.]Q-Ăsgi[of9;O|H@ x=k0UfyiR{2g%Nw^-ݸ)fp^7HY'XmzǎeYXuxύ>tK^ W$uᱞѫǛVJ}rīaXcIɦ难vdfd;Pxwr`prN3xVЕThR*00R:Bu:#Wg}3]}dKsdp0=CIhv+{w \w<ꯅTivab#MZ3ޯ|Ge}qC|7]a5͜p9gDռzW/j*QRʃV4]l}ⅰԭG$[IqV&FGg7j 7q+Mj+T|3lⷹ8G'(hw#䔪]xbƸu+׌$j+P85 UD쥡j^)d!۠5V2L1S>uޡc{iʒyXO/qhn䮏c[>KXBմ}Q~mkFleGf9zŚEŦەI 8Vqzթei.wo?]ֽf5Q7nz T,%XqM )OJڹMZs Y>cҞ>&)ca/jMhc$ʦ!5;=_E1XHrGsy'KHIloaũ$ 6p)5_| b蚔 z?"kUilt젞[6u͜qp1fJܧDqu~̿Qk:[Eyǘ0q\+,Msjp Wsm b,95Yuj8,cТ3jMޕ'I49$͟Qɼ#gZPvy62pOZpivz牬WQƩX7t ]͐x5wwDw=&n, 'kHԫ#9ѣ}O{l͛?@+,)8i\88ow fw$V$Mi \>{c 7mn9u >64 '=kA]CC1"泺9U+$kR1UX۟'S֘ z3jդ̔VsFA @= @" %W*8{laE `ÔǁtFӟΚЖؕ',(sRPuRk g<\Q=jEg*2qKpr%eS<11&JK"02uLwCA5,Z6F:qP<޵Q4}(q*4]cqUm1Ҧe'h0xrwBXlS_<ԻNHE2AC rzS6H$O5HGj`x+5Onp0<O ; R8yT"GZ=e*y*^IMlcIARCv`z"bRz c3֠pZ t͹.*b1\iYFdUA2ITCRZ˜+Fܧ6Gnj֢@29lTIo#j^j֨{BOp?SDa1QrSQʭdKMOZ u#;p*&:Bc\:ֆKU:ƴAbJڦνA9SC3]G\,kd VbGlӰ8˼zֳ0V'<dz؎ N!@ǜs `:-ڋP^F8I' fI#1TRԙx'Kڡ+{X~̶0s8BaIS6U|SӤ#.Y6rGZoݩ$#K! K[dN1Ǚ$Zs MJ3)9Xdu$ExMX ڙ`})}ػHsYJKstݬނi!\崗ǭtS}jm^qU\~+;3ަӌNxL:j@1=)}ZKXv++ۗQOH43itr /jk;  zЗ.hE^fd2!2{TL|"Flu5f-̛HwV8f_zVia»^6X4@ ݳi*/RMtSH:0P!{T$F<0T4OkkO"J5 ]]M jŧiTA]u?*uEAPzWԥUtR4PBXZ415mqGjK$289\x1N6&zFEwPCPA=4-~&TGU蚕ίG$7ztIϩOI=9ek#Vga^oL ~xsHP0+ :#NfFOodIqI.%ӼO}o$9'7CÚ:-BL(Utn@% ]NW|qJ%222#5/"@c1Sѝ=V?oa&=JPX(1]O i$6vrbE.q V1Q_d.vEk\ɂv֬3E}j/ '2\;]<$Z=*ƪ{g}y8;zգ{Xk7-1oqV>[I@^*3Z= )\P\% g~4@}XsSr\Ź[DXoq^8e9fSZ6"zTƬ WPSEs+3*8ɀ}$XD뷚tiU[$21[Gl䃬æ)}f63Xw{X4wE (2(߅C,sk}k'Z Ai= otءngZ Ym,̬rO'pXܡgAg(E1-ʉ@Ԍֽ1-n*эA5sK RXeR2oZta'i1J (qՖ-r:gkouKl㚫:"x&7E{NnAA5>C$] ď$`T(R,ץJkNcΜ'Qc @c{TE Q  IB$8]n#M%[ d`F ˒3Q:W-j՝zuӒZBcsySG^q\s-[ԚZm.[M#͗'~u1sɬH'ӗb*Ю6w =[SIr%̠6i^tNnw6k'(Z2Or&;؂EVOQ{Y-h>_1>h`"P[Cm9s޵4y%|wH(BoV*̕"QWJR`c^o}m>cr+gSw\kбeJmEk`xM`n٭}33NsxN>κ,qKf_,RG.n.nY=)9dkGj0Y.d%Fj]4x"L ocrbmXԶ*1q4Q2Q:WFjqn11f;PXܟ(:55C?4ܠȶGc+hv!-Ipaj[wey4U(O9jIhzSn69&1Z+cj+q)⥚5]0ƴ[$].˳0J--Qj&7 YgJ&lZ!}GOq]gw╬DVZ.*ɼxK$xR;'{)W#s6GNjG^ffi+:H1 HQ)G ?- ;{U&א9V+Ư$J5;9>AW7ymw^^'ޡĚ:qu-wkc;i#YћeKx%'aj>b:2RxUjDkVI6zQUw`+:Z;Ogy;T as=6+ukPc};֌Z̩|> *vXfuuIs"8--rMHtKiЪڢ?:❙խsmud2=8>"@+–bC#[pMf:k>,,5Zd[[ci _dj+*M2Ys,Ab2zʂqO.dziXg=mPomoYTW5#l )8IB>S;e#Gs3>F}qV-{e-4B\fP} K%(6M[QbWr:+N(GS[߂FR:\崫0@)JLI ¼6M_MYEZFy֭M14{vX7Z5mǜf=#Phʌub&JGMǒBImy$x : ^XySt~&kXT2y9 M])Òn䳼+3ls^KE.6ΐrǚ?/jQy]zҬЪH_ƻpè)Y<:ĩ81$o\f#m Ì],jGh]c"u }|Nr;]*%7LF?Is]qY<0ͬ[>>FZ}!ᑌt8Hiz#`M%I沓ķDZJ.D?$qm@3M_A$xa]x&!B;T#VvOQ*}Mk|\P$)b{R!2Ebj^$7$ec>^A/դk9.xݻZ=3'QkG3uG"wssv) %cPƼT9dv'ЌֶobH.25gt7Ux܉㠣IRQ y:Ww[i ' x@nI~;FQ,?;@Fqާ|p*7w&{.<8kLNent4 ;Jr D`kVVP:xaT?WbV7S(;@Yn,=MyώmX:T6$O?1M'5t%=[@Xۯj!-{x=={tٺHf;R Ywcg9Zkڱ2\س.%D'.sc떨\/Gxyø7ǩ OU3kE\ґYl #j M&# X*GZ@sNNthQmN5-岃j\E "]-@ T*6RFmJ*bJh-h$k-Ka$[d p9RTwCʮmG{w[5)xb(mZU Gx w~fQX 'do d+4sާsq<@Ī8~yeZI8냅xm~aXz7 AY7jqNȆP7\HVMr3V{%aOMɁZ+SMlrGА HH9G0axnvͳZ2fcp:=Wխ/zf3~ym XuHd};OJsIr1{7AΣj$R{:_y%k{81sW;N WR%_ 7\DR9`JZ]?ޤUhOg[iV=z^i@`>5xEү-ow+S[tbk[Shqv='ize7^ R:)ຜbC=I2c'[& xOzrR}&dIޓi\f+v7T\W=& m+6jjגmĜs4o*+5+5-+Ҽ!wX]Gakaix'*WMgTC$7>Q9OZ_ۖͫE$9Gz<=z\Y =+'e+F4:jKlyuGPF1޹ Vcw,0Gc^;qʗt h_Aݤ#Nw8Ian.M>䷵ya+}K>d6qN2' _mP +Or;]u%-Rmw`loohƫ0M(-f~S?:ʋ\(/=6vz> #he:S^֩%5_55φ>o3r1T|AIxA0`YqȭƜfKHg !2W{^"-#D׵yZHё-q^#F2-D:֑I+ogB_3^-Y|=}F>t#+: %7$xRkUkgЃ WTp2ky86:(Nw_xv{T%=Ûi3X09\5WWET$lO;3W<M6JVUχ-e<+9; ux7Zllp q:"ʌj’N69>OYK$1lbv`Ʊx'5WRį g862N[G5V0Zb<D&y@89 E"6iQtGcFt$>J᱔i 6y^jyݤ`$*s;ʵ9$M$ӣ Sm#UĐӕےrzT{ҺR:gf额8ANiR`8Jj;kJH灊AQJ:dQHeA)Il7k\dV;3PܣFv+e/U[dq B9O]JIdt:UR0wd8:U=6+ \OYMj:%n ֚b-ܭ95MGqO VEcQ KRzjNr\sS,LnnJvKRz _wQT6A֫Ĺ8?wcJ8-]s+:]iv% 1UmM;;Hp:}jrLc{WUn&U 4銖V]Z#l[la~Sz7`T>"6'AOM1RWwXlxǥ==>: (,( 8TРrrFE9$a JBޛN‚#JB1Np0$u"xf+XP`Mp1= nUW ܜxfr`PR۶=jgѐ<35nin$*3W'e{72 ierND2] jVuVŰe= O"Kss*;Vχ4q8洯A&Yxڥ y,\c7{Zr*n5kP#ɓ$ A@%+g-OYX= D!% [@,n#9y)w"1jԾ(. ?]2BQjέqt?]b& d+d9%噌'8c Rں<ԩ'_R@"aYqJ֪z A-7/3k3gi׺%dcY.tn5ı]ݾ7$xV9渨moY26{Lcq֡jΊ(е#$ɜtc]hDwqk# >գl2nw)9n<=/YD;{EdX$I"8{74&dPnS=Xyg4^᭣iv-|FEnpBՍcenKgQ7<[s# .J_WiFW=& "@R^JJ9%ѵUܤfVΪШ2J۾0ue/yq1Kݑ,[XGYÅٜ Mz-{^27)8`ףKkS̫ZSfޣA"DFMC0qm͎@U;;9\fiY涴;x]JER֥䑣_.Bp搟sQm)1ֶbe O^:WΊ%bo6"Tnra\uehNQqYJR&ܫT+7Dn%H{ ӵLmv9V;lR _*F֥HWVǫ:{x29a䀐bynD"҅-i&h/dTsK>ߓz7J[(Ȭ}sN4kȆ~4 I[*6:U??_u7NӛD=e_LUOz44e5ɧc#t.8M#z ܌ 眛'onf4 0$m);׭\H0 Ou9'9ҾCU]ij6JD<!k}XWDjAt9J8KtPjUuɀ lOj#h#j[0=+WZ=̽ \ǹɔE֠#'$t6+",N( 5e0NZϽ"Zk}?Pq`*fwB8PC2zjh#b䓚oܶrOrfcYW:F+9b/=&N $Vƭ%׏Gy}4,3ޮ%#fIߙҨ+saszXxWP> >]9nX2[01qc9EKVz}O'XU-沓ZpQGZrеß?^׻M|qÞsK;ϒFOi!`Lqk{`l F8Gj& aTbZS״^;)ǑMWOR1#Q1ּbi&X$hWPWNWGOᤛBǑqY.rCCXf Q+%p)Z囻m !gI5b=)b\28m|XzWEdF_Ke^-լ1dzE֧qNY ]G8IXnR6ϊ-$@<+/[vjw,&8癆1Mpԣ*ÑN #gljz|"g\o Op6Hm?'4:WGrkNuy}a:4ӵ*֭!#bj:4c>IF/Xο?(u d+KG<%ϘAwM@y\jxGHbS(nb%ee5D;8\Pwt)xHvWKe6SȮ{Wq.g (qkXHIv.&pMV}bo #4d%xt1X)EW8vq[eGtQeOS )Rv9o f<+o[l 0psr=%ͼdXHjOsL)TǚWVկ|'[{or:5Kh`T?0~v ݥ )Yށ^,V:WWiq: MzUI`p:R1u=00ءwTֶMzEC?*7Xaw [[ 9@y5]62OV#R\,R5˷@1ma|%$znP6 ^Xp7g<ȎўYyx9ɘ_li:Fn.H (mbD`Sh*#5RTh3kte֞K;23o\bPuvyPVVkpM;љc}($a,o0WWj*`u'E@IU-u5[&>Q\Sߐ֖c9J_7IV2rnVeeUITڅx9'۞V!T8$mEp^{gG8_XoE?ٮ֨)C^|;0 RCsYMno&jlڳintRǸu\Eǀ3) ǿJ- ш'4骗ѦEOe}SGst][ѧmpgXI_Njݗ/eܗ =k*%NocNkIӴ NI˘mZ=7ҹQmمL'r 8I}tz\HK[4P(^Gq%,z'q]41s6.J>5-.8皒\Ąg5a?/]3+rխKmxٺ7wL#uk;zڗ1`+4h\)'7`j2攱sbU"V+ux}z0=je{+3UˣpK6|zťa'VC-Һm"^°x./Sy5-5k6IṖ+' _S֊|3_jgQ)pkqWi Qi<|i{)F8ʐ֊S}D{O.4.RLZ԰n!iRL 3ǷL qUOVL\4xµ8RQVQ*h頸͘ +< 1,ӓK\kw~bkU,2w2k*8'N&{qHkvƕ53f3xrĽ NI%\(b8&21 Ɩˈ݁O;Ս/Jw_3$֭6YP I kgY[ˎU- {3-6rJ:f b)Xץw&8==v^+[H5vv{,sZXuA#Ed EuDk䌜^*SjW_C' #ѵ цk6Z9o"smF&>m2y"?,O^d\oH]kъռF,{]HAdZ>pv .#xoTee (^LxZ0 *&WI+D+?5sӼ+Z+K+3?*ҖKiaQQ1-uQFUhuK[b*tneMݩ[[[[ hzkxMX^x5x_td WtT3u)ɫ[9ҏuv/jxVIH#zY/lnοz<73t#zÚA֔}B{]X6ɭA  gu$RysbL fOtxكV yZB1m96IFJPVCM33L)u o ^~^+"V-( 'xnu {W:ësE22i{jӈD3#]r)2k43E$ggkh5<՝,3ѼZTEH `w/Mq#JcqWEھϛy.AqjL`S5Nь*s.j-/ifY$l|^ x0+֧ݾ'V=3UИ i4+F!RҖY e7@;WGʄf'<#4L9ⵍnz LX0ۈ zcV2rY4QĜS]4Փ9s,%Su4 l#Z:Ɐf*^}ұk܅OZXѫ;vM`a eݏLsXvr3\qpq]QUiMrVC8gk3c>؍e2+Ҳ.%@ OM M6GnUq ylS׸#n$Bd gSS+ RݓS28p"|^(6NF{fcj ' '>:H椉 Ƣ\: eЎݩ!4řJ#$&#n2j6)Či<~VGfLPr=ؖ,TE7);3 Р眊Jn@gm3jSNw9OɦD6֝qTNsUh@ rʤ㱪jNKdQ W<(;jq2,#j41n,Rd;avr1ڕrGniҪI)`Xw}iSbm95fLFX c$ c֣Qc&]OBRP\8 m5>/ "8WخUm”Q%@ZHmse/@,jv8nS}@>u|xjoZ,`*G@=*խb]v"h#9tOWTbh?ZPNwة{`)8zS6\)Cv JFhSm sY+29~9$eiL#*Fy\;TcV#Kb 2'ʑ{Ձ!\EMDIa~LbF&Sqz-%.5F!6G98攤Tm2dCHPI]qZH;scNia->\Օvҫ#=sR'Uԏ.K [awOrhȕOE]jdX~A=iɢqlm?u܎Ů`g'#e.[8`**ݼlwPKYYEj8lS;,k.Z&+c8{4T%U 79VؐL {}NTR ?MƝ-.WH\z/6p2R+bX@5n8kXTIlfw&J$F8ukϩj^ v'zR4G#S+rV; /8ZW0@V-[5f]u"\vǩ5rUW+5(ݍwMvGcֳuU~,X8v–EYsW_؅ L cVTJȃJkGzׂ7u4k+%yU Jc F1VR]&5.>v\Y1zvR8k1UR{f6JE.\&Esz$ygJfU֐v_ԥ0d vtǞr}+ίJVb;UiHJA!Hs}-4(ެ{k6F# גxV}MK/ .I82q"9560!rI=k VP#\D#FP;*#4N5O4>rO/sJҴeL'Y9(2эPϞ§ :v5$y< C$?6Oҡ2ї N:s^1O]G"٢&3lE(V4e{X)p_|E2v8bx"QWF0=14s?X6 Hdk ;'P3QjK{'5q(ytU{(ߘ8@)\U.^.xWh15aʀxYjk ٞS_ƺ#9I=0A"IƥKhո\Кs2G"" 0# + NzBɓtތ 9#p~D w ;H6@ ܚiy6p IGGRZNj& H܅5{ڝ"x[ q|щN9f׷6BG8\Qt7SsRp+ԵHn$-Y;R,{c,+Rwd^Mlfj&+H#]׼xɳ9OHҡ27;dfXDUqc<nZDr8)<-7y{b1xjrzX\uHFGk3"Bh]c9h=9 ?xtFE9m[!]߁x÷˻ rG_[N͒Dp8sM2oc59~o6W2OrڽJV~E#308U<jUu895_mekZMf'& 4Kvy*O=kJRLdԲ&bГ־mMmOԾM9Ѳ=V}oꋨ;&o0 ޱtG+V P(#<֒C~Y-7x5bŞ : i.nn@W3yp.e.Y9]yʶg NsҼcm4;LsuϏ5hf^q\ kL$4QՇ{hK>؟PkҮ"e[dl5:.Uc,Óz<5㩞UWR8WKUOvNdI.H+HRoMIvf+I8?Q /\[\< Y9XI9nʌU,T\#xt2=~4e[A뎟^.-+ocu y49&7~.TlՊG ˉ{y,q DqR@+ /};r6gI.O~ЪBJ:R%(DC!@Un.!f ^wmA 38]n4y'=i1KVmTXI-vQ֪xİ\Jǐ(^VnlX9ZOye\׌UniI`:czO=_s<{Wὖwb%|ycz_R:0QKܽ̍Kk7R'voB=<] i6-ǘqW fh_bǔB&GJ[uK|j@QAlti L@մ9%g|T1)adҮkj*20~i7*ȸc5~ dHƒ֔ b ;Wtm)4Nڕ̀7 1#zwȱETQ0+V9q qԐI 51`C7@I $(`>mQC(*|l6 X9Or\sC)M=;SIdSSrjjY^+'pNHҚb [nq)ȣ9ROҚwu#M:Ͷ92ƭX*R9*'zT~auOzh+Ȍ;$hf(ELYG}[MqڦmO0dŹ cLF \#) 5Dp͸zsQF̹<)ȢRr#nTZC%{ت(mJӮa%%!8KAZRAz)nK`}ipx櫒т }ɵFFAUIC#aa5erڴ}f`օ..2@ jmRBZT2H÷5GUIMr:Jﴜ, 9TݟKkPd3+H]2c;,Kʪ{]5b.ER\1f&D@(α& mϊI5ce87seN8e-t6@]ix5ŤiKƅb# : ;sZ- zTAjq<<s7VHQ"/kFK&*3wmzf [ S5 u\qN.O2[MNP B{g{mH'[R}{Ŷr<ө8JڶDkN@#@kkO唑0acϸopffu8YTBKԛv|?#G#&cY2ѢPN.ۉITU қokɴjLy8i?0 YQue]_tܮ튾1IZ%|89 wG[ yJK7H|=Rv9Q:%<)˞ޕf2Ub[=qWBX=sV cv\Glj8X}"1x`>8orRٕGLTiڊǂ5_$dE1Xw^&!# B;E5uv[ORi8#U[h!nluj̟SW'Ҟ $5ԧM# FtP.U ¬ì3\*N~-Ubў9^-ٹq|cjbPTɷ|a|q ָT}Kːv(c En脵;wTmX\ݽض#!-#ZOrclUXKIlm**TP\̬'T.<}*\39}UM&И=M LyaQѷl:TBkCXae- CõiCp "pքw|޸^ڝ0MvVÑک0/ڬoZ|^,sU#jtUW`XvOYnFOb:Tsgb`WlhF+ }ƃm&H7b@G#]+B7gJV"϶;w n'{V-l,0YLsD׹\ 0Oc\ң}$:V56%ČjZwz1uvq6HK GOX0GJI\;c 1YWsI;ݳ޳$N(A݀i_"qkQ-$`[Š6$qkKM6Z ^dDG=њ?nXo"23]6Qs3׮ UѮXI#3k݁ZZ^Э<`Yӝd(>o,՘-X0Ҷ$c)8E_L f팛Q*ÁQP(bz=(;25yv Zd!A'g9UxŷJmli 0kNMr:'i7qug\n2{y_&.`cZy_ \3. g+ݖ+P#95jhÚѶ.rNr*;wz?;keRmy 03,1,lUx+@G |@T%15sMb3p}1X BnwQ֞A,^[)rn̛˥GS| Ypk:eMI,vb} c}LtF>"YOֵn XV!K,j@W[ mv'=y4X#su"QyfwnVV9B;?n`+dq+h?4dzU=mr{q[q6rc9 1V!!Xi㩦ZZ*)3H\UEK`j72HGbjY#.HW=ƣ+E"jx lԎ)v I']]m]&}V&.JqU&L6fJ;g8PZ$C ZF4;t:ҒhCghdI"'u;mp)M5; C0zjjuu:q\?"`2{vHfv L2^P ڊV9j;YKB<Mv:Ua?/~rwHn3͎}3F7G(}4Ikt:98{/I|cX۸\ ~Xw#f{W.g p+U^0.E̮<Woeo.[<׸x+BK+ s<@1P;b* ^_Ԛg̔~ѯHVvOcֻ[ 5t+ 6jp RdN9ZϲVB[ZjpM`R) vHpCs*#M+8Z茜zў\F yd8V5*ڜ G-o` 1gTc?d2՜ {Î"|>+  62Mmܺ!+u-c`Eg?JF ]ʧ6$xǍ·>슲\~nqű5,NG|U GҺ#ֈ{#Z%on&攸Îp2I&2"\UE$cl8.板; lVY@,ÒⳔRWLԋڲ{ q29XzZF^BN÷ZzvQOZ\B7ydj9V{yE#FmEfӞV% ⸿M&Z(xz6+#cTMHHc0#sT[O"$-mh%w˘\sAӪ8~usԋݩGou"nx!zn^r)qq]pa7ps:Ɨ l+:r$5!-7 xR$~\&/ݴ1Z-R[](Кa-?%"I\*mkvryZ=>7 :L0;fBz'nYYTq_/3 r8?xq4a.5{+.deo3Ѯ5ɠE7`3r~&ִqoqs=A${#Iu|F9 5SN.yu!KF`ԍÞ*<=jNV]h`;+f\E+]Nn/h|ɷUڍ0jdPX:1[V,Q#FXNJܲ4ZMg,K]=O&ZtR7:nRMgOщtֽIѯGڡ!pG9%4&L`W<ɉ9Z/j fH[I/˦?@=+|YRRX⸫?^Ti#eA;}kuQNq4j}yhgȏĒam g6l$9Fr]0XzH%tT.f1pqWQvV庹ÜMsԊ%9ry4Y< )G[Utuƹ>\gA>JC[iK{Yc4wuY7hqi/un.qq ɴ³x>)3`Iqa'U,=#,Q}\ /҅Wl ϟz_dZU;#hw: ă$;k %B}kJ3:"Puy_"vGaijX̑^eͩ|<1]֝ ɑҴR4imkj 0\lF)9ZN1Dg5_F:G^,:WgQW]xgV Ҁ|3ӳ#>[so&ӌm?j(2"'T* YPA͐rjVY&Nw0^sR/kSq6KEKY1UcZҬn#yF0pV\I?g*;:ZF eI\GK}?Qr[piye$7n;WG>9EyNzuSwg~ N( ƻ]7Fi?Sy柢h*\pqҶX%RwsZ:wG<]ZgO(s⶛)[Fz+,-Y,g54sP7ְ÷K9┵OSoJ*5ӒU8#9 tԀ&pU+wJYs_+*==ZJzfxem@OjZۗ8Z r{v.Q֜*"(̒^]xlÑҩKrd A-UahۘMo]|2lgn+՞g|\S6 G^C?h:Ho5縑B)9*;W=ծʅfZRc{N2Mi<ie9RxZo@ȿ6pvs\;>Rr6 mZQM99NӿynN8)) ͙q#^x^QY%s'O ` ¸N/Yٳj*PVy.Vu #K:pA+4A0>xBx\ |qTz|=lZ%m1o|?v=p+.\wFMajO;IJ Mju%9qP0^BH"Q'}snAo/~n^gCsQrM4S+׭ øLlGlYh܄԰%Nj(ks)ԍ_q||?wLEt6kbQ3W[qG5꺢A i+W,_s~QH>pRsXqN sp]bGz}sb=9=ԱFܽeͱ4hHE&آOfM<(=s+N.ґ' ukY3w ҆AAZA䰈l4FS(N3ZIR+sD L.@ʳФpGc,nҫT_0t)di:.-VЈF fciGUAr'SUjV3z;MۛRB:02`Fdm8(+#o1bUZZ3t̷g=*]ҤP Qڴm[Ԁ}N9ec6ja;Ȏ_t*x][J~|UY4h\h%Adݓ9z,qE۬yjNXT Fu#oj, ɭ?WK!uZ2g8ȫ3E%;A R_mc%a)LoAu^=l瑚#6YB.1Q%YM)Nt+UPc *sɫZvC)9tOY_ ֩4l%;sH) x;ք3.1Ǧkfa1 !&PC֠ lsWZc2y0#$kpֻ~q3rԠtmι-cwƗL1L!8RN@)JvTF89Iuk`!&kxEP1JR0\XnE:y5mrH^sQjq\lņ 4JUbՎGNi&Wo7JZ Mb2g$uGD*<ԨWx@v*JQ]MգukV1nՓ"26RO|׳]5xc㜌;v290' b"vG$b3җօm8t_rĨ~'  G,h>H#+v)E2 DU<<۱mP\\+ʡr Ub\g$;=5@r DRޘV^~['bSO0À?㹬[cqM#xm4{&rv }kD,ڹ5!H$jqYIɭ)Zl 顡' =Z֬E9MrG;Le8-^?m\vW8T_ԞYš9}j+ \|"@֞N(6no9J<4jU;USTOs-6 @x.ivw!sz/j]$F8k#]yɭ0qΧ7j 3M/y '+z"D @T :J2%d)wt6h5cԲ6\]-.Q]y_MLwVѾccf7~D+kpF :?G#]͂21zy@TvN+77W-`*99k@A"2|i Q&eFc=8=;Ux l-ƨpU+Iݏ\VnY{z6G d|qܓ\<.ϒOܰR3җ-Vګ./≣l,1\dC3qN4"%pq]0ح=/_i`G=:\6C+`Vd"Ԏj㊲)N'"ntUƻY0߭pVI2ճ$# h{E%d]t#EC^UwwtE@nU*:jsT^=]Om&VVӅ)Gn* ©'piЧ$Q\Z>fe[L-4UId _u13oa$6-b%U~^>BE[-Y0o}*]sOR^ǡ2UpܶuBGV}ڱ[i?g䔒3YNYA;W֩Fp 4 [zc֨O{OQZĘ5ӬfzWNٲJ%(,2WKG@2ug";`JЋۇ#VV=I"v5wZv;*b'LW*)b.}dGWGw[<#[lEbÎ(#S,|=,(*NGZq1OSҷ$so+89<3@dV{ڴƧ2^ؓSb욲8}wiHj[OyiQܚm/4=6S]s]TZ#'l$l~oh֮Όq\6]D!Bw@[PC/qS^|QJR{nu r6nV<7"6Gs#J뺼XBwc0Q֩q6ۏk#}`kӯъrU@kXXvMzFggOTEI܃Vփqm-'Zmqs'vWRN96Hޠs^oN[iy޵ pBAU9%mI7MrITrǙ,sNs՘nHc3*e_ОƳjs!Z˩qPFsOG?Z Hlݷj8X⥋ZöHa$ c`֏3M? z 9=1[ ?2u,@:XO?dXb\ή4m9V!7hxr~8 hPzWqiufԂ}rMjhSFFo7i -: 氤cP?gOy9;2;}αe¸f9:У>\u-i--L3OlkQf1GoWy}rbIԞ&p1'e]iI$ڭɥ veR*g&&Rj# #GR0&ןq* yeeg\XSq!mN%'RX+g9S(f'ˊFӲklM8)ߥ\T+fL(vf5c8:օHd= #.#O3HP8 Ziu<To :=j[ّn“o2WnZ&5,` cc+$4cZ.298*7zƳ 4>3P,n!S3y\qR Q1lv)J̨] _YIyfϽZM =nA'jhM>ɻYZ8Įip8T [쐖KsY7z?$)9JAw:4|rF8R]ivīA++g&YgnnVMiXiDW~sYIEYnI@Gh׉!-9#0*mcm-Un 1L^t7ɔ*FsxcjyL-fߴ3KIckP,-?JCn/شs;cҦ:vIs]?t)dFp$Btm1wDE%%hF A =< { #U<UYW|(E`˩4R<ד,9 &0?QySM$VUE aɐz+wlIqMOa% : !' [X-j'={˔@-6/i @3ڶOtGR}MeDƃN pzϋ3yHWrZ~F8œ3Jwa%)=Nii22պ׆>HT.q>$lZYֳj5KO9-ԍj-B=2u4`㟚wYՃ) 6y#s&ok-Ҡc ֟< JvszFd3tƥem RU:=4G >M/ZATn+p]jvBO5W }QH3`WV^-ӑZPUMtǍMHp9F*ÜnwTTN@*9+YF˒kϨ殏Ziܹ6ii mkQ&1^S5kEYNܚ]ܘZ9yZq3gMYQi*^4܌`aӀfT+*†\5ί[YP1*Kg Y5jL1.x&EX$m`C X֟cN<ߌ]žhGv殕:3wi]#zITSؓS.fS#4 wöbǮȵMA<f\S֓ћ:4w31-=yk "lV=9CmJTӖwQ@e u+ye;nץBsW0kLw4"í9Ӽ5TMQ0 =jػ.'NO=+nKXɊ@).JϞK*&Gs /yGc,qU'OAu OXo >XQEepj1UUxt:}5*vo8Zܵڛ%PI=<`wz} qz;fM&u:ϋ[#py犼eqHbR+|&p@`0^?u7m]ŻONP|B?"|ow++$?=j]^ee2=MRͼsҽ'VV:> yI% Ω֊x›xhb8EzA^QۼjXqx8RGN(>xЫeX`BYbG1Ͻ?V/"BaFNt6whRy 6D珟%5 }ݞx:&IV=fa1vW\(ǪQRQj&0)QOT6kY&WC$ppAMcc4أqn Z] 6FYqWD#^Dg)I;C ot\n; Jm,I< 䃟|מxO qtp# kԴB $jֲnSӰWW0? 󛔚k+[^s^ j蓮f&EpdGOZB$̾|}41~8Z> Z0]Eh_]Aj?+ҮďXyOE-Qu%?/9/ |?dIIpEw"ԢނW2+Fz֡%avu9@T)xΝ+34'^^]*Oj_Az f1Y,>nb }͸tckc< _NM>]<=_x7WRĭ$.NEztkKò9i#,XHYZwo59#[-g$k %NWp7X9]w`"IE6$>K]`??l`brkI8nZ)#m~yᎃvdnpQFS\?# 8znDRף? t[}^dޑQFAMA T(7 dt;Ҵ{Y)f]^ eSw7:ݼoikڞ5cX*IiNeslaOoUq02%G[*Ɍ\M6a(]'u:މE[m@OrRs wefT\OzekF9⦴a%gAҝe3þ),W8NgK.́9k׉!i-QБɮ;-lÖrӍ8˖-uTjei)垌c5VkZ{o6K"?[?.38ʀ1TϮXhQY˸J1wB_q䚯b:< .m58بjcXSbV8 tkh#`ܕ"*^#E5>\}+[Lҧo炘*y$CgXl Q,3kpIDMIZr4CݜrYϦACo1c-]%( 8XѼ'71c$sRUZVj[6|;=eqFNHZU$QyhuB(<,T-w[dgEu*9>}?H=jܖ:Y!I8棞[# *Ȃݕ@u6y|6l<Й5-֑.UW+'f㭘RxQ`7FC_Qw+^8?W5k+ \KI/'̖e21lx)Sҫ2c֝,3Ļ0@2 Chʟ(ڮͭ>V[Kg39~x$)-qp&h* 󜎤U+SR]rLf7Pl*j,maZ6>ưvo^);dҰqs/Kn5Hq]2 ycOkC"6F c5xԩ=J&2閻ш \αs,gGzT0EUm丸,9kd/vF*јw< FzӤج@U9$j:>3ZDz&tP\nA \AY@%S޹no s3YBbIXg;`W%GFݐzkR҆ڔXKsÔpyf˝n![$%i#riXlJ.sZ]2]$s(e<,.8z,oic=#ҹ%%tuZ,cjcq85+4[uk#F |ޕbA)s=VM[ptju F97y#!UK3zJXn ozH47Sϯ 0^ #=qސp;TU{R \Uqڞn A}ЋA]JǩVk*͞?Jd2S)p޵ E݁銖A #< gҢ$Frr;gޕhX)i7SZ` 0p4)|pq4dyy>ir3%md<}j'W1'֜GIcQ'BMvG&d|#g3QJriPwYݐN:/FqK_ϥ 9M\!+Jl=lozsTRv1K 8|g!I&Z-sڒRH9rOx6IFDrS8RE#r;QpmR7ܞ,$"sޣi5$*-֥Hg馁onk_O8YΠv5p8"I^ j=[XuKF0Vwd';bjx,80ǵ\`Ց'!T #ڸQڢ09Y}j"ɍV+j#4q)\U£6pj*fRoAF|_=h$ HӃҥ xP45%֭m&gڥP$bKȦ(5~f*ҵ(Est:82eRjݞ }-SL%!@U\pvmK6*aF; iGb-zZDJ va*w$6S6J qZ?Śͻn8I FAv9[ ʱvY>g,Q$TWPV55} 1ZNHڥIijƆkH\jtҧc8pC[~nU&'ҽ'2TGg4"٬4 }ɷfN6xҖ!S@?}3)}DcE@2 rھw}9{vnNMQF u]Q/;RMw&2F'[θgK.B֜RF^q޶m؄e9ZSK$!G/2Jy)\7m}2;sr>f 15 PYGi;XŎwj!nXzf-oVLSҺVhnoDc[$I^G݆K՘џ(nJg7G8i89RA Ÿ^sS$U82FI7jݶsσJ ɭI-6V"g\c֒[ mj1Z 8>lYLjݥ8r1CRdE8=nTG(X ZB~_oZOa8>A8v8l(IAZ<j%[KSõ3(`O[>B qQN|ͣMWi~o9+UsaK`z{.#C {GWa\r9hRF-\譯c01бB{u>5.rK}-¸xP;uG{QGAq&7B0q}+礪4ֽ%3Sg )FZ_I*£P\Uұ@v4S-&py`Jo$qTYҙU5J`=*El#.!#Cܷ5g7H[11p^SȵA#CqHnI8c73$6q(aaDڂET㩩~֫KRICJبkd$壷O@¹n*|L6Îxir8?μactsY30UOv1yҿ09"SMYe޾8XϩbkW YI9RmqQ֢FX파:i61Hèjs4#KRi+~n4\v85[nsMN[ l͛kK#z]0^lhewsZ:=Fhãw=뒴$cEVP7B2c+| 划EPסCrlO>޵09iR7DsM˸G5 ě!@quB+niQU̩8OM AMk_XiaDЖ5C۝ZCQ5"5=JʻE<{Y9w;(zo J; -(J\* kɠX2MW, sY-݋y=j݇r*MHIH 9&_\ũ=U<3ҝeSDrT5X>Bbm*k|u ճ&eiis9SzKRti 㹫+8{9dOs!#AAa3FƤZk $楓U?+H\=kJHi.6ZC&1 Vg4)GzXBHzubTʅsZ6~!E,R]JM#-t:m-bI c9Oh%7zj 2gƖ;u,-J쪶б.R-P-m5*i4X1faCH2"&K[#vjHq4+EuHE˒?1(Nfl{^RIhGy[HdWjȦE=EV<+8$rby-[^b^jK,yeC p@>N :TXC(?S֣ &=k5Q7dS$]rNÐK5nK18=Hvsq<мHpqV,q ZqNTZT (=qY^%#TjBIjl/`DR:eꖓC7.z8OwҰ,3Yms$ O^X%wNPlXKI5ck/~AĎY4 Tt<9G$1/}5Lc,X/n+n&voFNI{hC}Fi"YqxoL{B ۏOlbF4ږKh2G5 iJQC`DWhƳ5=No~1j*zTuvǙMt)S㔪UwjrhwqwzgeeZq=.5b aO.{+8¤gО"Vx^KpfNiMEtQ4o]Y<$҅e&Z=?9H'yK)l\y7S/tqL\ *ZnY,ӿb\[C!h6O8/gr TmmY9$Vdub8[R١$kܗJԙ9*yk3Ğ1AgnݺQu\¹Xp#bճ(UO݊"y<]B22MYL!KzipLrY`G&6JF=NItyҼ3§Lop^qgYDʮy&k/cI[ܟbO=M'Q<!/HtyHpk-`ivG-HׇEOa-Vm εAoielX۔0\gWRa!qzD9ᰲ+w4r=j6Lm/ȶor~֡u~X :t5-޾΁$tVe)Z<4e;܅RQlxkR ]ܝ#bj~$ҙ$y$Myr)f9\ӵC;As@kJ1vNgD32r#vyOcҼSX0~+޴}+ȶfcTo? ]]glq?Z9GmN^i pLl͏OZ_ݬ\*?{xsxA*{_ X>.Q)Rrjs864xI`}#H?wh5w:tPdi[ĽˀMe]Yj*zQHa|1kdU>x\Ү4Ґ,g.ZC50wSe,؈;qN2ZhҭXTJ5>n×,epFCXZF5pNv~~5OL27zס躕훝JO-5:iJNoMjL6ƹ+].6g=Z_y&lW q,|$&i)JOc(+Os[G'Ĝĵ䈫l=8Gtp;utFRxurA^)gUVʻ x-[<95 hD\Jp;%R|Wӥ}@#o8$Y&+ap[9?}iH7O J )[_qɈRy<&fk{ԺT6ڬ`Lߘƽtx_Ri.@sί}kv~ѥ'#i9(ɝ0J/54-?MJw\sR:+ú]2DNx:ml& '5M+ mHc9^)#>~ dm>2UH|dHbڟߨJSm4̿{kB.'-2HP0DZ5;6&ci{ &w0K·S1ݚC8\sF+kCS!i1RXh ڥ-WOVMp px8Qzo$ZF/V>eTRxrOXb ZꏈthOTV%"/cxWrrhH^OX+ euo,zݱ(>uFL3[emYJ25WT#e85iRk͌W[kk.# 8"MKl;e^1ԗBU4pZ՝ͽf#$_.?u7Fq^6fD\WxEԷ}ܰ':؎Yӷ2r*;RCd.!s3:,I[$=Tq pԢӺz1tI~, .9f-יcqJKF '"+G@?d6xY>LJD~"mCskѮ윢6ӑGEs4$1HÜ_c^O fkQoJD㫈ެ[4a8\5T0 x9ɯt(F1\Gt/!1ƶ!-/NƴgZ$ZR>ເ+Ѵ[uaIJҖՉy͏JH8aC)a{VJ)=Jsk9nBM{yVqɮ*-\';⳵&[M.8$wSQ- Tܙ$IM.9PH9X*kSu.U<@ \{9ܤ|iZ߉O>:s KE"**_jf鋴 IU>cA@5ɩwcy57xDc8kk^I!z|!$0pI-x5HnueiQjJ=JGX<w9ͭhzC;ykEyׇGn5LYnW\Oc^ÆQ>{?ʗ2K\KǏ{"RÁsZ!.E[$$fD'm51ήRFMc`uEK _6Н/;+B•9?kdBDq|c2Z٣V5ISZE- VKD͝9O>Qkwm*|hc 1_:i h mvV_d;I;kُ72C dsU|7em(Gk$V7vo0TZ>xN:o pr}V:Z > i$khכZ\j<wRDId=f"Hr명i6L(٫{MGip ?dq #qW]][@[FqDy?iiw߼ #UDFqԯhyǪy8h5OtXaE.8xZ]%w+#S*]N{6u>G FP0(55ͨ?u`1^%['?7+z417P:VKD+u .#$'41vh$i" >d(nUNkμw,<Tg&D]W=R'EH!@9ܫT}D3u-5)}S֞eduTWǪ::憌&.B9 `_iOl77Mzva6G$f)"+l#+o Cf~lg5h^TFw)Ԃvl׷0Z;;)\gg]k+ .VL*S"6yO "7]zIhQ{Ãq\Ṕs隵֓; de$[n8rNط\DYYHQ.ochRZCo5@= gXy7t2+m&9K@zvd[gXo>,83 Ո@135>~K1afz4m3uȭbKXnswff+$_P)?t8v6IpOEKsP ި?湧OF\:$}҃:t-sU,aY<֕ f\٭G''A՛2iF@biU;zf_1]͙rwZ}]Zz7L$#{*ywm硫2DQqDfqM+t'$ɷnq]/&~=W;m$x$m ҫʾ- (;CGY*[B2yZWֶJ6}c§!UIH4!ǓgY^ֹTLWY$lp-QPp62ӚJru MT}vD8\Ug|~n>+OŒs~lgԖb`p09CQf}c8I =8X rqښ$c v撎>B*cjӿ<&!YG9\g5HF9Zkֳ)7$dr+'j$eHRgCpN1L`2A->de;X.#p%!{SŝH]պΌ|-Ό 0AlkEфև"m5ysƩ˦Ζd;֎ZhݝvHl9_`1ӽnn9F]©_cVVщm /#R#;9T=񒭑TkB@0i`ƱomzVylg `QѣY%uc"H ` c@y_m2hW J5noEH{\ Nޙd*P:7TH~l>q{j h8hɻ"B$6}iv6ՆH #>& J_ByWLqJ0kuku pC0n}=W$8N"f]& iB%@pzQ+@j`5BIϵ MQ*a94pDZs< YN*]ҭͩcp+mpqB0pB?&}{kKА# $S2ެZ)ZYnN\ n"+Zc N: Fy Vfwwdk沅8Z8;)!D(N̂:jGcRХ+Wd!K8I ێ)LS#*g])-G gPrrY!IԀ~Ui G b^>\'$cw> F';L^n*m$J0#T.R!#ϭ$\ZKeY>U##PYY'ZxQ?ZTsYH#nF=' 8ɦNp?Z"IRj2DsQ4r;pv!;+*Ǭ$O֚ 5oAU?^V>x)n3N=wVqtyv򺅉̭pבJq{+vUø@O)OeqW6tQەYiq#ִkRi~ a$VXHeN3[S][D5$QF2XchҰ+>M9t$~5k&X7i≰?yuV 85~ 1r>VϽYM$8TGOpt]9K_hxdϿ{:[Gب4b0~S:UIGMBtӱXu$7zJg7 sIA柩[ƨsErE8Lj7~%q#ٺtO(w̅WnEuzN˃nøQZH3ڭTr2 S>#) sHxX=2M5!pZHZPg,je2#GaӃIrGRTnVZ6 3cZ~oަXX?¯# sI>嘀Jӊ6䐪GfȖ`>9J-2VQu=+RAěOsTVÈsYqӊͭSm?3`N2Fjh1ޠuSR\'yM*=44Ũy#)0댞VӪ6r*|{r38>AuD>@K7QTD=1XcV&=G4-Sn /#㊱ dN;sb[HA-LTQe(>Wk2l"||[s̒IM#э:v5U\ޕv,9ɮp'ҮzRcU™B0RеGMO$W78^ EUE*8&eV8ͫ+i~@i z ӓAe@df뚕͛HGqR %NHWd@M(UMna"B+6? {HI:PƖ2P4iD%[ZH8@M&[Y%!z&B u([:g=RaZXȨ]1wHsmKV5cJrV6vͨJi׏?3J5^!x%mG^kBH-6k̼aKc(I2ynZ)_CʅFN{tM:.q]/㺊OG|qZ{cQќR3XFk-#ڛA k7VSێլ*GfȩνC I?q[v*nn^hLCUUYX[+]1}Q)5/?v} (ce}5Asқ$%:VM#= ~  83Uy_qIT г3PIIWi-=O(qQNnZlj&0_-Eu̡U2GN{F//''Z[.#cr(c] T[4\׬,492<3A7trɖ5oNqT-*0ų?t3:2+~'TUt֝|Y ƶI*1Y,;MZ𨴅Kk3nA[PdB?kR&TM Y]:*SNƭ nCl-#SMRTV=Ćjպgk=mf?u- e^jK+*NAq[N2$cJMI\WۃBQt)T׺OkCK~j I@2sPisawjްXv+n]6ҕc\I3dc*V2&xp$cu#;Mk w+"9wүZCe U8`=6[m>,< їޒEW ʯLU{XeBF?%񐟳ǵ fjwZ3ITomI[->dچ^m*ʰjJ;Egj7H InD*,Wkm*Dݛx~{;*Pyxj֙G0#zY[ܝ\$S-"lPft]1]P7Mۙd"i5;H5Aa"KBȌȭJ2F8RçbTi,Wt}"+zWKiR.%G'ڭlnTⷋ-"`#WPt6, SVկ su J&GU}z7@?ÊVB&j,k&ß _Lnylװ"k: jOoe#?/@(U"P5yKCnX3:UU:֞kޙ< zϻQgbcZ56.:r.H.t[hِ=$[Xj[/`qVe!Ihĩ8)g5$gjGOEΏrB, ɦ^iV)l۩#TG3gL;yo&YE޷NÚH'|ZCPVȺ bF>c޽JD@1銧Zm#(a9EGjk"jΡᷚ!ܫ uվ (PG,,P\5V(͵%5s ˎfQ[[үxY{o5 #|Cy>kGc:2gxsCZH,kR_/Fuq&< g*}2kR;%JD'^q1W7uƒH8W}i6o.@9=rW1HH ] q9|Z:eͽ#RZZ+Ffh[ڍqpqWgeR#@`$sIrJ7JfrWT؄d*JEk簭E%nՓ֥q#$gZɭy~binLuɮk]J3Ajqa7ߑHMTOYBz,RLGY2,s}5wN^n9 wLPT'5NSIgy=/.,Trk_N"f { ]FKpAV5ܺmr[X5uc*.<*g9ۚ϶(i1^ky(y+-v54.98vCTWl㤔F{WiXrII{z5/Uv BBq(]-قph̤$R+Fk{,m.ȫ{TKwSOqYN$bwbƺ* %MB0d$Oi4s.nVli``I㎵M< ,gUC(r٭fJ( YZfC"3K$-t'ήASmcoSvMk@QiݙN:z㮒wo*z[mtw>*Wӳ_owq2HpLjU9e ^I)Q0׊l1FR99R8 aNwWfEɝF&R \d[I7\_+ &V`'NjcTB4i]³o֯s{P<[tZ.k.bzU0+װ\>NX b{z3[Iy T5~G-jZC:[]U !n+wycA iQy7:b G9=:kԈFOƶ@mrʀ{6utm%A[9|CUĆ=T߀d#]'ՁKFQgx[7qvaҭ[*ãqyd )ٹDB;Tc5|F./Rc·Mg~f4cdחy ̞PIu9ۊPȫSz#odf/jSpGsڳ%-I爛,8Oz㝖oAEFN+fmy.\Dž$6Y$GQ|@׊pi W mqN 6 !h|E ۉWMݦSD8Mr-DBq /wV)\Y*ӊ+~#XajIzKE5;Vپw5۬vA]MƧc+[!#Uχ][N>H??28M6h:-Aw)c~5KbTd7tRKl4]3gٴ"P68kRQ2#ry=*p\Wib2XÍWjȹHcW-[5} Sww+v7|o"*#<"F r\~x0G.}E]F09ר˲t\5M&v,".f~Rd,Yڐ$K%q+Ү yH_ZUݭs`{^gl6~Z"Wj~bmBsެFIgkРԵE7U0ESriii[-ÌNkcX#I/uVͼk(>[yHFCcT\2)Wi.\tH,y&  oߊqЮ,N\3JcKr%)BVNvԮII7B6/o]" Ќ^\Gf#v K&2KVqiiJ2["l^bT%Qy&H1!iRI~[[ٖig.Aa¹;Uw{$E ٠v=IWj222L:Emё'w =sYǚ̧6֑aZK vZl4c8Sja6nha]GcsǛ"vkHqwլU"kpFqM,'+OCL}&- L r?CXzZf%>3Uyl>F[_͵U\G4gHW΄u8Nx3xDžT; Rf c+І*^W95%c4i+:P2qT4eդF&L`rgxj:sSVt%GڑՕioXK"¼+kՌ,Gc׮ VAj$hW,ܮ^7WPj|ƏU-WZ1,е`:3L6OV5ޞ!Uޜ4dB䜚s};קJ-RKy@bLZZ]48e$&T.G7e]G.ṰPqWVK{8@1"uk{s3StT%QZ8g\2c[2Sin;ǛVDQӼxF.Xc -WejI6#P%V|6{{OІ%i:"( EsL]8jЊI3+tjgQң2I J#<66մmHSsܧ!9'4)5o愇 Ս9++0CmeA{h5'i7&QQ|j"#*B 5 >\5q"tH=sG2fr31G8`2݂sZ][Vir$f#=iѪǒI) 1T0#`eq(??iH"_;"9U\ rjr6ztXg=yD!;XgsR-)[9F҆ܤ5ɖS 1nf K`kD͝1øޡf&3)$M67LB| $'RU|jp(OvEzS$HBB3HWϔ7o9[&LGJiAӞ)Y1; 皵 T *MZ C"!uB}Α nہF>b}sPޣE6ǭKJĶӣEڇ'LKrsZ\A'πF9WR ΚX}Ol{ivxuKX:zUƻz3'NC.8 ,xVefVݣH$E%;=M' X;Kz#ROmUꜷ9<92X8@+m98ɪivCUCRqc#mLqq]Ɯ̪ NuEb>VE-%dqPg7;R51sU%upޤTHǥG,1<`uX'E<3$ذāN3B9X:AT7=i0F W;VURjp /<\dQ+ WKL 1֜mNcܠTC+jw>bwۊ~U8VDmo*Jeۈ9&,`w`NXa 'VXL6K5NGYălf,]Ehz~W.-~I7Vh2X֛qsm?^;|(By4Y',S9{MF<ƾj *B?w M.p16sbч2=UUЉn̑depk \/C;Ѐy㱢4{X{+"Y'Mppe%1t-YNǷ<' ǁVC6Th}N} D*513R'9^k((*3f@˞G8ML^OVٙ ʇN1mծSsh"_jZP ]&u.C)]NUbi#XI6ʠ*^< `Q'v<+X%ncTZ,O1Qkl+|3 m7-)5jB_,юoAGj,w3՟,*h 5-wZد6r \rpiX)|1sJG1Z-Y 7+ڐ\3p,v[>iLcC{2kt@\?w٪h1"^5Vo !e2I$p%n(ʴt:IW0U=ɭ[+$$Vc'M#f'u^֚,~Vf|%46 s޻];Đ.*8PzD82IIe1¸q}J6z/jEoc$EcZ-,rMLeRJ1{g36e V/?Zղ#18]<ք0MTwU*?2vj: I\gUJWwEjxW3259 k^Q+>fv8AIكl9Ա1].љ3*$ ,tт՝ s\>bSޟw X꿍hBip:ԴBi՚1o^ W6U82ћ}bV&(+ cQ osME`.u#@pOWP-I/SgRUbW *GW6#U> Y;hyTeͧ4X ,}IgUBlS^tluA knPӉ"udkĬ{t Se CF9+1p\8׊{|O.%D*&8OGӑB"2xu%yfm^iWbux) Kq&8W_oi*[:} .ҀMEjڕ M]-O1V\g^)pM{dү-p=Diʫ-ɢxN6g+ZFrL>–-FydI >ö&C\TJ9mܩ3nU8 Ӥ RkoKz}$16!q\5^ūb[fe構ÐX[v9!Ka:U{{`mrm7Aق[zsqܓQ;d5o}#`p)%˪Dn$6_h]geo\g.ۜU&ߜV5' k֜Xp_cpFzWhZ[Xxor͒5aSrhvf8h{JRxFmCPfL/9^ ɑo .є0^ݒGqhi95;V^G - (4%^황SɉI 9aoÝ$ +v\ }iEoy?3Vga7[֦c!HSԥE o<`Jnu ?ZԘuF@6q3ꝡ\}.`@IjK4L2j/NF9ɡT~30ᔇszv[ .ͭ%sQ;vLbm\-wmJe@O5&pn9 hYSךtacb6w]y6;vU9ڃ#$[Xɒ9Fbom&Ilҵn|Cd$V}u\$kUNɩ=QE"'焢AF$@`j״ ar ͎9Tsڌ jț]];צj:\3Ƞ.y_xV@Ylgk m#96\\>j9+4l  f<k[4wad:]r͂;L>,=O5 26cj֗ˉ+Ώ +K~߼mzB"Eq\l1ŹfcWEhFD`V]T<26ʑg%؊;P1R' X1[ѣET! OM(B髖:$R>bG5o[T1zUF``ҕO1ssGtm5k-䤶G6Y5̢1շݽ%XٙrXĚ%#3ҹEo|ƅnUgMO4Jܩ5ut>մc1A$uzv[ΌykdbJ(`"pqʓ|weWV9f!w{U#0+.<Cw~+=ֆ(Q%e@ҝ{b61vֹ;ǂ+_0:sM钥r}?g`lv=kȋqzkRhX#TLD,*=+ԷJKT8ym&?wq5b8!xv1=+ѓ;wmXY@֡b'zM&>y=qةmQr=j{kp.3WkY(/L#D*Y&ƫ=3(f;n~DcjK%̄r1P촑OXOL.1nƛ]/@:sɯ>Ҵ!*]+ťޫ8ZY U$˴RgP7nfl'GomTZ" elҒ2X:ma6#qWUbpkVVw*AZZ{)W~'40@5y=;6󍵑<-pWU6/)摰*\z|ɛ1_Ae,0yUk\NrsUVFʱ֟+{jS')pX3{;48.vyhrTpkT|ɛ{nu-$vmcak>_2 O%ۜg Z57%^+NZt+\$dYz5o(p\I"4ѴLc0+GPtG@X ުKqk:<5jF+M*BOY9lW\r麭CTQ^jlf8D:֨L,wZW(j-kiic#mWZuV *BN3q<9۟y%i#H{&dz ʍ KHt- O!G#:Ŗ0ϼ]jc̭3){}JmCȦhwW0ՈeA6 0$dmWO2Q3ت)U}djȲKȩ{+-[\$\pzqLԒk=Ew)IT8t;Bup\*շgł:Z7zRJEqjҋwsݱCQoގps~%˺Hu3FOqΊ,ڻF0*Ɵw-d"G33 D}RϯuDR(pw.̗ ͋GO±- "H͜qlҦqƲqs4X(ŧm>cr G 6qVVӡvd(r *y Mv֖N:dqI-EYl ڴdtmoOH]rR"$|mzQ[kQip͹raZDpa,q*cQIͭ,Y<7|L~v)~.H`C{$~!"&UCXWAw;^ϱfGz׆gYs ˊ?bF#s{j%Jܿe]xufs޻ x6t#3Xy{PJâ7x ƥrWm gDZx²(H凮2ֵ",mCY\zb|:Fi!G_|m;#,V}iuBKiaHwop+F}pqȣqjHn4uGGΣnG )f^Fs)jlq%5߲?J̯͋̑猷^۪Q)^l;?.#6o1+Vս|j_oTq^ּK-Rd#i;I'Won LzSƻ]/VRX>WgGsHۊ3)&5֛]Q"nB>s*|NKc$Y1kVs8(ʴ乭U{pZ?KpO3`uox+B&[Gqc`+v \AEyޫm'n{YQgE&̾Jn^iƦx> ,q^sFΈ[v΋,lOrhԖKt)X̅2sI}m:dZz-6&ԏ.qw"g/Y k/5y.kyq!QV|B6zï:lJ3Sx-QătM@i3@$OjSzNN.V42喨6Ƞf&PZ{&KbR}H[6 eP:)hSKX:Pri'9݌^[ZAlEt;5rυmY\>a/39UI;:ԐXcA>k|Q%+*^xnЪYsZσFh(C=SeR(-QLg<ⰼC-+5CG3$+!*HDte. OSe5SB=4:)0/8,&Gh#c8,5kw2ٕ$+[09$9Y!ϒZNQWWOi/[kGOS}t+y8 V/>lXXa8lhTt- A YWf].k2HgŽf{;+]|6ڮ3IpCY\mpt*ILsҪKyVE<}tZzRyvsw9 D| Sc$`ƈö87:ʩ8c+'&mG ׮WҺ[ <{84oԊ卙h:J!wF瞕kmic.F`7\JtaҢgIn6p*g$ <$ܮV֤:lF8#oj)]ɺNJX:2B!zՎ*oxk0vK#Z{| 2BN4 p6zG$ad:Vџ4yZ+fV2iGpb;iXo[͊v)[hGe0XCJ[0f}n @{kY؂yUOĻ#0Vul, qT줉ef~E..@$#JLutܧҸy\wh[BXT]u-jK8dg3Yn`Y'VuҠ~P H隰v5Fq\Wi",19s䓚~IPCSY'${cf* ϧj|e[I<㚉 >➬{+L*Η9P Sؗ^x r+&@5miɮU>,PiH-z1QIdpI) jE;[!OZ&RZH@#j6:⭴G;xP6*Ftg~*3;Z Q3cSyu!ST'9=HEm06֮B" >wе x܃ҭcSUo*= ^5I93Ң0\( 6g$07\gE_7Q(MӐ1zip֋Vpb4ɂ=C9>yjkDzТRƃ5RRTzT2}Ma >9w\WW*IY-!.HO$+m tr0N;ў(Kqc^ygrM:C"Gm\Dpc{+rvPJ.u`rthK Wl[F՚ .@=k6eǂ2zcv.:eYqI:%V;;"Ж%qQG%Gf\TU<>J%r@M{+Y%q?i=OzJ(jKF͍ilu5>ʢr+[Ċef#ֻ]ܮ 5iv7 UΙtϲ~~^yQ}kv`) U׭t,]])7rkɼg[۶m7 UirJppzv*^FF:n Vtک 5{rH"*HÎ> ? 3ĩ/y&@FUN@a权t"&`mWBRF ѩ l ]Vޕ'fڊߕjp[\mVi"RG@==jNݜVjL#`XY?'Vχ#iB +t!*#7+iWJ7\*chKhSy޶H8=W@0h+NVWGB٭=;KΨe|ҭjz1y$Z&I=}k*ڍч9#Z#?15qtյljv,H@38$v8"2ꑌ_4^J襗$LGR{W{<[~ mYz֪#`F'U;q}rzbuFpe+͛*ְghj:٢nhw IRE 3^?Z~k%E\]:waCVۡcɓPv,}] +__ྕmM}-EjX|.[u٭`m㚊8=xFW@ZU)15,J]j|áY][5G؞y9q5WSϥ^)T#;/ZҔMtj?:~3rg9+8zWx{_tRv:Lju 5~7S\:ӟ,6̻܅גj:d}]z9l`xI ⣛U@g]ʹhogĉv|*0+X= 8I. Z̺|ʐGrU#s;k#}I]4RqԆv=Uޝe*ev*t2c472HJ)ֵ5i :ŝaYW?=5iҗBJ*:ܱ<`M+1LWf@<% #=ju sK1+Y":q qJ"hǏ,i!u''(־)G$h֥1 iAYWzm('nTm,nZ4,OZKVE8vZu5Lk@nṮvIh]hlo%NnD(9zu#l9\4cԺWzHUWFܺWc*y$-Fi>Ȱ4$b9&.M;Wul+iSV0K[8bmރa`9WEmxPOV`p JIh5Fmc2 zE;\JvjD}NV#̗%;q֥b"wȫiK.H֯Eao#Q'Jr)dB#vd!V  0 TtqTW6#",=qY]98[.J)lucֶ,dq$KiQ綾?h*b2r>m8[xq+\U- /qtRf<^-;b5`־+֤4`Dw~$Ԃ3Nj\c˴W-/.:+7RC.땣.k)&<:֍*sسjDy8jU3ֳ_V\ѮmOz7m* qs\[qwv% Z}BDH&bb?g9GՓQtVvuhk\Fr3J-ŏcΤԣ>I+#ԒMSuE,t54#=(Z2͎iB)_QT"V6$p:]rBdX\\\bWdv.h)u=a/Kr{[8pǽWvHAWdm!It}Ѱrz W^C9Y٭LPrzԦ dM+{2_~TKd 4-[FWn+9dj([ufaie# 8j֧8,v[.wp $8q'I=.෌pqޠWbT\4+R (&,w[| ㊨kpuVw^"{|=Gri%f&\-l~zFӑ##JP$,,nņ7m\eݹPp sNkQ zf={B:j)33O{wo<Ğ]Mj2ڴJÍˊJH;KShؒYKg}>& iMt?e~2@Q7ْ4vU)jTxtCHjEAy 0Y+5̮ +PR;0Z=JB.ubsT@a^56%c c#+yev)8($2j/,R:m" .$h9o#|+pn;;dRE]:1q47\b4խ'v#KxkYgmP9ۗ#L]*Fmy[{fe";V nfKt]idrsڎv<1\-h!Bn.eu$+3q!JRqٝ H'+@S՟~>\66*Q~8,zFz=L`uUoX5>\j#bjZ<# ֪jZ#9S=6TYS˫J2FxTw|}:sJ5t=u!֊bOekwB Gk퐶:R̴ 1걦vZL,UkM* s] j>i4c#q-xffæj T/k}'䴓m\(um}bFUY/\)kxjib]^tqM'CoM}ƾ{[- 5Yڄ@K29*sGl7*{eEjit Vn5sժF?qKQ7xx=tu;ROMZtIj}ZJr'sH([]vko*oL}kg ^q-a>Ur⚶nv.⣅=*G17!ws,HC[6VT\d%am>hŹ6\s[%+Nv\^M˨ݗaֶм; p3^[xl6_J¾.a(YZnRIr{(IOSI?6(5MlVټ?92$r#G]v/e}7VRkFЩfEqxv@ei /3^a4ّ;sVlu!`su` znl]{jqiWñx9B Mz]қn29jy1,cZTtHvrgmdeB99s_fYJx89O,CJ>(}9_X؆1?Wy7SVAm \*V7EZ}wBcb:X &}8:s$]OWVC,wR3̃wAi,G?ZmcNGt`r M[io-b, n,8xނ/7lpeUk[m"H]VAXs\۱?lN1P1o}W_ݡ5Ad,vbff`r_8x{c$q6둵|Mݤd3W9Ji.zM3hG?vMǻ̟WT8@KiE>,lFVHڸ? vsujK%1Փc)au~LQY_<<+k6#AWj~С5 m g>sYl1[1IUc7:(P~gv66:oL2Kw${W9Y.^\B`b#ÖxIo=R,cN˞-^^<%AZu-9 y€yYzGm;+?zv񃹲ğֶQQO'կ.~#CdʴQ'1Z.4_Bk3?pij^DCŠ%89jT ^Jֵ;29a:voi`d~uɬ g,4giBbHqkcZ,;S&x+~aϸ(x)ͭ8F],iL\lrfZ5N IoWL,ԅǺDgKphr[~8jcec`UuҢKrOZ-Ty>+i`O3\5c5#У'r5MCTkeR%V}ȶ Q2]۔h_]PYJܒ}=E;"2u1hm.wkP{m+ g/X,-ZIO\9T9;-EXj_+CB[Oπ+Vb's+|<%G}('o..<@a~5-Ǝ&q~*@cፔ]HfX齗T[_0Xd`99?ž,B,#Ӏei)?i&R74.iwu#O7lcy=kֵ{HB5>Ea,D,0W+um#cT'iF$bH5<(Blu* =@Gq$ۤ$)֤皸Jcfq֜`7mR 9;2ơx4ݼYsM~ҫu)}P 8*< `]*zR!-Gzm5++Js)$`dcxcV!߾i?zkJ66CCLF{y>s p*"8 sO2zg;h >Ir21&Ӝ=3;A) N_9|sIXǒGCj S WO5$Ej&$wȦ=is/#=1M mN^YPw|Hi!8)c<`@g?*;d3u >H~qSkru V<|,S[;xO[[B$SFr0(BO'ڑvU}vBpҐs^mn}}I&$`FqIB>\~;'<(փ3/y%@4٤2Bt'P'85^LCEo)2첀LVSdaf(01Q+ic=KO/bG29sU}>M R4;Jy;rH {LXKȸӭG7<׭@3֚򝧧8rbAᚉr #֛!>H*O֩ !?7qLfdL$pq+ar >NAne8h҅,:Dw艚_}8F-P⚪Bչd{- kpz։f\u UM1֕ӐFqh7ZVD,8@PTK}+0"}:\5iT'}.\:б #,W4vxIDZSgDڅ9=j͵Ž\s?fvp\FW#GJR{{R2L!\5ʶhBw1* TBE/) LtT"߲?}SXep:#iW)FVUUɴv>$QBckWWtdάǧ$cMgq_uZsUZ{ @EtMTþ[Ř! )[(0*̮@3+Z|Hn՝:vWDf<ؓ>٧&v 9jod|r,0kRx].a)өG$V ȱq 9,1Cȯ:5:ޛis$f-JIhօ$MkIck Ru+G x8Ȑ*TaIUzg#ZfoG;!-0gk|Ϊa*:S5;%Jch$AÉYaMl dS D# Ib=qZͥU|/-u5I1?#ğ_rǦkM/ǠƑ}E?/'5z9R ˡ){ZxL0[*;Z-GP{0;Hlgc0~D_ =AXVT3n9":etu~ +*,@F+4ϱͥP21ּ<AkWNbF5Zzfpp՟s5c1qk(]2Uy㼖bDI# %NFy"DQs=ɏGR94 @Y7^#JZýMԊ'b̋nU H+ՠ;Ɲ0+;HfH]>`J֒&nmEYma!qbqݎ(7zסc6! 6F8JmN2Uw;sQJOTpkl7oM^OC횁P/􉶆#Ƴn8\2k.X^X R/c)GFc Ǿ^䜃կ$p*Ft_J{@ٸAڮCaDsXf#EZOSRP)@cejŢE %U{T;Z5^]0thۢPFYZA&'Z-©{5)f̑b@9cve\ƛs{HV"G\EI-xՂ[YIYhDZ&l19梺]EbBV|~!Ƕ:S|hl_4V6FsYf&>n{N:-9,u?vc+4n{-vFp:Զ>"4iA@y-޴hJ"Y.cƹ.?A֔j6Ĭힵ-ց+ fsj*!}tqm\VWgj2 '}̍ڻ&ݩطbqT4nY:֋ `rrbV<֕7|pMmh(,&zU=l̎ie6>X=붹K].W%jPjr:+"[\Ǟ*MS2,3$KsO95{ [cjh/5 FpZ'%̠ [)nkOM6ɟgaҹvP*ħiȧhsQ]s"l:_:UySڴm Ύ ZCwI?V-֓|'‚xh^5iYAƑe"?X- ܹjQ+m13Wj\\=: !dW Gx+!U b=ZK!M,f? .ĎGo ?k`\q9Y p{׎&Y 1]VtToqI=1cY ϭ-\*"\)Ӏ #n/mbˌ<|٘80}=V`=+~ ^3`8{kH O5LGw,!e1,`gj~)Ҭf8z~ẇeӌs˷`K.I= qKJHJWgk^;Yԧah:eD \ gj61q>4IfPtd&O<)K5I['ʒn8+R3l;sЊ0Fs55.s7+R$Sn'q5|s8WMqS]S[-5tKb"IkFr2U챸`.EeKm$s֭҇T8WsӯrH*:`6x u +#1lvvja׎FU[jy2L@ۃR1qYմ :2!i~8y=Ҭk 1S,ja&jF3IǓ;ޭqyOnk٧{I0i3 oxӦaK݉^'پPplZ6ŒXWms5iq8" eM\4eNZLRhS1/qGbtLҢ&'Ű@%Oq _)z幮 M`\^ap0^%H-*k -.#]WV *M=N>RG lO(@'@"oeJsgMh-x{ѭ ކ3>[=Wͧt#)Hc{thynZ{C/ʽVH_jf.!_$GL'jrFPn1nɊ-3OXa+sl{N<'Ðt>̑bM0{Zd~D QGOΰJNVZ0qBtՆyTVuH$֯MzYYZ%:EuETk |;\KY/-.~*>:0\Es]MON7sN9X즪G:=YdH$~P9uRشV+Dy+t- c<Im,='\6ՙXRY8/Dr}+mJKiFTUB_HObs(JzBAI$`jKe^^^.-#,GY7l'sN?ZmB_ UI9vmnῈaURM5oGt+ 뢎"<Ԧe>e择 2|n?~D0D\@j>Xn?ZݟɃ!HjOMĠ-j,J#Vms*\HzdނnYǣEAwH’6z'W 4oA;w/j֟+P87 j+_D ՠSQ'>_r9I'-KݴzԋKk H4$K< VYɋd7?ֹ;r7[7'&09xyD\]G#׽Ԑ} ^ai$EXc4ZkṯXis*GNMi}N͊8PWu;-#\1G9`bJ]/6IZ tv;xySZ:RV%ԣ_V= m;Fin >F5͸ :Cǚ/#)؄H>l?&5|ojһ[o#iH sT4?_dFI3D[md#[xb0r}pz*^Lt)%5)Q)*J} hrJJUb4fh r7X&9y`UmCxY,k%iBYnIX]x TKҼr3RLROÚdQI}T:.<+CeM&均,EIxbF,b>]͚[ZrۄO{ [fòQu­fez#RrRtYnY`z |=VEIZ#Uֿ1t%,Jѐ g:ymz?:m:Q*SoY c5^ưV5ϊR+FNT*m]Za>UVBKfVRARkYm˹ +m"' zNKa)TŬς̽sҸxpW9-nhꞆ7kƼ WkJ7 |܊ӎp ԟ"Rb~R1u<~l-~^@=x{IAmnHJ}TGTj]SZMG1$T:dt ^%Y|'~7ˎk[Wf0I$/J|M ,!l|5׏. 9zh!B t zG 閆 kXK ۽IS^_Jхb>\s4ssSKAW.I8cq5xWa>Fu5v26$^5QOsW[%!H=+k۞$%sݪKSUV=jT#s"Y[E'T֢nÃg8-x8ɵvpHH%sSrQWV"=>G4;F7#끚5{ lTqP9<;7g8ЛؔzdpjqjnS6GxH#Bshw\5-*MhQf*xi@rq֤1}5NĪD;7tDAV%Eٜ4uP:v]6zUr<0jɼzSa8c$+Uzԡw($Ѳߥ5I {Q{`#i{S6 bf!S +"ʿxzSdN=jb3O"Ei9^TJя+Ԁrzr`ў=iܕT)P(\<ԯHPeI9=)]2H.bv RG¯^M] $ NqS涂z"UMA=cP8놫`}hu5+hBܥ !ANOPd6r}VXǕA*&$UWhB#px5(ۍzIPb@4y+- JG"8:w'qԌpi{E@I<;F=zU)u)C94:)#WvN.GpÊdIr鷏ƙ'9灞e5xe.OQap瑚UЌ ~Ey^bdzES6jdž#8+UsN*y]iNp03VR֤FC櫘2Opj4``+r=\eb$+Io yLd!sҮo-$ `#̄" ցm>8(sK}Pi}ʹʹ+|A6kmVa^]m!mn=*uSm¢AEzTFsOٛLgtː#N3Y\esR1 jMo#SEsL^Ƒ_f^+3z$zW&-˪;40%hJqjIXUtiݮu7zM)$sVʱjkPOS h +icT\zƅWʐH$ 4Zd_ "uT\5[YZThRНP I; ;qiKQ4r.ǃ`wt:%X h4ySWn Y&Oz-;J޻S̠01Җ $C KUk`g#uSHp~LQtVsmvm \e}3N4ʾ!I*$u5\)'իEqܙl+g #|2';}k@(8g(q!UrJhʒr'o֎<,9ǭ,%C{kgC"0kId:c)FA+Esh^w潎$eEqDpqiP WFxTS]Q13'9bq 켌<=s$#IBE:pW9 ar_w+Kv5xKK?p8k" _5j)JI^,JpVcSU@aJw DouJwɜH#H Ĝw=KsQd̿n TT^KsV<v N4^I&aD-=}k#1J510z "#]^g^*\iw2`gCpaˏrg(}+FьHSS::zE%R+cW Fܑτ|z⹪R5fuפ{|mq4B<?< F"8j&c,}Ik5W\!r:)2W ooZڝΫk[],S}3]krB|1s\߈C>$y(ʯ:)^ORҦ-ЃG'ߓPS]0E\NyVb'iZr(Hm9"_ JݔD(Gz߄-.cEs^V*3+\p8sX촟 /sb20EtZ?O qg šqîp?mHHc yʼ$.f'?ۘ6pya ]ωnzTuFlϕfǨ|Ү{+/[V]ߊNd<8Lݶ6i^oA+|1tTvzXӬ\ wş@!ڢ5,-ߚ<73D+MoElzvЮW`}XtֆO.V[k'+ b=8>nR[@Xi÷{1[Qo89RFʢKd j,?5Aq}+iuQ;WTOtF(SAz#Ov5uKޱF"㙮2v"KV*=:q“Pn)'fNK1=jnZ@W8wIfo zW_kIo:D_6r|gnNXI}rЩ ɿdDУ(NIԄt*Qu\U[oڢ|Ҹ'[e~J]3lxbͷ.z)ҌW3iF~nA$p`]PqZ 6 TqX;q $ nNҲ+$XߥJ޵Xj)4j+N[ 9T7Ei4[O⎨෗]Xy5KKBC0Cav/eY *fZ&U9ljF]s/n <'=kKF9qv"$WJQu vqzgPtNk̀9[= R\//Ia|ehGV' GJu#57cJK(C<_(۹R ɨ|^YV)gq`僗 gvz=Y;ӵ]N&'j$W1Y=}8E5Ύ/y^L+79V"3QX)NcxfN 6$ڦ 倫Z̹r[ƊKCoV8{#`v+d9<`nISiqܒrqYԃKC^/FT`s}JIGXFjoll猚X+8vw2% Qέ#<)_#Zg?#ޞ3:޺&ch–wN22AiYʇKXdc88dna#9D⋢=٤=Zw\mt9d|1Z]~JIiSĠ.jjOָitE ,j:CC6WjHJ:JZ>h6K0Owc!ܠ;q F ) e2:IgI2#g}+@¡V]]R4 0sU#*%Hqe~z]X;)I`Xⷩ)_SGcr$vK~nAoZyʑ,51Z\nzc=- FHizt3w K@;ZWB,<#H<sTv]zW  w5bB2cǨ5.4䵍Uk/uC$uejkONLYw.E{v; =Vc)yW<**-5k,Jc>,:́6Ȫ_֦>'f:v;/*I{ +]& ]vw>dG)^ lquX-FsjVHb!~凹Cvm"nッPXZH:㌚\%ّ,5x;1=*Oc-(R)$LIq; yU$m&2Iq❥vM {HV.d-yOXuk_&w:oLqK|/r͑S89;Z1jE^H|R3kkTzZ1hs]^i RK|Ņe*PKޱq2ɡw/,'vYöc; ӆK#cHB0β_ #Iҕe붚'˶PB?ah &EUJkm GYO`k-sTpFr Da/w~ Vn-#u856ڑgq k5M6TMqvb *gfJ܄58JyjT+I;V=? HdRf1R^jʼnjS\|3ر309,neP|wsFnWSڔ7V1I!U^WN+W:bFr0>[Ci$c3*3Em8~j)bI+emm޼wu8w}UI+k[I?1qE`s̡abgB֩s S^Ng>%&9R}"xİ`)c^ysU{MxYtO {KWVnTQ裘c˷8mW`{EN7^TOaAW[㿅YA)U 6dBF\(/zv?0[۸HlW;/cXIKE}(5F([ƼlWYBVP蟚9){ܯ3RLVcmd++ݼ&6z-qq(ҝ6S5 Fp5'(J_4t>ԯ˨툑r))~gYyǍU yeii@-iOh1_=RohOr0+_Cχc[ &&} m ~UzonQzIrZTקT}?KHa֦m Knb{ׂ^hjΠ?d~Zoh"8-qk_g~qiB&ՌG8|לjRpl49%s<rN}+OQPV};_µY'g5E|M>ެִ&mcۗI`3k#S 0I$u[ IU \s8#sU9W~*=ŋbxѾ ]ӵ ^0c6Ś]ّ<QZLA{Qy^A'J5bح m:{k)W8\/Z? K+5a|v&=F7i!` Kt<k[Ci5Y8潇º6oDc( Ge[[2m;Fc}_ԗJM[&mFCʫ 6zF8AMɯ' ̑`y'\ie2r+g({=^=gg"5@MS:bKqA\ο+՞Mb#y'٭+^wsȒ |˦k,=0t~JGI3uO!֨ϭ#tBaO$ב}JIb16[9cu%{2B!dRRW0!kϢz]]M {'G<׹o+)Nr144KeZ'̵eRKSf]s|bmiK!|35j['鱼QdbkRWr_Òl5mu|H1i\J{z< {&cEu2=Ē"~E;YO-T4d%OtgިB(XwqKky^I$2TB62|Lp* S޵YPI `wsđ5ܱqT-Ub@4؃$6e!Y;T(qVR_tFFq)6.rCzj5'Sqqґ֤2x+m{!n6)Y^1! T2oFc7aEPNׯ&E'QIIAI9=OibWzԘWh"6"f;*M,5/9 qV|ݰKeׁz$R<ο)=Nx5mt@1O\Tnl=G͎fvdJZv/RO& ##9$riyM^U$Ӯ*@z})\f9lEI|`iQ'8؞mtQXZX'= p3F夒"2;ҕ'1O1 Ut_MJ('4 IO4H`$ Z)Zk }(zzonp1L|ث 223QlH=rzN\RL sI:)R#2qS )r9K} V+4@D2ǎ7zU_],N!%g'=bBjeAr=ie(3X T.9QC'(Br 沕{ntF} ӱ$V9AN+J㩈$$2  ֨b.r*ޚwʽs6uBqfH^dT\{HDx|*)Q$oZݜ.o8OMýqVJ\( H!ECS4`ֺExzM|>>n v Z$»owC8Xkť9ѫ(t7SR* YZntD~ lc=hx`1"㐦Y{#RzN? JpŁKkgr n8QxCqy&ݱDF;^!Fe!^BflwM^| Z#z>@s'Jm߃pOBoTϭZH:8棝p>j%܂1aa_ZWVƁW Od?A\#I9lr(eyrΘkzGճ$Jv#gqzV͜ukjtcR"^4U`?Zx5XgQ%^}Ob;lL4j;SN䁺|Q;ޫK=lPV%K6ҹ^E/H5Ŋ'-T&fNv { ֳe==jQG4G VOjF;Ƥ՚B\;` `m%Z(;}ASedPJ`1H1Uɠ*W/,ޤpjݑ+ A6F%`b2?!E)a[Cd& 1x{ZRԖVSF m;ns] + s*0aA|!k5(f>ulW0򝣦Xs_sֻ(9+._ʀa׎s[i 4{8bUxoQ6!a:Li9gSUsEq/浴}"?kŮoKj8V ^Gu)L bvx MhɬeD-^ i;Õcu` 9 >Ρ(//(1> Ϙ57ČMVLwq+JVǖ.j#!qlxT&vOZ!.#ejjќ.AUe:I]7} ?Ϋ̲r530RXcVBB5^R1fMhyR`f,.ʅ8ڭ\os1WhĹM;Vc$g㊵4&ݠ>+8p[ں 0Z&aLOf87'*hpq^ XJI85VEy) # ȜTy>oN26+>1^xe~if4C/:`t%TOC>_ʡGmu")֥#zM6# QRjb\׼0sO91Zè 4Iդ0ǛV3\dW&Dǧ=BUs26Ҡ[ru4O:jSzYˀUY}H@j I­ٲ:P9VanI8*^{aM {\n1U{ge(&^SZ杽O[)lB4;?{5}mu f 8g;mSKN$S[TDRMٻScose&ͻP,r+G7Akt`"$({"UPӓvOpUj Aۤr:h3w Q[:|[$AH/TkTVֆNFe$WE.g W~q yw=EIYCu:)I|5Q7=WT}.h wg;@Q\VVF=2qU*8'>pJ9U8IoLuaŒhGeku# w2y3d]9 # 3 L hO##ӅHuKޗ YV忥[J{'m$nZhz}l\2bA*e ,lG\kΣw䐷8t?yWR[ Qx:~ /.aȀH#5x^W q*>pk;9, uSi|k*s95 rv<[ӭ}]ZΗer.FMXOhlЈW=6RKyoDJ87j/^+XFF'[K.kf}2̘~ݣL k(֮Sׯe1(G?*߷汱,FfnĆjaRJL ,dYJ"ZU!S2ֽ&$MŨhࢃXbf.cJZE%$*/zW x zcN#zܷ?N(sఄy*Kc=+(-EwյRTvZ$B3a1qn#65 <:Gu-֑/tP&}R9J\M'KViD}x&gq!snOC`ҧřVp>j5KlYoVd"HɯunؔrVi)j;`z<j*JJuft:YJX*B٭Ǔ^Z{ A QkV(+Ҕ'MI(꺫R5voxk7WZIc'?wFFsgzӴ#d *h)_ƺjJBiTfV:cҼK>$Kp"J5͡ɈPkRE) ^wo1_9D^ՠiok'IG#V=>J\/:/7s¼C88k-|?]D[KE{͜ė+8 LI+WY-43g n_#dZN7:Ni I k;~SZ bpٮGd8w7ԭQLuG ƲV~ƭgx/nӵh<5kB$c::_C}#u;Cg8k6E]d"!*nѻ<-qm^xنvDs^Ŧi:4{G$4MM>1djeiǗ;tQ%E7(ݚh$*^K\|Z@b%|9V\}Nj|Ŏ}*_^T?Gqx Uiu_\ CnwndP6X!a)V#-Y>']Im?j%%mFVw&}ڏ"RŁY2үcdh%P3b,|".<bTvP%Jy59-RM5oyU[q{YAi EPִ]H1zfL*wap+&}|O?ȥAsK-ʰ.2 Meɸd]s,nRsX1,3A)[XՏ,fTqbT=EAuN:յe&qew)O,y4^-1c'g4xTa);Us\JB)QUXG"3͞lzRD8֋]3><lӶ#g=i|2\wق!MF *R *R='z_QU~^@ v)cwnyI*Næ_D0GT=J#3T0Z| Q{Sd, izYn=) 8 08/ԓ(l SFAco-zPֈߖ`Nޢ!RurKr'`9#ѷq{S9=)=>m15?ˁҙ <Ћ騫qO`dwfƸp0in:HsyAb&8N'=;Snxάin#{e]p;u2@=)V'Ս[Ap~)sJioXW'oBjDi;yڞ2?w6o'q{ 8Zhvq֓v-ӯcJϠc%M81pIhKQQTL#TM_޴:hTi\*|pK+vۙ OIQ!}UBs:ZjRtnǵkG,RӳXwH8XZ$ O2rRΰTdc`~͸3#ZӴt5#V 8W,U"ˌu:FUw6>n1zOIHw[p8|DŸP(b_7i_絻-r8_z֐ bG |i*5J>Ңtzo/f>0K[Y&+HzchEJqc)ɇLAiclgf=/1TƉ2}B"g=+g*ѓ'ztNF+bX#dYi")%N_&xV`=bɻtrһ^n,tA)@JVIwn4׺ǭjak2.=I3xh ni28SZ1KkR0fa 3JCMkˢ^ȉ6(N GLqYʝ4"?dA#/C3=:⺫M`r4Wc=sKF k:+`*N33NK!oV~њGEcKϴmLmmhމ`Y<q޶,a^sM;hِNjdT1[{Q޸ ̰m>f¬ x*4Q$~5^HmROp+&1-h2ず꽙*Jښ+#+ X{mH5e0.|VFKr:psUcԴimcii8^@lsR]"RwU֘7Iv'V^t{ձQ+@ksFO-F7vHfahC(bsvt"E,(Yc cC T6>cf '5)eSdhG( /b}FU%<sދJ5wo[xK47Sl`m;n6ԎN)A[qI^#\{R&\yw?q!GV-!^Zv¹X8[bj95q֬&=k{F<ΝNbyi6)$h m[jq1\TRYwzP&$AZrGS8zjjZވ"IkJŝ \Tڶlw#1P͖.zSTD䉶96X_j=y g t\֭q2)*u6e첰>cNL\sX| rn ݀zs4ahu vFIsڳ 3c@Z䞤+oLqЅjޜ*Et5/omؐjr5j~I]ۇPIa jYԩ:AE^H{;T4EFGN+Fa%աIV29K$||M:퍟5stnByvFߊ|g%ʊ9\焧_gTIPmޡnXx+)T8aeKݤ쿮Ԕ ')qKw&Rf\:che'Ri8U=Mfh>|OJ݋J?(I3K(5$C>^1VTnoMS(b:g55ql61*e+66YX,^UץmMOzkyG7%͕>`~UZ"Ljf_'.=*ƻt5IFkfIجV iP"! b4 f\]0,?tQJ6|y[:EPs&% ygsy&@IkkF[yN%8W S\ȿ3c<m[Xg*G5%_# l .͜+_K튢2sPKkV#Y] ߭OmuHW+<\$_b#։XTkCZ͕RAW^;Ve"NӮiSyq-δ/"j'e5u\/m.G?xIG$i8"vD'SI k8Yc)-e;77sO"N`|@$Tis Jq~*DWUCW3'O4r) c(Dl=ZNWV.R9.i'O3kF-y|Yw=T`ڜ'qĽH`paLb5+kWiyekUWȮ[MȻaus PZ}dT웿sF7^l5ld|]2=;WG(gD:0*ըwk"vSRK=!UloF /&XXJ[cs Wǎ= {֑Y\^ΨMGS<&6ڣ>^ŵEgj}^gymk𾱪z~רC>~EJ'DZ8^HkYox &^lxZZ#ȣVciB kE_ȺIO_&駰c]5g#A\~ Y]!o St_ȑK>݃<9%+oR7-et.kuK@2N5蚨bgs,ƺ.GZ{R5Ve8DO&'a֞'XQwgG1gutY5jwV[>* I$ӵ{ۋd9 };8FxK3i5>);z,uPLp cMO VψE[16󣝥~K FpF5 ԯ)TQv9?\s\V{c ;W)V1ysֹۋvUG!V׽?qZOuKI?svq7WC,Uzg5n($XƸ=-)>" *n,v<}k WmץfϫDHIu8tV݊42$k(XkIEGg q0WRܙF []. +ZNsaC kϯ[9$F:]&7FqƹK/G[1](}~㣨<k}}5t:qI ȁ3ڨ`rbQZE{Fk_ػ>zQCkΞ-f)F×#kRx&v._LkvZDp`5r0D{ 秽5W/z-M%Wle{FvbsJBj|G`n$ |cwGAAq]ppTGnV&8w_M{|]xm`gk&},MqkkYT ]Z"*:WkF% ''!{pMEZQ/GM*{56]ԅuK+TR$6Q{[]Lwi + ?f@A)+,\7VJ$t(ԏ3N+Eu {]fCqa&@V?V|_qqGf tse,a" A=/>#QkDFq8E?r)\֭eʣ7gE}ZgY@95[Sf3!u^#y5Vh,c̖9¤uٜlܖtExXյo#] gp3TƲdlZgkM>FtJ!-NMZ6 K,Y# Z𖡬hRK/]˚l.VKDB}a' <Ƭnk۔N{EV JAEU e=!;ya jn=x Wf=#c'Nfϭ7&T`Tndl*3sL=rvsےbD4=3=i94|yjMthdT19# FG{zSzK[URCu})#˜3p4dG8I##BpF ߗi>^e'ma7~T'Qe$䷦)#6䞣)M8HPqK zwr!ەݸ޴7~Uxi+cheXI9#Fެ|Oٗ(JjѕEzpN=}jXa֓` Hp})#*:3aVKCZXsڰnO+íOzW"qV\gOjPNۗlP7JPyx( |9S6jrp6Vq}VeFy泮.r3j'ܹpp 1eG@d.1l8[ ֵla#W?qŏV[5䒾lV \3a)yeV(b`FuŦ]*ɶ2@mi4-ҹU"dܵr˞GxbhUY:u#71sySIt[{*zuKL}B=1?ζF0A%Zw\LՍ6VUhezӹd*ϴ\r11jƛ+zDw6 Fz՘-U'ּ<]ֿ fb#-qX]Wz3Ѵp^3ZF:~CMm01TڶIh&F#G`*ZaV %^!HOcAߚFkin12]f Fr7Vvhf2n?\ens\]bkep3ֲ.[Q_n Vܯ@by'40GS1k49MEдS䇽ۻ2kҿl*F%nČ).1qMk|ym$!I+;ktPqdOM:-Im_N'`Vk C5-AUw1\LjaOt"k'P }h6ȧ\ҹ^h<,\ tia^ c(-NF*G#֟73ئJ]O?xsOK9摞Slfaأ95i$d-0܌]$7c*+ #jUi6^Qw"p{a;2& qϭnFq]TU,K 2 ff]zu=yWXkj4bU=8ExľNfH0+5s8 Kg ;J9MTuiHsw?g*e=gӻi6 8=kD|B -8Ninshi y夌S]iaB*}BA^!)8F_si)P%!~sӌש[hvBKO>d4;ⵊ9|u⧎[%=ɫS)O;}w\1V n.! &hR@xc˱r8uQ&gF"W߽QhcxZz5 =k*ڴ$g5'kgE$\j㚷oFOMh!Sf[kRG)\ҡQqF~q[#sv s`ce6l0RíJpSb@yqZӢ1_:-#H2yI<0eizՍ5nKmVDr{\{V?Fޡ5Ս1f9"ĠZghUqژڥ#X(vE';6W7ڨT|qnmLgoLF61]1]Mp|`vIӘ_cqVO"J%-P#9z|lZio/rبtiMQv97Su\.#-mwLq3 a[Ժ"v/#(ix:{2]5*2zܟu+Xo,q9y3hG5i뙛0V˞`fOl)y//ZѲM|=B$n7\ML|FO/FzBHo1Ilky=KL삜;MYd ekzSysF pZR=\͎Tĺzua~֍ 'گd5'ƤB 9Y`cOlZ_%~u@ UKE򅟪gZ@Uv*#67 Vb&3֨OE}'4Vvee{|*Ybw?jm REso F섄VC&+3)p)AB8ʥmIvxQ\n R,KZ߸i.o@qH.l5+kՃz~Ր+G~Py]6xL¶=gkV8/Wu+hE'*:uԊvb`FY2РY]&$F.AҸGHޯw@?|/cGp]:0HtOOA4em:1gq}Ef7"#j*ѴvڿOMPWWBKkYk_4pz/Bq[Z1U]}INJ8[;v-J wY5&N*iʜkΥ5ROL͓U{bR8G?JjSy2?k?r#ӴmvkѮ30UXS*/67O&֑min,{yM!qʸV:&HiSMhUڱ}g=1aVTVT+HHs\r{qm^ֻ8?v2q?V;JILҼ޲ƊGm2R'QCVͲ"D\`$8Kw3.|6q**i=9+T|18UT<0&z t7,vOdK;GmB).e$`T^_#m>-=V0CFrQssx:\,d{^F@95^#0tSڵrN .S,[X"*1B {od#JΌ˶In|1'ҹkbZr+]摜d~BkMI,1]..*w Xq x޹㛹т\0pZϊ̭'+)OK#JnPTTgB8ReCqOٴY49b3|{⋗;|ռC;ẏA<挮7yQzF| Sx7/HQioy~K!mұosXrb0K9ⶍG5$ԩUeN.[rwڝI&l%d}+୴u[K)b=+Ԝ,Ϙ,|/[I?yDMğ%&E}>B [,Bۣ> b4%FӔ kےpk|@o1jcKපڰ\VdÊ竎KE$< t6F{<ˌO]6 vI0q<૘j:akӼ7elKXǩ@*x~4. Mx+Mr7~4ǍqXMW5DshI67/#RO2מ*Mץ2O|ԓJ'9N]Yz-F@g 5R_-Zn 0bG@*k#H7JN[KEdA[I2,}j71.̠<Œd~ܪ->B|1 9WvNNNI5 lԸT㩍|^yQLk~Uu!:f +}55(Qwd(Քdhd>BecFz֍[WL6.4&3`1&݉3TDm~5rKbm-Qu0A[]05fXygHۣfodd/o?0+К;Dy?9[_ɾbpj0F1*1XZx_Fn"N9}6;sgn}*UGT9m[OhQi%<6݃N 5ǚ@cUq^66:vǡOYFi'iCc-^n#Ҽ-ڧP1NsTuoh;u$ WUY@"{G~ue[OUm_FUZQr??ih^Nr{sg1I-+JgH[2fS7W5=ݻٗV;IeS{D'z}u \n{\:3ҽ[o4v5GQk+ry)iYz)NkYtUǖauxAu.Gkm*ˌ#*ƶ"`MY'bZ cA,ځxhִH[d[cC5xfH.^FUL9jiF)S;¤ }$} Ū[4A|*;Ėp+gethv{V֩3Q6WneIHQ\Z|_f$v O(nKxE͟I&{3 jzZ9`L1LW[kvG$R0{YDIZGz5Լ2ujjmz5c{_ yc\sҹ1U31,M}CxK;1ӭU>y.lW?hǦx6'Q'Z"2JG|>5Եh ykƗ"lj Oj#Hnn<=$]\NkKmWBZBq{+_ǖ\њmv>GcݍW-'<" ~Mn.1?.pe(Qq#A@=.0jF ܍E< qV#]):j(Sַ!>m)S8?04XF6=) Ory Jz')]3Nȵ{ N'֑Cl+&I+7/BI玕6jy ȏۗ#9~4g犎dW>mD)%a TA'$H*麘n`QTd(Yϭ<!@rOI[cm6dP:qLtvO S)*ǒ9A*_֣qW6;SbU$RH"!ޑ9B(7Jm:k]QEI!{Ӈ3VgB RdNHI֤joߌ4聫nfFq4a׎%ezuZlI$jЄP4Y ʃFH򤝋jȍ oMd`p=aHHQȤ6QÎdt5U``{Smf_(8T@|جFأΗ/r:OaF{6qk-–c[M|EkYsXXĆZnnqYC3GZSvE [,tP8nFH5vWi]1|]QBS+#M-u8F 8Ʋ4ƻ{!$5@19Q^%Jsɭ:7l@Xv%Tֺ&yJ:W|"qJvWlȵ ̜UHqUX8溢mbːJ=mpOpjk0H?(HKt>6TD͌J/81PMW$:# ;z6p +$ӭ RNԺD!mcT﵅W+4 T2ϙKPNd衕GsM#lM`Kjr_$z2sOg850$*zr!:Ҋ]G5"\sY~ricߥ4{GcUfӥYO6E*+gs[|BHǠ#luNHT73u5l#ӵsZuʴ`mÅs[ c9[nl9;A' YպdlUF9ȡU4I&N*I-$,8c=0 k3ޫKI):u9@ͅ\g2=aP=F7廓.HZrA-VV\*v-23(Oq*/s1L7qZvXztQڨORjj"6ݐ\nu%*s\0e (=ֳ, 'Е4gAOlJP\M\h͐ysw&61\xZCcdb`Ɏs\ʘ$~5}]}g؉6gvQ#LPB4A54ٝ'ަL&oNDk0jvҸQW9jŝN: zte{荹mcvIPY@vA;[*4c.G=+/ȠnŴ*e*qijk@D2(l~FV;zǹ*Q]tr;SJDXr5vRJL{YI@b2S`0DT8jKm,`Pǯ<5ZcV`–=G4/{aFucVRǰ=kRP0+jurONyṭ>=M/ *E[UQ&eCQDaa߭ՑrPx9 @#isV`HjgL5n[R$nowܚwsb]0BH޲z0)|M:GwVF#ptvF;Tƚz0kR ZhmQf͓3[Zj*3Z,:BHݝv$mthHeuMrzt[A k2{b#kS6%P,!iQ"ܮo}|+U XFvZuߖzL(áj3X]+]]{YUzמx\t /9ubuHMT4 B"኎I }Oz+m~gO5{՜')JtyE,xq^3g{up85vV|S(II##kzFwcc*:eP er:5 71,:Zk:6 +RڲU-c ڣhKR "<1Wu$B~B,-+5v6U\)n!KVHFq\R4KAWM<5^X~LqWm5uTXq5 i8l. te*sg5,MH㨨䷐ Mt v5a-mn{u9{-6IdVas|18?ʡmBJ7v9a*kعiVg*2IepyL@AYntf+Ce: ޵n!ڛc09T/?y?Nlys|'/aoP H+=ɬ%Fa^@Pa ðz-c24IRiKb}4Q/&+O[тp>nZ}1ZkFtjZDr }j)}F%oŮQ&FոL~֚~1r^NY;g|{*i5GIwJgkKɑyYG ;ۧԕAvKJ*/[P\,ڰ/$F#FǬ##0G*'m+沭NGC{f1$yzݼq^i9 1]Vq@2zTJ/x3X΢L0f^P%ϘLV,Q ܆F*U[S[r^Yq2pqEi#+^P߳0Ĥjƞr_HT 鴽h!y3[QHGJ翳5I<tz_-mqpZڱb`=sR'eE('i2.X_gf4f ljz<7q fxyžVyM:q]6rk&]%2,>oN7x-[LY';!yxtmvʌy;ȝܙR< ?R5>{-6cު7i"\M;4^i5[ 0Tnn7Z9;|fF[5@Gtu4Ym`7+NҦ@Eoz[*1nVR=vYmNj ٩ipqq <3L T%]Mb]>IvzRYEQ&x~Xsx^D)(qs[!9bMv2 7 ľ&Od'fs]TNZr9'71.<𾢷FXxno\E"(TspnM̑=A#BoTTҍ4E_ xB?[ =BHl’ȼm s:`0St.ьD+8ҕ%|55qDo[Qn+ֹcXSh#a+5lqئܾ'Jڲ#ŵ4Dבz% q ^bi!MV:nmɸt5.g+EChAP rc;7vpq\>*3O9#|RUXc].|PJot]Z`FQWx'VI֡,,~5-Um6+97haTl6wzNgpPFG$ԚާoDGyN6H'ʾ%N[]NpjEC|c"K)vUTU8?.gw1Ƚ1f3>%csXfM]ؖfc;h-$=7ľ1ffbz[_?)6'5_Msqq9SX]JqRwVFQN֤ܿ>lqY Gs>GjtI#%kDPSNJ##rGDs_CGR:,6bk~|-eN1kZ#?|75mIdC_C|=;IJi_׸>Ճ1r(;Uyk1GH38^xL|%KKmʌ60n1]dmhŽ4aU Kqm9>w7chQFy XF z?#) #Vt`Km5psi^)-f`7E\7wD *=CL#yZj06VJ+ݿ5FΖ#[_[\݈?JҸy'/K+;N,Y-R>dq[:Go-cZڟ΅8oM_ѱjiz9'g&%Ozie`DI t}"vuebq\x·2|kJrJ\̺rqًu=ԑ ]DդYm>j.ldd@pqQYCz=m,YuK5fy]ʚ6uAc| 䗌n>CX7wۏJpm2ޤ&I?c.!n~dTWܛy-2Gkwˎ<}r+,6k;\Q?V<%u\YC2cҺv\61z7%Ӗ(>VG-H{7Ur./˕b2~m_#/@Ե}R18o|%ܦ15K75f' bNSG''Y#ƍ EsT<=U[Z514]{ȓO &332#Q1x>99 V/XueF@TnR63#C $B1VGNsx#5R `cUI¡TЏbݕ;<'5b략7>Y]1$tc95"I 9V=)1dZ}B (S6s$c8,sE{hDԃM!i稧) 4Iȡe&1xa;dq߿N+.}Y_Ziwcޤ2 Q/9$b'x95p3Z|38&`sXsJMNPpZx$t(qɤC9+ }w7銑A8lq*< VVnJcE \Zn֗h+o5<%r9ǩe.z2L= .P<)t皴ƣnI[ؘڑD.A1^B(oCS$xfLz&T9*~^?-Hpvҫ+"p |猁=eM:i0z楲z8AHWcǵN9~PhO*Rv*; FTaV"gL*IL w =)  2)SƘ7|sWc6w"B'W֦B}twKRI>Py9jE R~+H(䓚p }sH8^ tÔdKžLI#wC}H87qv>2qzТ h0ƞ^6>P[+Cҁ9ࣥc0rXisZv+rڴ#8~Z(yN&NکI.NCg(Eny$昬ǁQEtE-g&*A 8o#hk;D`c]_>ȬcQEaVMEuaiM&zCcn6лyK! 0zhJZ2I#(&`w=WO#p:ETNjtjPZFU FsMqҊ+JFykÞ$Zo-QE|k{h8I7C|}24H(&.)Nl/9GCQ_yόyq2&vs̭) (ۛArջKyd'ZTv-<*m\uŒGVJ#aӒŠ(6 BGg0qҴs& Q]2rBmCA_3iin$E))r\/+;T9osu]6b88݌UfG朦M$c֊+ .ed೿cf>V V|BԔfIodcMhژyRG|QI6ˮvD= hp 瓊(#Q5^\ƃ8ϮMr>(ҖPv+LRumAlysu/DQErgBd$9b2@Zu ٢'Z~${0i[ąl8}hBVl渻fV=z4E\cEiE&1mŻ&э tl/Z(-:8fܱ>qHfUE)1-͔fw+u+[+"4QXߚZ Z7DF&D2'4Q[Κ&5+˨ OlrI+rgjsF#+1z&㱢ͣz֧ңpb+2{$T2VZ֮gٺ-shrrI35;l2d1yj((cXϛVvƬ_;7V٥g^\b3#fWڊ*FP+#p9ҭӣ:֊+zzoY7|WMcʯ4QWH/y##Rp8TK`AE9obkl*HASsEt6rV-,+*ղ]cvEdcKʆj cMu8; xM5j [ &N[3tR匟uFܲdV3czեIi DsE uuiCf͜ZˉaG\} +7M!(v.SZs[4+#ߏ]2Hŵ;*c+*1q[ӴpBniЈlظ(Q&,2DUj%E8붊([29Th>lVmY`qQviҏ.ƃZ,aU_z`XB #snDldʬu[w/9Vwi3oGy+#8m>"ԉ#QE]j0R)YHk>Ɇ9+ N\FquTS}3XJJu W m2VΜZn U;\t[ Zf`O\ULlZ(m2rܵocs{2[),h2I;g.HB5eqna.Q*1S%t"Ĩ-[Zgّe+ V(Oi(KBgcqimW\}:Ut}jPI4Q[sseWCn,-B2J庚{]j{UHیȢRF>rݑgeyICu5?QKGBI6\p`rr9w^ҭcB<WڨioC*OH `590^29Q]-$b߽aҭ=y!=h2V-iö8qQQځۮS4QZ-\c*L^VGqX:>vyIV0\Yj G}jqEdz=j7ŧg袮8XeJqK~mVdF QR9[+ ҕMH-M"hc?)_WS?~4QOZRzi(-o-EA_EF6[z3(jn+cIG0fCj{&bhNe|#JBf(i%$I7W\JTtS4QR:-+gLMc埌s^ɦhxP^+eN*\C˚ў)kމJ[uȫi6_/^Nhg)&C^*hmd 2vx?ďI wQ[ٲ7/C|Ker& 7$뙹6͜Er՛m#)E]S33x{71 n2W*iCon-Ns]1(:b+9ɭhK/K8.<CiFe V+ĵg ,Md)w2YAFrEsTR/ZT s+4{[H҂~\czT"Fz(1> ݪh'梊lerT?Sӵ?SX-Ci(kwZ!@E:m)Rj=[_pRO=袚ԙɫXmՀZuYSv8;+ExNME mv[A#v,xŸ=FEU=LUVc'>1EI&6DLAJ(CXt$}hk4:7b uT*t>QDFz )ؼvn c7q{OAqE&TjoLQE&dPzuP8(;IA(@==s4QVBLJT:8( $d <ӟMVw*jdgp &+]3CP6QAE6,NHC ^T )h8+D (GgEE S%$/QN\QoQWK}Qr[?kore/examples/generic/assets/private.html0000644000175000001440000000057412527355513020175 0ustar jorisusers Kore Authentication tests

The cookie session_id should now be set.

You can continue to view page handler in auth block

kore/examples/generic/assets/upload.html0000644000175000001440000000077512527355513020012 0ustar jorisusers Kore upload test

$upload$

$firstname$

kore/examples/generic/assets/style.css0000644000175000001440000000034012527355513017476 0ustar jorisusersbody { width: 100%; margin: 0px; color: #000; overflow: hidden; background-color: #fff; } .content { width: 800px; margin-left: auto; margin-right: auto; margin-top: 100px; font-size: 60px; text-align: center; } kore/examples/generic/assets/index.html0000644000175000001440000000034712527355513017630 0ustar jorisusers Your KORE module worked!

Your first Kore module worked.

kore/examples/headers/0000755000175000001440000000000012527355513014324 5ustar jorisuserskore/examples/headers/README.md0000644000175000001440000000037112527355513015604 0ustar jorisusersExample on how to read HTTP request headers and set your own custom ones. Run: ``` # kore run ``` Test: ``` # curl -H "X-Custom-Header: testing" -i -k https://127.0.0.1:8888 ``` If X-Custom-Header is given, it will be mirrored in the response. kore/examples/headers/conf/0000755000175000001440000000000012527355513015251 5ustar jorisuserskore/examples/headers/conf/headers.conf0000755000175000001440000000026612527355513017542 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./headers.so tls_dhparam dh2048.pem domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page } kore/examples/headers/.gitignore0000755000175000001440000000004312527355513016314 0ustar jorisusers*.o .objs headers.so assets.h cert kore/examples/headers/src/0000755000175000001440000000000012527355514015114 5ustar jorisuserskore/examples/headers/src/headers.c0000755000175000001440000000130112527355514016671 0ustar jorisusers#include #include int page(struct http_request *); int page(struct http_request *req) { char *custom; /* * We'll lookup if the X-Custom-Header is given in the request. * If it is we'll set it as a response header as well. * * The value returned by http_request_header() must be freed. * * NOTE: All custom headers you set must be in lower case due to * the SPDYv3 specification requiring this. */ if (http_request_header(req, "x-custom-header", &custom)) { http_response_header(req, "x-custom-header", custom); kore_mem_free(custom); } /* Return 200 with "ok\n" to the client. */ http_response(req, 200, "ok\n", 3); return (KORE_RESULT_OK); } kore/examples/pgsql/0000755000175000001440000000000012527355514014040 5ustar jorisuserskore/examples/pgsql/README.md0000644000175000001440000000051612527355514015321 0ustar jorisusersKore pgsql example. This example demonstrates how one can use Kore state machines and the pgsql api to make fully asynchronous SQL queries. Asynchronous in this case meaning, without interrupting a Kore worker its other clients their I/O or http requests. Tons of comments inside on how everything works. Run: ``` # kore run ``` kore/examples/pgsql/conf/0000755000175000001440000000000012527355514014765 5ustar jorisuserskore/examples/pgsql/conf/pgsql.conf0000755000175000001440000000032012527355514016760 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./pgsql.so init tls_dhparam dh2048.pem http_keepalive_time 0 domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page } kore/examples/pgsql/.gitignore0000755000175000001440000000004112527355514016026 0ustar jorisusers*.o .objs pgsql.so assets.h cert kore/examples/pgsql/src/0000755000175000001440000000000012527355514014627 5ustar jorisuserskore/examples/pgsql/src/pgsql.c0000644000175000001440000001335212527355514016125 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * This example demonstrates on how to use state machines and * asynchronous pgsql queries. * * While this example might seem overly complex for a simple pgsql * query, there is a reason behind its complexity: * Asynchronous pgsql queries mean that Kore will not block while * executing the queries, giving a worker time to continue handling * other events such as I/O or other http requests. * * The state machine framework present in Kore makes it trivial * to get going into dropping from your page handler into the right * state that you are currently in. * * The example connects to a local pgsql database (test) using a table * called "coders" (which has 2 columns): name, surname. */ #include #include #include #define REQ_STATE_QUERY 0 #define REQ_STATE_DB_WAIT 1 #define REQ_STATE_DB_READ 2 #define REQ_STATE_ERROR 3 #define REQ_STATE_DONE 4 int init(int); int page(struct http_request *); static int request_perform_query(struct http_request *); static int request_db_wait(struct http_request *); static int request_db_read(struct http_request *); static int request_error(struct http_request *); static int request_done(struct http_request *); struct http_state mystates[] = { { "REQ_STATE_QUERY", request_perform_query }, { "REQ_STATE_DB_WAIT", request_db_wait }, { "REQ_STATE_DB_READ", request_db_read }, { "REQ_STATE_ERROR", request_error }, { "REQ_STATE_DONE", request_done }, }; #define mystates_size (sizeof(mystates) / sizeof(mystates[0])) struct rstate { struct kore_pgsql sql; }; /* Called when our module is loaded (see config) */ int init(int state) { /* Set our connection string. */ pgsql_conn_string = "host=/var/run/postgresql/ dbname=test"; return (KORE_RESULT_OK); } /* Page handler entry point (see config) */ int page(struct http_request *req) { /* Drop into our state machine. */ kore_log(LOG_NOTICE, "page start"); return (http_state_run(mystates, mystates_size, req)); } /* The initial state, we setup our context and fire off the pgsql query. */ int request_perform_query(struct http_request *req) { struct rstate *state; /* Setup our state context. */ state = kore_malloc(sizeof(*state)); /* Attach the state to our request. */ req->hdlr_extra = state; /* We want to move to read result after this. */ req->fsm_state = REQ_STATE_DB_WAIT; /* Fire off the query. */ if (!kore_pgsql_query(&state->sql, req, "SELECT * FROM coders")) { /* If the state was still INIT, we'll try again later. */ if (state->sql.state == KORE_PGSQL_STATE_INIT) { req->fsm_state = REQ_STATE_QUERY; return (HTTP_STATE_RETRY); } /* * Let the state machine continue immediately since we * have an error anyway. */ return (HTTP_STATE_CONTINUE); } /* Resume state machine later when the query results start coming in. */ return (HTTP_STATE_RETRY); } /* * After firing off the query, we returned HTTP_STATE_RETRY (see above). * When request_db_wait() finally is called by Kore we will have results * from pgsql so we'll process them. */ int request_db_wait(struct http_request *req) { struct rstate *state = req->hdlr_extra; kore_log(LOG_NOTICE, "request_db_wait: %d", state->sql.state); /* * When we get here, our asynchronous pgsql query has * given us something, check the state to figure out what. */ switch (state->sql.state) { case KORE_PGSQL_STATE_WAIT: return (HTTP_STATE_RETRY); case KORE_PGSQL_STATE_COMPLETE: req->fsm_state = REQ_STATE_DONE; break; case KORE_PGSQL_STATE_ERROR: req->fsm_state = REQ_STATE_ERROR; kore_pgsql_logerror(&state->sql); break; case KORE_PGSQL_STATE_RESULT: req->fsm_state = REQ_STATE_DB_READ; break; default: /* This MUST be present in order to advance the pgsql state */ kore_pgsql_continue(req, &state->sql); break; } return (HTTP_STATE_CONTINUE); } /* * Called when there's an actual result to be gotten. After we handle the * entire result, we'll drop back into REQ_STATE_DB_WAIT (above) in order * to continue until the pgsql API returns KORE_PGSQL_STATE_COMPLETE. */ int request_db_read(struct http_request *req) { char *name; int i, rows; struct rstate *state = req->hdlr_extra; /* We have sql data to read! */ rows = kore_pgsql_ntuples(&state->sql); for (i = 0; i < rows; i++) { name = kore_pgsql_getvalue(&state->sql, i, 0); kore_log(LOG_NOTICE, "name: '%s'", name); } /* Continue processing our query results. */ kore_pgsql_continue(req, &state->sql); /* Back to our DB waiting state. */ req->fsm_state = REQ_STATE_DB_WAIT; return (HTTP_STATE_CONTINUE); } /* An error occurred. */ int request_error(struct http_request *req) { struct rstate *state = req->hdlr_extra; kore_pgsql_cleanup(&state->sql); http_response(req, 500, NULL, 0); return (HTTP_STATE_COMPLETE); } /* Request was completed succesfully. */ int request_done(struct http_request *req) { struct rstate *state = req->hdlr_extra; kore_pgsql_cleanup(&state->sql); http_response(req, 200, NULL, 0); return (HTTP_STATE_COMPLETE); } kore/examples/parameters/0000755000175000001440000000000012527355514015055 5ustar jorisuserskore/examples/parameters/README.md0000644000175000001440000000041412527355514016333 0ustar jorisusersExample on how to handle GET/POST parameters in Kore. Run: ``` # kore run ``` Test: ``` # curl -i -k https://127.0.0.1:8888/?id=123123 ``` The output will differ based on wether or not id is a valid u_int16_t number or not. (the string should always be present). kore/examples/parameters/conf/0000755000175000001440000000000012527355514016002 5ustar jorisuserskore/examples/parameters/conf/parameters.conf0000755000175000001440000000123412527355514021017 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./parameters.so tls_dhparam dh2048.pem # The validator used to validate the 'id' parameter # defined below. We'll use a simple regex to make sure # it only matches positive numbers. validator v_id regex ^[0-9]*$ domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page # The parameters allowed for "/" (GET method). # # If you would want to declare parameters available # to the page handler for POST, swap the 'get' setting # to 'post' instead, Kore takes care of the rest. params get / { # Validate the id parameter with the v_id validator. validate id v_id } } kore/examples/parameters/.gitignore0000755000175000001440000000004612527355514017050 0ustar jorisusers*.o .objs parameters.so assets.h cert kore/examples/parameters/src/0000755000175000001440000000000012527355514015644 5ustar jorisuserskore/examples/parameters/src/parameters.c0000755000175000001440000000556512527355514020171 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include int page(struct http_request *); int page(struct http_request *req) { int p; u_int16_t id; u_int32_t len; char *sid; struct kore_buf *buf; /* * Before we are able to obtain any parameters given to * us via the query string we must tell Kore to parse and * validate them. * * NOTE: All parameters MUST be declared in a params {} block * inside the configuration for Kore! Kore will filter out * any parameters not explicitly defined. * * See conf/parameters.conf on how that is done, this is an * important step as without the params block you will never * get any parameters returned from Kore. * * http_populate_arguments() returns the number of arguments * that were successfully processed and are available. */ p = http_populate_arguments(req); /* If we had no arguments available what so ever, return 400. */ if (p == 0) { http_response(req, 400, NULL, 0); return (KORE_RESULT_OK); } /* * Lets grab the "id" parameter if available. Kore can obtain * parameters in different data types native to C. * * In this scenario, lets grab it both as an actual string and * as an u_int16_t (unsigned short). * * If you grab it as a string, you can immediately ask for * the correct length as well, excluding the NUL terminator. * * When trying to obtain a parameter as something else then * a string, Kore will automatically check if the value fits * in said data type. * * For example if id is 65536 it won't fit in an u_int16_t * and Kore will return an error when trying to read it as such. */ buf = kore_buf_create(128); /* Grab it as a string, we shouldn't free the result in sid. */ if (http_argument_get_string("id", &sid, &len)) kore_buf_appendf(buf, "id as a string: '%s' (%d)\n", sid, len); /* Grab it as an actual u_int16_t. */ if (http_argument_get_uint16("id", &id)) kore_buf_appendf(buf, "id as an u_int16_t: %d\n", id); /* Now return the result to the client with a 200 status code. */ http_response(req, 200, buf->data, buf->offset); kore_buf_free(buf); return (KORE_RESULT_OK); } kore/examples/sse/0000755000175000001440000000000012527355514013504 5ustar jorisuserskore/examples/sse/README.md0000644000175000001440000000051112527355514014760 0ustar jorisusersThis example demonstrates SSE (Server Side Events) in Kore. Run: ``` $ kore run ``` Test (run different times to see the events broadcast): ``` curl -H 'accept: text/event-stream' -ik https://127.0.0.1:8888/subscribe ``` If you point a browser to https://127.0.0.1:8888 you will see a small log of what events are arriving. kore/examples/sse/conf/0000755000175000001440000000000012527355514014431 5ustar jorisuserskore/examples/sse/conf/sse.conf0000755000175000001440000000037712527355514016104 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./sse.so tls_dhparam dh2048.pem http_keepalive_time 600 spdy_idle_time 600 domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page static /subscribe subscribe } kore/examples/sse/.gitignore0000755000175000001440000000003712527355514015477 0ustar jorisusers*.o .objs sse.so assets.h cert kore/examples/sse/src/0000755000175000001440000000000012527355514014273 5ustar jorisuserskore/examples/sse/src/sse.c0000755000175000001440000001532012527355514015235 0ustar jorisusers/* * Copyright (c) 2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Simple example of how SSE (Server Side Events) could be used in Kore. * We deal with SSE both over normal HTTP/1.1 and over SPDY connections. * * Upon new arrivals, a join event is broadcast to all clients. * If a client goes away a leave event is broadcasted. * Each connection gets its own 10 second ping timer which will emit * a ping event to the connection endpoint. */ #include #include #include "assets.h" int page(struct http_request *); int subscribe(struct http_request *); void sse_disconnect(struct connection *); void sse_ping(void *, u_int64_t, u_int64_t); void sse_send(struct connection *, void *, size_t); void sse_broadcast(struct connection *, void *, size_t); void sse_spdy_stream_closed(struct connection *, struct spdy_stream *); int check_header(struct http_request *, const char *, const char *); /* * Each client subscribed to our SSE gets a state attached * to their hdlr_extra pointer member. */ struct sse_state { struct spdy_stream *stream; struct kore_timer *timer; }; int page(struct http_request *req) { if (req->method != HTTP_METHOD_GET) { http_response_header(req, "allow", "get"); http_response(req, 405, NULL, 0); return (KORE_RESULT_OK); } http_response_header(req, "content-type", "text/html"); http_response(req, 200, asset_index_html, asset_len_index_html); return (KORE_RESULT_OK); } int subscribe(struct http_request *req) { struct sse_state *state; char *hello = "event:join\ndata: client\n\n"; /* Preventive paranoia. */ if (req->hdlr_extra != NULL) { kore_log(LOG_ERR, "%p: already subscribed", req->owner); http_response(req, 500, NULL, 0); return (KORE_RESULT_OK); } /* Only allow GET methods. */ if (req->method != HTTP_METHOD_GET) { http_response_header(req, "allow", "get"); http_response(req, 405, NULL, 0); return (KORE_RESULT_OK); } /* Only do SSE if the client told us it wanted too. */ if (!check_header(req, "accept", "text/event-stream")) return (KORE_RESULT_OK); /* Do not include content-length in our response. */ req->flags |= HTTP_REQUEST_NO_CONTENT_LENGTH; /* Notify existing clients of our new client now. */ sse_broadcast(req->owner, hello, strlen(hello)); /* Set a disconnection method so we know when this client goes away. */ req->owner->disconnect = sse_disconnect; /* For non SPDY clients we do not expect any more data to arrive. */ if (req->owner->proto != CONN_PROTO_SPDY) req->owner->flags |= CONN_READ_BLOCK; /* Allocate a state to be carried by our connection. */ state = kore_malloc(sizeof(*state)); state->stream = req->stream; req->owner->hdlr_extra = state; /* SSE over SPDY will need this extra love. */ if (req->owner->proto == CONN_PROTO_SPDY) { /* Unset the http request attached to our SPDY stream. */ req->stream->httpreq = NULL; /* * Do not let the stream close unless a RST occurs or * until we close it ourselves. */ req->stream->flags |= SPDY_NO_CLOSE; /* Set a callback in case this stream gets a RST. */ req->stream->onclose = sse_spdy_stream_closed; } /* Now start a timer to send a ping back every 10 second. */ state->timer = kore_timer_add(sse_ping, 10000, req->owner, 0); /* Respond that the SSE channel is now open. */ kore_log(LOG_NOTICE, "%p: connected for SSE", req->owner); http_response_header(req, "content-type", "text/event-stream"); http_response(req, 200, NULL, 0); return (KORE_RESULT_OK); } void sse_broadcast(struct connection *src, void *data, size_t len) { struct connection *c; /* Broadcast the message to all other clients. */ TAILQ_FOREACH(c, &worker_clients, list) { if (c == src) continue; sse_send(c, data, len); } } void sse_send(struct connection *c, void *data, size_t len) { struct sse_state *state = c->hdlr_extra; /* Do not send to clients that do not have a state. */ if (state == NULL) return; /* SPDY connections need this extra bit of magic. */ if (c->proto == CONN_PROTO_SPDY) { if (state->stream == NULL) { kore_log(LOG_ERR, "no SPDY stream for sse_send()"); kore_connection_disconnect(c); return; } /* * Tell Kore to send a dataframe prelude + increase the * length of our stream to be sent. */ if (state->stream->send_size == 0) state->stream->flags |= SPDY_DATAFRAME_PRELUDE; state->stream->send_size += len; } /* Queue outgoing data now. */ net_send_queue(c, data, len, state->stream, NETBUF_LAST_CHAIN); net_send_flush(c); } void sse_ping(void *arg, u_int64_t now, u_int64_t delta) { struct connection *c = arg; char *ping = "event:ping\ndata:\n\n"; /* Send our ping to the client. */ sse_send(c, ping, strlen(ping)); } void sse_disconnect(struct connection *c) { struct sse_state *state = c->hdlr_extra; char *leaving = "event: leave\ndata: client\n\n"; kore_log(LOG_NOTICE, "%p: disconnecting for SSE", c); /* Tell others we are leaving. */ sse_broadcast(c, leaving, strlen(leaving)); /* Make sure we cleanup our hooked stream if any. */ if (c->proto == CONN_PROTO_SPDY && state->stream != NULL) { state->stream->onclose = NULL; spdy_stream_close(c, state->stream, SPDY_REMOVE_NETBUFS); } /* Kill our timer and free/remove the state. */ kore_timer_remove(state->timer); kore_mem_free(state); /* Prevent us to be called again. */ c->hdlr_extra = NULL; c->disconnect = NULL; } void sse_spdy_stream_closed(struct connection *c, struct spdy_stream *s) { struct sse_state *state = c->hdlr_extra; /* Paranoia. */ if (state->stream != s) { state->stream = NULL; kore_connection_disconnect(c); return; } /* Set our stream to NULL and call sse_disconnect. */ state->stream = NULL; sse_disconnect(c); } int check_header(struct http_request *req, const char *name, const char *value) { char *hdr; if (!http_request_header(req, name, &hdr)) { http_response(req, 400, NULL, 0); return (KORE_RESULT_ERROR); } if (strcmp(hdr, value)) { kore_mem_free(hdr); http_response(req, 400, NULL, 0); return (KORE_RESULT_ERROR); } kore_mem_free(hdr); return (KORE_RESULT_OK); } kore/examples/sse/assets/0000755000175000001440000000000012527355514015006 5ustar jorisuserskore/examples/sse/assets/index.html0000755000175000001440000000212312527355514017004 0ustar jorisusers

events

kore/examples/websocket/0000755000175000001440000000000012527355514014700 5ustar jorisuserskore/examples/websocket/README.md0000644000175000001440000000072212527355514016160 0ustar jorisusersKore example websocket server Run: ``` # kore run ``` Test: ``` Open a browser that does websockets, surf to https://127.0.0.1:8888 or whatever configured IP you have in the config. Hit the connect button to open a websocket session, open a second tab and surf to the same address and hit the connection button there as well. This should cause the number of messages sent/recv to keep incrementing as each message is broadcast to the other connection. ``` kore/examples/websocket/conf/0000755000175000001440000000000012527355514015625 5ustar jorisuserskore/examples/websocket/conf/websocket.conf0000755000175000001440000000041112527355514020461 0ustar jorisusers# Kore websocket example bind 127.0.0.1 8888 load ./websocket.so tls_dhparam dh2048.pem websocket_maxframe 65536 websocket_timeout 20 domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page static /connect page_ws_connect } kore/examples/websocket/.gitignore0000755000175000001440000000004512527355514016672 0ustar jorisusers*.o .objs websocket.so assets.h cert kore/examples/websocket/src/0000755000175000001440000000000012527355514015467 5ustar jorisuserskore/examples/websocket/src/websocket.c0000755000175000001440000000374012527355514017630 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "assets.h" int page(struct http_request *); int page_ws_connect(struct http_request *); void websocket_connect(struct connection *); void websocket_disconnect(struct connection *); void websocket_message(struct connection *, u_int8_t, void *, size_t); /* Websocket callbacks. */ struct kore_wscbs wscbs = { websocket_connect, websocket_message, websocket_disconnect }; /* Called whenever we get a new websocket connection. */ void websocket_connect(struct connection *c) { kore_log(LOG_NOTICE, "%p: connected", c); } void websocket_message(struct connection *c, u_int8_t op, void *data, size_t len) { kore_websocket_broadcast(c, op, data, len, WEBSOCKET_BROADCAST_LOCAL); } void websocket_disconnect(struct connection *c) { kore_log(LOG_NOTICE, "%p: disconnecting", c); } int page(struct http_request *req) { http_response_header(req, "content-type", "text/html"); http_response(req, 200, asset_frontend_html, asset_len_frontend_html); return (KORE_RESULT_OK); } int page_ws_connect(struct http_request *req) { /* Perform the websocket handshake, passing our callbacks. */ kore_websocket_handshake(req, &wscbs); return (KORE_RESULT_OK); } kore/examples/websocket/assets/0000755000175000001440000000000012527355514016202 5ustar jorisuserskore/examples/websocket/assets/frontend.html0000644000175000001440000000202412527355514020705 0ustar jorisusers
kore/examples/tasks/0000755000175000001440000000000012527355514014037 5ustar jorisuserskore/examples/tasks/README.md0000644000175000001440000000063212527355514015317 0ustar jorisusersKore task example. This example creates an asynchronous task from the page handler that performs a POST to the same server and fetches its data before returning to the client. Build: ``` # env LDFLAGS="-I/path/to/libcurl -lcurl" kore build ``` Run: ``` # kore run ``` Test: ``` # curl -i -k https://127.0.0.1:8888/?user=astring The returned data must match what you supplied in user ([a-z] string) ``` kore/examples/tasks/conf/0000755000175000001440000000000012527355514014764 5ustar jorisuserskore/examples/tasks/conf/tasks.conf0000644000175000001440000000057712527355514016771 0ustar jorisusers# Kore config for tasks example bind 127.0.0.1 8888 load ./tasks.so tls_dhparam dh2048.pem validator v_user regex ^[a-z]*$ domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key accesslog kore_access.log static / page_handler static /post_back post_back params get / { validate user v_user } params post /post_back { validate user v_user } } kore/examples/tasks/src/0000755000175000001440000000000012527355514014626 5ustar jorisuserskore/examples/tasks/src/tasks.c0000644000175000001440000001450512527355514016124 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * In this example, we use the background tasks available in Kore * to fire off a POST to our /post_back page handler containing * the user argument that was passed to us in our GET request to /. * * This illustrates how Kore its background tasks in effect work and * how to operate on the channel in order to pass data back and forth. * * You need libcurl installed for this to build (including headers) * * Read README.md on how to build and run this example. */ #include #include #include #include int run_curl(struct kore_task *); int post_back(struct http_request *); int page_handler(struct http_request *); size_t curl_write_cb(char *, size_t, size_t, void *); struct rstate { struct kore_task task; }; int page_handler(struct http_request *req) { u_int32_t len; struct rstate *state; char *user, result[64]; /* * Lets check if a task has been created yet, this is important * as we only want to fire this off once and we will be called * again once it has been created. * * In this example, we'll store our state with our task in hdlr_extra. */ if (req->hdlr_extra == NULL) { /* Grab the user argument */ http_populate_arguments(req); if (!http_argument_get_string("user", &user, &len)) { http_response(req, 500, "ERROR\n", 6); return (KORE_RESULT_OK); } /* * Allocate rstate and bind it to the hdlr_extra field. * Kore automatically frees this when freeing the result. */ state = kore_malloc(sizeof(*state)); req->hdlr_extra = state; /* * Create a new task that will execute the run_curl() * function and bind it to our request. * * Binding a task to a request means Kore will reschedule * the page handler for that request to refire after the * task has completed or when it writes on the task channel. */ kore_task_create(&state->task, run_curl); kore_task_bind_request(&state->task, req); /* * Start the task and write the user we received in our * GET request to its channel. */ kore_task_run(&state->task); kore_task_channel_write(&state->task, user, len); /* * Tell Kore to retry us later. */ return (KORE_RESULT_RETRY); } else { state = req->hdlr_extra; } /* * Our page handler is scheduled to be called when either the * task finishes or has written data onto the channel. * * In order to distinguish between the two we can inspect the * state of the task. */ if (kore_task_state(&state->task) != KORE_TASK_STATE_FINISHED) { http_request_sleep(req); return (KORE_RESULT_RETRY); } /* * Task is finished, check the result. */ if (kore_task_result(&state->task) != KORE_RESULT_OK) { kore_task_destroy(&state->task); http_response(req, 500, NULL, 0); return (KORE_RESULT_OK); } /* * Lets read what our task has written to the channel. * * kore_task_channel_read() will return the amount of bytes * that it received for that read. If the returned bytes is * larger then the buffer you passed this is a sign of truncation * and should be treated carefully. */ len = kore_task_channel_read(&state->task, result, sizeof(result)); if (len > sizeof(result)) { http_response(req, 500, NULL, 0); } else { http_response(req, 200, result, len); } /* We good, destroy the task. */ kore_task_destroy(&state->task); return (KORE_RESULT_OK); } int post_back(struct http_request *req) { u_int32_t len; char *user; if (req->method != HTTP_METHOD_POST) { http_response(req, 500, NULL, 0); return (KORE_RESULT_OK); } http_populate_arguments(req); if (!http_argument_get_string("user", &user, &len)) { http_response(req, 500, NULL, 0); return (KORE_RESULT_OK); } /* Simply echo the supplied user argument back. */ http_response(req, 200, user, len); return (KORE_RESULT_OK); } /* * This is the function that is executed by our task which is created * in the page_handler() callback. * * It sets up a CURL POST request to /post_back passing along the * user argument which it receives from its channel from page_handler(). */ int run_curl(struct kore_task *t) { struct kore_buf *b; u_int32_t len; CURLcode res; u_int8_t *data; CURL *curl; char user[64], fields[128]; /* * Read the channel in order to obtain the user argument * that was written to it by page_handler(). */ len = kore_task_channel_read(t, user, sizeof(user)); if (len > sizeof(user)) return (KORE_RESULT_ERROR); if (!kore_snprintf(fields, sizeof(fields), NULL, "user=%.*s", len, user)) return (KORE_RESULT_ERROR); if ((curl = curl_easy_init()) == NULL) return (KORE_RESULT_ERROR); b = kore_buf_create(128); /* Do CURL magic. */ curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_WRITEDATA, b); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb); curl_easy_setopt(curl, CURLOPT_URL, "https://127.0.0.1:8888/post_back"); res = curl_easy_perform(curl); if (res != CURLE_OK) { kore_buf_free(b); curl_easy_cleanup(curl); return (KORE_RESULT_ERROR); } /* * Grab the response from the CURL request and write the * result back to the task channel. */ data = kore_buf_release(b, &len); kore_task_channel_write(t, data, len); kore_mem_free(data); return (KORE_RESULT_OK); } size_t curl_write_cb(char *ptr, size_t size, size_t nmemb, void *udata) { struct kore_buf *b = udata; kore_buf_append(b, ptr, size * nmemb); return (size * nmemb); } kore/examples/json_yajl/0000755000175000001440000000000012527355514014702 5ustar jorisuserskore/examples/json_yajl/README.md0000644000175000001440000000072012527355514016160 0ustar jorisusersThis example demonstrates how you can use external libs in your application. In this case we link against yajl (Yet Another JSON library) in order to parse a JSON string that was POSTed to the server. Run: ``` env LDFLAGS="-lyajl" kore run ``` Test: ``` curl -i -k -d '{"foo":{"bar": "Hello world"}}' https://127.0.0.1:8888 ``` The result should echo back the foo.bar JSON path value: Hello world. The yajl repo is available @ https://github.com/lloyd/yajl kore/examples/json_yajl/conf/0000755000175000001440000000000012527355514015627 5ustar jorisuserskore/examples/json_yajl/conf/json_yajl.conf0000755000175000001440000000027112527355514020471 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./json_yajl.so tls_dhparam dh2048.pem domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page } kore/examples/json_yajl/.gitignore0000755000175000001440000000004512527355514016674 0ustar jorisusers*.o .objs json_yajl.so assets.h cert kore/examples/json_yajl/src/0000755000175000001440000000000012527355514015471 5ustar jorisuserskore/examples/json_yajl/src/json_yajl.c0000755000175000001440000000307312527355514017633 0ustar jorisusers#include #include #include int page(struct http_request *); int page(struct http_request *req) { struct kore_buf *buf; char *body; yajl_val node, v; char eb[1024]; const char *path[] = { "foo", "bar", NULL }; /* We only allow POST/PUT methods. */ if (req->method != HTTP_METHOD_POST && req->method != HTTP_METHOD_PUT) { http_response_header(req, "allow", "POST, PUT"); http_response(req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0); return (KORE_RESULT_OK); } /* * Grab the entire body we received as text (NUL-terminated). * Note: this can return NULL and the result MUST be freed. */ if ((body = http_body_text(req)) == NULL) { http_response(req, 400, NULL, 0); return (KORE_RESULT_OK); } /* Parse the body via yajl now. */ node = yajl_tree_parse(body, eb, sizeof(eb)); if (node == NULL) { if (strlen(eb)) { kore_log(LOG_NOTICE, "parse error: %s", eb); } else { kore_log(LOG_NOTICE, "parse error: unknown"); } kore_mem_free(body); http_response(req, 400, NULL, 0); return (KORE_RESULT_OK); } buf = kore_buf_create(128); /* Attempt to grab foo.bar from the JSON tree. */ v = yajl_tree_get(node, path, yajl_t_string); if (v == NULL) { kore_buf_appendf(buf, "no such path: foo.bar\n"); } else { kore_buf_appendf(buf, "foo.bar = '%s'\n", YAJL_GET_STRING(v)); } /* Release the JSON tree now. */ yajl_tree_free(node); kore_mem_free(body); /* Respond to the client. */ http_response(req, 200, buf->data, buf->offset); kore_buf_free(buf); return (KORE_RESULT_OK); } kore/examples/cpp/0000755000175000001440000000000012527355513013473 5ustar jorisuserskore/examples/cpp/README.md0000644000175000001440000000117712527355513014760 0ustar jorisusersKore example showing how to use C++ support! All functions accessible to kore must have their prototypes wrapped with the extern keyword like so: ``` extern “C” { int pageA(struct http_request *); int pageB(struct http_request *); int validatorA(struct http_request *, char *); } ``` In order to run this example with the default C++ settings (default compiler dialect, libstdc++): ``` # kore run ``` In order to run with a specific dialect and C++ runtime: ``` # env CXXSTD=c++11 CXXLIB=c++ kore run ``` You can also supply your own compiler combined with the above: ``` # env CC=clang++ CXXSTD=c++11 CXXLIB=c++ kore run ``` kore/examples/cpp/conf/0000755000175000001440000000000012527355513014420 5ustar jorisuserskore/examples/cpp/conf/cpp.conf0000755000175000001440000000026112527355513016053 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./cpp.so tls_dhparam dh2048.pem domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page } kore/examples/cpp/.gitignore0000644000175000001440000000003712527355513015463 0ustar jorisusers*.o .objs cpp.so assets.h cert kore/examples/cpp/src/0000755000175000001440000000000012527355513014262 5ustar jorisuserskore/examples/cpp/src/example_class.cpp0000644000175000001440000000167412527355513017616 0ustar jorisusers/* * Copyright (c) 2015 Jonathan Goodman * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "example_class.h" example_class::example_class() { } example_class::~example_class() { } const char * example_class::a() { return "Hello world!"; } kore/examples/cpp/src/example_class.h0000644000175000001440000000175512527355513017263 0ustar jorisusers/* * Copyright (c) 2015 Jonathan Goodman * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef ____example_class__ #define ____example_class__ #include class example_class { public: example_class(); ~example_class(); const char *a(); }; #endif /* defined(____example_class__) */ kore/examples/cpp/src/cpp.cpp0000755000175000001440000000215412527355513015555 0ustar jorisusers/* * Copyright (c) 2015 Jonathan Goodman * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "example_class.h" extern "C" { int page(struct http_request *); } int page(struct http_request *req) { example_class example; const char *str = example.a(); http_response(req, 200, static_cast(const_cast(str)), strlen(str)); return (KORE_RESULT_OK); } kore/examples/cpp/dh2048.pem0000755000175000001440000000064712527355513015121 0ustar jorisusers-----BEGIN DH PARAMETERS----- MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/ PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg== -----END DH PARAMETERS-----kore/examples/ktunnel/0000755000175000001440000000000012527355514014372 5ustar jorisuserskore/examples/ktunnel/README.md0000644000175000001440000000107312527355514015652 0ustar jorisusersKTunnel (anything over HTTPS) This example demonstrates how we can use Kore to create an anything-over-HTTPS tunnel. Build: ``` # kore build ``` Run: ``` # kore run ``` Test: ``` # openssl s_client -connect 127.0.0.1:8888 Then enter: GET /connect?host=74.125.232.248&port=80 HTTP/1.1 Host: 127.0.0.1 GET / HTTP/1.1 Host: www.google.se (And hit enter) ``` You should see Kore connect to the google server given and return the results back to you. A client for OSX exists under the **client/** directory. It requires you to link with -lssl and -lcrypto. kore/examples/ktunnel/client/0000755000175000001440000000000012527355514015650 5ustar jorisuserskore/examples/ktunnel/client/Makefile0000644000175000001440000000064212527355514017312 0ustar jorisusers# # You probably want to change the include and library # paths before compiling. # CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wsign-compare -Iincludes -g CFLAGS+=-I../../openssl-1.0.1i/include all: gcc $(CFLAGS) -c client.c -o client.o gcc -L../../openssl-1.0.1i/ client.o -o client -lcrypto -lssl clean: rm -f client *.o kore/examples/ktunnel/client/client.c0000755000175000001440000003602312527355514017301 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include "openssl/err.h" #include "openssl/ssl.h" #include #include #include #include #include #include #include #include #define errno_s strerror(errno) #define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) #define KQUEUE_EVENT_COUNT 100 #define NETBUF_RECV_MAX 8192 #define HTTP_REQUEST_FMT \ "GET %s?host=%s&port=%s HTTP/1.1\r\nHost: %s\r\n\r\n" struct netbuf { u_int8_t *data; u_int32_t offset; u_int32_t length; TAILQ_ENTRY(netbuf) list; }; TAILQ_HEAD(netbuf_list, netbuf); #define PEER_CAN_READ 0x01 #define PEER_CAN_WRITE 0x02 struct peer { int fd; int family; int flags; char *name; char *host; char *port; int (*write)(struct peer *); int (*read)(struct peer *, struct peer *); SSL *ssl; SSL_CTX *ssl_ctx; void *connection; struct peer *opposite; struct netbuf *recv_buf; struct netbuf_list write_queue; }; #define CONNECTION_WILL_DISCONNECT 0x01 struct connection { int flags; struct peer local; struct peer remote; TAILQ_ENTRY(connection) list; }; TAILQ_HEAD(, connection) clients; TAILQ_HEAD(, connection) disconnects; void usage(void); void fatal(const char *, ...); int ktunnel_peer_handle(struct peer *); void ktunnel_peer_cleanup(struct peer *); void ktunnel_connection_close(struct connection *); void ktunnel_connection_cleanup(struct connection *); void ktunnel_event_schedule(int, int, int, void *); void ktunnel_set_nonblock(int); int ktunnel_write_local(struct peer *); int ktunnel_write_remote(struct peer *); int ktunnel_read_local(struct peer *, struct peer *); int ktunnel_read_remote(struct peer *, struct peer *); void ktunnel_accept(struct peer *); void ktunnel_bind(struct peer *, struct addrinfo *); void ktunnel_connect(struct peer *, struct addrinfo *); void ktunnel_peer_init(struct peer *, const char *, void (*cb)(struct peer *, struct addrinfo *)); void ktunnel_netbuf_create(struct netbuf **, struct netbuf_list *, u_int8_t *, u_int32_t); int kfd = - 1; u_int32_t nchanges = 0; struct kevent *events = NULL; struct kevent *changelist = NULL; char *target_host = NULL; char *target_port = NULL; char *remote_name = NULL; char *http_hostname = NULL; char *http_path = "/connect"; void usage(void) { fprintf(stderr, "Usage: ktunnel-client [-h host] [-p path] " "local:port remote:port target:port\n"); exit(1); } int main(int argc, char *argv[]) { int n, i, ch; struct connection *c, *cnext; struct peer lpeer, *peer; while ((ch = getopt(argc, argv, "h:p:")) != -1) { switch (ch) { case 'h': http_hostname = optarg; break; case 'p': http_path = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 3) usage(); TAILQ_INIT(&clients); TAILQ_INIT(&disconnects); if ((kfd = kqueue()) == -1) fatal("kqueue(): %s", errno_s); nchanges = 0; events = calloc(KQUEUE_EVENT_COUNT, sizeof(struct kevent)); changelist = calloc(KQUEUE_EVENT_COUNT, sizeof(struct kevent)); if (events == NULL || changelist == NULL) fatal("calloc(): %s", errno_s); memset(&lpeer, 0, sizeof(lpeer)); ktunnel_peer_init(&lpeer, argv[0], ktunnel_bind); ktunnel_event_schedule(lpeer.fd, EVFILT_READ, EV_ADD, &lpeer); remote_name = argv[1]; target_host = argv[2]; if ((target_port = strchr(target_host, ':')) == NULL) fatal("Target host does not contain a port"); *(target_port)++ = '\0'; if (http_hostname == NULL) http_hostname = target_host; for (;;) { n = kevent(kfd, changelist, nchanges, events, KQUEUE_EVENT_COUNT, NULL); if (n == -1) { if (errno == EINTR) continue; fatal("kevent(): %s", errno_s); } nchanges = 0; for (i = 0; i < n; i++) { if (events[i].udata == NULL) fatal("events[%d].udata == NULL", i); peer = (struct peer *)events[i].udata; if (events[i].flags & EV_EOF || events[i].flags & EV_ERROR) { if (peer->fd == lpeer.fd) fatal("error on listening socket"); ktunnel_connection_close(peer->connection); continue; } if (peer->fd == lpeer.fd) { ktunnel_accept(peer); continue; } if (events[i].filter == EVFILT_READ) peer->flags |= PEER_CAN_READ; if (events[i].filter == EVFILT_WRITE) peer->flags |= PEER_CAN_WRITE; if (ktunnel_peer_handle(peer) == -1) { ktunnel_connection_close(peer->connection); } else { if (!TAILQ_EMPTY(&peer->write_queue)) { ktunnel_event_schedule(peer->fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, peer); } } } for (c = TAILQ_FIRST(&disconnects); c != NULL; c = cnext) { cnext = TAILQ_NEXT(c, list); TAILQ_REMOVE(&disconnects, c, list); ktunnel_connection_cleanup(c); } } return (0); } void ktunnel_peer_init(struct peer *peer, const char *name, void (*cb)(struct peer *, struct addrinfo *)) { int r; struct addrinfo *ai, *results; if ((peer->name = strdup(name)) == NULL) fatal("strdup() messed up"); peer->host = peer->name; if ((peer->port = strchr(peer->host, ':')) == NULL) fatal("No port section in given local host '%s'", peer->name); *(peer->port)++ = '\0'; r = getaddrinfo(peer->host, peer->port, NULL, &results); if (r != 0) fatal("%s: %s", name, gai_strerror(r)); for (ai = results; ai != NULL; ai = ai->ai_next) { if (ai->ai_socktype != SOCK_STREAM) continue; if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; cb(peer, ai); peer->family = ai->ai_family; break; } freeaddrinfo(results); } void ktunnel_accept(struct peer *peer) { int fd; struct connection *c; struct sockaddr_in sin4; struct sockaddr_in6 sin6; struct sockaddr *sin; socklen_t slen; sin = NULL; switch (peer->family) { case AF_INET: sin = (struct sockaddr *)&sin4; slen = sizeof(struct sockaddr_in); break; case AF_INET6: sin = (struct sockaddr *)&sin6; slen = sizeof(struct sockaddr_in6); break; default: fatal("Unknown peer family %d", peer->family); /* NOTREACHED */ } if ((fd = accept(peer->fd, sin, &slen)) == -1) fatal("accept(): %s", errno_s); if ((c = malloc(sizeof(*c))) == NULL) fatal("malloc(): %s", errno_s); memset(c, 0, sizeof(*c)); c->local.fd = fd; TAILQ_INIT(&c->local.write_queue); ktunnel_event_schedule(c->local.fd, EVFILT_READ, EV_ADD, &c->local); ktunnel_event_schedule(c->local.fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, &c->local); c->local.connection = c; c->local.opposite = &c->remote; c->local.read = ktunnel_read_local; c->local.write = ktunnel_write_local; c->remote.connection = c; c->remote.opposite = &c->local; c->remote.read = ktunnel_read_remote; c->remote.write = ktunnel_write_remote; ktunnel_peer_init(&c->remote, remote_name, ktunnel_connect); ktunnel_netbuf_create(&c->local.recv_buf, NULL, NULL, NETBUF_RECV_MAX); ktunnel_set_nonblock(c->local.fd); ktunnel_set_nonblock(c->remote.fd); TAILQ_INSERT_TAIL(&clients, c, list); printf("new connection %p (%p<->%p)\n", c, &c->local, &c->remote); } void ktunnel_bind(struct peer *peer, struct addrinfo *ai) { if ((peer->fd = socket(ai->ai_family, ai->ai_socktype, 0)) == -1) fatal("socket(): %s", errno_s); if (bind(peer->fd, ai->ai_addr, ai->ai_addrlen) == -1) { fatal("Cannot bind to %s:%s: %s", peer->host, peer->port, errno_s); } if (listen(peer->fd, 10) == -1) fatal("Cannot listen on socket: %s", errno_s); TAILQ_INIT(&peer->write_queue); ktunnel_netbuf_create(&peer->recv_buf, NULL, NULL, NETBUF_RECV_MAX); } void ktunnel_connect(struct peer *peer, struct addrinfo *ai) { int l; char *req; if ((peer->fd = socket(ai->ai_family, ai->ai_socktype, 0)) == -1) fatal("socket(): %s", errno_s); if (connect(peer->fd, ai->ai_addr, ai->ai_addrlen) == -1) { fatal("Cannot connect to %s:%s: %s", peer->host, peer->port, errno_s); } TAILQ_INIT(&peer->write_queue); ktunnel_netbuf_create(&peer->recv_buf, NULL, NULL, NETBUF_RECV_MAX); /* * XXX * - Add our client certs * - Verify server cert properly * - ... */ SSL_library_init(); SSL_load_error_strings(); if ((peer->ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) fatal("SSL_CTX_new(): %s", ssl_errno_s); SSL_CTX_set_mode(peer->ssl_ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_options(peer->ssl_ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(peer->ssl_ctx, SSL_OP_NO_SSLv3); SSL_CTX_set_options(peer->ssl_ctx, SSL_OP_NO_TLSv1); SSL_CTX_set_options(peer->ssl_ctx, SSL_OP_NO_TLSv1_1); if ((peer->ssl = SSL_new(peer->ssl_ctx)) == NULL) fatal("SSL_new(): %s", ssl_errno_s); if (!SSL_set_fd(peer->ssl, peer->fd)) fatal("SSL_set_fd(): %s", ssl_errno_s); if (!SSL_connect(peer->ssl)) { fatal("Could not establish an SSL connection to %s: %s", peer->host, ssl_errno_s); } /* Send custom HTTP command. */ l = asprintf(&req, HTTP_REQUEST_FMT, http_path, target_host, target_port, http_hostname); if (l == -1) fatal("asprintf(): %s", errno_s); if (SSL_write(peer->ssl, req, l) != l) { fatal("Failed to talk to %s:%s: %s", peer->host, peer->port, ssl_errno_s); } free(req); ktunnel_event_schedule(peer->fd, EVFILT_READ, EV_ADD, peer); ktunnel_event_schedule(peer->fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, peer); printf("Connected over SSL to %s:%s\n", peer->host, peer->port); } int ktunnel_peer_handle(struct peer *peer) { int r; printf("handling peer %p (%d)\n", peer, peer->flags); if (peer->flags & PEER_CAN_READ) { printf("\treading\n"); r = peer->read(peer, peer->opposite); } if (peer->flags & PEER_CAN_WRITE) { printf("\twriting\n"); r = peer->write(peer); } return (r); } void ktunnel_connection_close(struct connection *c) { printf("ktunnel_connection_close(%p)\n", c); if (!(c->flags & CONNECTION_WILL_DISCONNECT)) { c->flags |= CONNECTION_WILL_DISCONNECT; TAILQ_REMOVE(&clients, c, list); TAILQ_INSERT_TAIL(&disconnects, c, list); } } void ktunnel_connection_cleanup(struct connection *c) { ktunnel_peer_cleanup(&c->local); ktunnel_peer_cleanup(&c->remote); free(c); } void ktunnel_peer_cleanup(struct peer *peer) { struct netbuf *nb, *next; printf("ktunnel_peer_cleanup(%p)\n", peer); close(peer->fd); if (peer->ssl != NULL) SSL_free(peer->ssl); if (peer->ssl_ctx != NULL) SSL_CTX_free(peer->ssl_ctx); for (nb = TAILQ_FIRST(&peer->write_queue); nb != NULL; nb = next) { next = TAILQ_NEXT(nb, list); TAILQ_REMOVE(&peer->write_queue, nb, list); free(nb->data); free(nb); } free(peer->recv_buf->data); } void ktunnel_netbuf_create(struct netbuf **out, struct netbuf_list *head, u_int8_t *data, u_int32_t length) { struct netbuf *nb; if ((nb = malloc(sizeof(struct netbuf))) == NULL) fatal("malloc(): %s", errno_s); nb->offset = 0; nb->length = length; if ((nb->data = malloc(nb->length)) == NULL) fatal("malloc(): %s", errno_s); if (data != NULL) memcpy(nb->data, data, nb->length); if (head != NULL) TAILQ_INSERT_TAIL(head, nb, list); if (out != NULL) *out = nb; } void ktunnel_event_schedule(int fd, int type, int flags, void *udata) { if (nchanges >= KQUEUE_EVENT_COUNT) fatal("nchanges > KQUEUE_EVENT_COUNT"); EV_SET(&changelist[nchanges], fd, type, flags, 0, 0, udata); nchanges++; } int ktunnel_read_local(struct peer *in, struct peer *out) { int r; printf("ktunnel_read_local: %p\n", in); r = read(in->fd, in->recv_buf->data, in->recv_buf->length); if (r == -1) { if (errno != EINTR && errno != EAGAIN) { printf("read error on local peer: %s\n", errno_s); return (-1); } return (0); } if (r == 0) { printf("local peer closed connection\n"); return (-1); } printf("ktunnel_read_local: %p -- %d bytes --> %p\n", in, r, out); ktunnel_netbuf_create(NULL, &(out->write_queue), in->recv_buf->data, r); return (ktunnel_write_remote(out)); } int ktunnel_write_local(struct peer *peer) { int r; struct netbuf *nb; while (!TAILQ_EMPTY(&peer->write_queue)) { nb = TAILQ_FIRST(&peer->write_queue); printf("ktunnel_write_local: %p writing %d/%d\n", peer, nb->offset, nb->length); r = write(peer->fd, (nb->data + nb->offset), (nb->length - nb->offset)); if (r == -1) { switch (errno) { case EINTR: case EAGAIN: peer->flags &= ~PEER_CAN_WRITE; return (0); default: printf("failed to write to local peer: %s\n", errno_s); return (-1); } } nb->offset += r; printf("ktunnel_write_local: %p progress %d/%d\n", peer, nb->offset, nb->length); if (nb->offset == nb->length) { TAILQ_REMOVE(&peer->write_queue, nb, list); free(nb->data); free(nb); } } return (0); } int ktunnel_read_remote(struct peer *in, struct peer *out) { int r; r = SSL_read(in->ssl, in->recv_buf->data, in->recv_buf->length); if (r <= 0) { r = SSL_get_error(in->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: in->flags &= ~PEER_CAN_READ; return (0); default: printf("failed to read from remote peer: %d, %s\n", r, ssl_errno_s); return (-1); } } ktunnel_netbuf_create(NULL, &(out->write_queue), in->recv_buf->data, r); return (ktunnel_write_local(out)); } int ktunnel_write_remote(struct peer *peer) { int r; struct netbuf *nb; while (!TAILQ_EMPTY(&peer->write_queue)) { nb = TAILQ_FIRST(&peer->write_queue); printf("ktunnel_write_remote: %p writing %d/%d bytes\n", peer, nb->offset, nb->length); r = SSL_write(peer->ssl, (nb->data + nb->offset), (nb->length - nb->offset)); if (r <= 0) { r = SSL_get_error(peer->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: peer->flags &= ~PEER_CAN_WRITE; return (0); default: printf("failed to write to remote peer: %s\n", ssl_errno_s); return (-1); } } nb->offset += r; printf("ktunnel_write_remote: %p progress %d/%d\n", peer, nb->offset, nb->length); if (nb->offset == nb->length) { TAILQ_REMOVE(&peer->write_queue, nb, list); free(nb->data); free(nb); } } return (0); } void ktunnel_set_nonblock(int fd) { int flags; if ((flags = fcntl(fd, F_GETFL, 0)) == -1) fatal("fcntl(): get %s", errno_s); flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) fatal("fnctl(): set %s", errno_s); } void fatal(const char *fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); printf("\n"); exit(1); } kore/examples/ktunnel/conf/0000755000175000001440000000000012527355514015317 5ustar jorisuserskore/examples/ktunnel/conf/ktunnel.conf0000755000175000001440000000063012527355514017650 0ustar jorisusers# kTunnel configuration bind 127.0.0.1 8888 load ./ktunnel.so tls_dhparam dh2048.pem # Regexes here are incorrect. validator v_host regex ^.*$ validator v_port regex ^[0-9]*$ # Disable timeouts http_keepalive_time 0 domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static /connect open_connection params get /connect { validate host v_host validate port v_port } } kore/examples/ktunnel/.gitignore0000755000175000001440000000004312527355514016362 0ustar jorisusers*.o .objs ktunnel.so assets.h cert kore/examples/ktunnel/src/0000755000175000001440000000000012527355514015161 5ustar jorisuserskore/examples/ktunnel/src/ktunnel.c0000755000175000001440000001237712527355514017022 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include /* * KTunnel shows how Kore exposes its net internals to its libraries * and how we can "abuse" these internals to create a "anything" * over HTTPS tunnel. */ int open_connection(struct http_request *); static int ktunnel_pipe_data(struct netbuf *); static void ktunnel_pipe_disconnect(struct connection *); static int ktunnel_pipe_create(struct connection *, const char *, const char *); /* * Receive a request to open a new connection. */ int open_connection(struct http_request *req) { char *host, *port; /* Don't want to deal with SPDY connections. */ if (req->owner->proto != CONN_PROTO_HTTP) { http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0); return (KORE_RESULT_OK); } /* Parse the query string and grab our arguments. */ http_populate_arguments(req); if (!http_argument_get_string("host", &host, NULL) || !http_argument_get_string("port", &port, NULL)) { http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0); return (KORE_RESULT_OK); } /* Create our tunnel. */ if (!ktunnel_pipe_create(req->owner, host, port)) { http_response(req, HTTP_STATUS_INTERNAL_ERROR, NULL, 0); return (KORE_RESULT_OK); } /* * Hack so http_response() doesn't end up queueing a new * netbuf for receiving more HTTP requests on the same connection. */ req->owner->flags |= CONN_CLOSE_EMPTY; /* Respond to the client now that we're good to go. */ http_response(req, HTTP_STATUS_OK, NULL, 0); /* Unset this so we don't disconnect after returning. */ req->owner->flags &= ~CONN_CLOSE_EMPTY; return (KORE_RESULT_OK); } /* * Connect to our target host:port and attach it to a struct connection that * Kore understands. We set the disconnect method so we get a callback * whenever either of the connections will go away so we can cleanup the * one it is attached to. */ static int ktunnel_pipe_create(struct connection *c, const char *host, const char *port) { struct sockaddr_in sin; struct connection *cpipe; u_int16_t nport; int fd, err; nport = kore_strtonum(port, 10, 1, SHRT_MAX, &err); if (err == KORE_RESULT_ERROR) { kore_log(LOG_ERR, "invalid port given %s", port); return (KORE_RESULT_ERROR); } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { kore_log(LOG_ERR, "socket(): %s", errno_s); return (KORE_RESULT_ERROR); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(nport); sin.sin_addr.s_addr = inet_addr(host); kore_log(LOG_NOTICE, "Attempting to connect to %s:%s", host, port); if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { close(fd); kore_log(LOG_ERR, "connect(): %s", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(fd)) { close(fd); return (KORE_RESULT_ERROR); } cpipe = kore_connection_new(c); cpipe->fd = fd; cpipe->addr.ipv4 = sin; cpipe->read = net_read; cpipe->write = net_write; cpipe->addrtype = AF_INET; cpipe->proto = CONN_PROTO_UNKNOWN; cpipe->state = CONN_STATE_ESTABLISHED; /* Don't let these connections timeout any time soon. */ cpipe->idle_timer.length = 10000000000; c->idle_timer.length = 10000000000; c->hdlr_extra = cpipe; cpipe->hdlr_extra = c; c->disconnect = ktunnel_pipe_disconnect; cpipe->disconnect = ktunnel_pipe_disconnect; kore_worker_connection_add(cpipe); kore_connection_start_idletimer(cpipe); kore_platform_event_all(cpipe->fd, cpipe); net_recv_reset(c, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data); net_recv_queue(cpipe, NETBUF_SEND_PAYLOAD_MAX, NETBUF_CALL_CB_ALWAYS, ktunnel_pipe_data); printf("connection started to %s (%p -> %p)\n", host, c, cpipe); return (KORE_RESULT_OK); } /* * Called everytime new data is read from any of the connections * that are part of a pipe. */ static int ktunnel_pipe_data(struct netbuf *nb) { struct connection *src = nb->owner; struct connection *dst = src->hdlr_extra; printf("received %d bytes on pipe %p (-> %p)\n", nb->s_off, src, dst); net_send_queue(dst, nb->buf, nb->s_off, NULL, NETBUF_LAST_CHAIN); net_send_flush(dst); net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data); return (KORE_RESULT_OK); } /* * Called when either part of the pipe disconnects. */ static void ktunnel_pipe_disconnect(struct connection *c) { struct connection *cpipe = c->hdlr_extra; printf("ktunnel_pipe_disconnect(%p)->%p\n", c, cpipe); if (cpipe != NULL) { /* Prevent Kore from calling kore_mem_free() on hdlr_extra. */ c->hdlr_extra = NULL; kore_connection_disconnect(cpipe); } } kore/examples/integers/0000755000175000001440000000000012527355514014532 5ustar jorisuserskore/examples/integers/README.md0000644000175000001440000000036612527355514016016 0ustar jorisusersTest parameter to integer conversions. Run: ``` # kore run ``` Test: ``` # curl -i -k https://127.0.0.1:8888/?id=123123 # curl -i -k https://127.0.0.1:8888/?id=-123123 ``` The correct integer types should only be represented in the output. kore/examples/integers/conf/0000755000175000001440000000000012527355514015457 5ustar jorisuserskore/examples/integers/conf/integers.conf0000755000175000001440000000045112527355514020151 0ustar jorisusers# Placeholder configuration bind 127.0.0.1 8888 load ./integers.so workers 2 worker_max_connections 5000 tls_dhparam dh2048.pem validator v_id regex ^-?[0-9]*$ domain 127.0.0.1 { certfile cert/server.crt certkey cert/server.key static / page params get / { validate id v_id } } kore/examples/integers/.gitignore0000755000175000001440000000004412527355514016523 0ustar jorisusers*.o .objs integers.so static.h cert kore/examples/integers/src/0000755000175000001440000000000012527355514015321 5ustar jorisuserskore/examples/integers/src/check_integers.c0000755000175000001440000000206112527355514020444 0ustar jorisusers#include #include int page(struct http_request *); int page(struct http_request *req) { int16_t s16; u_int16_t u16; int32_t s32; int64_t s64; u_int64_t u64; struct kore_buf *buf; u_int32_t u32, len; u_int8_t c, *data; http_populate_arguments(req); buf = kore_buf_create(128); if (http_argument_get_byte("id", &c)) kore_buf_appendf(buf, "byte\t%c\n", c); if (http_argument_get_int16("id", &s16)) kore_buf_appendf(buf, "int16\t%d\n", s16); if (http_argument_get_uint16("id", &u16)) kore_buf_appendf(buf, "uint16\t%d\n", u16); if (http_argument_get_int32("id", &s32)) kore_buf_appendf(buf, "int32\t%d\n", s32); if (http_argument_get_uint32("id", &u32)) kore_buf_appendf(buf, "uint32\t%d\n", u32); if (http_argument_get_int64("id", &s64)) kore_buf_appendf(buf, "int64\t%ld\n", s64); if (http_argument_get_uint64("id", &u64)) kore_buf_appendf(buf, "uint64\t%lu\n", u64); data = kore_buf_release(buf, &len); http_response(req, 200, data, len); kore_mem_free(data); return (KORE_RESULT_OK); } kore/README.md0000644000175000001440000000521312527355661012357 0ustar jorisusersAbout ----- [![Build Status](https://travis-ci.org/jorisvink/kore.svg?branch=master)](https://travis-ci.org/jorisvink/kore) Kore (https://kore.io) is an easy to use web application framework for writing scalable web APIs in C. Its main goals are security, scalability and allowing rapid development and deployment of such APIs. Because of this Kore is an ideal candidate for building robust, scalable and secure web things. Features -------- * Supports SNI * Supports SPDY/3.1 * Supports HTTP/1.1 * Websocket support * Lightweight background tasks * Built-in parameter validation * Only HTTPS connections allowed * Multiple modules can be loaded at once * Built-in asynchronous PostgreSQL support * Default sane TLS ciphersuites (PFS in all major browsers) * Load your web application as a precompiled dynamic library * Modules can be reloaded on-the-fly, even while serving content * Event driven (epoll/kqueue) architecture with per CPU core workers License ------- * Kore is licensed under the ISC license Platforms supported ------------------- * Linux * OpenBSD * FreeBSD * OSX See https://kore.io/doc/#requirements for more information. Latest release -------------- * [2015-05-21] version 1.2.3 - https://kore.io/release/kore-1.2.3-release.tgz Old releases ------------ * [2015-04-09] version 1.2.2 - https://kore.io/release/kore-1.2.2-release.tgz * [2014-12-12] version 1.2.1 - https://kore.io/release/kore-1.2.1-release.tgz * [2014-08-25] version 1.2 - https://kore.io/release/kore-1.2-stable.tgz * [2014-03-01] version 1.1 - https://kore.io/release/kore-1.1-stable.tgz Building Kore ------------- Requirements * libz * openssl >= 1.0.1i Requirements for background tasks (optional) * pthreads Requirements for pgsql (optional) * libpq Normal compilation and installation: ``` # git clone https://github.com/jorisvink/kore.git # cd kore # make # make install ``` If you would like to build a specific flavor, you can enable those by setting a shell environment variable before running **_make_**. * TASKS=1 (compiles in task support) * PGSQL=1 (compiles in pgsql support) * DEBUG=1 (enables use of -d for debug) * BENCHMARK=1 (compiles Kore without OpenSSL) * KORE_PEDANTIC_MALLOC=1 (zero all allocated memory) Example libraries ----------------- You can find example libraries under **_examples/_**. The examples contain a README file with instructions on how to build or use them. I apologize for unclear examples or documentation, I am working on improving those. Bugs, contributions and more ---------------------------- If you run into any bugs, have suggestions or patches please contact me at joris@coders.se. More information can be found on https://kore.io/ kore/Makefile0000644000175000001440000000357112527355513012541 0ustar jorisusers# Kore Makefile CC?=gcc PREFIX?=/usr/local KORE=kore INSTALL_DIR=$(PREFIX)/bin INCLUDE_DIR=$(PREFIX)/include/kore S_SRC= src/kore.c src/accesslog.c src/auth.c src/buf.c src/cli.c src/config.c \ src/connection.c src/domain.c src/http.c src/mem.c src/module.c \ src/net.c src/pool.c src/spdy.c src/timer.c src/validator.c \ src/utils.c src/websocket.c src/worker.c src/zlib_dict.c S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wsign-compare -Iincludes -g CFLAGS+=-DPREFIX='"$(PREFIX)"' LDFLAGS+=-rdynamic -lssl -lcrypto -lz ifneq ("$(DEBUG)", "") CFLAGS+=-DKORE_DEBUG endif ifneq ("$(KORE_PEDANTIC_MALLOC)", "") CFLAGS+=-DKORE_PEDANTIC_MALLOC endif ifneq ("$(BENCHMARK)", "") CFLAGS+=-DKORE_BENCHMARK LDFLAGS=-rdynamic -lz -lcrypto endif ifneq ("$(PGSQL)", "") S_SRC+=src/pgsql.c LDFLAGS+=-L$(shell pg_config --libdir) -lpq CFLAGS+=-I$(shell pg_config --includedir) -DKORE_USE_PGSQL \ -DPGSQL_INCLUDE_PATH="\"$(shell pg_config --includedir)\"" endif ifneq ("$(TASKS)", "") S_SRC+=src/tasks.c LDFLAGS+=-lpthread CFLAGS+=-DKORE_USE_TASKS endif OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) ifeq ("$(OSNAME)", "darwin") CFLAGS+=-I/opt/local/include/ -I/usr/local/opt/openssl/include LDFLAGS+=-L/opt/local/lib -L/usr/local/opt/openssl/lib S_SRC+=src/bsd.c else ifeq ("$(OSNAME)", "linux") CFLAGS+=-D_GNU_SOURCE=1 LDFLAGS+=-ldl S_SRC+=src/linux.c else S_SRC+=src/bsd.c endif all: $(S_OBJS) $(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE) install: mkdir -p $(INCLUDE_DIR) mkdir -p $(INSTALL_DIR) install -m 555 $(KORE) $(INSTALL_DIR)/$(KORE) install -m 644 includes/*.h $(INCLUDE_DIR) uninstall: rm -f $(INSTALL_DIR)/$(KORE) rm -rf $(INCLUDE_DIR) .c.o: $(CC) $(CFLAGS) -c $< -o $@ clean: find . -type f -name \*.o -exec rm {} \; rm -f $(KORE) .PHONY: clean kore/includes/0000755000175000001440000000000012527355514012702 5ustar jorisuserskore/includes/kore.h0000644000175000001440000003766712527355514014036 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __H_KORE_H #define __H_KORE_H #if defined(__APPLE__) #define daemon portability_is_king #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__cplusplus) extern "C" { #endif #if defined(__APPLE__) #undef daemon extern int daemon(int, int); #endif #include "spdy.h" #define KORE_RESULT_ERROR 0 #define KORE_RESULT_OK 1 #define KORE_RESULT_RETRY 2 #define KORE_VERSION_MAJOR 1 #define KORE_VERSION_MINOR 2 #define KORE_VERSION_PATCH 3 #define KORE_VERSION_STATE "release" #define KORE_TLS_VERSION_1_2 0 #define KORE_TLS_VERSION_1_0 1 #define KORE_TLS_VERSION_BOTH 2 #define errno_s strerror(errno) #define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) #define KORE_DOMAINNAME_LEN 254 #define KORE_PIDFILE_DEFAULT "kore.pid" #define KORE_DEFAULT_CIPHER_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA" #if defined(KORE_DEBUG) #define kore_debug(fmt, ...) \ if (kore_debug) \ kore_debug_internal(__FILE__, __LINE__, fmt, ##__VA_ARGS__) #else #define kore_debug(fmt, ...) #endif #define NETBUF_RECV 0 #define NETBUF_SEND 1 #define NETBUF_SEND_PAYLOAD_MAX 8192 #define NETBUF_LAST_CHAIN 0 #define NETBUF_BEFORE_CHAIN 1 #define NETBUF_CALL_CB_ALWAYS 0x01 #define NETBUF_FORCE_REMOVE 0x02 #define NETBUF_MUST_RESEND 0x04 #define NETBUF_IS_STREAM 0x10 #define X509_GET_CN(c, o, l) \ X509_NAME_get_text_by_NID(X509_get_subject_name(c), \ NID_commonName, o, l) #define X509_CN_LENGTH (ub_common_name + 1) /* XXX hackish. */ struct http_request; struct spdy_stream; struct netbuf { u_int8_t *buf; u_int32_t s_off; u_int32_t b_len; u_int32_t m_len; u_int8_t type; u_int8_t flags; void *owner; struct spdy_stream *stream; void *extra; int (*cb)(struct netbuf *); TAILQ_ENTRY(netbuf) list; }; TAILQ_HEAD(netbuf_head, netbuf); #define KORE_TYPE_LISTENER 1 #define KORE_TYPE_CONNECTION 2 #define KORE_TYPE_PGSQL_CONN 3 #define KORE_TYPE_TASK 4 struct listener { u_int8_t type; int fd; u_int8_t addrtype; union { struct sockaddr_in ipv4; struct sockaddr_in6 ipv6; } addr; LIST_ENTRY(listener) list; }; LIST_HEAD(listener_head, listener); #define CONN_STATE_UNKNOWN 0 #define CONN_STATE_SSL_SHAKE 1 #define CONN_STATE_ESTABLISHED 2 #define CONN_STATE_DISCONNECTING 3 #define CONN_PROTO_UNKNOWN 0 #define CONN_PROTO_SPDY 1 #define CONN_PROTO_HTTP 2 #define CONN_PROTO_WEBSOCKET 3 #define CONN_READ_POSSIBLE 0x01 #define CONN_WRITE_POSSIBLE 0x02 #define CONN_WRITE_BLOCK 0x04 #define CONN_IDLE_TIMER_ACT 0x10 #define CONN_READ_BLOCK 0x20 #define CONN_CLOSE_EMPTY 0x40 #define SPDY_CONN_GOAWAY 0x80 #define KORE_IDLE_TIMER_MAX 20000 #define WEBSOCKET_OP_CONT 0x00 #define WEBSOCKET_OP_TEXT 0x01 #define WEBSOCKET_OP_BINARY 0x02 #define WEBSOCKET_OP_CLOSE 0x08 #define WEBSOCKET_OP_PING 0x09 #define WEBSOCKET_OP_PONG 0x10 #define WEBSOCKET_BROADCAST_LOCAL 1 #define WEBSOCKET_BROADCAST_GLOBAL 2 #define KORE_TIMER_ONESHOT 0x01 struct connection { u_int8_t type; int fd; u_int8_t state; u_int8_t proto; void *owner; SSL *ssl; u_int8_t flags; void *hdlr_extra; X509 *cert; void *wscbs; int tls_reneg; void (*disconnect)(struct connection *); int (*read)(struct connection *, int *); int (*write)(struct connection *, int, int *); u_int8_t addrtype; union { struct sockaddr_in ipv4; struct sockaddr_in6 ipv6; } addr; struct { u_int64_t length; u_int64_t start; } idle_timer; u_int8_t inflate_started; z_stream z_inflate; u_int8_t deflate_started; z_stream z_deflate; u_int32_t wsize_initial; u_int32_t spdy_send_wsize; u_int32_t spdy_recv_wsize; struct netbuf_head send_queue; struct netbuf *snb; struct netbuf *rnb; u_int32_t client_stream_id; TAILQ_HEAD(, spdy_stream) spdy_streams; TAILQ_HEAD(, http_request) http_requests; TAILQ_ENTRY(connection) list; TAILQ_ENTRY(connection) flush_list; }; TAILQ_HEAD(connection_list, connection); extern struct connection_list worker_clients; struct kore_handler_params { char *name; u_int8_t method; struct kore_validator *validator; TAILQ_ENTRY(kore_handler_params) list; }; #define KORE_AUTH_TYPE_COOKIE 1 #define KORE_AUTH_TYPE_HEADER 2 #define KORE_AUTH_TYPE_REQUEST 3 struct kore_auth { u_int8_t type; char *name; char *value; char *redirect; struct kore_validator *validator; TAILQ_ENTRY(kore_auth) list; }; #define KORE_MODULE_LOAD 1 #define KORE_MODULE_UNLOAD 2 #define HANDLER_TYPE_STATIC 1 #define HANDLER_TYPE_DYNAMIC 2 struct kore_module { void *handle; char *path; char *onload; int (*ocb)(int); time_t mtime; TAILQ_ENTRY(kore_module) list; }; struct kore_module_handle { char *path; char *func; void *addr; int type; int errors; regex_t rctx; struct kore_domain *dom; struct kore_auth *auth; TAILQ_HEAD(, kore_handler_params) params; TAILQ_ENTRY(kore_module_handle) list; }; struct kore_worker { u_int8_t id; u_int8_t cpu; pid_t pid; u_int8_t has_lock; struct kore_module_handle *active_hdlr; }; struct kore_domain { char *domain; char *certfile; char *certkey; char *cafile; char *crlfile; int accesslog; SSL_CTX *ssl_ctx; TAILQ_HEAD(, kore_module_handle) handlers; TAILQ_ENTRY(kore_domain) list; }; TAILQ_HEAD(kore_domain_h, kore_domain); #define KORE_VALIDATOR_TYPE_REGEX 1 #define KORE_VALIDATOR_TYPE_FUNCTION 2 struct kore_validator { u_int8_t type; char *name; char *arg; regex_t rctx; int (*func)(struct http_request *, char *); TAILQ_ENTRY(kore_validator) list; }; #define KORE_BUF_INITIAL 128 #define KORE_BUF_INCREMENT KORE_BUF_INITIAL struct kore_buf { u_int8_t *data; u_int64_t length; u_int64_t offset; }; struct kore_pool_region { void *start; LIST_ENTRY(kore_pool_region) list; }; struct kore_pool_entry { u_int8_t state; struct kore_pool_region *region; LIST_ENTRY(kore_pool_entry) list; }; struct kore_pool { u_int32_t elen; u_int32_t slen; u_int32_t elms; u_int32_t inuse; char *name; LIST_HEAD(, kore_pool_region) regions; LIST_HEAD(, kore_pool_entry) freelist; }; struct kore_wscbs { void (*connect)(struct connection *); void (*message)(struct connection *, u_int8_t, void *, size_t); void (*disconnect)(struct connection *); }; struct kore_timer { u_int64_t nextrun; u_int64_t interval; int flags; void *arg; void (*cb)(void *, u_int64_t, u_int64_t); TAILQ_ENTRY(kore_timer) list; }; extern pid_t kore_pid; extern int foreground; extern int kore_debug; extern int skip_chroot; extern char *chroot_path; extern int skip_runas; extern char *runas_user; extern char *kore_pidfile; extern char *config_file; extern char *kore_tls_cipher_list; extern int tls_version; extern DH *tls_dhparam; extern u_int8_t nlisteners; extern u_int64_t spdy_idle_time; extern u_int16_t cpu_count; extern u_int8_t worker_count; extern u_int8_t worker_set_affinity; extern u_int32_t worker_rlimit_nofiles; extern u_int32_t worker_max_connections; extern u_int32_t worker_active_connections; extern u_int32_t worker_accept_threshold; extern u_int64_t kore_websocket_maxframe; extern u_int64_t kore_websocket_timeout; extern u_int32_t kore_socket_backlog; extern struct listener_head listeners; extern struct kore_worker *worker; extern struct kore_domain_h domains; extern struct kore_domain *primary_dom; extern struct kore_pool nb_pool; void kore_cli_usage(int); int kore_cli_main(int, char **); void kore_signal(int); void kore_worker_wait(int); void kore_worker_init(void); void kore_worker_shutdown(void); void kore_worker_dispatch_signal(int); void kore_worker_spawn(u_int16_t, u_int16_t); void kore_worker_entry(struct kore_worker *); void kore_worker_connection_add(struct connection *); void kore_worker_connection_move(struct connection *); void kore_worker_connection_remove(struct connection *); void kore_worker_websocket_broadcast(struct connection *, void (*cb)(struct connection *, void *), void *); void kore_platform_init(void); void kore_platform_event_init(void); void kore_platform_proctitle(char *); void kore_platform_disable_read(int); void kore_platform_enable_accept(void); void kore_platform_disable_accept(void); int kore_platform_event_wait(u_int64_t); void kore_platform_event_all(int, void *); void kore_platform_schedule_read(int, void *); void kore_platform_event_schedule(int, int, int, void *); void kore_platform_worker_setcpu(struct kore_worker *); void kore_accesslog_init(void); int kore_accesslog_wait(void); void kore_accesslog_worker_init(void); int kore_auth_run(struct http_request *, struct kore_auth *); void kore_auth_init(void); int kore_auth_new(const char *); struct kore_auth *kore_auth_lookup(const char *); void kore_timer_init(void); u_int64_t kore_timer_run(u_int64_t); void kore_timer_remove(struct kore_timer *); struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t, u_int64_t), u_int64_t, void *, int); int kore_tls_sni_cb(SSL *, int *, void *); int kore_server_bind(const char *, const char *); int kore_tls_npn_cb(SSL *, const u_char **, unsigned int *, void *); void kore_tls_info_callback(const SSL *, int, int); void kore_connection_init(void); struct connection *kore_connection_new(void *); int kore_connection_nonblock(int); int kore_connection_handle(struct connection *); void kore_connection_remove(struct connection *); void kore_connection_disconnect(struct connection *); void kore_connection_start_idletimer(struct connection *); void kore_connection_stop_idletimer(struct connection *); void kore_connection_check_idletimer(u_int64_t, struct connection *); int kore_connection_accept(struct listener *, struct connection **); u_int64_t kore_time_ms(void); void kore_log_init(void); void *kore_malloc(size_t); void kore_parse_config(void); void *kore_calloc(size_t, size_t); void *kore_realloc(void *, size_t); void kore_mem_free(void *); void kore_mem_init(void); #if defined(KORE_PEDANTIC_MALLOC) void explicit_bzero(void *, size_t); #endif void *kore_pool_get(struct kore_pool *); void kore_pool_put(struct kore_pool *, void *); void kore_pool_init(struct kore_pool *, const char *, u_int32_t, u_int32_t); time_t kore_date_to_time(char *); char *kore_time_to_date(time_t); char *kore_strdup(const char *); void kore_log(int, const char *, ...); u_int64_t kore_strtonum64(const char *, int, int *); void kore_strlcpy(char *, const char *, size_t); void kore_server_disconnect(struct connection *); int kore_split_string(char *, char *, char **, size_t); void kore_strip_chars(char *, char, char **); int kore_snprintf(char *, size_t, int *, const char *, ...); long long kore_strtonum(const char *, int, long long, long long, int *); int kore_base64_encode(u_int8_t *, u_int32_t, char **); int kore_base64_decode(char *, u_int8_t **, u_int32_t *); void *kore_mem_find(void *, size_t, void *, u_int32_t); void kore_websocket_handshake(struct http_request *, struct kore_wscbs *); void kore_websocket_send(struct connection *, u_int8_t, void *, size_t); void kore_websocket_broadcast(struct connection *, u_int8_t, void *, size_t, int); void kore_domain_init(void); int kore_domain_new(char *); void kore_module_init(void); void kore_module_reload(int); void kore_module_onload(void); int kore_module_loaded(void); void kore_domain_closelogs(void); void *kore_module_getsym(const char *); void kore_domain_load_crl(void); void kore_module_load(const char *, const char *); void kore_domain_sslstart(struct kore_domain *); int kore_module_handler_new(const char *, const char *, const char *, const char *, int); struct kore_domain *kore_domain_lookup(const char *); struct kore_module_handle *kore_module_handler_find(const char *, const char *); void kore_validator_init(void); void kore_validator_reload(void); int kore_validator_add(const char *, u_int8_t, const char *); int kore_validator_run(struct http_request *, const char *, char *); int kore_validator_check(struct http_request *, struct kore_validator *, void *); struct kore_validator *kore_validator_lookup(const char *); void fatal(const char *, ...) __attribute__((noreturn)); void kore_debug_internal(char *, int, const char *, ...); u_int16_t net_read16(u_int8_t *); u_int32_t net_read32(u_int8_t *); u_int64_t net_read64(u_int8_t *); void net_write16(u_int8_t *, u_int16_t); void net_write32(u_int8_t *, u_int32_t); void net_write64(u_int8_t *, u_int64_t); void net_init(void); int net_send(struct connection *); int net_send_flush(struct connection *); int net_recv_flush(struct connection *); int net_read(struct connection *, int *); int net_read_ssl(struct connection *, int *); int net_write(struct connection *, int, int *); int net_write_ssl(struct connection *, int, int *); void net_recv_reset(struct connection *, u_int32_t, int (*cb)(struct netbuf *)); void net_remove_netbuf(struct netbuf_head *, struct netbuf *); void net_recv_queue(struct connection *, u_int32_t, int, int (*cb)(struct netbuf *)); void net_recv_expand(struct connection *c, u_int32_t, int (*cb)(struct netbuf *)); void net_send_queue(struct connection *, void *, u_int32_t, struct spdy_stream *, int); void net_send_stream(struct connection *, void *, u_int32_t, struct spdy_stream *, int (*cb)(struct netbuf *), struct netbuf **); void kore_buf_free(struct kore_buf *); struct kore_buf *kore_buf_create(u_int32_t); void kore_buf_append(struct kore_buf *, void *, u_int32_t); u_int8_t *kore_buf_release(struct kore_buf *, u_int32_t *); void kore_buf_appendf(struct kore_buf *, const char *, ...); void kore_buf_appendv(struct kore_buf *, const char *, va_list); void kore_buf_appendb(struct kore_buf *, struct kore_buf *); void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t); struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t); int spdy_stream_get_header(struct spdy_header_block *, const char *, char **); void spdy_update_wsize(struct connection *, struct spdy_stream *, u_int32_t); int spdy_frame_recv(struct netbuf *); int spdy_dataframe_begin(struct connection *); void spdy_session_teardown(struct connection *c, u_int8_t); void spdy_frame_send(struct connection *, u_int16_t, u_int8_t, u_int32_t, struct spdy_stream *, u_int32_t); void spdy_header_block_add(struct spdy_header_block *, char *, char *); u_int8_t *spdy_header_block_release(struct connection *, struct spdy_header_block *, u_int32_t *); void spdy_stream_close(struct connection *, struct spdy_stream *, int); struct spdy_header_block *spdy_header_block_create(int); #if defined(__cplusplus) } #endif #endif /* !__H_KORE_H */ kore/includes/tasks.h0000644000175000001440000000441012527355514014177 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __H_KORE_TASKS #define __H_KORE_TASKS #include #define KORE_TASK_STATE_CREATED 1 #define KORE_TASK_STATE_RUNNING 2 #define KORE_TASK_STATE_FINISHED 3 #define KORE_TASK_STATE_ABORT 4 #if defined(__cplusplus) extern "C" { #endif struct http_request; struct kore_task { u_int8_t type; int state; int result; pthread_rwlock_t lock; struct http_request *req; int fds[2]; int (*entry)(struct kore_task *); struct kore_task_thread *thread; TAILQ_ENTRY(kore_task) list; LIST_ENTRY(kore_task) rlist; }; struct kore_task_thread { u_int8_t idx; pthread_t tid; pthread_mutex_t lock; pthread_cond_t cond; TAILQ_HEAD(, kore_task) tasks; TAILQ_ENTRY(kore_task_thread) list; }; void kore_task_init(void); void kore_task_run(struct kore_task *); void kore_task_finish(struct kore_task *); void kore_task_destroy(struct kore_task *); int kore_task_finished(struct kore_task *); void kore_task_handle(struct kore_task *, int); void kore_task_bind_request(struct kore_task *, struct http_request *); void kore_task_create(struct kore_task *, int (*entry)(struct kore_task *)); u_int32_t kore_task_channel_read(struct kore_task *, void *, u_int32_t); void kore_task_channel_write(struct kore_task *, void *, u_int32_t); void kore_task_set_state(struct kore_task *, int); void kore_task_set_result(struct kore_task *, int); int kore_task_state(struct kore_task *); int kore_task_result(struct kore_task *); #if defined(__cplusplus) } #endif #endif kore/includes/pgsql.h0000644000175000001440000000422512527355514014204 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _H_KORE_PGSQL #define _H_KORE_PGSQL #include #define KORE_PGSQL_FORMAT_TEXT 0 #define KORE_PGSQL_FORMAT_BINARY 1 #if defined(__cplusplus) extern "C" { #endif struct pgsql_conn { u_int8_t type; u_int8_t flags; PGconn *db; struct pgsql_job *job; TAILQ_ENTRY(pgsql_conn) list; }; struct kore_pgsql { u_int8_t state; char *error; PGresult *result; struct pgsql_conn *conn; LIST_ENTRY(kore_pgsql) rlist; }; extern u_int16_t pgsql_conn_max; extern char *pgsql_conn_string; void kore_pgsql_init(void); void kore_pgsql_handle(void *, int); void kore_pgsql_cleanup(struct kore_pgsql *); void kore_pgsql_continue(struct http_request *, struct kore_pgsql *); int kore_pgsql_query(struct kore_pgsql *, struct http_request *, const char *); int kore_pgsql_query_params(struct kore_pgsql *, struct http_request *, const char *, int, u_int8_t, ...); int kore_pgsql_ntuples(struct kore_pgsql *); void kore_pgsql_logerror(struct kore_pgsql *); void kore_pgsql_queue_remove(struct http_request *); char *kore_pgsql_getvalue(struct kore_pgsql *, int, int); int kore_pgsql_getlength(struct kore_pgsql *, int, int); #if defined(__cplusplus) } #endif #define KORE_PGSQL_STATE_INIT 1 #define KORE_PGSQL_STATE_WAIT 2 #define KORE_PGSQL_STATE_RESULT 3 #define KORE_PGSQL_STATE_ERROR 4 #define KORE_PGSQL_STATE_DONE 5 #define KORE_PGSQL_STATE_COMPLETE 6 #endif kore/includes/http.h0000644000175000001440000002072712527355514014042 0ustar jorisusers/* * Copyright (c) 2013 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __H_HTTP_H #define __H_HTTP_H #if defined(__cplusplus) extern "C" { #endif #define HTTP_KEEPALIVE_TIME 20 #define HTTP_HSTS_ENABLE 31536000 #define HTTP_HEADER_MAX_LEN 4096 #define HTTP_BODY_MAX_LEN 10240000 #define HTTP_URI_LEN 2000 #define HTTP_USERAGENT_LEN 256 #define HTTP_REQ_HEADER_MAX 25 #define HTTP_MAX_QUERY_ARGS 10 #define HTTP_MAX_COOKIES 10 #define HTTP_REQUEST_LIMIT 1000 #define HTTP_ARG_TYPE_RAW 0 #define HTTP_ARG_TYPE_BYTE 1 #define HTTP_ARG_TYPE_INT16 2 #define HTTP_ARG_TYPE_UINT16 3 #define HTTP_ARG_TYPE_INT32 4 #define HTTP_ARG_TYPE_UINT32 5 #define HTTP_ARG_TYPE_STRING 6 #define HTTP_ARG_TYPE_INT64 7 #define HTTP_ARG_TYPE_UINT64 8 #define HTTP_STATE_ERROR 0 #define HTTP_STATE_CONTINUE 1 #define HTTP_STATE_COMPLETE 2 #define HTTP_STATE_RETRY 3 struct http_header { char *header; char *value; TAILQ_ENTRY(http_header) list; }; struct http_arg { char *name; void *value; u_int32_t len; char *s_value; u_int32_t s_len; TAILQ_ENTRY(http_arg) list; }; #define COPY_ARG_TYPE(v, l, t) \ do { \ if (l != NULL) \ *l = sizeof(t); \ *(t *)nout = v; \ } while (0); #define COPY_ARG_INT64(type, sign) \ do { \ int err; \ type nval; \ nval = (type)kore_strtonum64(q->s_value, sign, &err); \ if (err != KORE_RESULT_OK) \ return (KORE_RESULT_ERROR); \ COPY_ARG_TYPE(nval, len, type); \ } while (0); #define COPY_ARG_INT(min, max, type) \ do { \ int err; \ int64_t nval; \ nval = kore_strtonum(q->s_value, 10, min, max, &err); \ if (err != KORE_RESULT_OK) \ return (KORE_RESULT_ERROR); \ COPY_ARG_TYPE(nval, len, type); \ } while (0); #define CACHE_STRING() \ do { \ if (q->s_value == NULL) { \ q->s_len = q->len + 1; \ q->s_value = kore_malloc(q->s_len); \ kore_strlcpy(q->s_value, q->value, q->s_len); \ } \ } while (0); #define COPY_AS_INTTYPE_64(type, sign) \ do { \ if (nout == NULL) \ return (KORE_RESULT_ERROR); \ CACHE_STRING(); \ COPY_ARG_INT64(type, sign); \ } while (0); #define COPY_AS_INTTYPE(min, max, type) \ do { \ if (nout == NULL) \ return (KORE_RESULT_ERROR); \ CACHE_STRING(); \ COPY_ARG_INT(min, max, type); \ } while (0); #define http_argument_type(r, n, so, no, l, t) \ http_argument_get(r, n, so, no, l, t) #define http_argument_get_string(n, o, l) \ http_argument_type(req, n, (void **)o, NULL, l, HTTP_ARG_TYPE_STRING) #define http_argument_get_byte(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_BYTE) #define http_argument_get_uint16(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_UINT16) #define http_argument_get_int16(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_INT16) #define http_argument_get_uint32(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_UINT32) #define http_argument_get_int32(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_INT32) #define http_argument_get_uint64(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_UINT64) #define http_argument_get_int64(n, o) \ http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_INT64) struct http_file { char *name; char *filename; u_int8_t *data; u_int32_t len; TAILQ_ENTRY(http_file) list; }; #define HTTP_METHOD_GET 0 #define HTTP_METHOD_POST 1 #define HTTP_METHOD_PUT 2 #define HTTP_METHOD_DELETE 3 #define HTTP_METHOD_HEAD 4 #define HTTP_REQUEST_COMPLETE 0x01 #define HTTP_REQUEST_DELETE 0x02 #define HTTP_REQUEST_SLEEPING 0x04 #define HTTP_REQUEST_PGSQL_QUEUE 0x10 #define HTTP_REQUEST_EXPECT_BODY 0x20 #define HTTP_REQUEST_RETAIN_EXTRA 0x40 #define HTTP_REQUEST_NO_CONTENT_LENGTH 0x80 struct kore_task; struct http_request { u_int8_t method; u_int8_t flags; u_int8_t fsm_state; u_int16_t status; u_int64_t start; u_int64_t end; u_int64_t total; char *host; char *path; char *agent; struct connection *owner; struct spdy_stream *stream; struct kore_buf *http_body; void *hdlr_extra; char *query_string; u_int8_t *multipart_body; struct kore_module_handle *hdlr; LIST_HEAD(, kore_task) tasks; LIST_HEAD(, kore_pgsql) pgsqls; TAILQ_HEAD(, http_header) req_headers; TAILQ_HEAD(, http_header) resp_headers; TAILQ_HEAD(, http_arg) arguments; TAILQ_HEAD(, http_file) files; TAILQ_ENTRY(http_request) list; TAILQ_ENTRY(http_request) olist; }; struct http_state { const char *name; int (*cb)(struct http_request *); }; extern int http_request_count; extern u_int16_t http_header_max; extern u_int64_t http_body_max; extern u_int64_t http_hsts_enable; extern u_int16_t http_keepalive_time; extern u_int32_t http_request_limit; void http_init(void); void http_process(void); const char *http_status_text(int); time_t http_date_to_time(char *); void http_request_free(struct http_request *); void http_request_sleep(struct http_request *); void http_request_wakeup(struct http_request *); char *http_body_text(struct http_request *); void http_process_request(struct http_request *, int); u_int8_t *http_body_bytes(struct http_request *, u_int32_t *); void http_response(struct http_request *, int, void *, u_int32_t); void http_response_stream(struct http_request *, int, void *, u_int64_t, int (*cb)(struct netbuf *), void *); int http_request_header(struct http_request *, const char *, char **); void http_response_header(struct http_request *, const char *, const char *); int http_request_new(struct connection *, struct spdy_stream *, const char *, const char *, const char *, const char *, struct http_request **); int http_state_run(struct http_state *, u_int8_t, struct http_request *); int http_argument_urldecode(char *); int http_header_recv(struct netbuf *); int http_generic_404(struct http_request *); int http_populate_arguments(struct http_request *); int http_populate_multipart_form(struct http_request *, int *); int http_argument_get(struct http_request *, const char *, void **, void *, u_int32_t *, int); int http_file_lookup(struct http_request *, const char *, char **, u_int8_t **, u_int32_t *); void kore_accesslog(struct http_request *); enum http_status_code { HTTP_STATUS_CONTINUE = 100, HTTP_STATUS_SWITCHING_PROTOCOLS = 101, HTTP_STATUS_OK = 200, HTTP_STATUS_CREATED = 201, HTTP_STATUS_ACCEPTED = 202, HTTP_STATUS_NON_AUTHORITATIVE = 203, HTTP_STATUS_NO_CONTENT = 204, HTTP_STATUS_RESET_CONTENT = 205, HTTP_STATUS_PARTIAL_CONTENT = 206, HTTP_STATUS_MULTIPLE_CHOICES = 300, HTTP_STATUS_MOVED_PERMANENTLY = 301, HTTP_STATUS_FOUND = 302, HTTP_STATUS_SEE_OTHER = 303, HTTP_STATUS_NOT_MODIFIED = 304, HTTP_STATUS_USE_PROXY = 305, HTTP_STATUS_TEMPORARY_REDIRECT = 307, HTTP_STATUS_BAD_REQUEST = 400, HTTP_STATUS_UNAUTHORIZED = 401, HTTP_STATUS_PAYMENT_REQUIRED = 402, HTTP_STATUS_FORBIDDEN = 403, HTTP_STATUS_NOT_FOUND = 404, HTTP_STATUS_METHOD_NOT_ALLOWED = 405, HTTP_STATUS_NOT_ACCEPTABLE = 406, HTTP_STATUS_PROXY_AUTH_REQUIRED = 407, HTTP_STATUS_REQUEST_TIMEOUT = 408, HTTP_STATUS_CONFLICT = 409, HTTP_STATUS_GONE = 410, HTTP_STATUS_LENGTH_REQUIRED = 411, HTTP_STATUS_PRECONDITION_FAILED = 412, HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413, HTTP_STATUS_REQUEST_URI_TOO_LARGE = 414, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, HTTP_STATUS_REQUEST_RANGE_INVALID = 416, HTTP_STATUS_EXPECTATION_FAILED = 417, HTTP_STATUS_INTERNAL_ERROR = 500, HTTP_STATUS_NOT_IMPLEMENTED = 501, HTTP_STATUS_BAD_GATEWAY = 502, HTTP_STATUS_SERVICE_UNAVAILABLE = 503, HTTP_STATUS_GATEWAY_TIMEOUT = 504, HTTP_STATUS_BAD_VERSION = 505 }; #if defined(__cplusplus) } #endif #endif /* !__H_HTTP_H */ kore/includes/spdy.h0000644000175000001440000000642012527355514014034 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __H_SPDY_H #define __H_SPDY_H #include #include #if defined(__cplusplus) extern "C" { #endif /* XXX */ struct connection; struct http_request; struct spdy_ctrl_frame { u_int16_t version; u_int16_t type; u_int8_t flags; u_int32_t length; }; struct spdy_data_frame { u_int32_t stream_id; u_int8_t flags; u_int32_t length; }; struct spdy_syn_stream { u_int32_t stream_id; u_int32_t assoc_stream_id; u_int8_t slot; u_int8_t reserved; u_int8_t prio; }; struct spdy_header_block { u_int8_t *header_block; u_int32_t header_block_len; u_int32_t header_offset; u_int32_t header_pairs; }; struct spdy_stream { u_int32_t stream_id; u_int8_t flags; u_int8_t prio; u_int64_t post_size; u_int64_t send_size; u_int32_t frame_size; u_int32_t recv_wsize; u_int32_t send_wsize; void (*onclose)(struct connection *, struct spdy_stream *); struct http_request *httpreq; struct spdy_header_block *hblock; TAILQ_ENTRY(spdy_stream) list; }; extern const unsigned char SPDY_dictionary_txt[]; #if defined(__cplusplus) } #endif #define KORE_SSL_PROTO_STRING "\x08spdy/3.1\x08http/1.1" #define SPDY_CONTROL_FRAME(x) ((x & (1 << 31))) #define SPDY_FRAME_SIZE 8 #define SPDY_SYNFRAME_SIZE 10 #define SPDY_ZLIB_DICT_SIZE 1423 #define SPDY_ZLIB_CHUNK 16348 #define SPDY_INIT_WSIZE 65536 /* control frames */ #define SPDY_CTRL_FRAME_SYN_STREAM 1 #define SPDY_CTRL_FRAME_SYN_REPLY 2 #define SPDY_CTRL_FRAME_RST_STREAM 3 #define SPDY_CTRL_FRAME_SETTINGS 4 #define SPDY_CTRL_FRAME_PING 6 #define SPDY_CTRL_FRAME_GOAWAY 7 #define SPDY_CTRL_FRAME_WINDOW 9 #define SPDY_DATA_FRAME 99 /* session error codes */ #define SPDY_SESSION_ERROR_OK 0 #define SPDY_SESSION_ERROR_PROTOCOL 1 #define SPDY_SESSION_ERROR_INTERNAL 2 /* flags */ #define FLAG_FIN 0x01 #define FLAG_UNIDIRECTIONAL 0x02 /* settings */ #define SETTINGS_UPLOAD_BANDWIDTH 1 #define SETTINGS_DOWNLOAD_BANDWIDTH 2 #define SETTINGS_ROUND_TRIP_TIME 3 #define SETTINGS_MAX_CONCURRENT_STREAMS 4 #define SETTINGS_CURRENT_CWND 5 #define SETTINGS_DOWNLOAD_RETRANS_RATE 6 #define SETTINGS_INITIAL_WINDOW_SIZE 7 #define SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE 8 #define SPDY_HBLOCK_NORMAL 0 #define SPDY_HBLOCK_DELAYED_ALLOC 1 #define SPDY_FLOW_WINDOW_MAX 2147483647 /* internal flags (make sure they don't clash with SPDY stream flags) */ #define SPDY_KORE_FIN 0x10 #define SPDY_DATAFRAME_PRELUDE 0x20 #define SPDY_NO_CLOSE 0x40 #define SPDY_KEEP_NETBUFS 0 #define SPDY_REMOVE_NETBUFS 1 #endif /* !__H_SPDY_H */ kore/LICENSE0000644000175000001440000000143012527355513012076 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ kore/conf/0000755000175000001440000000000012527355513012020 5ustar jorisuserskore/conf/kore.conf.example0000644000175000001440000001734612527355513015274 0ustar jorisusers# Example Kore configuration # Below you will find all available configuration # options for Kore. Options which have a default value # and can be left out of the configuration are commented # out with their default value specified. # Maximum length to queue pending connections (see listen(2)) # MUST be set before any bind directive. #socket_backlog 5000 # Server configuration. bind 127.0.0.1 443 # The path worker processes will chroot into after starting. chroot /home/joris/src/kore # Worker processes will run as the specified user. runas joris # Set workers to the amount of CPU's available in your system, # kore will automatically distribute all workers on them. workers 4 # The number of active connections each worker can handle. # You might have to tweak this number based on your hardware. #worker_max_connections 250 # Limit of maximum open files per worker. #worker_rlimit_nofiles 1024 # Limit the number of new connections a worker can accept # in a single event loop. # NOTE: This can have a *MASSIVE* impact as this controls # how new connections are spread across worker processes. # # This is disabled by default. If you wish to enable this # specify the number of connections a worker will accept # before returning from the accept loop. #worker_accept_threshold 0 # Workers bind themselves to a single CPU by default. # Turn this off by setting this option to 0 #worker_set_affinity 1 # Store the pid of the main process in this file. #pidfile kore.pid # HTTP specific settings. # http_header_max Maximum size of HTTP headers (in bytes). # # http_body_max Maximum size of an HTTP body (in bytes). # # http_keepalive_time Maximum seconds an HTTP connection can be # kept alive by the browser. # (Set to 0 to disable keepalive completely). # # http_hsts_enable Send Strict Transport Security header in # all responses. Parameter is the age. # (Set to 0 to disable sending this header). # # http_request_limit Limit the number of requests Kore processes # in a single event loop. #http_header_max 4096 #http_body_max 10240000 #http_keepalive_time 0 #http_hsts_enable 31536000 #http_request_limit 1000 # Websocket specific settings. # websocket_maxframe Specifies the maximum frame size we can receive # websocket_timeout Specifies the time in seconds before a websocket # connection would be closed due to inactivity. #websocket_maxframe 16384 #websocket_timeout 120 # Load modules (you can load multiple at the same time). # An additional parameter can be specified as the "onload" function # which Kore will call when the module is loaded/reloaded. load contrib/examples/generic/example.module example_load # Validators # validator name type regex|function # validator v_example function v_example_func validator v_regex regex ^/test/[a-z]*$ validator v_number regex ^[0-9]*$ validator v_session function v_session_validate # Specify what TLS version to be used. Default is TLSv1.2 # Allowed values: # 1.2 for TLSv1.2 (default) # 1.0 for TLSv1.0 # both for TLSv1.0 and TLSv1.2 #tls_version 1.2 # Specify the TLS ciphers that will be used. #tls_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA # If you wish to use EDH / ECDH specify a file containing # a generated DH key (See OpenSSL dhparam). #tls_dhparam dh2048.pem # Specify the amount of seconds a SPDY connection is kept open. # You can keep it open indefinitely by setting this to 0. #spdy_idle_time 120 # Authentication configuration # # Using authentication blocks you can define a standard way for # Kore to validate your users. In the example below we create # a authentication block called auth_example, which requires # a cookie (session_id) to be set. # # If no cookie is present or the cookie is not valid according # to the set validator, Kore will redirect the browser to the # URI set in authentication_uri. # # Page handlers can be bound to authentication by specifying # authentication block at the end of the page directive (see below). authentication auth_example { # The authentication type denotes the way the user should # be authenticated. # # Allow values: # - cookie (checks for the cookie presence + pass to validator) # - header (checks for header presence + pass to validator) # - request (passes the http_request to the validator) # # Use cases for request could for example be IP based ACLs or # any other criteria that can be extracted from a http_request. # # The request type does not need an authentication_validator. # authentication_type cookie # The name of whatever we are looking for. authentication_value session_id # The validator that will be called to verify the cookie. # Note this is YOUR validator, Kore does not have built-in # session support. You must add this manually using your # preferred method (Storing it in postgres, redis, ...) authentication_validator v_session # The URI Kore will redirect to if a authentication fails. # If this is not set, Kore will return a simple 403. authentication_uri /private } # Domain configuration # # Each domain configuration starts with listing what domain # the directives that follow are to be applied upon. # # Additionally you can specify the following in a domain configuration: # # accesslog # - File where all requests are logged. # client_certificates [CA] [optional CRL] # - Require client certificates to be sent for the given # CA with an optional CRL file. # # Handlers # # Handlers are either static (for fixed paths) or dynamic. # Dynamic handlers take a POSIX regular expression as its path. # # Syntax: # handler path module_callback [auth block] # # Note that the auth block is optional and if set will force Kore to # authenticate the user according to the authentication block its settings # before allowing access to the page. # Example domain that responds to localhost. domain localhost { certfile cert/server.crt certkey cert/server.key accesslog /var/log/kore_access.log # Page handlers with no authentication required. static /css/style.css serve_style_css static / serve_index static /intro.jpg serve_intro static /b64test serve_b64test static /spdy-reset serve_spdyreset static /upload serve_file_upload static /lock-test serve_lock_test static /validator serve_validator static /params-test serve_params_test static /private serve_private # Page handlers with authentication. static /private/test serve_private_test auth_example # Configure /params-test POST to only accept the following parameters. # They are automatically tested against the validator listed. # If the validator would fail Kore will automatically remove the # failing parameter, indicating something was wrong with it. # Any parameters not present in the params block are also filtered out. params post /params-test { validate test1 v_example validate test2 v_regex } # Configure a GET parameter that /params-test can received. As before # this is validated against the validator and removed if validation # fails. All extra parameters in the GET query are filtered out. params get /params-test { validate arg1 v_example validate id v_number } } #domain domain.com { # certfile cert/other/server.crt # certkey cert/other/server.key # accesslog /var/log/other_kore_access.log # client_certificates cert/other/ca.crt # static /css/style.css serve_style_css # static / serve_index # dynamic ^/[a-z0-9_]*$ serve_profile #} kore/.gitignore0000644000175000001440000000004412527355513013061 0ustar jorisuserskore *.o *.swp *.module *.DSYM cert kore/src/0000755000175000001440000000000012527355514011663 5ustar jorisuserskore/src/linux.c0000644000175000001440000001263312527355514013173 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include "kore.h" #if defined(KORE_USE_PGSQL) #include "pgsql.h" #endif #if defined(KORE_USE_TASKS) #include "tasks.h" #endif static int efd = -1; static u_int32_t event_count = 0; static struct epoll_event *events = NULL; void kore_platform_init(void) { long n; if ((n = sysconf(_SC_NPROCESSORS_ONLN)) == -1) { kore_debug("could not get number of cpu's falling back to 1"); cpu_count = 1; } else { cpu_count = (u_int16_t)n; } } void kore_platform_worker_setcpu(struct kore_worker *kw) { cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(kw->cpu, &cpuset); if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) == -1) { kore_debug("kore_worker_setcpu(): %s", errno_s); } else { kore_debug("kore_worker_setcpu(): worker %d on cpu %d", kw->id, kw->cpu); } } void kore_platform_event_init(void) { if ((efd = epoll_create(10000)) == -1) fatal("epoll_create(): %s", errno_s); event_count = worker_max_connections + nlisteners; events = kore_calloc(event_count, sizeof(struct epoll_event)); } int kore_platform_event_wait(u_int64_t timer) { u_int32_t r; struct connection *c; struct listener *l; u_int8_t type; int n, i; n = epoll_wait(efd, events, event_count, timer); if (n == -1) { if (errno == EINTR) return (0); fatal("epoll_wait(): %s", errno_s); } if (n > 0) { kore_debug("main(): %d sockets available", n); } r = 0; for (i = 0; i < n; i++) { if (events[i].data.ptr == NULL) fatal("events[%d].data.ptr == NULL", i); type = *(u_int8_t *)events[i].data.ptr; if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) { switch (type) { case KORE_TYPE_LISTENER: fatal("failed on listener socket"); /* NOTREACHED */ #if defined(KORE_USE_PGSQL) case KORE_TYPE_PGSQL_CONN: kore_pgsql_handle(events[i].data.ptr, 1); break; #endif #if defined(KORE_USE_TASKS) case KORE_TYPE_TASK: kore_task_handle(events[i].data.ptr, 1); break; #endif default: c = (struct connection *)events[i].data.ptr; kore_connection_disconnect(c); break; } continue; } switch (type) { case KORE_TYPE_LISTENER: l = (struct listener *)events[i].data.ptr; while (worker_active_connections < worker_max_connections) { if (worker_accept_threshold != 0 && r >= worker_accept_threshold) break; if (!kore_connection_accept(l, &c)) { r = 1; break; } if (c == NULL) break; r++; kore_platform_event_all(c->fd, c); } break; case KORE_TYPE_CONNECTION: c = (struct connection *)events[i].data.ptr; if (events[i].events & EPOLLIN && !(c->flags & CONN_READ_BLOCK)) c->flags |= CONN_READ_POSSIBLE; if (events[i].events & EPOLLOUT && !(c->flags & CONN_WRITE_BLOCK)) c->flags |= CONN_WRITE_POSSIBLE; if (!kore_connection_handle(c)) kore_connection_disconnect(c); break; #if defined(KORE_USE_PGSQL) case KORE_TYPE_PGSQL_CONN: kore_pgsql_handle(events[i].data.ptr, 0); break; #endif #if defined(KORE_USE_TASKS) case KORE_TYPE_TASK: kore_task_handle(events[i].data.ptr, 0); break; #endif default: fatal("wrong type in event %d", type); } } return (r); } void kore_platform_event_all(int fd, void *c) { kore_platform_event_schedule(fd, EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET, 0, c); } void kore_platform_event_schedule(int fd, int type, int flags, void *udata) { struct epoll_event evt; kore_debug("kore_platform_event_schedule(%d, %d, %d, %p)", fd, type, flags, udata); evt.events = type; evt.data.ptr = udata; if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &evt) == -1) { if (errno == EEXIST) { if (epoll_ctl(efd, EPOLL_CTL_MOD, fd, &evt) == -1) fatal("epoll_ctl() MOD: %s", errno_s); } else { fatal("epoll_ctl() ADD: %s", errno_s); } } } void kore_platform_schedule_read(int fd, void *data) { kore_platform_event_schedule(fd, EPOLLIN, 0, data); } void kore_platform_disable_read(int fd) { if (epoll_ctl(efd, EPOLL_CTL_DEL, fd, NULL) == -1) fatal("kore_platform_disable_read: %s", errno_s); } void kore_platform_enable_accept(void) { struct listener *l; kore_debug("kore_platform_enable_accept()"); LIST_FOREACH(l, &listeners, list) kore_platform_event_schedule(l->fd, EPOLLIN, 0, l); } void kore_platform_disable_accept(void) { struct listener *l; kore_debug("kore_platform_disable_accept()"); LIST_FOREACH(l, &listeners, list) { if (epoll_ctl(efd, EPOLL_CTL_DEL, l->fd, NULL) == -1) fatal("kore_platform_disable_accept: %s", errno_s); } } void kore_platform_proctitle(char *title) { if (prctl(PR_SET_NAME, title) == -1) { kore_debug("prctl(): %s", errno_s); } } kore/src/buf.c0000644000175000001440000000577012527355514012614 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "kore.h" struct kore_buf * kore_buf_create(u_int32_t initial) { struct kore_buf *buf; buf = kore_malloc(sizeof(*buf)); buf->data = kore_malloc(initial); buf->length = initial; buf->offset = 0; return (buf); } void kore_buf_append(struct kore_buf *buf, void *d, u_int32_t len) { if ((buf->offset + len) >= buf->length) { buf->length += len + KORE_BUF_INCREMENT; buf->data = kore_realloc(buf->data, buf->length); } memcpy((buf->data + buf->offset), d, len); buf->offset += len; } void kore_buf_appendb(struct kore_buf *buf, struct kore_buf *src) { u_int8_t *d; u_int32_t len; d = kore_buf_release(src, &len); kore_buf_append(buf, d, len); kore_mem_free(d); } void kore_buf_appendv(struct kore_buf *buf, const char *fmt, va_list args) { int l; char *b, sb[BUFSIZ]; l = vsnprintf(sb, sizeof(sb), fmt, args); if (l == -1) fatal("kore_buf_appendv(): vsnprintf error"); if ((size_t)l >= sizeof(sb)) { l = vasprintf(&b, fmt, args); if (l == -1) fatal("kore_buf_appendv(): error or truncation"); } else { b = sb; } kore_buf_append(buf, (u_int8_t *)b, l); if (b != sb) free(b); } void kore_buf_appendf(struct kore_buf *buf, const char *fmt, ...) { va_list args; va_start(args, fmt); kore_buf_appendv(buf, fmt, args); va_end(args); } u_int8_t * kore_buf_release(struct kore_buf *buf, u_int32_t *len) { u_int8_t *p; p = buf->data; *len = buf->offset; kore_mem_free(buf); return (p); } void kore_buf_free(struct kore_buf *buf) { kore_mem_free(buf->data); kore_mem_free(buf); } void kore_buf_replace_string(struct kore_buf *b, char *src, void *dst, size_t len) { u_int32_t blen, off, off2; size_t nlen, klen; char *key, *end, *tmp, *p; off = 0; klen = strlen(src); for (;;) { blen = b->offset; nlen = blen + len; p = (char *)b->data; key = kore_mem_find(p + off, b->offset - off, src, klen); if (key == NULL) break; end = key + klen; off = key - p; off2 = ((char *)(b->data + b->offset) - end); tmp = kore_malloc(nlen); memcpy(tmp, p, off); if (dst != NULL) memcpy((tmp + off), dst, len); memcpy((tmp + off + len), end, off2); kore_mem_free(b->data); b->data = (u_int8_t *)tmp; b->offset = off + len + off2; b->length = nlen; off = off + len; } } kore/src/config.c0000644000175000001440000005753112527355514013307 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "kore.h" #include "http.h" #if defined(KORE_USE_PGSQL) #include "pgsql.h" #endif /* XXX - This is becoming a clusterfuck. Fix it. */ static int configure_include(char **); static int configure_bind(char **); static int configure_load(char **); static int configure_handler(char **); static int configure_domain(char **); static int configure_chroot(char **); static int configure_runas(char **); static int configure_workers(char **); static int configure_pidfile(char **); static int configure_accesslog(char **); static int configure_certfile(char **); static int configure_certkey(char **); static int configure_rlimit_nofiles(char **); static int configure_max_connections(char **); static int configure_accept_threshold(char **); static int configure_set_affinity(char **); static int configure_tls_version(char **); static int configure_tls_cipher(char **); static int configure_tls_dhparam(char **); static int configure_spdy_idle_time(char **); static int configure_http_header_max(char **); static int configure_http_body_max(char **); static int configure_http_hsts_enable(char **); static int configure_http_keepalive_time(char **); static int configure_http_request_limit(char **); static int configure_validator(char **); static int configure_params(char **); static int configure_validate(char **); static int configure_client_certificates(char **); static int configure_authentication(char **); static int configure_authentication_uri(char **); static int configure_authentication_type(char **); static int configure_authentication_value(char **); static int configure_authentication_validator(char **); static int configure_websocket_maxframe(char **); static int configure_websocket_timeout(char **); static int configure_socket_backlog(char **); #if defined(KORE_USE_PGSQL) static int configure_pgsql_conn_max(char **); #endif static void domain_sslstart(void); static void kore_parse_config_file(char *); static struct { const char *name; int (*configure)(char **); } config_names[] = { { "include", configure_include }, { "bind", configure_bind }, { "load", configure_load }, { "static", configure_handler }, { "dynamic", configure_handler }, { "tls_version", configure_tls_version }, { "tls_cipher", configure_tls_cipher }, { "tls_dhparam", configure_tls_dhparam }, { "spdy_idle_time", configure_spdy_idle_time }, { "domain", configure_domain }, { "chroot", configure_chroot }, { "runas", configure_runas }, { "workers", configure_workers }, { "worker_max_connections", configure_max_connections }, { "worker_rlimit_nofiles", configure_rlimit_nofiles }, { "worker_accept_threshold", configure_accept_threshold }, { "worker_set_affinity", configure_set_affinity }, { "pidfile", configure_pidfile }, { "accesslog", configure_accesslog }, { "certfile", configure_certfile }, { "certkey", configure_certkey }, { "client_certificates", configure_client_certificates }, { "http_header_max", configure_http_header_max }, { "http_body_max", configure_http_body_max }, { "http_hsts_enable", configure_http_hsts_enable }, { "http_keepalive_time", configure_http_keepalive_time }, { "http_request_limit", configure_http_request_limit }, { "validator", configure_validator }, { "params", configure_params }, { "validate", configure_validate }, { "authentication", configure_authentication }, { "authentication_uri", configure_authentication_uri }, { "authentication_type", configure_authentication_type }, { "authentication_value", configure_authentication_value }, { "authentication_validator", configure_authentication_validator }, { "websocket_maxframe", configure_websocket_maxframe }, { "websocket_timeout", configure_websocket_timeout }, { "socket_backlog", configure_socket_backlog }, #if defined(KORE_USE_PGSQL) { "pgsql_conn_max", configure_pgsql_conn_max }, #endif { NULL, NULL }, }; char *config_file = NULL; static u_int8_t current_method = 0; static struct kore_auth *current_auth = NULL; static struct kore_domain *current_domain = NULL; static struct kore_module_handle *current_handler = NULL; void kore_parse_config(void) { kore_parse_config_file(config_file); if (!kore_module_loaded()) fatal("no site module was loaded"); if (LIST_EMPTY(&listeners)) fatal("no listeners defined"); if (skip_chroot != 1 && chroot_path == NULL) { fatal("missing a chroot path"); } if (getuid() != 0 && skip_chroot == 0) { fatal("cannot chroot, use -n to skip it"); } if (skip_runas != 1 && runas_user == NULL) { fatal("missing runas user"); } if (getuid() != 0 && skip_runas == 0) { fatal("cannot drop privileges, use -p to skip it"); } } static void kore_parse_config_file(char *fpath) { FILE *fp; int i, lineno; char buf[BUFSIZ], *p, *t, *argv[5]; if ((fp = fopen(fpath, "r")) == NULL) fatal("configuration given cannot be opened: %s", fpath); kore_debug("parsing configuration file '%s'", fpath); lineno = 1; while (fgets(buf, sizeof(buf), fp) != NULL) { p = buf; buf[strcspn(buf, "\n")] = '\0'; while (isspace(*p)) p++; if (p[0] == '#' || p[0] == '\0') { lineno++; continue; } for (t = p; *t != '\0'; t++) { if (*t == '\t') *t = ' '; } if (!strcmp(p, "}") && current_handler != NULL) { lineno++; current_handler = NULL; continue; } if (!strcmp(p, "}") && current_auth != NULL) { if (current_auth->validator == NULL) { fatal("no authentication validator for %s", current_auth->name); } lineno++; current_auth = NULL; continue; } if (!strcmp(p, "}") && current_domain != NULL) domain_sslstart(); if (!strcmp(p, "}")) { lineno++; continue; } kore_split_string(p, " ", argv, 5); for (i = 0; config_names[i].name != NULL; i++) { if (!strcmp(config_names[i].name, argv[0])) { if (!config_names[i].configure(argv)) { fatal("configuration error on line %d", lineno); } break; } } if (config_names[i].name == NULL) { printf("unknown configuration option \"%s\" on line %d\n", p, lineno); } lineno++; } fclose(fp); } static int configure_include(char **argv) { if (argv[1] == NULL) { printf("No file given in include directive\n"); return (KORE_RESULT_ERROR); } kore_parse_config_file(argv[1]); return (KORE_RESULT_OK); } static int configure_bind(char **argv) { if (argv[1] == NULL || argv[2] == NULL) return (KORE_RESULT_ERROR); return (kore_server_bind(argv[1], argv[2])); } static int configure_load(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); kore_module_load(argv[1], argv[2]); return (KORE_RESULT_OK); } static int configure_tls_version(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (!strcmp(argv[1], "1.2")) { tls_version = KORE_TLS_VERSION_1_2; } else if (!strcmp(argv[1], "1.0")) { tls_version = KORE_TLS_VERSION_1_0; } else if (!strcmp(argv[1], "both")) { tls_version = KORE_TLS_VERSION_BOTH; } else { printf("unknown value for tls_version: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_tls_cipher(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (strcmp(kore_tls_cipher_list, KORE_DEFAULT_CIPHER_LIST)) { kore_debug("duplicate tls_cipher directive specified"); return (KORE_RESULT_ERROR); } kore_tls_cipher_list = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_tls_dhparam(char **argv) { #if !defined(KORE_BENCHMARK) BIO *bio; if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (tls_dhparam != NULL) { kore_debug("duplicate tls_dhparam directive specified"); return (KORE_RESULT_ERROR); } if ((bio = BIO_new_file(argv[1], "r")) == NULL) { printf("%s did not exist\n", argv[1]); return (KORE_RESULT_ERROR); } tls_dhparam = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (tls_dhparam == NULL) { printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s); return (KORE_RESULT_ERROR); } #endif return (KORE_RESULT_OK); } static int configure_spdy_idle_time(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); spdy_idle_time = kore_strtonum(argv[1], 10, 0, 65535, &err); if (err != KORE_RESULT_OK) { printf("spdy_idle_time has invalid value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } spdy_idle_time = spdy_idle_time * 1000; return (KORE_RESULT_OK); } static int configure_domain(char **argv) { if (argv[2] == NULL) return (KORE_RESULT_ERROR); if (current_domain != NULL) { printf("previous domain configuration not closed\n"); return (KORE_RESULT_ERROR); } if (strcmp(argv[2], "{")) { printf("missing { for domain directive\n"); return (KORE_RESULT_ERROR); } if (!kore_domain_new(argv[1])) { printf("could not create new domain %s\n", argv[1]); return (KORE_RESULT_ERROR); } current_domain = kore_domain_lookup(argv[1]); return (KORE_RESULT_OK); } static int configure_handler(char **argv) { int type; if (current_domain == NULL) { printf("missing domain for page handler\n"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL || argv[2] == NULL) return (KORE_RESULT_ERROR); if (!strcmp(argv[0], "static")) type = HANDLER_TYPE_STATIC; else if (!strcmp(argv[0], "dynamic")) type = HANDLER_TYPE_DYNAMIC; else return (KORE_RESULT_ERROR); if (!kore_module_handler_new(argv[1], current_domain->domain, argv[2], argv[3], type)) { kore_debug("cannot create handler for %s", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_client_certificates(char **argv) { if (current_domain == NULL) { printf("missing domain for require_client_cert\n"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) { printf("missing argument for require_client_cert\n"); return (KORE_RESULT_ERROR); } if (current_domain->cafile != NULL) { printf("require_client_cert already set for %s\n", current_domain->domain); return (KORE_RESULT_ERROR); } current_domain->cafile = kore_strdup(argv[1]); if (argv[2] != NULL) current_domain->crlfile = kore_strdup(argv[2]); return (KORE_RESULT_OK); } static int configure_chroot(char **argv) { if (chroot_path != NULL) { kore_debug("duplicate chroot path specified"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) return (KORE_RESULT_ERROR); chroot_path = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_runas(char **argv) { if (runas_user != NULL) { kore_debug("duplicate runas user specified"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) return (KORE_RESULT_ERROR); runas_user = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_workers(char **argv) { int err; if (worker_count != 0) { kore_debug("duplicate worker directive specified"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) return (KORE_RESULT_ERROR); worker_count = kore_strtonum(argv[1], 10, 1, 255, &err); if (err != KORE_RESULT_OK) { printf("%s is not a correct worker number\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_pidfile(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT)) { kore_debug("duplicate pidfile directive specified"); return (KORE_RESULT_ERROR); } kore_pidfile = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_accesslog(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (current_domain == NULL) { kore_debug("missing domain for accesslog"); return (KORE_RESULT_ERROR); } if (current_domain->accesslog != -1) { kore_debug("domain %s already has an open accesslog", current_domain->domain); return (KORE_RESULT_ERROR); } current_domain->accesslog = open(argv[1], O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (current_domain->accesslog == -1) { kore_debug("open(%s): %s", argv[1], errno_s); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_certfile(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (current_domain == NULL) { printf("missing domain for certfile\n"); return (KORE_RESULT_ERROR); } if (current_domain->certfile != NULL) { kore_debug("domain already has a certfile set"); return (KORE_RESULT_ERROR); } current_domain->certfile = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_certkey(char **argv) { if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (current_domain == NULL) { printf("missing domain for certkey\n"); return (KORE_RESULT_ERROR); } if (current_domain->certkey != NULL) { kore_debug("domain already has a certkey set"); return (KORE_RESULT_ERROR); } current_domain->certkey = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_max_connections(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); worker_max_connections = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad value for worker_max_connections: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_rlimit_nofiles(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); worker_rlimit_nofiles = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad value for worker_rlimit_nofiles: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_accept_threshold(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); worker_accept_threshold = kore_strtonum(argv[1], 0, 1, UINT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad value for worker_accept_threshold: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_set_affinity(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); worker_set_affinity = kore_strtonum(argv[1], 10, 0, 1, &err); if (err != KORE_RESULT_OK) { printf("bad value for worker_set_affinity: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_http_header_max(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (http_header_max != HTTP_HEADER_MAX_LEN) { kore_debug("http_header_max already set"); return (KORE_RESULT_ERROR); } http_header_max = kore_strtonum(argv[1], 10, 1, 65535, &err); if (err != KORE_RESULT_OK) { printf("bad http_header_max value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_http_body_max(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (http_body_max != HTTP_BODY_MAX_LEN) { kore_debug("http_body_max already set"); return (KORE_RESULT_ERROR); } http_body_max = kore_strtonum(argv[1], 10, 1, LONG_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad http_body_max value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_http_hsts_enable(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (http_hsts_enable != HTTP_HSTS_ENABLE) { kore_debug("http_hsts_enable already set"); return (KORE_RESULT_ERROR); } http_hsts_enable = kore_strtonum(argv[1], 10, 0, LONG_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad http_hsts_enable value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_http_keepalive_time(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); if (http_keepalive_time != HTTP_KEEPALIVE_TIME) { kore_debug("http_keepalive_time already set"); return (KORE_RESULT_ERROR); } http_keepalive_time = kore_strtonum(argv[1], 10, 0, USHRT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad http_keepalive_time value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_http_request_limit(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); http_request_limit = kore_strtonum(argv[1], 10, 0, UINT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad http_request_limit value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_validator(char **argv) { u_int8_t type; if (argv[3] == NULL) return (KORE_RESULT_ERROR); if (!strcmp(argv[2], "regex")) { type = KORE_VALIDATOR_TYPE_REGEX; } else if (!strcmp(argv[2], "function")) { type = KORE_VALIDATOR_TYPE_FUNCTION; } else { printf("bad type for validator %s\n", argv[1]); return (KORE_RESULT_ERROR); } if (!kore_validator_add(argv[1], type, argv[3])) { printf("bad validator specified: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_params(char **argv) { struct kore_module_handle *hdlr; if (current_domain == NULL) { printf("params keyword used in wrong context\n"); return (KORE_RESULT_ERROR); } if (current_handler != NULL) { printf("previous params block not closed\n"); return (KORE_RESULT_ERROR); } if (argv[2] == NULL) return (KORE_RESULT_ERROR); if (!strcasecmp(argv[1], "post")) { current_method = HTTP_METHOD_POST; } else if (!strcasecmp(argv[1], "get")) { current_method = HTTP_METHOD_GET; } else if (!strcasecmp(argv[1], "put")) { current_method = HTTP_METHOD_PUT; } else if (!strcasecmp(argv[1], "delete")) { current_method = HTTP_METHOD_DELETE; } else if (!strcasecmp(argv[1], "head")) { current_method = HTTP_METHOD_HEAD; } else { printf("unknown method: %s in params block for %s\n", argv[1], argv[2]); return (KORE_RESULT_ERROR); } /* * Find the handler ourselves, otherwise the regex is applied * in case of a dynamic page. */ TAILQ_FOREACH(hdlr, &(current_domain->handlers), list) { if (!strcmp(hdlr->path, argv[2])) { current_handler = hdlr; return (KORE_RESULT_OK); } } printf("params for unknown page handler: %s\n", argv[2]); return (KORE_RESULT_ERROR); } static int configure_validate(char **argv) { struct kore_handler_params *p; struct kore_validator *val; if (current_handler == NULL) { printf("validate keyword used in wrong context\n"); return (KORE_RESULT_ERROR); } if (argv[2] == NULL) return (KORE_RESULT_ERROR); if ((val = kore_validator_lookup(argv[2])) == NULL) { printf("unknown validator %s for %s\n", argv[2], argv[1]); return (KORE_RESULT_ERROR); } p = kore_malloc(sizeof(*p)); p->validator = val; p->method = current_method; p->name = kore_strdup(argv[1]); TAILQ_INSERT_TAIL(&(current_handler->params), p, list); return (KORE_RESULT_OK); } static int configure_authentication(char **argv) { if (argv[2] == NULL) { printf("Missing name for authentication block\n"); return (KORE_RESULT_ERROR); } if (current_auth != NULL) { printf("Previous authentication block not closed\n"); return (KORE_RESULT_ERROR); } if (strcmp(argv[2], "{")) { printf("missing { for authentication block\n"); return (KORE_RESULT_ERROR); } if (!kore_auth_new(argv[1])) return (KORE_RESULT_ERROR); current_auth = kore_auth_lookup(argv[1]); return (KORE_RESULT_OK); } static int configure_authentication_type(char **argv) { if (current_auth == NULL) { printf("authentication_type outside authentication block\n"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) { printf("missing parameter for authentication_type\n"); return (KORE_RESULT_ERROR); } if (!strcmp(argv[1], "cookie")) { current_auth->type = KORE_AUTH_TYPE_COOKIE; } else if (!strcmp(argv[1], "header")) { current_auth->type = KORE_AUTH_TYPE_HEADER; } else if (!strcmp(argv[1], "request")) { current_auth->type = KORE_AUTH_TYPE_REQUEST; } else { printf("unknown authentication type '%s'\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_authentication_value(char **argv) { if (current_auth == NULL) { printf("authentication_value outside authentication block\n"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) { printf("missing parameter for authentication_value\n"); return (KORE_RESULT_ERROR); } if (current_auth->value != NULL) { printf("duplicate authentication_value found\n"); return (KORE_RESULT_ERROR); } current_auth->value = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_authentication_validator(char **argv) { struct kore_validator *val; if (current_auth == NULL) { printf("authentication_validator outside authentication\n"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) { printf("missing parameter for authentication_validator\n"); return (KORE_RESULT_ERROR); } if (current_auth->validator != NULL) { printf("duplicate authentication_validator found\n"); return (KORE_RESULT_ERROR); } if ((val = kore_validator_lookup(argv[1])) == NULL) { printf("authentication validator '%s' not found\n", argv[1]); return (KORE_RESULT_ERROR); } current_auth->validator = val; return (KORE_RESULT_OK); } static int configure_authentication_uri(char **argv) { if (current_auth == NULL) { printf("authentication_uri outside authentication block\n"); return (KORE_RESULT_ERROR); } if (argv[1] == NULL) { printf("missing parameter for authentication_uri\n"); return (KORE_RESULT_ERROR); } if (current_auth->redirect != NULL) { printf("duplicate authentication_uri found\n"); return (KORE_RESULT_ERROR); } current_auth->redirect = kore_strdup(argv[1]); return (KORE_RESULT_OK); } static int configure_websocket_maxframe(char **argv) { int err; if (argv[1] == NULL) { printf("missing parameter for kore_websocket_maxframe\n"); return (KORE_RESULT_ERROR); } kore_websocket_maxframe = kore_strtonum64(argv[1], 1, &err); if (err != KORE_RESULT_OK) { printf("bad kore_websocket_maxframe value\n"); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static int configure_websocket_timeout(char **argv) { int err; if (argv[1] == NULL) { printf("missing parameter for kore_websocket_timeout\n"); return (KORE_RESULT_ERROR); } kore_websocket_timeout = kore_strtonum64(argv[1], 1, &err); if (err != KORE_RESULT_OK) { printf("bad kore_websocket_timeout value\n"); return (KORE_RESULT_ERROR); } kore_websocket_timeout = kore_websocket_timeout * 1000; return (KORE_RESULT_OK); } static int configure_socket_backlog(char **argv) { int err; if (argv[1] == NULL) return (KORE_RESULT_ERROR); kore_socket_backlog = kore_strtonum(argv[1], 10, 0, UINT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad socket_backlog value: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } static void domain_sslstart(void) { kore_domain_sslstart(current_domain); current_domain = NULL; } #if defined(KORE_USE_PGSQL) static int configure_pgsql_conn_max(char **argv) { int err; if (argv[1] == NULL) { printf("missing parameter for pgsql_conn_max\n"); return (KORE_RESULT_ERROR); } pgsql_conn_max = kore_strtonum(argv[1], 10, 0, USHRT_MAX, &err); if (err != KORE_RESULT_OK) { printf("bad value for pgsql_conn_max: %s\n", argv[1]); return (KORE_RESULT_ERROR); } return (KORE_RESULT_OK); } #endif kore/src/zlib_dict.c0000644000175000001440000003175712527355514014007 0ustar jorisusers/* * Copyright (c) 2013 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ const unsigned char SPDY_dictionary_txt[] = { 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // - - - - o p t i 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // o n s - - - - h 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // e a d - - - - p 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // o s t - - - - p 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // u t - - - - d e 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // l e t e - - - - 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // t r a c e - - - 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // - a c c e p t - 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t - c h a r s e 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t - - - - a c c 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e p t - e n c o 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // d i n g - - - - 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // a c c e p t - l 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // a n g u a g e - 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t - r a n g e s 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // - - - - a g e - 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // - - - a l l o w 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // - - - - a u t h 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // o r i z a t i o 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n - - - - c a c 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // h e - c o n t r 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // o l - - - - c o 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // n n e c t i o n 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // e n t - b a s e 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e n t - e n c o 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // d i n g - - - - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // c o n t e n t - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // l a n g u a g e 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // e n t - l e n g 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // t h - - - - c o 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // n t e n t - l o 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // c a t i o n - - 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t - m d 5 - - - 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // - c o n t e n t 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // - r a n g e - - 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t - t y p e - - 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // - - d a t e - - 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // - - e t a g - - 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // - - e x p e c t 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // - - - - e x p i 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // r e s - - - - f 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // r o m - - - - h 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // o s t - - - - i 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f - m a t c h - 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // - - - i f - m o 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // d i f i e d - s 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // i n c e - - - - 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // i f - n o n e - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // m a t c h - - - 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // - i f - r a n g 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e - - - - i f - 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // u n m o d i f i 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // e d - s i n c e 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // - - - - l a s t 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // - m o d i f i e 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d - - - - l o c 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // a t i o n - - - 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // - m a x - f o r 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // w a r d s - - - 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // - p r a g m a - 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // - - - p r o x y 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // - a u t h e n t 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // i c a t e - - - 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // - p r o x y - a 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // u t h o r i z a 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // t i o n - - - - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // r a n g e - - - 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // - r e f e r e r 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // - - - - r e t r 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y - a f t e r - 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // - - - s e r v e 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r - - - - t e - 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // - - - t r a i l 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // e r - - - - t r 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // a n s f e r - e 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // n c o d i n g - 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // - - - u p g r a 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // d e - - - - u s 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // e r - a g e n t 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // - - - - v a r y 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // - - - - v i a - 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // - - - w a r n i 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // n g - - - - w w 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w - a u t h e n 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // t i c a t e - - 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // - - m e t h o d 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // - - - - g e t - 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // - - - s t a t u 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s - - - - 2 0 0 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // - O K - - - - v 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // e r s i o n - - 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // - - H T T P - 1 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // - 1 - - - - u r 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l - - - - p u b 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // l i c - - - - s 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // e t - c o o k i 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e - - - - k e e 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p - a l i v e - 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // - - - o r i g i 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n 1 0 0 1 0 1 2 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 0 1 2 0 2 2 0 5 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 2 0 6 3 0 0 3 0 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 2 3 0 3 3 0 4 3 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 0 5 3 0 6 3 0 7 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 4 0 2 4 0 5 4 0 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 6 4 0 7 4 0 8 4 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 0 9 4 1 0 4 1 1 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 4 1 2 4 1 3 4 1 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 4 4 1 5 4 1 6 4 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 1 7 5 0 2 5 0 4 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 5 0 5 2 0 3 - N 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // o n - A u t h o 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // r i t a t i v e 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // - I n f o r m a 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // t i o n 2 0 4 - 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // N o - C o n t e 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // n t 3 0 1 - M o 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // v e d - P e r m 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // a n e n t l y 4 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 0 0 - B a d - R 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // e q u e s t 4 0 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1 - U n a u t h 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // o r i z e d 4 0 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3 - F o r b i d 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // d e n 4 0 4 - N 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // o t - F o u n d 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 5 0 0 - I n t e 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // r n a l - S e r 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // v e r - E r r o 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r 5 0 1 - N o t 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // - I m p l e m e 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // n t e d 5 0 3 - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // S e r v i c e - 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // U n a v a i l a 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // b l e J a n - F 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // e b - M a r - A 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // p r - M a y - J 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // u n - J u l - A 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // u g - S e p t - 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // O c t - N o v - 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // D e c - 0 0 - 0 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0 - 0 0 - M o n 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // - - T u e - - W 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // e d - - T h u - 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // - F r i - - S a 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t - - S u n - - 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // G M T c h u n k 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // e d - t e x t - 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // h t m l - i m a 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // g e - p n g - i 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // m a g e - j p g 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // - i m a g e - g 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // i f - a p p l i 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // m l - a p p l i 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // h t m l - x m l 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // - t e x t - p l 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // a i n - t e x t 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // - j a v a s c r 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // i p t - p u b l 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // i c p r i v a t 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // e m a x - a g e 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // - g z i p - d e 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // f l a t e - s d 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // c h c h a r s e 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t - u t f - 8 c 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // h a r s e t - i 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // s o - 8 8 5 9 - 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1 - u t f - - - 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // - e n q - 0 - }; kore/src/domain.c0000644000175000001440000001546412527355514013310 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "kore.h" #define SSL_SESSION_ID "kore_ssl_sessionid" struct kore_domain_h domains; struct kore_domain *primary_dom = NULL; DH *tls_dhparam = NULL; int tls_version = KORE_TLS_VERSION_1_2; static void domain_load_crl(struct kore_domain *); #if !defined(KORE_BENCHMARK) static int domain_x509_verify(int, X509_STORE_CTX *); #endif void kore_domain_init(void) { TAILQ_INIT(&domains); } int kore_domain_new(char *domain) { struct kore_domain *dom; if (kore_domain_lookup(domain) != NULL) return (KORE_RESULT_ERROR); kore_debug("kore_domain_new(%s)", domain); dom = kore_malloc(sizeof(*dom)); dom->accesslog = -1; dom->cafile = NULL; dom->certkey = NULL; dom->ssl_ctx = NULL; dom->certfile = NULL; dom->crlfile = NULL; dom->domain = kore_strdup(domain); TAILQ_INIT(&(dom->handlers)); TAILQ_INSERT_TAIL(&domains, dom, list); if (primary_dom == NULL) primary_dom = dom; return (KORE_RESULT_OK); } void kore_domain_sslstart(struct kore_domain *dom) { #if !defined(KORE_BENCHMARK) STACK_OF(X509_NAME) *certs; X509_STORE *store; const SSL_METHOD *method; #if !defined(OPENSSL_NO_EC) EC_KEY *ecdh; #endif kore_debug("kore_domain_sslstart(%s)", dom->domain); switch (tls_version) { case KORE_TLS_VERSION_1_2: method = TLSv1_2_server_method(); break; case KORE_TLS_VERSION_1_0: method = TLSv1_server_method(); break; case KORE_TLS_VERSION_BOTH: method = SSLv23_server_method(); break; default: fatal("unknown tls_version: %d", tls_version); return; } dom->ssl_ctx = SSL_CTX_new(method); if (dom->ssl_ctx == NULL) fatal("kore_domain_sslstart(): SSL_ctx_new(): %s", ssl_errno_s); if (!SSL_CTX_use_certificate_chain_file(dom->ssl_ctx, dom->certfile)) { fatal("SSL_CTX_use_certificate_chain_file(%s): %s", dom->certfile, ssl_errno_s); } if (!SSL_CTX_use_PrivateKey_file(dom->ssl_ctx, dom->certkey, SSL_FILETYPE_PEM)) { fatal("SSL_CTX_use_PrivateKey_file(%s): %s", dom->certkey, ssl_errno_s); } if (!SSL_CTX_check_private_key(dom->ssl_ctx)) fatal("Public/Private key for %s do not match", dom->domain); if (tls_dhparam == NULL) fatal("No DH parameters given"); SSL_CTX_set_tmp_dh(dom->ssl_ctx, tls_dhparam); SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE); #if !defined(OPENSSL_NO_EC) if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) != NULL) { SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh); EC_KEY_free(ecdh); } #endif SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION); if (dom->cafile != NULL) { if ((certs = SSL_load_client_CA_file(dom->cafile)) == NULL) { fatal("SSL_load_client_CA_file(%s): %s", dom->cafile, ssl_errno_s); } SSL_CTX_load_verify_locations(dom->ssl_ctx, dom->cafile, NULL); SSL_CTX_set_verify_depth(dom->ssl_ctx, 1); SSL_CTX_set_client_CA_list(dom->ssl_ctx, certs); SSL_CTX_set_verify(dom->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); if ((store = SSL_CTX_get_cert_store(dom->ssl_ctx)) == NULL) fatal("SSL_CTX_get_cert_store(): %s", ssl_errno_s); X509_STORE_set_verify_cb(store, domain_x509_verify); } SSL_CTX_set_session_id_context(dom->ssl_ctx, (unsigned char *)SSL_SESSION_ID, strlen(SSL_SESSION_ID)); /* * Force OpenSSL to not use its freelists. Even without using * SSL_MODE_RELEASE_BUFFERS there are times it will use the * freelists. So forcefully putting its max length to 0 is the * only we choice we seem to have. * * Note that OpenBSD has since heartbleed removed freelists * from its OpenSSL in base so we don't need to care about it. */ #if !defined(OpenBSD) || (OpenBSD < 201405) dom->ssl_ctx->freelist_max_len = 0; #endif SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); if (tls_version == KORE_TLS_VERSION_BOTH) { SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_SSLv3); SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_TLSv1_1); } SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); SSL_CTX_set_cipher_list(dom->ssl_ctx, kore_tls_cipher_list); SSL_CTX_set_info_callback(dom->ssl_ctx, kore_tls_info_callback); SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb); SSL_CTX_set_next_protos_advertised_cb(dom->ssl_ctx, kore_tls_npn_cb, NULL); kore_mem_free(dom->certfile); kore_mem_free(dom->certkey); #endif } struct kore_domain * kore_domain_lookup(const char *domain) { struct kore_domain *dom; TAILQ_FOREACH(dom, &domains, list) { if (!strcmp(dom->domain, domain)) return (dom); } return (NULL); } void kore_domain_closelogs(void) { struct kore_domain *dom; TAILQ_FOREACH(dom, &domains, list) close(dom->accesslog); } void kore_domain_load_crl(void) { struct kore_domain *dom; TAILQ_FOREACH(dom, &domains, list) domain_load_crl(dom); } static void domain_load_crl(struct kore_domain *dom) { #if !defined(KORE_BENCHMARK) X509_STORE *store; ERR_clear_error(); if (dom->cafile == NULL) return; if (dom->crlfile == NULL) { kore_log(LOG_WARNING, "WARNING: Running without CRL"); return; } if ((store = SSL_CTX_get_cert_store(dom->ssl_ctx)) == NULL) { kore_log(LOG_ERR, "SSL_CTX_get_cert_store(): %s", ssl_errno_s); return; } if (!X509_STORE_load_locations(store, dom->crlfile, NULL)) { kore_log(LOG_ERR, "X509_STORE_load_locations(): %s", ssl_errno_s); return; } X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #endif } #if !defined(KORE_BENCHMARK) static int domain_x509_verify(int ok, X509_STORE_CTX *ctx) { X509 *cert; const char *text; int error, depth; error = X509_STORE_CTX_get_error(ctx); cert = X509_STORE_CTX_get_current_cert(ctx); if (ok == 0 && cert != NULL) { text = X509_verify_cert_error_string(error); depth = X509_STORE_CTX_get_error_depth(ctx); kore_log(LOG_WARNING, "X509 verification error depth:%d - %s", depth, text); /* Continue on CRL validity errors. */ switch (error) { case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_UNABLE_TO_GET_CRL: ok = 1; break; } } return (ok); } #endif kore/src/spdy.c0000644000175000001440000006356012527355514013020 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "spdy.h" #include "kore.h" #include "http.h" static int spdy_ctrl_frame_syn_stream(struct netbuf *); static int spdy_ctrl_frame_rst_stream(struct netbuf *); static int spdy_ctrl_frame_settings(struct netbuf *); static int spdy_ctrl_frame_ping(struct netbuf *); static int spdy_ctrl_frame_window(struct netbuf *); static int spdy_ctrl_frame_goaway(struct netbuf *); static int spdy_data_frame_recv(struct netbuf *); static void spdy_block_write(struct connection *); static void spdy_enable_write(struct connection *); static int spdy_zlib_inflate(struct connection *, u_int8_t *, size_t, u_int8_t **, u_int32_t *); static int spdy_zlib_deflate(struct connection *, u_int8_t *, size_t, u_int8_t **, u_int32_t *); u_int64_t spdy_idle_time = 120000; u_int32_t spdy_recv_wsize = SPDY_INIT_WSIZE; int spdy_frame_recv(struct netbuf *nb) { struct spdy_stream *s; struct spdy_ctrl_frame ctrl; struct spdy_data_frame data; int (*cb)(struct netbuf *), r; struct connection *c = (struct connection *)nb->owner; kore_debug("spdy_frame_recv(%p)", nb); if (SPDY_CONTROL_FRAME(net_read32(nb->buf))) { ctrl.version = net_read16(nb->buf) & 0x7fff; ctrl.type = net_read16(nb->buf + 2); ctrl.flags = *(u_int8_t *)(nb->buf + 4); ctrl.length = net_read32(nb->buf + 4) & 0xffffff; kore_debug("received control frame %d", ctrl.type); if ((int)ctrl.length < 0) { spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } if (ctrl.version != 3) { kore_debug("protocol mismatch (recv version %u)", ctrl.version); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } switch (ctrl.type) { case SPDY_CTRL_FRAME_SYN_STREAM: cb = spdy_ctrl_frame_syn_stream; break; case SPDY_CTRL_FRAME_RST_STREAM: cb = spdy_ctrl_frame_rst_stream; break; case SPDY_CTRL_FRAME_SETTINGS: cb = spdy_ctrl_frame_settings; break; case SPDY_CTRL_FRAME_PING: cb = spdy_ctrl_frame_ping; break; case SPDY_CTRL_FRAME_WINDOW: cb = spdy_ctrl_frame_window; break; case SPDY_CTRL_FRAME_GOAWAY: cb = spdy_ctrl_frame_goaway; break; default: cb = NULL; break; } r = KORE_RESULT_OK; if (cb != NULL) { net_recv_expand(c, ctrl.length, cb); } else { kore_debug("no callback for type %u", ctrl.type); } } else { data.stream_id = net_read32(nb->buf) & ~(1 << 31); if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) { if (!(c->flags & SPDY_CONN_GOAWAY)) { kore_debug("recv dataframe for bad stream: %u", data.stream_id); r = KORE_RESULT_ERROR; } else { r = KORE_RESULT_OK; } } else if (s->flags & FLAG_FIN) { kore_debug("received data frame but FLAG_FIN was set"); r = KORE_RESULT_ERROR; } else { data.flags = *(u_int8_t *)(nb->buf + 4); data.length = net_read32(nb->buf + 4) & 0xffffff; if ((int)data.length < 0) { r = KORE_RESULT_ERROR; } else { r = KORE_RESULT_OK; net_recv_expand(c, data.length, spdy_data_frame_recv); } } } if (r != KORE_RESULT_OK) { r = KORE_RESULT_OK; spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); } return (r); } int spdy_dataframe_begin(struct connection *c) { struct spdy_stream *s = c->snb->stream; kore_debug("spdy_dataframe_begin(%p): s:%u fz:%d sz:%d wz:%d cwz:%d", c, s->stream_id, s->frame_size, s->send_size, s->send_wsize, c->spdy_send_wsize); if (s->frame_size != 0 || s->send_size == 0) { fatal("spdy_dataframe_begin(): s:%u fz:%d - sz:%d", s->stream_id, s->frame_size, s->send_size); } if ((int)s->send_wsize <= 0 || (int)c->spdy_send_wsize <= 0) { kore_debug("no space for new dataframe right now"); spdy_block_write(c); return (KORE_RESULT_ERROR); } s->frame_size = MIN(NETBUF_SEND_PAYLOAD_MAX, s->send_size); kore_debug("spdy_dataframe_begin(): %u: fz:%d wz:%d cwz:%d", s->stream_id, s->frame_size, s->send_size, c->spdy_send_wsize); s->flags &= ~SPDY_DATAFRAME_PRELUDE; spdy_frame_send(c, SPDY_DATA_FRAME, 0, s->frame_size, s, 0); return (KORE_RESULT_OK); } void spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags, u_int32_t len, struct spdy_stream *s, u_int32_t misc) { u_int8_t nb[16]; u_int32_t length; kore_debug("spdy_frame_send(%p, %u, %u, %u, %p, %u)", c, type, flags, len, s, misc); switch (type) { case SPDY_CTRL_FRAME_SYN_REPLY: case SPDY_DATA_FRAME: if (s == NULL) fatal("spdy_frame_send(): stream is NULL for %d", type); break; } length = 0; memset(nb, 0, sizeof(nb)); switch (type) { case SPDY_CTRL_FRAME_PING: case SPDY_CTRL_FRAME_SYN_REPLY: net_write16(&nb[0], 3); nb[0] |= (1 << 7); net_write16(&nb[2], type); if (type != SPDY_CTRL_FRAME_PING) { net_write32(&nb[4], len + 4); nb[4] = flags; net_write32(&nb[8], s->stream_id); } else { net_write32(&nb[4], len); nb[4] = flags; net_write32(&nb[8], misc); } length = 12; break; case SPDY_CTRL_FRAME_GOAWAY: net_write16(&nb[0], 3); nb[0] |= (1 << 7); net_write16(&nb[2], type); net_write32(&nb[4], len); nb[4] = flags; length = 8; break; case SPDY_CTRL_FRAME_WINDOW: net_write16(&nb[0], 3); nb[0] |= (1 << 7); net_write16(&nb[2], type); net_write32(&nb[4], len); nb[4] = flags; net_write32(&nb[8], (s != NULL) ? s->stream_id : 0); net_write32(&nb[12], misc); length = 16; break; case SPDY_DATA_FRAME: net_write32(&nb[0], s->stream_id); nb[0] &= ~(1 << 7); net_write32(&nb[4], len); nb[4] = flags; length = 8; break; } if (type == SPDY_DATA_FRAME && !(flags & FLAG_FIN)) { net_send_queue(c, nb, length, NULL, NETBUF_BEFORE_CHAIN); } else { net_send_queue(c, nb, length, NULL, NETBUF_LAST_CHAIN); } } struct spdy_stream * spdy_stream_lookup(struct connection *c, u_int32_t id) { struct spdy_stream *s; TAILQ_FOREACH(s, &(c->spdy_streams), list) { if (s->stream_id == id) return (s); } return (NULL); } struct spdy_header_block * spdy_header_block_create(int delayed_alloc) { struct spdy_header_block *hblock; kore_debug("spdy_header_block_create()"); hblock = kore_malloc(sizeof(*hblock)); if (delayed_alloc == SPDY_HBLOCK_NORMAL) { hblock->header_block = kore_malloc(128); hblock->header_block_len = 128; hblock->header_offset = 4; } else { hblock->header_block = NULL; hblock->header_block_len = 0; hblock->header_offset = 0; } hblock->header_pairs = 0; return (hblock); } void spdy_header_block_add(struct spdy_header_block *hblock, char *name, char *value) { u_int8_t *p; u_int32_t nlen, vlen, tlen; kore_debug("spdy_header_block_add(%p, %s, %s)", hblock, name, value); nlen = strlen(name); vlen = strlen(value); tlen = nlen + 4 + vlen + 4; if ((tlen + hblock->header_offset) > hblock->header_block_len) { hblock->header_block_len += nlen + vlen + 128; hblock->header_block = kore_realloc(hblock->header_block, hblock->header_block_len); } p = hblock->header_block + hblock->header_offset; net_write32(p, nlen); memcpy((p + 4), (u_int8_t *)name, nlen); hblock->header_offset += 4 + nlen; p = hblock->header_block + hblock->header_offset; net_write32(p, vlen); memcpy((p + 4), (u_int8_t *)value, vlen); hblock->header_offset += 4 + vlen; hblock->header_pairs++; } u_int8_t * spdy_header_block_release(struct connection *c, struct spdy_header_block *hblock, u_int32_t *len) { u_int8_t *deflated; kore_debug("spdy_header_block_release(%p, %p)", hblock, len); net_write32(hblock->header_block, hblock->header_pairs); if (!spdy_zlib_deflate(c, hblock->header_block, hblock->header_offset, &deflated, len)) { kore_mem_free(hblock->header_block); kore_mem_free(hblock); return (NULL); } kore_mem_free(hblock->header_block); kore_mem_free(hblock); return (deflated); } int spdy_stream_get_header(struct spdy_header_block *s, const char *header, char **out) { char *cmp; u_int8_t *p, *end; u_int32_t i, nlen, vlen; kore_debug("spdy_stream_get_header(%p, %s) <%d>", s, header, s->header_pairs); p = s->header_block + 4; end = s->header_block + s->header_block_len; if (p >= end) { kore_debug("p >= end when looking for headers"); return (KORE_RESULT_ERROR); } for (i = 0; i < s->header_pairs; i++) { nlen = net_read32(p); if ((int)nlen < 0 || (p + nlen + 4) > end) { kore_debug("nlen out of bounds on %u (%u)", i, nlen); return (KORE_RESULT_ERROR); } vlen = net_read32(p + nlen + 4); if ((int)vlen < 0 || (p + nlen + vlen + 8) > end) { kore_debug("vlen out of bounds on %u (%u)", i, vlen); return (KORE_RESULT_ERROR); } cmp = (char *)(p + 4); if (!strncasecmp(cmp, header, nlen)) { cmp = (char *)(p + nlen + 8); *out = kore_malloc(vlen + 1); kore_strlcpy(*out, cmp, vlen + 1); return (KORE_RESULT_OK); } p += nlen + vlen + 8; } return (KORE_RESULT_ERROR); } void spdy_session_teardown(struct connection *c, u_int8_t err) { u_int8_t d[8]; kore_debug("spdy_session_teardown(%p, %u)", c, err); net_write32((u_int8_t *)&d[0], c->client_stream_id); net_write32((u_int8_t *)&d[4], err); spdy_frame_send(c, SPDY_CTRL_FRAME_GOAWAY, 0, 8, NULL, 0); net_send_queue(c, d, sizeof(d), NULL, NETBUF_LAST_CHAIN); c->flags &= ~CONN_READ_POSSIBLE; c->flags |= CONN_READ_BLOCK; net_send_flush(c); kore_connection_disconnect(c); } void spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len) { s->send_size -= len; s->frame_size -= len; s->send_wsize -= len; c->spdy_send_wsize -= len; kore_debug("spdy_update_wsize(): s:%u fz:%d sz:%d wz:%d cwz:%d", s->stream_id, s->frame_size, s->send_size, s->send_wsize, c->spdy_send_wsize); if (s->frame_size == 0 && s->send_size > 0) { kore_debug("spdy_update_wsize(): starting new data frame"); s->flags |= SPDY_DATAFRAME_PRELUDE; } if (s->send_size == 0 && !(s->flags & SPDY_NO_CLOSE)) { if (!(s->flags & SPDY_KORE_FIN)) { s->flags |= SPDY_KORE_FIN; kore_debug("sending final frame %u", s->stream_id); spdy_frame_send(c, SPDY_DATA_FRAME, FLAG_FIN, 0, s, 0); } if (s->flags & (SPDY_KORE_FIN | FLAG_FIN)) { spdy_stream_close(c, s, SPDY_KEEP_NETBUFS); return; } kore_debug("%u remains half open\n", s->stream_id); } if ((int)s->send_wsize <= 0 || (int)c->spdy_send_wsize <= 0) { kore_debug("flow control kicked in for %p:%p", c, s); spdy_block_write(c); } } void spdy_stream_close(struct connection *c, struct spdy_stream *s, int rb) { struct http_request *req; struct netbuf *nb, *nt; kore_debug("spdy_stream_close(%p, %p) <%d>", c, s, s->stream_id); if (s->onclose != NULL) s->onclose(c, s); if (rb) { for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = nt) { nt = TAILQ_NEXT(nb, list); if (nb->stream == s) { kore_debug("spdy_stream_close: killing %p", nb); net_remove_netbuf(&(c->send_queue), nb); } } } TAILQ_REMOVE(&(c->spdy_streams), s, list); if (s->hblock != NULL) { if (s->hblock->header_block != NULL) kore_mem_free(s->hblock->header_block); kore_mem_free(s->hblock); } if (s->httpreq != NULL) { req = s->httpreq; req->stream = NULL; req->flags |= HTTP_REQUEST_DELETE; } kore_mem_free(s); } static int spdy_ctrl_frame_syn_stream(struct netbuf *nb) { struct spdy_stream *s; struct spdy_syn_stream syn; struct spdy_ctrl_frame ctrl; u_int8_t *src; char *host, *method, *path, *version; struct connection *c = (struct connection *)nb->owner; ctrl.version = net_read16(nb->buf) & 0x7fff; ctrl.type = net_read16(nb->buf + 2); ctrl.flags = *(u_int8_t *)(nb->buf + 4); ctrl.length = net_read32(nb->buf + 4) & 0xffffff; syn.stream_id = net_read32(nb->buf + 8); syn.assoc_stream_id = net_read32(nb->buf + 12); syn.prio = net_read16(nb->buf + 16) & 0xe000; syn.slot = net_read16(nb->buf + 16) & 0x7; kore_debug("spdy_ctrl_frame_syn_stream()"); kore_debug("stream_id: %u", syn.stream_id); kore_debug("length : %u", ctrl.length); if (c->spdy_send_wsize > 0 && (c->flags & CONN_WRITE_BLOCK)) spdy_enable_write(c); if ((int)ctrl.length < 0) { spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } if ((syn.stream_id % 2) == 0 || syn.stream_id == 0) { kore_debug("client sent incorrect id for SPDY_SYN_STREAM (%u)", syn.stream_id); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } if (syn.stream_id < c->client_stream_id) { kore_debug("client sent incorrect id SPDY_SYN_STREAM (%u < %u)", syn.stream_id, c->client_stream_id); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } if ((s = spdy_stream_lookup(c, syn.stream_id)) != NULL) { kore_debug("duplicate SPDY_SYN_STREAM (%u)", syn.stream_id); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } s = kore_malloc(sizeof(*s)); s->send_size = 0; s->frame_size = 0; s->httpreq = NULL; s->onclose = NULL; s->prio = syn.prio; s->flags = ctrl.flags; s->recv_wsize = spdy_recv_wsize; s->send_wsize = c->wsize_initial; s->stream_id = syn.stream_id; s->hblock = spdy_header_block_create(SPDY_HBLOCK_DELAYED_ALLOC); src = (nb->buf + SPDY_FRAME_SIZE + SPDY_SYNFRAME_SIZE); kore_debug("compressed headers are %u bytes long", ctrl.length - 10); if (!spdy_zlib_inflate(c, src, (ctrl.length - SPDY_SYNFRAME_SIZE), &(s->hblock->header_block), &(s->hblock->header_block_len))) { kore_mem_free(s->hblock->header_block); kore_mem_free(s->hblock); kore_mem_free(s); spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL); return (KORE_RESULT_OK); } s->hblock->header_pairs = net_read32(s->hblock->header_block); if ((int)s->hblock->header_pairs < 0) { kore_mem_free(s->hblock->header_block); kore_mem_free(s->hblock); kore_mem_free(s); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } kore_debug("got %u headers", s->hblock->header_pairs); path = NULL; host = NULL; method = NULL; version = NULL; #define GET_HEADER(n, r) \ if (!spdy_stream_get_header(s->hblock, n, r)) { \ kore_mem_free(s->hblock->header_block); \ kore_mem_free(s->hblock); \ kore_mem_free(s); \ kore_debug("no such header: %s", n); \ if (path != NULL) \ kore_mem_free(path); \ if (host != NULL) \ kore_mem_free(host); \ if (method != NULL) \ kore_mem_free(method); \ if (version != NULL) \ kore_mem_free(version); \ spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); \ return (KORE_RESULT_OK); \ } GET_HEADER(":path", &path); GET_HEADER(":method", &method); GET_HEADER(":host", &host); GET_HEADER(":version", &version); c->client_stream_id = s->stream_id; TAILQ_INSERT_TAIL(&(c->spdy_streams), s, list); /* * We don't care so much for what http_request_new() tells us here, * we just have to clean up after passing our stuff to it. */ (void)http_request_new(c, s, host, method, path, version, (struct http_request **)&(s->httpreq)); kore_mem_free(path); kore_mem_free(method); kore_mem_free(host); kore_mem_free(version); net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); kore_debug("SPDY_SYN_STREAM: %u:%u:%u", s->stream_id, s->flags, s->prio); return (KORE_RESULT_OK); } static int spdy_ctrl_frame_rst_stream(struct netbuf *nb) { struct spdy_stream *s; u_int32_t stream_id; struct connection *c = (struct connection *)nb->owner; stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE); if ((stream_id % 2) == 0) { kore_debug("received RST for non-client stream %u", stream_id); return (KORE_RESULT_ERROR); } if ((s = spdy_stream_lookup(c, stream_id)) == NULL) { kore_debug("received RST for unknown stream %u", stream_id); return (KORE_RESULT_ERROR); } spdy_stream_close(c, s, SPDY_REMOVE_NETBUFS); net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); return (KORE_RESULT_OK); } static int spdy_ctrl_frame_settings(struct netbuf *nb) { struct spdy_stream *s; u_int8_t *buf; u_int32_t ecount, i, id, val, length, diff; struct connection *c = (struct connection *)nb->owner; ecount = net_read32(nb->buf + SPDY_FRAME_SIZE); length = net_read32(nb->buf + 4) & 0xffffff; if ((int)ecount < 0 || (int)length < 0) { spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } kore_debug("SPDY_SETTINGS: %u settings present", ecount); if (length != ((ecount * 8) + 4)) { kore_debug("ecount is not correct (%u != %u)", length, (ecount * 8) + 4); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } buf = nb->buf + SPDY_FRAME_SIZE + 4; for (i = 0; i < ecount; i++) { id = net_read32(buf) & 0xffffff; val = net_read32(buf + 4); if ((int)val < 0) { buf += 8; continue; } switch (id) { case SETTINGS_INITIAL_WINDOW_SIZE: diff = val - c->wsize_initial; c->wsize_initial = val; TAILQ_FOREACH(s, &(c->spdy_streams), list) s->send_wsize += diff; kore_debug("updated wsize with %d", diff); break; default: kore_debug("no handling for setting %u:%u", id, val); break; } buf += 8; } net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); return (KORE_RESULT_OK); } static int spdy_ctrl_frame_ping(struct netbuf *nb) { u_int32_t id; struct connection *c = (struct connection *)nb->owner; id = ntohl(*(u_int32_t *)(nb->buf + SPDY_FRAME_SIZE)); kore_debug("SPDY_PING: %u", id); /* XXX todo - check if we sent the ping. */ if ((id % 2) == 0) { kore_debug("received malformed client PING (%u)", id); spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); return (KORE_RESULT_OK); } spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, NULL, id); net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); return (KORE_RESULT_OK); } static int spdy_ctrl_frame_window(struct netbuf *nb) { int r; struct spdy_stream *s; u_int32_t stream_id, window_size; struct connection *c = (struct connection *)nb->owner; stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE); window_size = net_read32(nb->buf + SPDY_FRAME_SIZE + 4); kore_debug("window_update: %u for %u", window_size, stream_id); r = KORE_RESULT_OK; if ((s = spdy_stream_lookup(c, stream_id)) != NULL) { s->send_wsize += window_size; if ((u_int64_t)s->send_wsize > SPDY_FLOW_WINDOW_MAX) { kore_debug("window_update: size too large"); return (KORE_RESULT_ERROR); } if (c->flags & CONN_WRITE_BLOCK && s->send_wsize > 0 && c->spdy_send_wsize > 0) { kore_debug("stream %u no longer blocked", s->stream_id); spdy_enable_write(c); r = net_send_flush(c); } } else { c->spdy_send_wsize += window_size; if ((u_int64_t)c->spdy_send_wsize > SPDY_FLOW_WINDOW_MAX) { kore_debug("window_update: size too large"); return (KORE_RESULT_ERROR); } if (c->flags & CONN_WRITE_BLOCK && c->spdy_send_wsize > 0) { kore_debug("session %p no longer blocked", c); spdy_enable_write(c); r = net_send_flush(c); } } net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); return (r); } static int spdy_ctrl_frame_goaway(struct netbuf *nb) { struct connection *c = (struct connection *)nb->owner; kore_debug("spdy_ctrl_frame_goaway(%p)", c); c->flags |= SPDY_CONN_GOAWAY; kore_connection_disconnect(c); return (KORE_RESULT_OK); } static int spdy_data_frame_recv(struct netbuf *nb) { struct spdy_stream *s; int err; struct http_request *req; struct spdy_data_frame data; char *content; struct connection *c = (struct connection *)nb->owner; data.stream_id = net_read32(nb->buf) & ~(1 << 31); data.flags = *(u_int8_t *)(nb->buf + 4); data.length = net_read32(nb->buf + 4) & 0xffffff; kore_debug("SPDY_SESSION_DATA: %u:%u:%u", data.stream_id, data.flags, data.length); if ((int)data.length < 0) return (KORE_RESULT_ERROR); if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) { kore_debug("session data for non-existant stream"); /* stream error */ return (KORE_RESULT_ERROR); } req = (struct http_request *)s->httpreq; if (req == NULL || !(req->flags & HTTP_REQUEST_EXPECT_BODY)) { kore_debug("data frame for non post received"); /* stream error */ return (KORE_RESULT_ERROR); } if (req->http_body == NULL) { if (!spdy_stream_get_header(s->hblock, "content-length", &content)) { kore_debug("no content-length found for body"); return (KORE_RESULT_ERROR); } s->post_size = kore_strtonum(content, 10, 0, LLONG_MAX, &err); if (err == KORE_RESULT_ERROR) { kore_debug("bad content-length: %s", content); kore_mem_free(content); return (KORE_RESULT_ERROR); } kore_mem_free(content); if (s->post_size == 0) { req->flags |= HTTP_REQUEST_COMPLETE; req->flags &= ~HTTP_REQUEST_EXPECT_BODY; net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); return (KORE_RESULT_OK); } if (s->post_size > http_body_max) { kore_log(LOG_NOTICE, "body data too large (%ld > %ld)", s->post_size, http_body_max); return (KORE_RESULT_ERROR); } req->http_body = kore_buf_create(s->post_size); } if ((req->http_body->offset + data.length) > s->post_size) { kore_debug("POST would grow too large"); return (KORE_RESULT_ERROR); } kore_buf_append(req->http_body, (nb->buf + SPDY_FRAME_SIZE), data.length); if (data.flags & FLAG_FIN || req->http_body->offset == s->post_size) { if (req->http_body->offset != s->post_size) { kore_debug("FLAG_FIN before all POST data received"); return (KORE_RESULT_ERROR); } s->post_size = 0; s->flags |= FLAG_FIN; req->flags |= HTTP_REQUEST_COMPLETE; req->flags &= ~HTTP_REQUEST_EXPECT_BODY; } net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv); /* * XXX - This can be implemented better so we can stagger * window updates a bit and not constantly hit flow control. */ s->recv_wsize -= data.length; spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW, 0, 8, s, data.length); s->recv_wsize += data.length; c->spdy_recv_wsize -= data.length; spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW, 0, 8, NULL, data.length); c->spdy_recv_wsize += data.length; kore_debug("data frame recv: wz:%d cwz:%d", s->recv_wsize, c->spdy_recv_wsize); return (KORE_RESULT_OK); } static void spdy_block_write(struct connection *c) { kore_debug("spdy_block_write(%p)", c); c->flags |= CONN_WRITE_BLOCK; c->flags &= ~CONN_WRITE_POSSIBLE; } static void spdy_enable_write(struct connection *c) { kore_debug("spdy_enable_write(%p)", c); c->flags &= ~CONN_WRITE_BLOCK; c->flags |= CONN_WRITE_POSSIBLE; } static int spdy_zlib_inflate(struct connection *c, u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) { size_t have; int r, ret; u_char inflate_buffer[SPDY_ZLIB_CHUNK]; kore_debug("spdy_zlib_inflate(%p, %p, %d)", c, src, len); if (c->inflate_started == 0) { c->z_inflate.avail_in = 0; c->z_inflate.next_in = Z_NULL; c->z_inflate.zalloc = Z_NULL; c->z_inflate.zfree = Z_NULL; if ((r = inflateInit(&(c->z_inflate))) != Z_OK) { kore_debug("inflateInit() failed: %d", r); return (KORE_RESULT_ERROR); } c->inflate_started = 1; } *olen = 0; *dst = NULL; ret = -1; c->z_inflate.avail_in = len; c->z_inflate.next_in = src; while (ret == -1) { c->z_inflate.avail_out = SPDY_ZLIB_CHUNK; c->z_inflate.next_out = inflate_buffer; r = inflate(&(c->z_inflate), Z_SYNC_FLUSH); switch (r) { case Z_NEED_DICT: r = inflateSetDictionary(&(c->z_inflate), SPDY_dictionary_txt, SPDY_ZLIB_DICT_SIZE); if (r != Z_OK) { inflateEnd(&(c->z_inflate)); kore_debug("inflateSetDictionary(): %d", r); return (KORE_RESULT_ERROR); } continue; case Z_BUF_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: ret = KORE_RESULT_ERROR; kore_debug("inflate(): %d", r); break; case Z_OK: have = SPDY_ZLIB_CHUNK - c->z_inflate.avail_out; *olen += have; *dst = kore_realloc(*dst, *olen); memcpy((*dst) + (*olen - have), inflate_buffer, have); if (c->z_inflate.avail_in != 0 || c->z_inflate.avail_out == 0) break; /* FALLTHROUGH */ case Z_STREAM_END: ret = KORE_RESULT_OK; break; } } return (ret); } static int spdy_zlib_deflate(struct connection *c, u_int8_t *src, size_t len, u_int8_t **dst, u_int32_t *olen) { size_t have; int r, ret; u_char deflate_buffer[SPDY_ZLIB_CHUNK]; kore_debug("spdy_zlib_deflate(%p, %p, %d)", c, src, len); if (c->deflate_started == 0) { c->z_deflate.avail_in = 0; c->z_deflate.next_in = Z_NULL; c->z_deflate.zalloc = Z_NULL; c->z_deflate.zfree = Z_NULL; if ((r = deflateInit(&(c->z_deflate), -1)) != Z_OK) { kore_debug("deflateInit() failed: %d", r); return (KORE_RESULT_ERROR); } r = deflateSetDictionary(&(c->z_deflate), SPDY_dictionary_txt, SPDY_ZLIB_DICT_SIZE); if (r != Z_OK) { deflateEnd(&(c->z_deflate)); kore_debug("deflateSetDictionary(): %d", r); return (KORE_RESULT_ERROR); } c->deflate_started = 1; } *olen = 0; *dst = NULL; ret = -1; c->z_deflate.avail_in = len; c->z_deflate.next_in = src; while (ret == -1) { c->z_deflate.avail_out = SPDY_ZLIB_CHUNK; c->z_deflate.next_out = deflate_buffer; r = deflate(&(c->z_deflate), Z_SYNC_FLUSH); switch (r) { case Z_BUF_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: ret = KORE_RESULT_ERROR; kore_debug("deflate(): %d", r); break; case Z_OK: have = SPDY_ZLIB_CHUNK - c->z_deflate.avail_out; *olen += have; *dst = kore_realloc(*dst, *olen); memcpy((*dst) + (*olen - have), deflate_buffer, have); if (c->z_deflate.avail_in == 0 && c->z_deflate.avail_out != 0) ret = KORE_RESULT_OK; break; } } return (ret); } kore/src/http.c0000644000175000001440000010176412527355514013017 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include "spdy.h" #include "kore.h" #include "http.h" #if defined(KORE_USE_PGSQL) #include "pgsql.h" #endif #if defined(KORE_USE_TASKS) #include "tasks.h" #endif static int http_body_recv(struct netbuf *); static void http_error_response(struct connection *, struct spdy_stream *, int); static void http_argument_add(struct http_request *, const char *, void *, u_int32_t, int); static void http_file_add(struct http_request *, const char *, const char *, u_int8_t *, u_int32_t); static void http_response_normal(struct http_request *, struct connection *, int, void *, u_int32_t); static void http_response_spdy(struct http_request *, struct connection *, struct spdy_stream *, int, void *, u_int32_t); static struct kore_buf *header_buf; static char http_version[32]; static u_int16_t http_version_len; static char http_version_spdy[32]; static TAILQ_HEAD(, http_request) http_requests; static TAILQ_HEAD(, http_request) http_requests_sleeping; static struct kore_pool http_request_pool; static struct kore_pool http_header_pool; static struct kore_pool http_host_pool; static struct kore_pool http_path_pool; int http_request_count = 0; u_int32_t http_request_limit = HTTP_REQUEST_LIMIT; u_int64_t http_hsts_enable = HTTP_HSTS_ENABLE; u_int16_t http_header_max = HTTP_HEADER_MAX_LEN; u_int16_t http_keepalive_time = HTTP_KEEPALIVE_TIME; u_int64_t http_body_max = HTTP_BODY_MAX_LEN; void http_init(void) { int prealloc, l; TAILQ_INIT(&http_requests); TAILQ_INIT(&http_requests_sleeping); header_buf = kore_buf_create(1024); l = snprintf(http_version_spdy, sizeof(http_version_spdy), "kore (%d.%d.%d-%s)", KORE_VERSION_MAJOR, KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE); if (l == -1 || (size_t)l >= sizeof(http_version_spdy)) fatal("http_init(): http_version_spdy buffer too small"); l = snprintf(http_version, sizeof(http_version), "server: kore (%d.%d.%d-%s)\r\n", KORE_VERSION_MAJOR, KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE); if (l == -1 || (size_t)l >= sizeof(http_version)) fatal("http_init(): http_version buffer too small"); http_version_len = l; prealloc = MIN((worker_max_connections / 10), 1000); kore_pool_init(&http_request_pool, "http_request_pool", sizeof(struct http_request), prealloc); kore_pool_init(&http_header_pool, "http_header_pool", sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX); kore_pool_init(&http_host_pool, "http_host_pool", KORE_DOMAINNAME_LEN, prealloc); kore_pool_init(&http_path_pool, "http_path_pool", HTTP_URI_LEN, prealloc); } int http_request_new(struct connection *c, struct spdy_stream *s, const char *host, const char *method, const char *path, const char *version, struct http_request **out) { char *p; struct http_request *req; int m, flags; size_t hostlen, pathlen; kore_debug("http_request_new(%p, %p, %s, %s, %s, %s)", c, s, host, method, path, version); if ((hostlen = strlen(host)) >= KORE_DOMAINNAME_LEN - 1) { http_error_response(c, s, 500); return (KORE_RESULT_ERROR); } if ((pathlen = strlen(path)) >= HTTP_URI_LEN - 1) { http_error_response(c, s, 414); return (KORE_RESULT_ERROR); } if (strcasecmp(version, "http/1.1")) { http_error_response(c, s, 505); return (KORE_RESULT_ERROR); } if (!strcasecmp(method, "get")) { m = HTTP_METHOD_GET; flags = HTTP_REQUEST_COMPLETE; } else if (!strcasecmp(method, "delete")) { m = HTTP_METHOD_DELETE; flags = HTTP_REQUEST_COMPLETE; } else if (!strcasecmp(method, "post")) { m = HTTP_METHOD_POST; flags = HTTP_REQUEST_EXPECT_BODY; } else if (!strcasecmp(method, "put")) { m = HTTP_METHOD_PUT; flags = HTTP_REQUEST_EXPECT_BODY; } else if (!strcasecmp(method, "head")) { m = HTTP_METHOD_HEAD; flags = HTTP_REQUEST_COMPLETE; } else { http_error_response(c, s, 400); return (KORE_RESULT_ERROR); } req = kore_pool_get(&http_request_pool); req->end = 0; req->total = 0; req->start = 0; req->owner = c; req->status = 0; req->stream = s; req->method = m; req->hdlr = NULL; req->agent = NULL; req->flags = flags; req->fsm_state = 0; req->http_body = NULL; req->hdlr_extra = NULL; req->query_string = NULL; req->multipart_body = NULL; if ((p = strrchr(host, ':')) != NULL) *p = '\0'; req->host = kore_pool_get(&http_host_pool); (void)memcpy(req->host, host, hostlen); req->host[hostlen] = '\0'; req->path = kore_pool_get(&http_path_pool); (void)memcpy(req->path, path, pathlen); req->path[pathlen] = '\0'; if ((req->query_string = strchr(req->path, '?')) != NULL) *(req->query_string)++ = '\0'; TAILQ_INIT(&(req->resp_headers)); TAILQ_INIT(&(req->req_headers)); TAILQ_INIT(&(req->arguments)); TAILQ_INIT(&(req->files)); if (s != NULL) { if (!http_request_header(req, "user-agent", &(req->agent))) req->agent = kore_strdup("unknown"); } #if defined(KORE_USE_TASKS) LIST_INIT(&(req->tasks)); #endif #if defined(KORE_USE_PGSQL) LIST_INIT(&(req->pgsqls)); #endif http_request_count++; TAILQ_INSERT_HEAD(&http_requests, req, list); TAILQ_INSERT_TAIL(&(c->http_requests), req, olist); if (out != NULL) *out = req; return (KORE_RESULT_OK); } void http_request_sleep(struct http_request *req) { if (!(req->flags & HTTP_REQUEST_SLEEPING)) { kore_debug("http_request_sleep: %p napping", req); req->flags |= HTTP_REQUEST_SLEEPING; TAILQ_REMOVE(&http_requests, req, list); TAILQ_INSERT_TAIL(&http_requests_sleeping, req, list); } } void http_request_wakeup(struct http_request *req) { if (req->flags & HTTP_REQUEST_SLEEPING) { kore_debug("http_request_wakeup: %p woke up", req); req->flags &= ~HTTP_REQUEST_SLEEPING; TAILQ_REMOVE(&http_requests_sleeping, req, list); TAILQ_INSERT_TAIL(&http_requests, req, list); } } void http_process(void) { u_int32_t count; struct http_request *req, *next; count = 0; for (req = TAILQ_FIRST(&http_requests); req != NULL; req = next) { if (count >= http_request_limit) break; next = TAILQ_NEXT(req, list); if (req->flags & HTTP_REQUEST_DELETE) { http_request_free(req); continue; } /* Sleeping requests should be in http_requests_sleeping. */ if (req->flags & HTTP_REQUEST_SLEEPING) fatal("http_process: sleeping request on list"); if (!(req->flags & HTTP_REQUEST_COMPLETE)) continue; count++; http_process_request(req, 0); } } void http_process_request(struct http_request *req, int retry_only) { struct kore_module_handle *hdlr; int r, (*cb)(struct http_request *); kore_debug("http_process_request: %p->%p (%s)", req->owner, req, req->path); if (req->flags & HTTP_REQUEST_DELETE) return; if (req->hdlr != NULL) hdlr = req->hdlr; else hdlr = kore_module_handler_find(req->host, req->path); req->start = kore_time_ms(); if (hdlr == NULL) { r = http_generic_404(req); } else { if (req->hdlr != hdlr && hdlr->auth != NULL) r = kore_auth_run(req, hdlr->auth); else r = KORE_RESULT_OK; switch (r) { case KORE_RESULT_OK: req->hdlr = hdlr; cb = hdlr->addr; worker->active_hdlr = hdlr; r = cb(req); worker->active_hdlr = NULL; break; case KORE_RESULT_RETRY: break; case KORE_RESULT_ERROR: /* * Set r to KORE_RESULT_OK so we can properly * flush the result from kore_auth_run(). */ r = KORE_RESULT_OK; break; default: fatal("kore_auth() returned unknown %d", r); } } req->end = kore_time_ms(); req->total += req->end - req->start; if (retry_only == 1 && r != KORE_RESULT_RETRY) fatal("http_process_request: expected RETRY but got %d", r); switch (r) { case KORE_RESULT_OK: r = net_send_flush(req->owner); if (r == KORE_RESULT_ERROR) kore_connection_disconnect(req->owner); break; case KORE_RESULT_ERROR: kore_connection_disconnect(req->owner); break; case KORE_RESULT_RETRY: return; default: fatal("A page handler returned an unknown result: %d", r); } if (hdlr != NULL && hdlr->dom->accesslog != -1) kore_accesslog(req); req->flags |= HTTP_REQUEST_DELETE; } void http_response_header(struct http_request *req, const char *header, const char *value) { struct http_header *hdr; kore_debug("http_response_header(%p, %s, %s)", req, header, value); hdr = kore_pool_get(&http_header_pool); hdr->header = kore_strdup(header); hdr->value = kore_strdup(value); TAILQ_INSERT_TAIL(&(req->resp_headers), hdr, list); } void http_request_free(struct http_request *req) { #if defined(KORE_USE_TASKS) struct kore_task *t, *nt; int pending_tasks; #endif #if defined(KORE_USE_PGSQL) struct kore_pgsql *pgsql; #endif struct http_file *f, *fnext; struct http_arg *q, *qnext; struct http_header *hdr, *next; #if defined(KORE_USE_TASKS) pending_tasks = 0; for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) { nt = LIST_NEXT(t, rlist); if (!kore_task_finished(t)) { pending_tasks++; } else { kore_task_destroy(t); } } if (pending_tasks) { kore_debug("http_request_free %d pending tasks", pending_tasks); return; } #endif #if defined(KORE_USE_PGSQL) while (!LIST_EMPTY(&(req->pgsqls))) { pgsql = LIST_FIRST(&(req->pgsqls)); kore_pgsql_cleanup(pgsql); } if (req->flags & HTTP_REQUEST_PGSQL_QUEUE) kore_pgsql_queue_remove(req); #endif kore_debug("http_request_free: %p->%p", req->owner, req); kore_pool_put(&http_host_pool, req->host); kore_pool_put(&http_path_pool, req->path); req->host = NULL; req->path = NULL; TAILQ_REMOVE(&http_requests, req, list); TAILQ_REMOVE(&(req->owner->http_requests), req, olist); for (hdr = TAILQ_FIRST(&(req->resp_headers)); hdr != NULL; hdr = next) { next = TAILQ_NEXT(hdr, list); TAILQ_REMOVE(&(req->resp_headers), hdr, list); kore_mem_free(hdr->header); kore_mem_free(hdr->value); kore_pool_put(&http_header_pool, hdr); } for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) { next = TAILQ_NEXT(hdr, list); TAILQ_REMOVE(&(req->req_headers), hdr, list); kore_mem_free(hdr->header); kore_mem_free(hdr->value); kore_pool_put(&http_header_pool, hdr); } for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) { qnext = TAILQ_NEXT(q, list); TAILQ_REMOVE(&(req->arguments), q, list); kore_mem_free(q->name); if (q->value != NULL) kore_mem_free(q->value); if (q->s_value != NULL) kore_mem_free(q->s_value); kore_mem_free(q); } for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) { fnext = TAILQ_NEXT(f, list); TAILQ_REMOVE(&(req->files), f, list); kore_mem_free(f->filename); kore_mem_free(f->name); kore_mem_free(f); } if (req->http_body != NULL) kore_buf_free(req->http_body); if (req->multipart_body != NULL) kore_mem_free(req->multipart_body); if (req->agent != NULL) kore_mem_free(req->agent); if (req->hdlr_extra != NULL && !(req->flags & HTTP_REQUEST_RETAIN_EXTRA)) kore_mem_free(req->hdlr_extra); kore_pool_put(&http_request_pool, req); http_request_count--; } void http_response(struct http_request *req, int status, void *d, u_int32_t l) { kore_debug("http_response(%p, %d, %p, %d)", req, status, d, l); req->status = status; switch (req->owner->proto) { case CONN_PROTO_SPDY: http_response_spdy(req, req->owner, req->stream, status, d, l); break; case CONN_PROTO_HTTP: http_response_normal(req, req->owner, status, d, l); break; default: fatal("http_response() bad proto %d", req->owner->proto); /* NOTREACHED. */ } } void http_response_stream(struct http_request *req, int status, void *base, u_int64_t len, int (*cb)(struct netbuf *), void *arg) { struct netbuf *nb; req->status = status; switch (req->owner->proto) { case CONN_PROTO_SPDY: http_response_spdy(req, req->owner, req->stream, status, NULL, len); break; case CONN_PROTO_HTTP: http_response_normal(req, req->owner, status, NULL, len); break; default: fatal("http_response_stream() bad proto %d", req->owner->proto); /* NOTREACHED. */ } if (req->method != HTTP_METHOD_HEAD) { net_send_stream(req->owner, base, len, req->stream, cb, &nb); nb->extra = arg; } } int http_request_header(struct http_request *req, const char *header, char **out) { int r; struct http_header *hdr; if (req->owner->proto == CONN_PROTO_SPDY) { r = spdy_stream_get_header(req->stream->hblock, header, out); } else { TAILQ_FOREACH(hdr, &(req->req_headers), list) { if (!strcasecmp(hdr->header, header)) { r = strlen(hdr->value) + 1; *out = kore_malloc(r); kore_strlcpy(*out, hdr->value, r); return (KORE_RESULT_OK); } } r = KORE_RESULT_ERROR; } return (r); } int http_header_recv(struct netbuf *nb) { size_t len; u_int64_t clen; struct http_header *hdr; struct http_request *req; u_int8_t *end_headers; int h, i, v, skip, bytes_left; char *request[4], *host[3], *hbuf; char *p, *headers[HTTP_REQ_HEADER_MAX]; struct connection *c = (struct connection *)nb->owner; kore_debug("http_header_recv(%p)", nb); if (nb->b_len < 4) return (KORE_RESULT_OK); skip = 4; end_headers = kore_mem_find(nb->buf, nb->s_off, "\r\n\r\n", 4); if (end_headers == NULL) { end_headers = kore_mem_find(nb->buf, nb->s_off, "\n\n", 2); if (end_headers == NULL) return (KORE_RESULT_OK); skip = 2; } *end_headers = '\0'; end_headers += skip; nb->flags |= NETBUF_FORCE_REMOVE; len = end_headers - nb->buf; hbuf = (char *)nb->buf; h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX); if (h < 2) { http_error_response(c, NULL, 400); return (KORE_RESULT_OK); } v = kore_split_string(headers[0], " ", request, 4); if (v != 3) { http_error_response(c, NULL, 400); return (KORE_RESULT_OK); } skip = 0; host[0] = NULL; for (i = 0; i < h; i++) { if (strncasecmp(headers[i], "host", 4)) continue; v = kore_split_string(headers[i], ":", host, 3); if (v != 2) { http_error_response(c, NULL, 400); return (KORE_RESULT_OK); } if ((host[1] - host[0]) != 5 || strncasecmp(host[0], "host", 4) || host[1] == '\0') { http_error_response(c, NULL, 400); return (KORE_RESULT_OK); } host[1]++; skip = i; break; } if (host[0] == NULL) { http_error_response(c, NULL, 400); return (KORE_RESULT_OK); } if (!http_request_new(c, NULL, host[1], request[0], request[1], request[2], &req)) return (KORE_RESULT_OK); for (i = 1; i < h; i++) { if (i == skip) continue; p = strchr(headers[i], ':'); if (p == NULL) { kore_debug("malformed header: '%s'", headers[i]); continue; } *(p++) = '\0'; if (*p == ' ') p++; hdr = kore_pool_get(&http_header_pool); hdr->header = kore_strdup(headers[i]); hdr->value = kore_strdup(p); TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list); if (req->agent == NULL && !strcasecmp(hdr->header, "user-agent")) req->agent = kore_strdup(hdr->value); } if (req->flags & HTTP_REQUEST_EXPECT_BODY) { if (!http_request_header(req, "content-length", &p)) { kore_debug("expected body but no content-length"); req->flags |= HTTP_REQUEST_DELETE; http_error_response(req->owner, NULL, 411); return (KORE_RESULT_OK); } clen = kore_strtonum(p, 10, 0, LONG_MAX, &v); if (v == KORE_RESULT_ERROR) { kore_debug("content-length invalid: %s", p); kore_mem_free(p); req->flags |= HTTP_REQUEST_DELETE; http_error_response(req->owner, NULL, 411); return (KORE_RESULT_OK); } kore_mem_free(p); if (clen == 0) { req->flags |= HTTP_REQUEST_COMPLETE; req->flags &= ~HTTP_REQUEST_EXPECT_BODY; return (KORE_RESULT_OK); } if (clen > http_body_max) { kore_log(LOG_NOTICE, "body too large (%ld > %ld)", clen, http_body_max); req->flags |= HTTP_REQUEST_DELETE; http_error_response(req->owner, NULL, 411); return (KORE_RESULT_OK); } req->http_body = kore_buf_create(clen); kore_buf_append(req->http_body, end_headers, (nb->s_off - len)); bytes_left = clen - (nb->s_off - len); if (bytes_left > 0) { kore_debug("%ld/%ld (%ld - %ld) more bytes for body", bytes_left, clen, nb->s_off, len); net_recv_reset(c, bytes_left, http_body_recv); c->rnb->extra = req; c->rnb->flags &= ~NETBUF_CALL_CB_ALWAYS; } else if (bytes_left == 0) { req->flags |= HTTP_REQUEST_COMPLETE; req->flags &= ~HTTP_REQUEST_EXPECT_BODY; } else { kore_debug("bytes_left would become zero (%ld)", clen); http_error_response(req->owner, NULL, 500); } } return (KORE_RESULT_OK); } int http_populate_arguments(struct http_request *req) { u_int32_t len; int i, v, c, count; char *query, *args[HTTP_MAX_QUERY_ARGS], *val[3]; if (req->method == HTTP_METHOD_POST) { if (req->http_body == NULL) return (0); query = http_body_text(req); } else { if (req->query_string == NULL) return (0); query = kore_strdup(req->query_string); } count = 0; v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS); for (i = 0; i < v; i++) { c = kore_split_string(args[i], "=", val, 3); if (c != 1 && c != 2) { kore_debug("malformed query argument"); continue; } if (val[1] != NULL) { len = strlen(val[1]); http_argument_add(req, val[0], val[1], len, HTTP_ARG_TYPE_STRING); count++; } } kore_mem_free(query); return (count); } int http_argument_get(struct http_request *req, const char *name, void **out, void *nout, u_int32_t *len, int type) { struct http_arg *q; if (len != NULL) *len = 0; TAILQ_FOREACH(q, &(req->arguments), list) { if (!strcmp(q->name, name)) { switch (type) { case HTTP_ARG_TYPE_RAW: if (len != NULL) *len = q->len; *out = q->value; return (KORE_RESULT_OK); case HTTP_ARG_TYPE_BYTE: COPY_ARG_TYPE(*(u_int8_t *)q->value, len, u_int8_t); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_INT16: COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_UINT16: COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_INT32: COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_UINT32: COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_INT64: COPY_AS_INTTYPE_64(int64_t, 1); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_UINT64: COPY_AS_INTTYPE_64(u_int64_t, 0); return (KORE_RESULT_OK); case HTTP_ARG_TYPE_STRING: CACHE_STRING(); *out = q->s_value; if (len != NULL) *len = q->s_len - 1; return (KORE_RESULT_OK); default: return (KORE_RESULT_ERROR); } } } return (KORE_RESULT_ERROR); } int http_argument_urldecode(char *arg) { u_int8_t v; int err; size_t len; char *p, *in, h[5]; p = arg; in = arg; len = strlen(arg); while (*p != '\0' && p < (arg + len)) { if (*p == '+') *p = ' '; if (*p != '%') { *in++ = *p++; continue; } if ((p + 2) >= (arg + len)) { kore_debug("overflow in '%s'", arg); return (KORE_RESULT_ERROR); } if (!isxdigit(*(p + 1)) || !isxdigit(*(p + 2))) { *in++ = *p++; continue; } h[0] = '0'; h[1] = 'x'; h[2] = *(p + 1); h[3] = *(p + 2); h[4] = '\0'; v = kore_strtonum(h, 16, 0, 255, &err); if (err != KORE_RESULT_OK) return (err); *in++ = (char)v; p += 3; } *in = '\0'; return (KORE_RESULT_OK); } int http_file_lookup(struct http_request *req, const char *name, char **fname, u_int8_t **data, u_int32_t *len) { struct http_file *f; TAILQ_FOREACH(f, &(req->files), list) { if (!strcmp(f->name, name)) { *len = f->len; *data = f->data; *fname = f->filename; return (KORE_RESULT_OK); } } return (KORE_RESULT_ERROR); } int http_populate_multipart_form(struct http_request *req, int *v) { int h, i, c, l; u_int32_t blen, slen, len; u_int8_t *s, *end, *e, *end_headers, *data; char *d, *val, *type, *boundary, *fname; char *headers[5], *args[5], *opt[5], *name; *v = 0; if (req->method != HTTP_METHOD_POST) return (KORE_RESULT_ERROR); if (!http_request_header(req, "content-type", &type)) return (KORE_RESULT_ERROR); h = kore_split_string(type, ";", args, 3); if (h != 2) { kore_mem_free(type); return (KORE_RESULT_ERROR); } if (strcasecmp(args[0], "multipart/form-data")) { kore_mem_free(type); return (KORE_RESULT_ERROR); } if ((val = strchr(args[1], '=')) == NULL) { kore_mem_free(type); return (KORE_RESULT_ERROR); } val++; slen = strlen(val); boundary = kore_malloc(slen + 3); if (!kore_snprintf(boundary, slen + 3, &l, "--%s", val)) { kore_mem_free(boundary); kore_mem_free(type); return (KORE_RESULT_ERROR); } slen = l; kore_mem_free(type); req->multipart_body = http_body_bytes(req, &blen); if (slen < 3 || blen < (slen * 2)) { kore_mem_free(boundary); return (KORE_RESULT_ERROR); } end = req->multipart_body + blen - 2; if (end < req->multipart_body || (end - 2) < req->multipart_body) { kore_mem_free(boundary); return (KORE_RESULT_ERROR); } if (memcmp((end - slen - 2), boundary, slen) || memcmp((end - 2), "--", 2)) { kore_mem_free(boundary); return (KORE_RESULT_ERROR); } s = req->multipart_body + slen + 2; while (s < end) { e = kore_mem_find(s, end - s, boundary, slen); if (e == NULL) { kore_mem_free(boundary); return (KORE_RESULT_ERROR); } *(e - 2) = '\0'; end_headers = kore_mem_find(s, (e - 2) - s, "\r\n\r\n", 4); if (end_headers == NULL) { kore_mem_free(boundary); return (KORE_RESULT_ERROR); } *end_headers = '\0'; data = end_headers + 4; h = kore_split_string((char *)s, "\r\n", headers, 5); for (i = 0; i < h; i++) { c = kore_split_string(headers[i], ":", args, 5); if (c != 2) continue; /* Ignore other headers for now. */ if (strcasecmp(args[0], "content-disposition")) continue; for (d = args[1]; isspace(*d); d++) ; c = kore_split_string(d, ";", opt, 5); if (c < 2) continue; if (strcasecmp(opt[0], "form-data")) continue; if ((val = strchr(opt[1], '=')) == NULL) continue; if (strlen(val) < 3) continue; val++; kore_strip_chars(val, '"', &name); if (opt[2] == NULL) { *v = *v + 1; http_argument_add(req, name, data, (e - 2) - data, HTTP_ARG_TYPE_STRING); kore_mem_free(name); continue; } for (d = opt[2]; isspace(*d); d++) ; len = MIN(strlen("filename="), strlen(d)); if (!strncasecmp(d, "filename=", len)) { if ((val = strchr(d, '=')) == NULL) { kore_mem_free(name); continue; } val++; kore_strip_chars(val, '"', &fname); if (strlen(fname) > 0) { *v = *v + 1; http_file_add(req, name, fname, data, (e - 2) - data); } kore_mem_free(fname); } else { kore_debug("got unknown: %s", opt[2]); } kore_mem_free(name); } s = e + slen + 2; } kore_mem_free(boundary); return (KORE_RESULT_OK); } int http_generic_404(struct http_request *req) { kore_debug("http_generic_404(%s, %d, %s)", req->host, req->method, req->path); http_response(req, 404, NULL, 0); return (KORE_RESULT_OK); } char * http_body_text(struct http_request *req) { u_int32_t len; u_int8_t *data; char *text; if (req->http_body == NULL) return (NULL); data = kore_buf_release(req->http_body, &len); req->http_body = NULL; len++; text = kore_malloc(len); kore_strlcpy(text, (char *)data, len); kore_mem_free(data); return (text); } u_int8_t * http_body_bytes(struct http_request *req, u_int32_t *len) { u_int8_t *data; if (req->http_body == NULL) return (NULL); data = kore_buf_release(req->http_body, len); req->http_body = NULL; return (data); } int http_state_run(struct http_state *states, u_int8_t elm, struct http_request *req) { int r, done; done = 0; while (!done) { if (req->fsm_state >= elm) { fatal("http_state_run: fsm_state > elm (%d/%d)", req->fsm_state, elm); } kore_debug("http_state_run: running %s", states[req->fsm_state].name); r = states[req->fsm_state].cb(req); switch (r) { case HTTP_STATE_ERROR: return (KORE_RESULT_OK); case HTTP_STATE_RETRY: return (KORE_RESULT_RETRY); case HTTP_STATE_CONTINUE: break; case HTTP_STATE_COMPLETE: done = 1; break; default: fatal("http_state_run: unknown return value %d", r); } } req->fsm_state = 0; kore_debug("http_state_run(%p): done", req); return (KORE_RESULT_OK); } static void http_argument_add(struct http_request *req, const char *name, void *value, u_int32_t len, int type) { struct http_arg *q; struct kore_handler_params *p; if (len == 0 || value == NULL) { kore_debug("http_argument_add: with NULL value"); return; } TAILQ_FOREACH(p, &(req->hdlr->params), list) { if (p->method != req->method) continue; if (!strcmp(p->name, name)) { if (type == HTTP_ARG_TYPE_STRING) { http_argument_urldecode(value); len = strlen(value); } if (kore_validator_check(req, p->validator, value)) { q = kore_malloc(sizeof(struct http_arg)); q->len = len; q->s_value = NULL; q->name = kore_strdup(name); q->value = kore_malloc(len); memcpy(q->value, value, len); TAILQ_INSERT_TAIL(&(req->arguments), q, list); } return; } } } static void http_file_add(struct http_request *req, const char *name, const char *filename, u_int8_t *data, u_int32_t len) { struct http_file *f; f = kore_malloc(sizeof(struct http_file)); f->len = len; f->data = data; f->name = kore_strdup(name); f->filename = kore_strdup(filename); TAILQ_INSERT_TAIL(&(req->files), f, list); } static int http_body_recv(struct netbuf *nb) { struct http_request *req = (struct http_request *)nb->extra; kore_buf_append(req->http_body, nb->buf, nb->s_off); req->flags |= HTTP_REQUEST_COMPLETE; req->flags &= ~HTTP_REQUEST_EXPECT_BODY; nb->extra = NULL; kore_debug("received all body data for request %p", req); return (KORE_RESULT_OK); } static void http_error_response(struct connection *c, struct spdy_stream *s, int status) { kore_debug("http_error_response(%p, %p, %d)", c, s, status); switch (c->proto) { case CONN_PROTO_SPDY: http_response_spdy(NULL, c, s, status, NULL, 0); break; case CONN_PROTO_HTTP: if (s != NULL) kore_log(LOG_NOTICE, "http_error_response: s != NULL"); http_response_normal(NULL, c, status, NULL, 0); break; default: fatal("http_error_response() bad proto %d", c->proto); /* NOTREACHED. */ } } static void http_response_spdy(struct http_request *req, struct connection *c, struct spdy_stream *s, int status, void *d, u_int32_t len) { u_int32_t hlen; struct http_header *hdr; u_int8_t *htext; struct spdy_header_block *hblock; char sbuf[512]; (void)snprintf(sbuf, sizeof(sbuf), "%d %s", status, http_status_text(status)); hblock = spdy_header_block_create(SPDY_HBLOCK_NORMAL); spdy_header_block_add(hblock, ":status", sbuf); spdy_header_block_add(hblock, ":version", "HTTP/1.1"); spdy_header_block_add(hblock, ":server", http_version_spdy); if (http_hsts_enable) { (void)snprintf(sbuf, sizeof(sbuf), "max-age=%" PRIu64 "; includeSubDomains", http_hsts_enable); spdy_header_block_add(hblock, ":strict-transport-security", sbuf); } if (req != NULL) { TAILQ_FOREACH(hdr, &(req->resp_headers), list) spdy_header_block_add(hblock, hdr->header, hdr->value); } htext = spdy_header_block_release(c, hblock, &hlen); if (htext == NULL) { spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL); return; } spdy_frame_send(c, SPDY_CTRL_FRAME_SYN_REPLY, 0, hlen, s, 0); net_send_queue(c, htext, hlen, NULL, NETBUF_LAST_CHAIN); kore_mem_free(htext); if (len > 0 && req != NULL && req->method != HTTP_METHOD_HEAD) { s->send_size += len; s->flags |= SPDY_DATAFRAME_PRELUDE; if (d != NULL) net_send_queue(c, d, len, s, NETBUF_LAST_CHAIN); } if ((req != NULL && req->method == HTTP_METHOD_HEAD) || (len == 0 && !(s->flags & SPDY_NO_CLOSE))) { spdy_frame_send(c, SPDY_DATA_FRAME, FLAG_FIN, 0, s, 0); spdy_stream_close(c, s, SPDY_KEEP_NETBUFS); } } static void http_response_normal(struct http_request *req, struct connection *c, int status, void *d, u_int32_t len) { struct http_header *hdr; char *conn; int connection_close; header_buf->offset = 0; kore_buf_appendf(header_buf, "HTTP/1.1 %d %s\r\n", status, http_status_text(status)); kore_buf_append(header_buf, http_version, http_version_len); if (c->flags & CONN_CLOSE_EMPTY) connection_close = 1; else connection_close = 0; if (connection_close == 0 && req != NULL) { if (http_request_header(req, "connection", &conn)) { if ((*conn == 'c' || *conn == 'C') && !strcasecmp(conn, "close")) connection_close = 1; kore_mem_free(conn); } } if (http_keepalive_time && connection_close == 0) { kore_buf_appendf(header_buf, "connection: keep-alive\r\n"); kore_buf_appendf(header_buf, "keep-alive: timeout=%d\r\n", http_keepalive_time); } else { c->flags |= CONN_CLOSE_EMPTY; kore_buf_appendf(header_buf, "connection: close\r\n"); } if (http_hsts_enable) { kore_buf_appendf(header_buf, "strict-transport-security: "); kore_buf_appendf(header_buf, "max-age=%" PRIu64 "; includeSubDomains\r\n", http_hsts_enable); } if (req != NULL) { TAILQ_FOREACH(hdr, &(req->resp_headers), list) { kore_buf_appendf(header_buf, "%s: %s\r\n", hdr->header, hdr->value); } if (status != 204 && status >= 200 && !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) { kore_buf_appendf(header_buf, "content-length: %d\r\n", len); } } else { if (status != 204 && status >= 200) { kore_buf_appendf(header_buf, "content-length: %d\r\n", len); } } kore_buf_append(header_buf, "\r\n", 2); net_send_queue(c, header_buf->data, header_buf->offset, NULL, NETBUF_LAST_CHAIN); if (d != NULL && req != NULL && req->method != HTTP_METHOD_HEAD) net_send_queue(c, d, len, NULL, NETBUF_LAST_CHAIN); if (!(c->flags & CONN_CLOSE_EMPTY)) net_recv_reset(c, http_header_max, http_header_recv); } const char * http_status_text(int status) { char *r; switch (status) { case HTTP_STATUS_CONTINUE: r = "Continue"; break; case HTTP_STATUS_SWITCHING_PROTOCOLS: r = "Switching Protocols"; break; case HTTP_STATUS_OK: r = "OK"; break; case HTTP_STATUS_CREATED: r = "Created"; break; case HTTP_STATUS_ACCEPTED: r = "Accepted"; break; case HTTP_STATUS_NON_AUTHORITATIVE: r = "Non-Authoritative Information"; break; case HTTP_STATUS_NO_CONTENT: r = "No Content"; break; case HTTP_STATUS_RESET_CONTENT: r = "Reset Content"; break; case HTTP_STATUS_PARTIAL_CONTENT: r = "Partial Content"; break; case HTTP_STATUS_MULTIPLE_CHOICES: r = "Multiple Choices"; break; case HTTP_STATUS_MOVED_PERMANENTLY: r = "Moved Permanently"; break; case HTTP_STATUS_FOUND: r = "Found"; break; case HTTP_STATUS_SEE_OTHER: r = "See Other"; break; case HTTP_STATUS_NOT_MODIFIED: r = "Not Modified"; break; case HTTP_STATUS_USE_PROXY: r = "Use Proxy"; break; case HTTP_STATUS_TEMPORARY_REDIRECT: r = "Temporary Redirect"; break; case HTTP_STATUS_BAD_REQUEST: r = "Bad Request"; break; case HTTP_STATUS_UNAUTHORIZED: r = "Unauthorized"; break; case HTTP_STATUS_PAYMENT_REQUIRED: r = "Payment Required"; break; case HTTP_STATUS_FORBIDDEN: r = "Forbidden"; break; case HTTP_STATUS_NOT_FOUND: r = "Not Found"; break; case HTTP_STATUS_METHOD_NOT_ALLOWED: r = "Method Not Allowed"; break; case HTTP_STATUS_NOT_ACCEPTABLE: r = "Not Acceptable"; break; case HTTP_STATUS_PROXY_AUTH_REQUIRED: r = "Proxy Authentication Required"; break; case HTTP_STATUS_REQUEST_TIMEOUT: r = "Request Time-out"; break; case HTTP_STATUS_CONFLICT: r = "Conflict"; break; case HTTP_STATUS_GONE: r = "Gone"; break; case HTTP_STATUS_LENGTH_REQUIRED: r = "Length Required"; break; case HTTP_STATUS_PRECONDITION_FAILED: r = "Precondition Failed"; break; case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE: r = "Request Entity Too Large"; break; case HTTP_STATUS_REQUEST_URI_TOO_LARGE: r = "Request-URI Too Large"; break; case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: r = "Unsupported Media Type"; break; case HTTP_STATUS_REQUEST_RANGE_INVALID: r = "Requested range not satisfiable"; break; case HTTP_STATUS_EXPECTATION_FAILED: r = "Expectation Failed"; break; case HTTP_STATUS_INTERNAL_ERROR: r = "Internal Server Error"; break; case HTTP_STATUS_NOT_IMPLEMENTED: r = "Not Implemented"; break; case HTTP_STATUS_BAD_GATEWAY: r = "Bad Gateway"; break; case HTTP_STATUS_SERVICE_UNAVAILABLE: r = "Service Unavailable"; break; case HTTP_STATUS_GATEWAY_TIMEOUT: r = "Gateway Time-out"; break; case HTTP_STATUS_BAD_VERSION: r = "HTTP Version not supported"; break; default: r = ""; break; } return (r); } kore/src/timer.c0000644000175000001440000000456112527355514013155 0ustar jorisusers/* * Copyright (c) 2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "kore.h" TAILQ_HEAD(timerlist, kore_timer) kore_timers; void kore_timer_init(void) { TAILQ_INIT(&kore_timers); } struct kore_timer * kore_timer_add(void (*cb)(void *, u_int64_t, u_int64_t), u_int64_t interval, void *arg, int flags) { struct kore_timer *timer, *t; timer = kore_malloc(sizeof(*timer)); timer->cb = cb; timer->arg = arg; timer->flags = flags; timer->interval = interval; timer->nextrun = kore_time_ms() + timer->interval; TAILQ_FOREACH(t, &kore_timers, list) { if (t->nextrun > timer->nextrun) { TAILQ_INSERT_BEFORE(t, timer, list); return (timer); } } TAILQ_INSERT_TAIL(&kore_timers, timer, list); return (timer); } void kore_timer_remove(struct kore_timer *timer) { TAILQ_REMOVE(&kore_timers, timer, list); kore_mem_free(timer); } u_int64_t kore_timer_run(u_int64_t now) { struct kore_timer *timer, *t; u_int64_t next_timer, delta; next_timer = 100; while ((timer = TAILQ_FIRST(&kore_timers)) != NULL) { if (timer->nextrun > now) { next_timer = timer->nextrun - now; break; } TAILQ_REMOVE(&kore_timers, timer, list); delta = now - timer->nextrun; timer->cb(timer->arg, now, delta); if (timer->flags & KORE_TIMER_ONESHOT) { kore_mem_free(timer); } else { timer->nextrun += timer->interval - delta; TAILQ_FOREACH(t, &kore_timers, list) { if (t->nextrun > timer->nextrun) { TAILQ_INSERT_BEFORE(t, timer, list); break; } } if (t == NULL) TAILQ_INSERT_TAIL(&kore_timers, timer, list); } } if (next_timer > 1) next_timer -= 1; return (next_timer); } kore/src/mem.c0000644000175000001440000000565012527355514012613 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include "kore.h" #define KORE_MEM_MAGIC 0xd0d0 #define KORE_MEMSIZE(x) \ (*(u_int32_t *)((u_int8_t *)x - sizeof(u_int32_t))) #define KORE_MEMINFO(x) \ (struct meminfo *)((u_int8_t *)x + KORE_MEMSIZE(x)) struct meminfo { u_int16_t magic; }; void kore_mem_init(void) { } void * kore_malloc(size_t len) { size_t mlen; void *ptr; struct meminfo *mem; u_int8_t *addr; u_int32_t *plen; if (len == 0) fatal("kore_malloc(): zero size"); mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo); if ((ptr = malloc(mlen)) == NULL) fatal("kore_malloc(%d): %d", len, errno); plen = (u_int32_t *)ptr; *plen = len; addr = (u_int8_t *)ptr + sizeof(u_int32_t); mem = KORE_MEMINFO(addr); mem->magic = KORE_MEM_MAGIC; #if defined(KORE_PEDANTIC_MALLOC) explicit_bzero(addr, len); #endif return (addr); } void * kore_realloc(void *ptr, size_t len) { struct meminfo *mem; void *nptr; if (len == 0) fatal("kore_realloc(): zero size"); if (ptr == NULL) { nptr = kore_malloc(len); } else { mem = KORE_MEMINFO(ptr); if (mem->magic != KORE_MEM_MAGIC) fatal("kore_realloc(): magic boundary not found"); nptr = kore_malloc(len); memcpy(nptr, ptr, MIN(len, KORE_MEMSIZE(ptr))); kore_mem_free(ptr); } return (nptr); } void * kore_calloc(size_t memb, size_t len) { if (memb == 0 || len == 0) fatal("kore_calloc(): zero size"); if (SIZE_MAX / memb < len) fatal("kore_calloc: memb * len > SIZE_MAX"); return (kore_malloc(memb * len)); } void kore_mem_free(void *ptr) { u_int8_t *addr; struct meminfo *mem; if (ptr == NULL) return; mem = KORE_MEMINFO(ptr); if (mem->magic != KORE_MEM_MAGIC) fatal("kore_mem_free(): magic boundary not found"); #if defined(KORE_PEDANTIC_MALLOC) explicit_bzero(ptr, KORE_MEMSIZE(ptr)); #endif addr = (u_int8_t *)ptr - sizeof(u_int32_t); free(addr); } char * kore_strdup(const char *str) { size_t len; char *nstr; len = strlen(str) + 1; nstr = kore_malloc(len); kore_strlcpy(nstr, str, len); return (nstr); } #if defined(KORE_PEDANTIC_MALLOC) void explicit_bzero(void *addr, size_t len) { bzero(addr, len); } #endif kore/src/connection.c0000644000175000001440000002165612527355514014200 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include "kore.h" #include "http.h" struct kore_pool connection_pool; void kore_connection_init(void) { kore_pool_init(&connection_pool, "connection_pool", sizeof(struct connection), worker_max_connections); } struct connection * kore_connection_new(void *owner) { struct connection *c; c = kore_pool_get(&connection_pool); c->ssl = NULL; c->flags = 0; c->rnb = NULL; c->snb = NULL; c->cert = NULL; c->wscbs = NULL; c->owner = owner; c->tls_reneg = 0; c->disconnect = NULL; c->hdlr_extra = NULL; c->inflate_started = 0; c->deflate_started = 0; c->client_stream_id = 0; c->proto = CONN_PROTO_UNKNOWN; c->type = KORE_TYPE_CONNECTION; c->wsize_initial = SPDY_INIT_WSIZE; c->spdy_send_wsize = SPDY_INIT_WSIZE; c->spdy_recv_wsize = SPDY_INIT_WSIZE; c->idle_timer.start = 0; c->idle_timer.length = KORE_IDLE_TIMER_MAX; TAILQ_INIT(&(c->send_queue)); TAILQ_INIT(&(c->spdy_streams)); TAILQ_INIT(&(c->http_requests)); return (c); } int kore_connection_accept(struct listener *l, struct connection **out) { struct connection *c; struct sockaddr *sin; socklen_t len; kore_debug("kore_connection_accept(%p)", l); *out = NULL; c = kore_connection_new(l); c->addrtype = l->addrtype; if (c->addrtype == AF_INET) { len = sizeof(struct sockaddr_in); sin = (struct sockaddr *)&(c->addr.ipv4); } else { len = sizeof(struct sockaddr_in6); sin = (struct sockaddr *)&(c->addr.ipv6); } if ((c->fd = accept(l->fd, sin, &len)) == -1) { kore_pool_put(&connection_pool, c); kore_debug("accept(): %s", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(c->fd)) { close(c->fd); kore_pool_put(&connection_pool, c); return (KORE_RESULT_ERROR); } #if !defined(KORE_BENCHMARK) c->state = CONN_STATE_SSL_SHAKE; c->write = net_write_ssl; c->read = net_read_ssl; #else c->state = CONN_STATE_ESTABLISHED; c->proto = CONN_PROTO_HTTP; c->write = net_write; c->read = net_read; if (http_keepalive_time != 0) c->idle_timer.length = http_keepalive_time * 1000; net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS, http_header_recv); #endif kore_worker_connection_add(c); kore_connection_start_idletimer(c); *out = c; return (KORE_RESULT_OK); } void kore_connection_disconnect(struct connection *c) { if (c->state != CONN_STATE_DISCONNECTING) { kore_debug("preparing %p for disconnection", c); c->state = CONN_STATE_DISCONNECTING; if (c->disconnect) c->disconnect(c); kore_worker_connection_move(c); } } int kore_connection_handle(struct connection *c) { #if !defined(KORE_BENCHMARK) int r; u_int32_t len; const u_char *data; char cn[X509_CN_LENGTH]; #endif kore_debug("kore_connection_handle(%p) -> %d", c, c->state); kore_connection_stop_idletimer(c); switch (c->state) { #if !defined(KORE_BENCHMARK) case CONN_STATE_SSL_SHAKE: if (c->ssl == NULL) { c->ssl = SSL_new(primary_dom->ssl_ctx); if (c->ssl == NULL) { kore_debug("SSL_new(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } SSL_set_fd(c->ssl, c->fd); SSL_set_accept_state(c->ssl); SSL_set_app_data(c->ssl, c); } r = SSL_accept(c->ssl); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return (KORE_RESULT_OK); default: kore_debug("SSL_accept(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } if (SSL_get_verify_mode(c->ssl) & SSL_VERIFY_PEER) { c->cert = SSL_get_peer_certificate(c->ssl); if (c->cert == NULL) { kore_log(LOG_NOTICE, "no client certificate presented?"); return (KORE_RESULT_ERROR); } if (X509_GET_CN(c->cert, cn, sizeof(cn)) == -1) { kore_log(LOG_NOTICE, "no CN found in client certificate"); return (KORE_RESULT_ERROR); } } r = SSL_get_verify_result(c->ssl); if (r != X509_V_OK) { kore_debug("SSL_get_verify_result(): %d, %s", r, ssl_errno_s); return (KORE_RESULT_ERROR); } SSL_get0_next_proto_negotiated(c->ssl, &data, &len); if (data) { if (!memcmp(data, "spdy/3", MIN(6, len))) { c->proto = CONN_PROTO_SPDY; c->idle_timer.length = spdy_idle_time; net_recv_queue(c, SPDY_FRAME_SIZE, 0, spdy_frame_recv); } else if (!memcmp(data, "http/1.1", MIN(8, len))) { c->proto = CONN_PROTO_HTTP; if (http_keepalive_time != 0) { c->idle_timer.length = http_keepalive_time * 1000; } net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS, http_header_recv); } else { kore_log(LOG_NOTICE, "npn: received unknown protocol"); return (KORE_RESULT_ERROR); } } else { c->proto = CONN_PROTO_HTTP; if (http_keepalive_time != 0) { c->idle_timer.length = http_keepalive_time * 1000; } net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS, http_header_recv); } c->state = CONN_STATE_ESTABLISHED; /* FALLTHROUGH */ #endif /* !KORE_BENCHMARK */ case CONN_STATE_ESTABLISHED: if (c->flags & CONN_READ_POSSIBLE) { if (!net_recv_flush(c)) return (KORE_RESULT_ERROR); } if (c->flags & CONN_WRITE_POSSIBLE) { if (!net_send_flush(c)) return (KORE_RESULT_ERROR); } break; case CONN_STATE_DISCONNECTING: break; default: kore_debug("unknown state on %d (%d)", c->fd, c->state); break; } kore_connection_start_idletimer(c); return (KORE_RESULT_OK); } void kore_connection_remove(struct connection *c) { struct netbuf *nb, *next; struct spdy_stream *s, *snext; struct http_request *req, *rnext; kore_debug("kore_connection_remove(%p)", c); #if !defined(KORE_BENCHMARK) if (c->ssl != NULL) { SSL_shutdown(c->ssl); SSL_free(c->ssl); } if (c->cert != NULL) X509_free(c->cert); #endif close(c->fd); if (c->hdlr_extra != NULL) kore_mem_free(c->hdlr_extra); if (c->inflate_started) inflateEnd(&(c->z_inflate)); if (c->deflate_started) deflateEnd(&(c->z_deflate)); for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) { rnext = TAILQ_NEXT(req, olist); TAILQ_REMOVE(&(c->http_requests), req, olist); req->flags |= HTTP_REQUEST_DELETE; http_request_wakeup(req); } for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = next) { next = TAILQ_NEXT(nb, list); TAILQ_REMOVE(&(c->send_queue), nb, list); if (!(nb->flags & NETBUF_IS_STREAM)) { kore_mem_free(nb->buf); } else if (nb->cb != NULL) { (void)nb->cb(nb); } kore_pool_put(&nb_pool, nb); } if (c->rnb != NULL) { kore_mem_free(c->rnb->buf); kore_pool_put(&nb_pool, c->rnb); } for (s = TAILQ_FIRST(&(c->spdy_streams)); s != NULL; s = snext) { snext = TAILQ_NEXT(s, list); TAILQ_REMOVE(&(c->spdy_streams), s, list); if (s->hblock != NULL) { if (s->hblock->header_block != NULL) kore_mem_free(s->hblock->header_block); kore_mem_free(s->hblock); } kore_mem_free(s); } kore_worker_connection_remove(c); kore_pool_put(&connection_pool, c); } void kore_connection_check_idletimer(u_int64_t now, struct connection *c) { u_int64_t d; d = now - c->idle_timer.start; if (d >= c->idle_timer.length) { kore_debug("%p idle for %d ms, expiring", c, d); if (c->proto == CONN_PROTO_SPDY) spdy_session_teardown(c, SPDY_SESSION_ERROR_OK); else kore_connection_disconnect(c); } } void kore_connection_start_idletimer(struct connection *c) { kore_debug("kore_connection_start_idletimer(%p)", c); c->flags |= CONN_IDLE_TIMER_ACT; c->idle_timer.start = kore_time_ms(); } void kore_connection_stop_idletimer(struct connection *c) { kore_debug("kore_connection_stop_idletimer(%p)", c); c->flags &= ~CONN_IDLE_TIMER_ACT; c->idle_timer.start = 0; } int kore_connection_nonblock(int fd) { int flags; kore_debug("kore_connection_nonblock(%d)", fd); if ((flags = fcntl(fd, F_GETFL, 0)) == -1) { kore_debug("fcntl(): F_GETFL %s", errno_s); return (KORE_RESULT_ERROR); } flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) { kore_debug("fcntl(): F_SETFL %s", errno_s); return (KORE_RESULT_ERROR); } flags = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flags, sizeof(flags)) == -1) { kore_log(LOG_NOTICE, "failed to set TCP_NODELAY on %d", fd); } return (KORE_RESULT_OK); } kore/src/module.c0000644000175000001440000001246012527355514013317 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "kore.h" static TAILQ_HEAD(, kore_module) modules; void kore_module_init(void) { TAILQ_INIT(&modules); TAILQ_INIT(&domains); } void kore_module_load(const char *path, const char *onload) { struct stat st; struct kore_module *module; kore_debug("kore_module_load(%s, %s)", path, onload); if (stat(path, &st) == -1) fatal("stat(%s): %s", path, errno_s); module = kore_malloc(sizeof(struct kore_module)); module->path = kore_strdup(path); module->mtime = st.st_mtime; module->onload = NULL; module->ocb = NULL; module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL); if (module->handle == NULL) fatal("%s: %s", path, dlerror()); if (onload != NULL) { module->onload = kore_strdup(onload); module->ocb = dlsym(module->handle, onload); if (module->ocb == NULL) fatal("%s: onload '%s' not present", path, onload); } TAILQ_INSERT_TAIL(&modules, module, list); } void kore_module_onload(void) { struct kore_module *module; TAILQ_FOREACH(module, &modules, list) { if (module->ocb == NULL) continue; (void)module->ocb(KORE_MODULE_LOAD); } } void kore_module_reload(int cbs) { struct stat st; struct kore_domain *dom; struct kore_module_handle *hdlr; struct kore_module *module; TAILQ_FOREACH(module, &modules, list) { if (stat(module->path, &st) == -1) { kore_log(LOG_NOTICE, "stat(%s): %s, skipping reload", module->path, errno_s); continue; } if (module->mtime == st.st_mtime) continue; if (module->ocb != NULL && cbs == 1) { if (!module->ocb(KORE_MODULE_UNLOAD)) { kore_log(LOG_NOTICE, "not reloading %s", module->path); continue; } } module->mtime = st.st_mtime; if (dlclose(module->handle)) fatal("cannot close existing module: %s", dlerror()); module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL); if (module->handle == NULL) fatal("kore_module_reload(): %s", dlerror()); if (module->onload != NULL) { module->ocb = dlsym(module->handle, module->onload); if (module->ocb == NULL) { fatal("%s: onload '%s' not present", module->path, module->onload); } if (cbs) (void)module->ocb(KORE_MODULE_LOAD); } kore_log(LOG_NOTICE, "reloaded '%s' module", module->path); } TAILQ_FOREACH(dom, &domains, list) { TAILQ_FOREACH(hdlr, &(dom->handlers), list) { hdlr->addr = kore_module_getsym(hdlr->func); if (hdlr->func == NULL) fatal("no function '%s' found", hdlr->func); hdlr->errors = 0; } } kore_validator_reload(); } int kore_module_loaded(void) { if (TAILQ_EMPTY(&modules)) return (0); return (1); } int kore_module_handler_new(const char *path, const char *domain, const char *func, const char *auth, int type) { struct kore_auth *ap; void *addr; struct kore_domain *dom; struct kore_module_handle *hdlr; kore_debug("kore_module_handler_new(%s, %s, %s, %s, %d)", path, domain, func, auth, type); addr = kore_module_getsym(func); if (addr == NULL) { kore_debug("function '%s' not found", func); return (KORE_RESULT_ERROR); } if ((dom = kore_domain_lookup(domain)) == NULL) return (KORE_RESULT_ERROR); if (auth != NULL) { if ((ap = kore_auth_lookup(auth)) == NULL) fatal("no authentication block '%s' found", auth); } else { ap = NULL; } hdlr = kore_malloc(sizeof(*hdlr)); hdlr->auth = ap; hdlr->dom = dom; hdlr->errors = 0; hdlr->addr = addr; hdlr->type = type; TAILQ_INIT(&(hdlr->params)); hdlr->path = kore_strdup(path); hdlr->func = kore_strdup(func); if (hdlr->type == HANDLER_TYPE_DYNAMIC) { if (regcomp(&(hdlr->rctx), hdlr->path, REG_EXTENDED | REG_NOSUB)) { kore_mem_free(hdlr->func); kore_mem_free(hdlr->path); kore_mem_free(hdlr); kore_debug("regcomp() on %s failed", path); return (KORE_RESULT_ERROR); } } TAILQ_INSERT_TAIL(&(dom->handlers), hdlr, list); return (KORE_RESULT_OK); } struct kore_module_handle * kore_module_handler_find(const char *domain, const char *path) { struct kore_domain *dom; struct kore_module_handle *hdlr; if ((dom = kore_domain_lookup(domain)) == NULL) return (NULL); TAILQ_FOREACH(hdlr, &(dom->handlers), list) { if (hdlr->type == HANDLER_TYPE_STATIC) { if (!strcmp(hdlr->path, path)) return (hdlr); } else { if (!regexec(&(hdlr->rctx), path, 0, NULL, 0)) return (hdlr); } } return (NULL); } void * kore_module_getsym(const char *symbol) { void *ptr; struct kore_module *module; TAILQ_FOREACH(module, &modules, list) { ptr = dlsym(module->handle, symbol); if (ptr != NULL) return (ptr); } return (NULL); } kore/src/utils.c0000644000175000001440000002201212527355514013164 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "kore.h" static struct { char *name; int value; } month_names[] = { { "Jan", 0 }, { "Feb", 1 }, { "Mar", 2 }, { "Apr", 3 }, { "May", 4 }, { "Jun", 5 }, { "Jul", 6 }, { "Aug", 7 }, { "Sep", 8 }, { "Oct", 9 }, { "Nov", 10 }, { "Dec", 11 }, { NULL, 0 }, }; static char b64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; void kore_debug_internal(char *file, int line, const char *fmt, ...) { va_list args; char buf[2048]; va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printf("[%d] %s:%d - %s\n", kore_pid, file, line, buf); } void kore_log_init(void) { if (!foreground) openlog("kore", LOG_NDELAY | LOG_PID, LOG_DAEMON); } void kore_log(int prio, const char *fmt, ...) { va_list args; char buf[2048]; va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (worker != NULL) { if (foreground) printf("[wrk %d]: %s\n", worker->id, buf); else syslog(prio, "[wrk %d]: %s", worker->id, buf); } else { if (foreground) printf("[parent]: %s\n", buf); else syslog(prio, "[parent]: %s", buf); } } void kore_strlcpy(char *dst, const char *src, size_t len) { char *d = dst; const char *s = src; const char *end = dst + len - 1; while ((*d = *s) != '\0') { if (d == end) { *d = '\0'; break; } d++; s++; } } int kore_snprintf(char *str, size_t size, int *len, const char *fmt, ...) { int l; va_list args; va_start(args, fmt); l = vsnprintf(str, size, fmt, args); va_end(args); if (l == -1 || (size_t)l >= size) return (KORE_RESULT_ERROR); if (len != NULL) *len = l; return (KORE_RESULT_OK); } long long kore_strtonum(const char *str, int base, long long min, long long max, int *err) { long long l; char *ep; if (min > max) { *err = KORE_RESULT_ERROR; return (0); } errno = 0; l = strtoll(str, &ep, base); if (errno != 0 || str == ep || *ep != '\0') { *err = KORE_RESULT_ERROR; return (0); } if (l < min) { *err = KORE_RESULT_ERROR; return (0); } if (l > max) { *err = KORE_RESULT_ERROR; return (0); } *err = KORE_RESULT_OK; return (l); } u_int64_t kore_strtonum64(const char *str, int sign, int *err) { u_int64_t l; long long ll; char *ep; int check; l = 0; check = 1; ll = strtoll(str, &ep, 10); if ((errno == EINVAL || errno == ERANGE) && (ll == LLONG_MIN || ll == LLONG_MAX)) { if (sign) { *err = KORE_RESULT_ERROR; return (0); } check = 0; } if (!sign) { l = strtoull(str, &ep, 10); if ((errno == EINVAL || errno == ERANGE) && l == ULONG_MAX) { *err = KORE_RESULT_ERROR; return (0); } if (check && ll < 0) { *err = KORE_RESULT_ERROR; return (0); } } if (str == ep || *ep != '\0') { *err = KORE_RESULT_ERROR; return (0); } *err = KORE_RESULT_OK; return ((sign) ? (u_int64_t)ll : l); } int kore_split_string(char *input, char *delim, char **out, size_t ele) { int count; char **ap; count = 0; for (ap = out; ap < &out[ele - 1] && (*ap = strsep(&input, delim)) != NULL;) { if (**ap != '\0') { ap++; count++; } } *ap = NULL; return (count); } void kore_strip_chars(char *in, char strip, char **out) { u_int32_t len; char *s, *p; len = strlen(in); *out = kore_malloc(len + 1); p = *out; for (s = in; s < (in + len); s++) { if (*s == strip) continue; *p++ = *s; } *p = '\0'; } time_t kore_date_to_time(char *http_date) { time_t t; int err, i; struct tm tm, *ltm; char *args[7], *tbuf[5], *sdup; time(&t); ltm = localtime(&t); sdup = kore_strdup(http_date); t = KORE_RESULT_ERROR; if (kore_split_string(sdup, " ", args, 7) != 6) { kore_debug("misformed http-date: '%s'", http_date); goto out; } memset(&tm, 0, sizeof(tm)); tm.tm_year = kore_strtonum(args[3], 10, 1900, 2068, &err) - 1900; if (err == KORE_RESULT_ERROR) { kore_debug("misformed year in http-date: '%s'", http_date); goto out; } for (i = 0; month_names[i].name != NULL; i++) { if (!strcmp(month_names[i].name, args[2])) { tm.tm_mon = month_names[i].value; break; } } if (month_names[i].name == NULL) { kore_debug("misformed month in http-date: '%s'", http_date); goto out; } tm.tm_mday = kore_strtonum(args[1], 10, 1, 31, &err); if (err == KORE_RESULT_ERROR) { kore_debug("misformed mday in http-date: '%s'", http_date); goto out; } if (kore_split_string(args[4], ":", tbuf, 5) != 3) { kore_debug("misformed HH:MM:SS in http-date: '%s'", http_date); goto out; } tm.tm_hour = kore_strtonum(tbuf[0], 10, 0, 23, &err); if (err == KORE_RESULT_ERROR) { kore_debug("misformed hour in http-date: '%s'", http_date); goto out; } tm.tm_min = kore_strtonum(tbuf[1], 10, 0, 59, &err); if (err == KORE_RESULT_ERROR) { kore_debug("misformed minutes in http-date: '%s'", http_date); goto out; } tm.tm_sec = kore_strtonum(tbuf[2], 10, 0, 60, &err); if (err == KORE_RESULT_ERROR) { kore_debug("misformed seconds in http-date: '%s'", http_date); goto out; } tm.tm_isdst = ltm->tm_isdst; t = mktime(&tm) + ltm->tm_gmtoff; if (t == -1) { t = 0; kore_debug("mktime() on '%s' failed", http_date); } out: kore_mem_free(sdup); return (t); } char * kore_time_to_date(time_t now) { struct tm *tm; static time_t last = 0; static char tbuf[32]; if (now != last) { last = now; tm = gmtime(&now); if (!strftime(tbuf, sizeof(tbuf), "%a, %d %b %Y %T GMT", tm)) { kore_debug("strftime() gave us NULL (%ld)", now); return (NULL); } } return (tbuf); } u_int64_t kore_time_ms(void) { struct timeval tv; if (gettimeofday(&tv, NULL) == -1) return (0); return (tv.tv_sec * 1000 + (tv.tv_usec / 1000)); } int kore_base64_encode(u_int8_t *data, u_int32_t len, char **out) { struct kore_buf *res; u_int8_t n, *pdata; int i, padding; u_int32_t idx, b, plen; if ((len % 3) != 0) { padding = 3 - (len % 3); plen = len + padding; pdata = kore_malloc(plen); memcpy(pdata, data, len); memset(pdata + len, 0, padding); } else { plen = len; padding = 0; pdata = data; } res = kore_buf_create(plen); i = 2; b = 0; for (idx = 0; idx < plen; idx++) { b |= (pdata[idx] << (i * 8)); if (i-- == 0) { for (i = 3; i >= 0; i--) { n = (b >> (6 * i)) & 0x3f; if (n >= sizeof(b64table)) { kore_debug("unable to encode %d", n); kore_buf_free(res); return (KORE_RESULT_ERROR); } if (idx >= len && i < padding) break; kore_buf_append(res, &(b64table[n]), 1); } b = 0; i = 2; } } for (i = 0; i < padding; i++) kore_buf_append(res, (u_int8_t *)"=", 1); if (pdata != data) kore_mem_free(pdata); pdata = kore_buf_release(res, &plen); *out = kore_malloc(plen + 1); kore_strlcpy(*out, (char *)pdata, plen + 1); kore_mem_free(pdata); return (KORE_RESULT_OK); } int kore_base64_decode(char *in, u_int8_t **out, u_int32_t *olen) { int i, c; struct kore_buf *res; u_int8_t d, n, o; u_int32_t b, len, idx; i = 4; b = 0; d = 0; c = 0; len = strlen(in); res = kore_buf_create(len); for (idx = 0; idx < len; idx++) { c = in[idx]; if (c == '=') break; for (o = 0; o < sizeof(b64table); o++) { if (b64table[o] == c) { d = o; break; } } if (o == sizeof(b64table)) { *out = NULL; kore_buf_free(res); return (KORE_RESULT_ERROR); } b |= (d & 0x3f) << ((i - 1) * 6); i--; if (i == 0) { for (i = 2; i >= 0; i--) { n = (b >> (8 * i)); kore_buf_append(res, &n, 1); } b = 0; i = 4; } } if (c == '=') { if (i > 2) { *out = NULL; kore_buf_free(res); return (KORE_RESULT_ERROR); } o = i; for (i = 2; i >= o; i--) { n = (b >> (8 * i)); kore_buf_append(res, &n, 1); } } *out = kore_buf_release(res, olen); return (KORE_RESULT_OK); } void * kore_mem_find(void *src, size_t slen, void *needle, u_int32_t len) { u_int8_t *p, *end; end = (u_int8_t *)src + slen; for (p = src; p < end; p++) { if (*p != *(u_int8_t *)needle) continue; if ((end - p) < len) return (NULL); if (!memcmp(p, needle, len)) return (p); } return (NULL); } void fatal(const char *fmt, ...) { va_list args; char buf[2048]; va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (!foreground) kore_log(LOG_ERR, "%s", buf); printf("kore: %s\n", buf); exit(1); } kore/src/net.c0000644000175000001440000002247712527355514012631 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #if defined(__linux__) #include #elif defined(__MACH__) #include #define htobe64(x) OSSwapHostToBigInt64(x) #define be64toh(x) OSSwapBigToHostInt64(x) #else #include #endif #include "kore.h" struct kore_pool nb_pool; void net_init(void) { kore_pool_init(&nb_pool, "nb_pool", sizeof(struct netbuf), 1000); } void net_send_queue(struct connection *c, void *data, u_int32_t len, struct spdy_stream *s, int before) { u_int8_t *d; struct netbuf *nb; u_int32_t avail; kore_debug("net_send_queue(%p, %p, %d, %p, %d)", c, data, len, s, before); d = data; if (before == NETBUF_LAST_CHAIN) { nb = TAILQ_LAST(&(c->send_queue), netbuf_head); if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) && nb->stream == s && nb->b_len < nb->m_len) { avail = nb->m_len - nb->b_len; if (len < avail) { memcpy(nb->buf + nb->b_len, d, len); nb->b_len += len; return; } else if (len > avail) { memcpy(nb->buf + nb->b_len, d, avail); nb->b_len += avail; len -= avail; d += avail; if (len == 0) return; } } } nb = kore_pool_get(&nb_pool); nb->flags = 0; nb->cb = NULL; nb->owner = c; nb->s_off = 0; nb->stream = s; nb->b_len = len; nb->type = NETBUF_SEND; if (nb->b_len < NETBUF_SEND_PAYLOAD_MAX) nb->m_len = NETBUF_SEND_PAYLOAD_MAX; else nb->m_len = nb->b_len; nb->buf = kore_malloc(nb->m_len); if (len > 0) memcpy(nb->buf, d, nb->b_len); if (before == NETBUF_BEFORE_CHAIN) { TAILQ_INSERT_BEFORE(c->snb, nb, list); } else { TAILQ_INSERT_TAIL(&(c->send_queue), nb, list); } } void net_send_stream(struct connection *c, void *data, u_int32_t len, struct spdy_stream *s, int (*cb)(struct netbuf *), struct netbuf **out) { struct netbuf *nb; kore_debug("net_send_stream(%p, %p, %d, %p)", c, data, len, s); nb = kore_pool_get(&nb_pool); nb->cb = cb; nb->owner = c; nb->s_off = 0; nb->buf = data; nb->stream = s; nb->b_len = len; nb->m_len = nb->b_len; nb->type = NETBUF_SEND; nb->flags = NETBUF_IS_STREAM; TAILQ_INSERT_TAIL(&(c->send_queue), nb, list); if (out != NULL) *out = nb; } void net_recv_reset(struct connection *c, u_int32_t len, int (*cb)(struct netbuf *)) { kore_debug("net_recv_reset(): %p %d", c, len); if (c->rnb->type != NETBUF_RECV) fatal("net_recv_reset(): wrong netbuf type"); c->rnb->cb = cb; c->rnb->s_off = 0; c->rnb->b_len = len; if (c->rnb->b_len <= c->rnb->m_len && c->rnb->m_len < (NETBUF_SEND_PAYLOAD_MAX / 2)) return; kore_mem_free(c->rnb->buf); c->rnb->m_len = len; c->rnb->buf = kore_malloc(c->rnb->m_len); } void net_recv_queue(struct connection *c, u_int32_t len, int flags, int (*cb)(struct netbuf *)) { kore_debug("net_recv_queue(): %p %d %d", c, len, flags); if (c->rnb != NULL) fatal("net_recv_queue(): called incorrectly for %p", c); c->rnb = kore_pool_get(&nb_pool); c->rnb->cb = cb; c->rnb->owner = c; c->rnb->s_off = 0; c->rnb->b_len = len; c->rnb->m_len = len; c->rnb->extra = NULL; c->rnb->stream = NULL; c->rnb->flags = flags; c->rnb->type = NETBUF_RECV; c->rnb->buf = kore_malloc(c->rnb->b_len); } void net_recv_expand(struct connection *c, u_int32_t len, int (*cb)(struct netbuf *)) { kore_debug("net_recv_expand(): %p %d", c, len); if (c->rnb->type != NETBUF_RECV) fatal("net_recv_expand(): wrong netbuf type"); c->rnb->cb = cb; c->rnb->b_len += len; c->rnb->m_len = c->rnb->b_len; c->rnb->buf = kore_realloc(c->rnb->buf, c->rnb->b_len); } int net_send(struct connection *c) { int r; u_int32_t len, smin; c->snb = TAILQ_FIRST(&(c->send_queue)); if (c->snb->b_len != 0) { if (c->snb->stream != NULL && (c->snb->stream->flags & SPDY_DATAFRAME_PRELUDE)) { if (!spdy_dataframe_begin(c)) { c->snb = NULL; return (KORE_RESULT_OK); } c->snb = TAILQ_FIRST(&(c->send_queue)); } smin = c->snb->b_len - c->snb->s_off; if (c->snb->stream != NULL && c->snb->stream->frame_size > 0) { smin = MIN(smin, c->snb->stream->frame_size); } len = MIN(NETBUF_SEND_PAYLOAD_MAX, smin); if (!c->write(c, len, &r)) return (KORE_RESULT_ERROR); if (!(c->flags & CONN_WRITE_POSSIBLE)) return (KORE_RESULT_OK); kore_debug("net_send(%p/%d/%d bytes), progress with %d", c->snb, c->snb->s_off, c->snb->b_len, r); c->snb->s_off += (size_t)r; c->snb->flags &= ~NETBUF_MUST_RESEND; if (c->snb->stream != NULL) spdy_update_wsize(c, c->snb->stream, r); } if (c->snb->s_off == c->snb->b_len || (c->snb->flags & NETBUF_FORCE_REMOVE)) { net_remove_netbuf(&(c->send_queue), c->snb); c->snb = NULL; } return (KORE_RESULT_OK); } int net_send_flush(struct connection *c) { kore_debug("net_send_flush(%p)", c); while (!TAILQ_EMPTY(&(c->send_queue)) && (c->flags & CONN_WRITE_POSSIBLE)) { if (!net_send(c)) return (KORE_RESULT_ERROR); } if ((c->flags & CONN_CLOSE_EMPTY) && TAILQ_EMPTY(&(c->send_queue))) kore_connection_disconnect(c); return (KORE_RESULT_OK); } int net_recv_flush(struct connection *c) { int r; kore_debug("net_recv_flush(%p)", c); if (c->rnb == NULL) fatal("net_recv_flush(): c->rnb == NULL"); while (c->flags & CONN_READ_POSSIBLE) { if (!c->read(c, &r)) return (KORE_RESULT_ERROR); if (!(c->flags & CONN_READ_POSSIBLE)) break; kore_debug("net_recv(%ld/%ld bytes), progress with %d", c->rnb->s_off, c->rnb->b_len, r); c->rnb->s_off += (size_t)r; if (c->rnb->s_off == c->rnb->b_len || (c->rnb->flags & NETBUF_CALL_CB_ALWAYS)) { r = c->rnb->cb(c->rnb); if (r != KORE_RESULT_OK) return (r); } } return (KORE_RESULT_OK); } void net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb) { kore_debug("net_remove_netbuf(%p, %p, %p)", list, nb, nb->stream); if (nb->type == NETBUF_RECV) fatal("net_remove_netbuf(): cannot remove recv netbuf"); nb->stream = NULL; if (nb->flags & NETBUF_MUST_RESEND) { kore_debug("retaining %p (MUST_RESEND)", nb); nb->flags |= NETBUF_FORCE_REMOVE; return; } if (!(nb->flags & NETBUF_IS_STREAM)) { kore_mem_free(nb->buf); } else if (nb->cb != NULL) { (void)nb->cb(nb); } TAILQ_REMOVE(list, nb, list); kore_pool_put(&nb_pool, nb); } #if !defined(KORE_BENCHMARK) int net_write_ssl(struct connection *c, int len, int *written) { int r; r = SSL_write(c->ssl, (c->snb->buf + c->snb->s_off), len); if (c->tls_reneg > 1) return (KORE_RESULT_ERROR); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: c->snb->flags |= NETBUF_MUST_RESEND; c->flags &= ~CONN_WRITE_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("SSL_write(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } *written = r; return (KORE_RESULT_OK); } int net_read_ssl(struct connection *c, int *bytes) { int r; r = SSL_read(c->ssl, (c->rnb->buf + c->rnb->s_off), (c->rnb->b_len - c->rnb->s_off)); if (c->tls_reneg > 1) return (KORE_RESULT_ERROR); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: c->flags &= ~CONN_READ_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("SSL_read(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } *bytes = r; return (KORE_RESULT_OK); } #endif int net_write(struct connection *c, int len, int *written) { int r; r = write(c->fd, (c->snb->buf + c->snb->s_off), len); if (r <= -1) { switch (errno) { case EINTR: case EAGAIN: c->flags &= ~CONN_WRITE_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("write: %s", errno_s); return (KORE_RESULT_ERROR); } } *written = r; return (KORE_RESULT_OK); } int net_read(struct connection *c, int *bytes) { int r; r = read(c->fd, (c->rnb->buf + c->rnb->s_off), (c->rnb->b_len - c->rnb->s_off)); if (r <= 0) { switch (errno) { case EINTR: case EAGAIN: c->flags &= ~CONN_READ_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("read(): %s", errno_s); return (KORE_RESULT_ERROR); } } *bytes = r; return (KORE_RESULT_OK); } u_int16_t net_read16(u_int8_t *b) { u_int16_t r; r = *(u_int16_t *)b; return (ntohs(r)); } u_int32_t net_read32(u_int8_t *b) { u_int32_t r; r = *(u_int32_t *)b; return (ntohl(r)); } void net_write16(u_int8_t *p, u_int16_t n) { u_int16_t r; r = htons(n); memcpy(p, &r, sizeof(r)); } void net_write32(u_int8_t *p, u_int32_t n) { u_int32_t r; r = htonl(n); memcpy(p, &r, sizeof(r)); } u_int64_t net_read64(u_int8_t *b) { u_int64_t r; r = *(u_int64_t *)b; return (be64toh(r)); } void net_write64(u_int8_t *p, u_int64_t n) { u_int64_t r; r = htobe64(n); memcpy(p, &r, sizeof(r)); } kore/src/websocket.c0000755000175000001440000002054512527355514014026 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "kore.h" #include "http.h" #define WEBSOCKET_FRAME_HDR 2 #define WEBSOCKET_MASK_LEN 4 #define WEBSOCKET_FRAME_MAXLEN 16384 #define WEBSOCKET_PAYLOAD_SINGLE 125 #define WEBSOCKET_PAYLOAD_EXTEND_1 126 #define WEBSOCKET_PAYLOAD_EXTEND_2 127 #define WEBSOCKET_OPCODE_MASK 0x0f #define WEBSOCKET_FRAME_LENGTH(x) ((x) & ~(1 << 7)) #define WEBSOCKET_HAS_MASK(x) ((x) & (1 << 7)) #define WEBSOCKET_HAS_FINFLAG(x) ((x) & (1 << 7)) #define WEBSOCKET_RSV(x, i) ((x) & (1 << (7 - i))) #define WEBSOCKET_SERVER_RESPONSE "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" struct websocket_data { u_int8_t op; void *data; size_t len; }; u_int64_t kore_websocket_timeout = 120000; u_int64_t kore_websocket_maxframe = 16384; static int websocket_recv_frame(struct netbuf *); static int websocket_recv_opcode(struct netbuf *); static void websocket_disconnect(struct connection *); static void websocket_send_single(struct connection *, void *); void websocket_send(struct connection *, u_int8_t, void *, size_t); void kore_websocket_handshake(struct http_request *req, struct kore_wscbs *wscbs) { SHA_CTX sctx; struct kore_buf *buf; char *key, *base64, *version; u_int8_t digest[SHA_DIGEST_LENGTH]; if (!http_request_header(req, "sec-websocket-key", &key)) { http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0); return; } if (!http_request_header(req, "sec-websocket-version", &version)) { kore_mem_free(key); http_response_header(req, "sec-websocket-version", "13"); http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0); return; } if (strcmp(version, "13")) { kore_mem_free(key); kore_mem_free(version); http_response_header(req, "sec-websocket-version", "13"); http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0); return; } kore_mem_free(version); buf = kore_buf_create(128); kore_buf_appendf(buf, "%s%s", key, WEBSOCKET_SERVER_RESPONSE); kore_mem_free(key); (void)SHA1_Init(&sctx); (void)SHA1_Update(&sctx, buf->data, buf->offset); (void)SHA1_Final(digest, &sctx); kore_buf_free(buf); if (!kore_base64_encode(digest, sizeof(digest), &base64)) { kore_debug("failed to base64 encode digest"); http_response(req, HTTP_STATUS_INTERNAL_ERROR, NULL, 0); return; } http_response_header(req, "upgrade", "websocket"); http_response_header(req, "connection", "upgrade"); http_response_header(req, "sec-websocket-accept", base64); kore_mem_free(base64); kore_debug("%p: new websocket connection", req->owner); http_response(req, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL, 0); net_recv_reset(req->owner, WEBSOCKET_FRAME_HDR, websocket_recv_opcode); req->owner->disconnect = websocket_disconnect; req->owner->rnb->flags &= ~NETBUF_CALL_CB_ALWAYS; req->owner->proto = CONN_PROTO_WEBSOCKET; req->owner->wscbs = wscbs; req->owner->idle_timer.start = kore_time_ms(); req->owner->idle_timer.length = kore_websocket_timeout; if (wscbs->connect != NULL) wscbs->connect(req->owner); } void kore_websocket_send(struct connection *c, u_int8_t op, void *data, size_t len) { u_int8_t len_1; u_int16_t len16; u_int64_t len64; struct kore_buf *frame; if (c->proto != CONN_PROTO_WEBSOCKET) fatal("kore_websocket_send(): to non websocket connection"); kore_debug("%p: sending %ld bytes", c, len); if (len > WEBSOCKET_PAYLOAD_SINGLE) { if (len < USHRT_MAX) len_1 = WEBSOCKET_PAYLOAD_EXTEND_1; else len_1 = WEBSOCKET_PAYLOAD_EXTEND_2; } else { len_1 = len; } frame = kore_buf_create(len); op |= (1 << 7); kore_buf_append(frame, &op, sizeof(op)); len_1 &= ~(1 << 7); kore_buf_append(frame, &len_1, sizeof(len_1)); if (len_1 != len) { switch (len_1) { case WEBSOCKET_PAYLOAD_EXTEND_1: net_write16((u_int8_t *)&len16, len); kore_buf_append(frame, &len16, sizeof(len16)); break; case WEBSOCKET_PAYLOAD_EXTEND_2: net_write64((u_int8_t *)&len64, len); kore_buf_append(frame, &len64, sizeof(len64)); break; } } kore_buf_append(frame, data, len); net_send_queue(c, frame->data, frame->offset, NULL, NETBUF_LAST_CHAIN); kore_buf_free(frame); } void kore_websocket_broadcast(struct connection *c, u_int8_t op, void *data, size_t len, int scope) { struct websocket_data arg; arg.op = op; arg.len = len; arg.data = data; kore_worker_websocket_broadcast(c, websocket_send_single, &arg); if (scope == WEBSOCKET_BROADCAST_GLOBAL) fatal("kore_websocket_broadcast: no global scope yet"); } static void websocket_send_single(struct connection *c, void *args) { struct websocket_data *arg = args; kore_websocket_send(c, arg->op, arg->data, arg->len); net_send_flush(c); } static int websocket_recv_opcode(struct netbuf *nb) { u_int8_t op, len; struct connection *c = nb->owner; if (!WEBSOCKET_HAS_MASK(nb->buf[1])) { kore_debug("%p: frame did not have a mask set", c); return (KORE_RESULT_ERROR); } if (WEBSOCKET_RSV(nb->buf[0], 1) || WEBSOCKET_RSV(nb->buf[0], 2) || WEBSOCKET_RSV(nb->buf[0], 2)) { kore_debug("%p: RSV bits are not zero", c); return (KORE_RESULT_ERROR); } len = WEBSOCKET_FRAME_LENGTH(nb->buf[1]); op = nb->buf[0] & WEBSOCKET_OPCODE_MASK; switch (op) { case WEBSOCKET_OP_CONT: case WEBSOCKET_OP_TEXT: case WEBSOCKET_OP_BINARY: break; case WEBSOCKET_OP_CLOSE: case WEBSOCKET_OP_PING: case WEBSOCKET_OP_PONG: if (len > WEBSOCKET_PAYLOAD_SINGLE || !WEBSOCKET_HAS_FINFLAG(nb->buf[0])) { kore_debug("%p: large or fragmented control frame", c); return (KORE_RESULT_ERROR); } break; default: kore_debug("%p: bad websocket op %d", c, op); return (KORE_RESULT_ERROR); } switch (len) { case WEBSOCKET_PAYLOAD_EXTEND_1: len += sizeof(u_int16_t); break; case WEBSOCKET_PAYLOAD_EXTEND_2: len += sizeof(u_int64_t); break; } len += WEBSOCKET_MASK_LEN; net_recv_expand(c, len, websocket_recv_frame); return (KORE_RESULT_OK); } static int websocket_recv_frame(struct netbuf *nb) { struct connection *c; int ret; struct kore_wscbs *wscbs; u_int64_t len, i, total; u_int8_t op, moff, extra; c = nb->owner; wscbs = c->wscbs; op = nb->buf[0] & WEBSOCKET_OPCODE_MASK; len = WEBSOCKET_FRAME_LENGTH(nb->buf[1]); switch (len) { case WEBSOCKET_PAYLOAD_EXTEND_1: moff = 4; extra = sizeof(u_int16_t); len = net_read16(&nb->buf[2]); break; case WEBSOCKET_PAYLOAD_EXTEND_2: moff = 10; extra = sizeof(u_int64_t); len = net_read64(&nb->buf[2]); break; default: extra = 0; moff = 2; break; } if (len > kore_websocket_maxframe) { kore_debug("%p: frame too big", c); return (KORE_RESULT_ERROR); } extra += WEBSOCKET_FRAME_HDR; total = len + extra + WEBSOCKET_MASK_LEN; if (total > nb->b_len) { total -= nb->b_len; net_recv_expand(c, total, websocket_recv_frame); return (KORE_RESULT_OK); } if (total != nb->b_len) return (KORE_RESULT_ERROR); for (i = 0; i < len; i++) nb->buf[moff + 4 + i] ^= nb->buf[moff + (i % 4)]; ret = KORE_RESULT_OK; switch (op) { case WEBSOCKET_OP_CONT: case WEBSOCKET_OP_PONG: ret = KORE_RESULT_ERROR; kore_log(LOG_ERR, "%p: we do not support op 0x%02x yet", c, op); break; case WEBSOCKET_OP_TEXT: case WEBSOCKET_OP_BINARY: if (wscbs->message != NULL) wscbs->message(c, op, &nb->buf[moff + 4], len); break; case WEBSOCKET_OP_CLOSE: kore_connection_disconnect(c); break; case WEBSOCKET_OP_PING: kore_websocket_send(c, WEBSOCKET_OP_PONG, &nb->buf[moff + 4], len); break; default: kore_debug("%p: bad websocket op %d", c, op); return (KORE_RESULT_ERROR); } net_recv_reset(c, WEBSOCKET_FRAME_HDR, websocket_recv_opcode); return (ret); } static void websocket_disconnect(struct connection *c) { struct kore_wscbs *wscbs = c->wscbs; if (wscbs->disconnect != NULL) wscbs->disconnect(c); } kore/src/worker.c0000644000175000001440000002567712527355514013361 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include "kore.h" #include "http.h" #if defined(KORE_USE_PGSQL) #include "pgsql.h" #endif #if defined(KORE_USE_TASKS) #include "tasks.h" #endif #if defined(WORKER_DEBUG) #define worker_debug(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define worker_debug(fmt, ...) #endif #define KORE_SHM_KEY 15000 #define WORKER_LOCK_TIMEOUT 500 #define WORKER(id) \ (struct kore_worker *)((u_int8_t *)kore_workers + \ (sizeof(struct kore_worker) * id)) struct wlock { volatile int lock; pid_t current; }; static int worker_trylock(void); static void worker_unlock(void); static inline int kore_worker_acceptlock_obtain(void); static inline void kore_worker_acceptlock_release(void); static struct connection_list disconnected; static struct kore_worker *kore_workers; static int shm_accept_key; static struct wlock *accept_lock; extern volatile sig_atomic_t sig_recv; struct kore_worker *worker = NULL; struct connection_list worker_clients; u_int8_t worker_set_affinity = 1; u_int32_t worker_accept_threshold = 0; u_int32_t worker_rlimit_nofiles = 1024; u_int32_t worker_max_connections = 250; u_int32_t worker_active_connections = 0; void kore_worker_init(void) { size_t len; u_int16_t i, cpu; if (worker_count == 0) worker_count = 1; len = sizeof(*accept_lock) + (sizeof(struct kore_worker) * worker_count); shm_accept_key = shmget(IPC_PRIVATE, len, IPC_CREAT | IPC_EXCL | 0700); if (shm_accept_key == -1) fatal("kore_worker_init(): shmget() %s", errno_s); if ((accept_lock = shmat(shm_accept_key, NULL, 0)) == (void *)-1) fatal("kore_worker_init(): shmat() %s", errno_s); accept_lock->lock = 0; accept_lock->current = 0; kore_workers = (struct kore_worker *)((u_int8_t *)accept_lock + sizeof(*accept_lock)); memset(kore_workers, 0, sizeof(struct kore_worker) * worker_count); kore_debug("kore_worker_init(): system has %d cpu's", cpu_count); kore_debug("kore_worker_init(): starting %d workers", worker_count); if (worker_count > cpu_count) { kore_debug("kore_worker_init(): more workers then cpu's"); } cpu = 0; for (i = 0; i < worker_count; i++) { kore_worker_spawn(i, cpu++); if (cpu == cpu_count) cpu = 0; } } void kore_worker_spawn(u_int16_t id, u_int16_t cpu) { struct kore_worker *kw; kw = WORKER(id); kw->id = id; kw->cpu = cpu; kw->has_lock = 0; kw->active_hdlr = NULL; kw->pid = fork(); if (kw->pid == -1) fatal("could not spawn worker child: %s", errno_s); if (kw->pid == 0) { kw->pid = getpid(); kore_worker_entry(kw); /* NOTREACHED */ } } void kore_worker_shutdown(void) { struct kore_worker *kw; u_int16_t id, done; kore_log(LOG_NOTICE, "waiting for workers to drain and shutdown"); for (;;) { done = 0; for (id = 0; id < worker_count; id++) { kw = WORKER(id); if (kw->pid != 0) kore_worker_wait(1); else done++; } if (done == worker_count) break; } if (shmctl(shm_accept_key, IPC_RMID, NULL) == -1) { kore_log(LOG_NOTICE, "failed to deleted shm segment: %s", errno_s); } } void kore_worker_dispatch_signal(int sig) { u_int16_t id; struct kore_worker *kw; for (id = 0; id < worker_count; id++) { kw = WORKER(id); if (kill(kw->pid, sig) == -1) { kore_debug("kill(%d, %d): %s", kw->pid, sig, errno_s); } } } void kore_worker_entry(struct kore_worker *kw) { size_t fd; struct rlimit rl; char buf[16]; struct connection *c, *cnext; int quit, had_lock, r; u_int64_t now, idle_check, next_lock, netwait; struct passwd *pw = NULL; worker = kw; /* Must happen before chroot. */ if (skip_runas == 0) { pw = getpwnam(runas_user); if (pw == NULL) { fatal("cannot getpwnam(\"%s\") runas user: %s", runas_user, errno_s); } } if (skip_chroot == 0) { if (chroot(chroot_path) == -1) { fatal("cannot chroot(\"%s\"): %s", chroot_path, errno_s); } if (chdir("/") == -1) fatal("cannot chdir(\"/\"): %s", errno_s); } if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { kore_log(LOG_WARNING, "getrlimit(RLIMIT_NOFILE): %s", errno_s); } else { for (fd = 0; fd < rl.rlim_cur; fd++) { if (fcntl(fd, F_GETFD, NULL) != -1) { worker_rlimit_nofiles++; } } } rl.rlim_cur = worker_rlimit_nofiles; rl.rlim_max = worker_rlimit_nofiles; if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { kore_log(LOG_ERR, "setrlimit(RLIMIT_NOFILE, %d): %s", worker_rlimit_nofiles, errno_s); } if (skip_runas == 0) { if (setgroups(1, &pw->pw_gid) || #ifdef __MACH__ setgid(pw->pw_gid) || setegid(pw->pw_gid) || setuid(pw->pw_uid) || seteuid(pw->pw_uid)) #else setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) #endif fatal("cannot drop privileges"); } (void)snprintf(buf, sizeof(buf), "kore [wrk %d]", kw->id); kore_platform_proctitle(buf); if (worker_set_affinity == 1) kore_platform_worker_setcpu(kw); kore_pid = kw->pid; sig_recv = 0; signal(SIGHUP, kore_signal); signal(SIGQUIT, kore_signal); signal(SIGPIPE, SIG_IGN); if (foreground) signal(SIGINT, kore_signal); else signal(SIGINT, SIG_IGN); net_init(); http_init(); kore_timer_init(); kore_connection_init(); kore_domain_load_crl(); TAILQ_INIT(&disconnected); TAILQ_INIT(&worker_clients); quit = 0; had_lock = 0; next_lock = 0; idle_check = 0; kore_platform_event_init(); kore_accesslog_worker_init(); #if defined(KORE_USE_PGSQL) kore_pgsql_init(); #endif #if defined(KORE_USE_TASKS) kore_task_init(); #endif kore_log(LOG_NOTICE, "worker %d started (cpu#%d)", kw->id, kw->cpu); kore_module_onload(); for (;;) { if (sig_recv != 0) { if (sig_recv == SIGHUP) kore_module_reload(1); else if (sig_recv == SIGQUIT || sig_recv == SIGINT) quit = 1; sig_recv = 0; } now = kore_time_ms(); netwait = kore_timer_run(now); if (now > next_lock) { if (kore_worker_acceptlock_obtain()) { if (had_lock == 0) { kore_platform_enable_accept(); had_lock = 1; } } } if (!worker->has_lock) { if (had_lock == 1) { had_lock = 0; kore_platform_disable_accept(); } } r = kore_platform_event_wait(netwait); if (worker->has_lock && r > 0) { kore_worker_acceptlock_release(); next_lock = now + WORKER_LOCK_TIMEOUT; } http_process(); if ((now - idle_check) >= 10000) { idle_check = now; now = kore_time_ms(); TAILQ_FOREACH(c, &worker_clients, list) { if (c->proto == CONN_PROTO_SPDY && c->idle_timer.length == 0 && !(c->flags & CONN_WRITE_BLOCK) && !(c->flags & CONN_READ_BLOCK)) continue; if (!(c->flags & CONN_IDLE_TIMER_ACT)) continue; kore_connection_check_idletimer(now, c); } } for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) { cnext = TAILQ_NEXT(c, list); TAILQ_REMOVE(&disconnected, c, list); kore_connection_remove(c); } if (quit && http_request_count == 0) break; } for (c = TAILQ_FIRST(&worker_clients); c != NULL; c = cnext) { cnext = TAILQ_NEXT(c, list); net_send_flush(c); kore_connection_disconnect(c); } for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) { cnext = TAILQ_NEXT(c, list); net_send_flush(c); TAILQ_REMOVE(&disconnected, c, list); kore_connection_remove(c); } kore_debug("worker %d shutting down", kw->id); exit(0); } void kore_worker_connection_add(struct connection *c) { TAILQ_INSERT_TAIL(&worker_clients, c, list); worker_active_connections++; } void kore_worker_connection_move(struct connection *c) { TAILQ_REMOVE(&worker_clients, c, list); TAILQ_INSERT_TAIL(&disconnected, c, list); } void kore_worker_connection_remove(struct connection *c) { worker_active_connections--; } void kore_worker_websocket_broadcast(struct connection *src, void (*cb)(struct connection *, void *), void *args) { struct connection *c; TAILQ_FOREACH(c, &worker_clients, list) { if (c != src && c->proto == CONN_PROTO_WEBSOCKET) cb(c, args); } } void kore_worker_wait(int final) { u_int16_t id; pid_t pid; struct kore_worker *kw; int status; if (final) pid = waitpid(WAIT_ANY, &status, 0); else pid = waitpid(WAIT_ANY, &status, WNOHANG); if (pid == -1) { kore_debug("waitpid(): %s", errno_s); return; } if (pid == 0) return; for (id = 0; id < worker_count; id++) { kw = WORKER(id); if (kw->pid != pid) continue; kore_log(LOG_NOTICE, "worker %d (%d)-> status %d", kw->id, pid, status); if (final) { kw->pid = 0; break; } if (WEXITSTATUS(status) || WTERMSIG(status) || WCOREDUMP(status)) { kore_log(LOG_NOTICE, "worker %d (pid: %d) (hdlr: %s) gone", kw->id, kw->pid, (kw->active_hdlr != NULL) ? kw->active_hdlr->func : "none"); if (kw->pid == accept_lock->current) worker_unlock(); if (kw->active_hdlr != NULL) { kw->active_hdlr->errors++; kore_log(LOG_NOTICE, "hdlr %s has caused %d error(s)", kw->active_hdlr->func, kw->active_hdlr->errors); } kore_log(LOG_NOTICE, "restarting worker %d", kw->id); kore_worker_spawn(kw->id, kw->cpu); } else { kore_log(LOG_NOTICE, "worker %d (pid: %d) signaled us (%d)", kw->id, kw->pid, status); } break; } } static inline void kore_worker_acceptlock_release(void) { if (worker_count == 1) return; if (worker->has_lock != 1) return; worker_unlock(); worker->has_lock = 0; } static inline int kore_worker_acceptlock_obtain(void) { int r; if (worker->has_lock == 1) return (1); if (worker_count == 1) { worker->has_lock = 1; return (1); } if (worker_active_connections >= worker_max_connections) return (0); r = 0; if (worker_trylock()) { r = 1; worker->has_lock = 1; } return (r); } static int worker_trylock(void) { if (!__sync_bool_compare_and_swap(&(accept_lock->lock), 0, 1)) return (0); worker_debug("wrk#%d grabbed lock (%d/%d)\n", worker->id, worker_active_connections, worker_max_connections); accept_lock->current = worker->pid; return (1); } static void worker_unlock(void) { accept_lock->current = 0; if (!__sync_bool_compare_and_swap(&(accept_lock->lock), 1, 0)) kore_log(LOG_NOTICE, "worker_unlock(): wasnt locked"); } kore/src/kore.c0000644000175000001440000002031512527355514012770 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "kore.h" volatile sig_atomic_t sig_recv; struct listener_head listeners; u_int8_t nlisteners; pid_t kore_pid = -1; u_int16_t cpu_count = 1; int foreground = 0; int kore_debug = 0; u_int8_t worker_count = 0; int skip_chroot = 0; char *chroot_path = NULL; int skip_runas = 0; char *runas_user = NULL; u_int32_t kore_socket_backlog = 5000; char *kore_pidfile = KORE_PIDFILE_DEFAULT; char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST; static void usage(void); static void version(void); static void kore_server_start(void); static void kore_write_kore_pid(void); static void kore_server_sslstart(void); static void usage(void) { fprintf(stderr, "Usage: kore [options | command]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Available options:\n"); fprintf(stderr, "\t-c\tspecify the configuration file to use\n"); fprintf(stderr, "\t-d\trun with debug on (if compiled in)\n"); fprintf(stderr, "\t-f\tstart kore in foreground mode\n"); fprintf(stderr, "\t-h\tthis help text\n"); fprintf(stderr, "\t-n\tdo not chroot (if not starting kore as root)\n"); fprintf(stderr, "\t-r\tdo not runas (uid drop) (if not starting kore as root)\n"); fprintf(stderr, "\t-v\tdisplay kore's version information\n"); kore_cli_usage(0); } static void version(void) { printf("kore %d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE); #if defined(KORE_USE_PGSQL) printf("pgsql "); #endif #if defined(KORE_USE_TASKS) printf("tasks "); #endif printf("\n"); exit(0); } int main(int argc, char *argv[]) { struct listener *l; int ch, flags; flags = 0; while ((ch = getopt(argc, argv, "c:dfhnrv")) != -1) { flags++; switch (ch) { case 'c': config_file = optarg; break; case 'd': #if defined(KORE_DEBUG) kore_debug = 1; #else printf("kore not compiled with debug support\n"); #endif break; case 'f': foreground = 1; break; case 'h': usage(); break; case 'n': skip_chroot = 1; break; case 'r': skip_runas = 1; break; case 'v': version(); break; default: usage(); } } argc -= optind; argv += optind; kore_mem_init(); if (argc > 0) { if (flags) fatal("You cannot specify kore flags and a command"); return (kore_cli_main(argc, argv)); } kore_pid = getpid(); nlisteners = 0; LIST_INIT(&listeners); kore_log_init(); kore_auth_init(); kore_domain_init(); kore_module_init(); kore_validator_init(); kore_server_sslstart(); if (config_file == NULL) usage(); kore_parse_config(); kore_platform_init(); kore_accesslog_init(); sig_recv = 0; signal(SIGHUP, kore_signal); signal(SIGQUIT, kore_signal); if (foreground) signal(SIGINT, kore_signal); else signal(SIGINT, SIG_IGN); kore_server_start(); kore_log(LOG_NOTICE, "server shutting down"); kore_worker_shutdown(); if (!foreground) unlink(kore_pidfile); LIST_FOREACH(l, &listeners, list) close(l->fd); kore_log(LOG_NOTICE, "goodbye"); return (0); } #if !defined(KORE_BENCHMARK) int kore_tls_npn_cb(SSL *ssl, const u_char **data, unsigned int *len, void *arg) { kore_debug("kore_tls_npn_cb(): sending protocols"); *data = (const unsigned char *)KORE_SSL_PROTO_STRING; *len = strlen(KORE_SSL_PROTO_STRING); return (SSL_TLSEXT_ERR_OK); } int kore_tls_sni_cb(SSL *ssl, int *ad, void *arg) { struct kore_domain *dom; const char *sname; sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); kore_debug("kore_tls_sni_cb(): received host %s", sname); if (sname != NULL && (dom = kore_domain_lookup(sname)) != NULL) { kore_debug("kore_ssl_sni_cb(): Using %s CTX", sname); SSL_set_SSL_CTX(ssl, dom->ssl_ctx); if (dom->cafile != NULL) { SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); } else { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } return (SSL_TLSEXT_ERR_OK); } return (SSL_TLSEXT_ERR_NOACK); } void kore_tls_info_callback(const SSL *ssl, int flags, int ret) { struct connection *c; if (flags & SSL_CB_HANDSHAKE_START) { if ((c = SSL_get_app_data(ssl)) == NULL) fatal("no SSL_get_app_data"); c->tls_reneg++; } } #endif int kore_server_bind(const char *ip, const char *port) { struct listener *l; int on, r; struct addrinfo *results; kore_debug("kore_server_bind(%s, %s)", ip, port); r = getaddrinfo(ip, port, NULL, &results); if (r != 0) fatal("getaddrinfo(%s): %s", ip, gai_strerror(r)); l = kore_malloc(sizeof(struct listener)); l->type = KORE_TYPE_LISTENER; l->addrtype = results->ai_family; if (l->addrtype != AF_INET && l->addrtype != AF_INET6) fatal("getaddrinfo(): unknown address family %d", l->addrtype); if ((l->fd = socket(results->ai_family, SOCK_STREAM, 0)) == -1) { kore_mem_free(l); freeaddrinfo(results); kore_debug("socket(): %s", errno_s); printf("failed to create socket: %s\n", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(l->fd)) { kore_mem_free(l); freeaddrinfo(results); printf("failed to make socket non blocking: %s\n", errno_s); return (KORE_RESULT_ERROR); } on = 1; if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) == -1) { close(l->fd); kore_mem_free(l); freeaddrinfo(results); kore_debug("setsockopt(): %s", errno_s); printf("failed to set SO_REUSEADDR: %s\n", errno_s); return (KORE_RESULT_ERROR); } if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) { close(l->fd); kore_mem_free(l); freeaddrinfo(results); kore_debug("bind(): %s", errno_s); printf("failed to bind to %s port %s: %s\n", ip, port, errno_s); return (KORE_RESULT_ERROR); } freeaddrinfo(results); if (listen(l->fd, kore_socket_backlog) == -1) { close(l->fd); kore_mem_free(l); kore_debug("listen(): %s", errno_s); printf("failed to listen on socket: %s\n", errno_s); return (KORE_RESULT_ERROR); } nlisteners++; LIST_INSERT_HEAD(&listeners, l, list); if (foreground) kore_log(LOG_NOTICE, "running on https://%s:%s", ip, port); return (KORE_RESULT_OK); } void kore_signal(int sig) { sig_recv = sig; } static void kore_server_sslstart(void) { #if !defined(KORE_BENCHMARK) kore_debug("kore_server_sslstart()"); SSL_library_init(); SSL_load_error_strings(); #endif } static void kore_server_start(void) { int quit; if (foreground == 0 && daemon(1, 1) == -1) fatal("cannot daemon(): %s", errno_s); kore_pid = getpid(); if (!foreground) kore_write_kore_pid(); kore_log(LOG_NOTICE, "kore is starting up"); #if defined(KORE_USE_PGSQL) kore_log(LOG_NOTICE, "pgsql built-in enabled"); #endif #if defined(KORE_USE_TASKS) kore_log(LOG_NOTICE, "tasks built-in enabled"); #endif kore_platform_proctitle("kore [parent]"); kore_worker_init(); quit = 0; while (quit != 1) { if (sig_recv != 0) { switch (sig_recv) { case SIGHUP: kore_worker_dispatch_signal(sig_recv); kore_module_reload(0); break; case SIGINT: case SIGQUIT: quit = 1; kore_worker_dispatch_signal(sig_recv); continue; default: kore_log(LOG_NOTICE, "no action taken for signal %d", sig_recv); break; } sig_recv = 0; } if (!kore_accesslog_wait()) break; kore_worker_wait(0); } } static void kore_write_kore_pid(void) { FILE *fp; if ((fp = fopen(kore_pidfile, "w+")) == NULL) { printf("warning: couldn't write pid to %s (%s)\n", kore_pidfile, errno_s); } else { fprintf(fp, "%d\n", kore_pid); fclose(fp); } } kore/src/pgsql.c0000644000175000001440000002527612527355514013171 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include "kore.h" #include "http.h" #include "pgsql.h" struct pgsql_job { char *query; struct http_request *req; struct kore_pgsql *pgsql; TAILQ_ENTRY(pgsql_job) list; }; struct pgsql_wait { struct http_request *req; TAILQ_ENTRY(pgsql_wait) list; }; #define PGSQL_IS_BLOCKING 0 #define PGSQL_IS_ASYNC 1 #define PGSQL_CONN_MAX 2 #define PGSQL_CONN_FREE 0x01 static void pgsql_queue_wakeup(void); static int pgsql_conn_create(struct kore_pgsql *); static void pgsql_queue_add(struct http_request *); static void pgsql_conn_release(struct kore_pgsql *); static void pgsql_conn_cleanup(struct pgsql_conn *); static void pgsql_read_result(struct kore_pgsql *, int); static void pgsql_schedule(struct kore_pgsql *, struct http_request *); static int pgsql_prepare(struct kore_pgsql *, struct http_request *, const char *); static struct kore_pool pgsql_job_pool; static struct kore_pool pgsql_wait_pool; static TAILQ_HEAD(, pgsql_conn) pgsql_conn_free; static TAILQ_HEAD(, pgsql_wait) pgsql_wait_queue; static u_int16_t pgsql_conn_count; char *pgsql_conn_string = NULL; u_int16_t pgsql_conn_max = PGSQL_CONN_MAX; void kore_pgsql_init(void) { pgsql_conn_count = 0; TAILQ_INIT(&pgsql_conn_free); TAILQ_INIT(&pgsql_wait_queue); kore_pool_init(&pgsql_job_pool, "pgsql_job_pool", sizeof(struct pgsql_job), 100); kore_pool_init(&pgsql_wait_pool, "pgsql_wait_pool", sizeof(struct pgsql_wait), 100); } int kore_pgsql_query(struct kore_pgsql *pgsql, struct http_request *req, const char *query) { if (!pgsql_prepare(pgsql, req, query)) return (KORE_RESULT_ERROR); if (!PQsendQuery(pgsql->conn->db, query)) { pgsql_conn_cleanup(pgsql->conn); return (KORE_RESULT_ERROR); } pgsql_schedule(pgsql, req); return (KORE_RESULT_OK); } int kore_pgsql_query_params(struct kore_pgsql *pgsql, struct http_request *req, const char *query, int result, u_int8_t count, ...) { u_int8_t i; va_list args; char **values; int *lengths, *formats; if (!pgsql_prepare(pgsql, req, query)) return (KORE_RESULT_ERROR); if (count > 0) { va_start(args, count); lengths = kore_calloc(count, sizeof(int)); formats = kore_calloc(count, sizeof(int)); values = kore_calloc(count, sizeof(char *)); for (i = 0; i < count; i++) { values[i] = va_arg(args, void *); lengths[i] = va_arg(args, u_int32_t); formats[i] = va_arg(args, int); } } else { lengths = NULL; formats = NULL; values = NULL; } if (!PQsendQueryParams(pgsql->conn->db, query, count, NULL, (const char * const *)values, lengths, formats, result)) { kore_mem_free(values); kore_mem_free(lengths); kore_mem_free(formats); pgsql_conn_cleanup(pgsql->conn); return (KORE_RESULT_ERROR); } kore_mem_free(values); kore_mem_free(lengths); kore_mem_free(formats); pgsql_schedule(pgsql, req); return (KORE_RESULT_OK); } void kore_pgsql_handle(void *c, int err) { struct http_request *req; struct kore_pgsql *pgsql; struct pgsql_conn *conn = (struct pgsql_conn *)c; if (err) { pgsql_conn_cleanup(conn); return; } req = conn->job->req; pgsql = conn->job->pgsql; kore_debug("kore_pgsql_handle: %p (%d)", req, pgsql->state); if (!PQconsumeInput(conn->db)) { pgsql->state = KORE_PGSQL_STATE_ERROR; pgsql->error = kore_strdup(PQerrorMessage(conn->db)); } else { pgsql_read_result(pgsql, PGSQL_IS_ASYNC); } if (pgsql->state == KORE_PGSQL_STATE_WAIT) { http_request_sleep(req); } else { http_request_wakeup(req); } } void kore_pgsql_continue(struct http_request *req, struct kore_pgsql *pgsql) { kore_debug("kore_pgsql_continue: %p->%p (%d)", req->owner, req, pgsql->state); if (pgsql->error) { kore_mem_free(pgsql->error); pgsql->error = NULL; } if (pgsql->result) { PQclear(pgsql->result); pgsql->result = NULL; } switch (pgsql->state) { case KORE_PGSQL_STATE_INIT: case KORE_PGSQL_STATE_WAIT: break; case KORE_PGSQL_STATE_DONE: http_request_wakeup(req); pgsql_conn_release(pgsql); break; case KORE_PGSQL_STATE_ERROR: case KORE_PGSQL_STATE_RESULT: kore_pgsql_handle(pgsql->conn, 0); break; default: fatal("unknown pgsql state %d", pgsql->state); } } void kore_pgsql_cleanup(struct kore_pgsql *pgsql) { kore_debug("kore_pgsql_cleanup(%p)", pgsql); if (pgsql->result != NULL) PQclear(pgsql->result); if (pgsql->error != NULL) kore_mem_free(pgsql->error); if (pgsql->conn != NULL) pgsql_conn_release(pgsql); pgsql->result = NULL; pgsql->error = NULL; pgsql->conn = NULL; LIST_REMOVE(pgsql, rlist); } void kore_pgsql_logerror(struct kore_pgsql *pgsql) { kore_log(LOG_NOTICE, "pgsql error: %s", (pgsql->error) ? pgsql->error : "unknown"); } int kore_pgsql_ntuples(struct kore_pgsql *pgsql) { return (PQntuples(pgsql->result)); } int kore_pgsql_getlength(struct kore_pgsql *pgsql, int row, int col) { return (PQgetlength(pgsql->result, row, col)); } char * kore_pgsql_getvalue(struct kore_pgsql *pgsql, int row, int col) { return (PQgetvalue(pgsql->result, row, col)); } void kore_pgsql_queue_remove(struct http_request *req) { struct pgsql_wait *pgw, *next; for (pgw = TAILQ_FIRST(&pgsql_wait_queue); pgw != NULL; pgw = next) { next = TAILQ_NEXT(pgw, list); if (pgw->req != req) continue; TAILQ_REMOVE(&pgsql_wait_queue, pgw, list); kore_pool_put(&pgsql_wait_pool, pgw); return; } } static int pgsql_prepare(struct kore_pgsql *pgsql, struct http_request *req, const char *query) { struct pgsql_conn *conn; pgsql->state = KORE_PGSQL_STATE_INIT; pgsql->result = NULL; pgsql->error = NULL; pgsql->conn = NULL; if (TAILQ_EMPTY(&pgsql_conn_free)) { if (pgsql_conn_count >= pgsql_conn_max) { pgsql_queue_add(req); return (KORE_RESULT_ERROR); } if (!pgsql_conn_create(pgsql)) return (KORE_RESULT_ERROR); } http_request_sleep(req); conn = TAILQ_FIRST(&pgsql_conn_free); if (!(conn->flags & PGSQL_CONN_FREE)) fatal("received a pgsql conn that was not free?"); conn->flags &= ~PGSQL_CONN_FREE; TAILQ_REMOVE(&pgsql_conn_free, conn, list); pgsql->conn = conn; conn->job = kore_pool_get(&pgsql_job_pool); conn->job->query = kore_strdup(query); conn->job->pgsql = pgsql; conn->job->req = req; LIST_INSERT_HEAD(&(req->pgsqls), pgsql, rlist); return (KORE_RESULT_OK); } static void pgsql_schedule(struct kore_pgsql *pgsql, struct http_request *req) { int fd; fd = PQsocket(pgsql->conn->db); if (fd < 0) fatal("PQsocket returned < 0 fd on open connection"); kore_platform_schedule_read(fd, pgsql->conn); pgsql->state = KORE_PGSQL_STATE_WAIT; } static void pgsql_queue_add(struct http_request *req) { struct pgsql_wait *pgw; http_request_sleep(req); pgw = kore_pool_get(&pgsql_wait_pool); pgw->req = req; pgw->req->flags |= HTTP_REQUEST_PGSQL_QUEUE; TAILQ_INSERT_TAIL(&pgsql_wait_queue, pgw, list); } static void pgsql_queue_wakeup(void) { struct pgsql_wait *pgw, *next; for (pgw = TAILQ_FIRST(&pgsql_wait_queue); pgw != NULL; pgw = next) { next = TAILQ_NEXT(pgw, list); if (pgw->req->flags & HTTP_REQUEST_DELETE) continue; http_request_wakeup(pgw->req); pgw->req->flags &= ~HTTP_REQUEST_PGSQL_QUEUE; TAILQ_REMOVE(&pgsql_wait_queue, pgw, list); kore_pool_put(&pgsql_wait_pool, pgw); return; } } static int pgsql_conn_create(struct kore_pgsql *pgsql) { struct pgsql_conn *conn; if (pgsql_conn_string == NULL) fatal("pgsql_conn_create: no connection string"); pgsql_conn_count++; conn = kore_malloc(sizeof(*conn)); kore_debug("pgsql_conn_create(): %p", conn); memset(conn, 0, sizeof(*conn)); conn->db = PQconnectdb(pgsql_conn_string); if (conn->db == NULL || (PQstatus(conn->db) != CONNECTION_OK)) { pgsql->state = KORE_PGSQL_STATE_ERROR; pgsql->error = kore_strdup(PQerrorMessage(conn->db)); pgsql_conn_cleanup(conn); return (KORE_RESULT_ERROR); } conn->job = NULL; conn->flags = PGSQL_CONN_FREE; conn->type = KORE_TYPE_PGSQL_CONN; TAILQ_INSERT_TAIL(&pgsql_conn_free, conn, list); return (KORE_RESULT_OK); } static void pgsql_conn_release(struct kore_pgsql *pgsql) { int fd; if (pgsql->conn == NULL) return; kore_mem_free(pgsql->conn->job->query); kore_pool_put(&pgsql_job_pool, pgsql->conn->job); /* Drain just in case. */ while (PQgetResult(pgsql->conn->db) != NULL) ; pgsql->conn->job = NULL; pgsql->conn->flags |= PGSQL_CONN_FREE; TAILQ_INSERT_TAIL(&pgsql_conn_free, pgsql->conn, list); fd = PQsocket(pgsql->conn->db); kore_platform_disable_read(fd); pgsql->conn = NULL; pgsql->state = KORE_PGSQL_STATE_COMPLETE; pgsql_queue_wakeup(); } static void pgsql_conn_cleanup(struct pgsql_conn *conn) { struct http_request *req; struct kore_pgsql *pgsql; kore_debug("pgsql_conn_cleanup(): %p", conn); if (conn->flags & PGSQL_CONN_FREE) TAILQ_REMOVE(&pgsql_conn_free, conn, list); if (conn->job) { req = conn->job->req; pgsql = conn->job->pgsql; http_request_wakeup(req); pgsql->conn = NULL; pgsql->state = KORE_PGSQL_STATE_ERROR; pgsql->error = kore_strdup(PQerrorMessage(conn->db)); kore_mem_free(conn->job->query); kore_pool_put(&pgsql_job_pool, conn->job); conn->job = NULL; } if (conn->db != NULL) PQfinish(conn->db); pgsql_conn_count--; kore_mem_free(conn); } static void pgsql_read_result(struct kore_pgsql *pgsql, int async) { if (async) { if (PQisBusy(pgsql->conn->db)) { pgsql->state = KORE_PGSQL_STATE_WAIT; return; } } pgsql->result = PQgetResult(pgsql->conn->db); if (pgsql->result == NULL) { pgsql->state = KORE_PGSQL_STATE_DONE; return; } switch (PQresultStatus(pgsql->result)) { case PGRES_COPY_OUT: case PGRES_COPY_IN: case PGRES_NONFATAL_ERROR: case PGRES_COPY_BOTH: break; case PGRES_COMMAND_OK: pgsql->state = KORE_PGSQL_STATE_DONE; break; case PGRES_TUPLES_OK: #if PG_VERSION_NUM >= 90200 case PGRES_SINGLE_TUPLE: #endif pgsql->state = KORE_PGSQL_STATE_RESULT; break; case PGRES_EMPTY_QUERY: case PGRES_BAD_RESPONSE: case PGRES_FATAL_ERROR: pgsql->state = KORE_PGSQL_STATE_ERROR; pgsql->error = kore_strdup(PQresultErrorMessage(pgsql->result)); break; } } kore/src/validator.c0000644000175000001440000000600212527355514014012 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "kore.h" TAILQ_HEAD(, kore_validator) validators; void kore_validator_init(void) { TAILQ_INIT(&validators); } int kore_validator_add(const char *name, u_int8_t type, const char *arg) { struct kore_validator *val; val = kore_malloc(sizeof(*val)); val->type = type; switch (val->type) { case KORE_VALIDATOR_TYPE_REGEX: if (regcomp(&(val->rctx), arg, REG_EXTENDED | REG_NOSUB)) { kore_mem_free(val); kore_log(LOG_NOTICE, "validator %s has bad regex %s", name, arg); return (KORE_RESULT_ERROR); } break; case KORE_VALIDATOR_TYPE_FUNCTION: if ((val->func = kore_module_getsym(arg)) == NULL) { kore_mem_free(val); kore_log(LOG_NOTICE, "validator %s has undefined callback %s", name, arg); return (KORE_RESULT_ERROR); } break; default: kore_mem_free(val); return (KORE_RESULT_ERROR); } val->arg = kore_strdup(arg); val->name = kore_strdup(name); TAILQ_INSERT_TAIL(&validators, val, list); return (KORE_RESULT_OK); } int kore_validator_run(struct http_request *req, const char *name, char *data) { struct kore_validator *val; TAILQ_FOREACH(val, &validators, list) { if (strcmp(val->name, name)) continue; return (kore_validator_check(req, val, data)); } return (KORE_RESULT_ERROR); } int kore_validator_check(struct http_request *req, struct kore_validator *val, void *data) { int r; switch (val->type) { case KORE_VALIDATOR_TYPE_REGEX: if (!regexec(&(val->rctx), data, 0, NULL, 0)) r = KORE_RESULT_OK; else r = KORE_RESULT_ERROR; break; case KORE_VALIDATOR_TYPE_FUNCTION: r = val->func(req, data); break; default: r = KORE_RESULT_ERROR; kore_log(LOG_NOTICE, "invalid type %d for validator %s", val->type, val->name); break; } return (r); } void kore_validator_reload(void) { struct kore_validator *val; TAILQ_FOREACH(val, &validators, list) { if (val->type != KORE_VALIDATOR_TYPE_FUNCTION) continue; if ((val->func = kore_module_getsym(val->arg)) == NULL) fatal("no function for validator %s found", val->name); } } struct kore_validator * kore_validator_lookup(const char *name) { struct kore_validator *val; TAILQ_FOREACH(val, &validators, list) { if (!strcmp(val->name, name)) return (val); } return (NULL); } kore/src/tasks.c0000644000175000001440000001633512527355514013164 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include "kore.h" #include "http.h" #include "tasks.h" static u_int8_t threads; static pthread_mutex_t task_thread_lock; static TAILQ_HEAD(, kore_task_thread) task_threads; static void *task_thread(void *); static void task_channel_read(int, void *, u_int32_t); static void task_channel_write(int, void *, u_int32_t); static void task_thread_spawn(struct kore_task_thread **); #define THREAD_FD_ASSIGN(t, f, i, o) \ do { \ if (pthread_self() == t) { \ f = i; \ } else { \ f = o; \ } \ } while (0); void kore_task_init(void) { int r; threads = 0; TAILQ_INIT(&task_threads); if ((r = pthread_mutex_init(&task_thread_lock, NULL)) != 0) fatal("kore_task_init: pthread_mutex_init: %d", r); } void kore_task_create(struct kore_task *t, int (*entry)(struct kore_task *)) { t->req = NULL; t->entry = entry; t->type = KORE_TYPE_TASK; t->state = KORE_TASK_STATE_CREATED; pthread_rwlock_init(&(t->lock), NULL); if (socketpair(AF_UNIX, SOCK_STREAM, 0, t->fds) == -1) fatal("kore_task_create: socketpair() %s", errno_s); } void kore_task_run(struct kore_task *t) { struct kore_task_thread *tt; kore_platform_schedule_read(t->fds[0], t); pthread_mutex_lock(&task_thread_lock); if (TAILQ_EMPTY(&task_threads)) task_thread_spawn(&tt); else tt = TAILQ_FIRST(&task_threads); pthread_mutex_unlock(&task_thread_lock); pthread_mutex_lock(&(tt->lock)); t->thread = tt; TAILQ_INSERT_TAIL(&(tt->tasks), t, list); pthread_mutex_unlock(&(tt->lock)); pthread_cond_signal(&(tt->cond)); } void kore_task_bind_request(struct kore_task *t, struct http_request *req) { kore_debug("kore_task_bind_request: %p bound to %p", req, t); t->req = req; LIST_INSERT_HEAD(&(req->tasks), t, rlist); http_request_sleep(req); } void kore_task_destroy(struct kore_task *t) { kore_debug("kore_task_destroy: %p", t); if (t->req != NULL) { t->req = NULL; LIST_REMOVE(t, rlist); } pthread_rwlock_wrlock(&(t->lock)); if (t->fds[0] != -1) { (void)close(t->fds[0]); t->fds[0] = -1; } if (t->fds[1] != -1) { (void)close(t->fds[1]); t->fds[1] = -1; } pthread_rwlock_unlock(&(t->lock)); pthread_rwlock_destroy(&(t->lock)); } int kore_task_finished(struct kore_task *t) { return ((kore_task_state(t) == KORE_TASK_STATE_FINISHED)); } void kore_task_finish(struct kore_task *t) { kore_debug("kore_task_finished: %p (%d)", t, t->result); pthread_rwlock_wrlock(&(t->lock)); if (t->fds[1] != -1) { (void)close(t->fds[1]); t->fds[1] = -1; } pthread_rwlock_unlock(&(t->lock)); } void kore_task_channel_write(struct kore_task *t, void *data, u_int32_t len) { int fd; kore_debug("kore_task_channel_write: %p <- %p (%ld)", t, data, len); THREAD_FD_ASSIGN(t->thread->tid, fd, t->fds[1], t->fds[0]); task_channel_write(fd, &len, sizeof(len)); task_channel_write(fd, data, len); } u_int32_t kore_task_channel_read(struct kore_task *t, void *out, u_int32_t len) { int fd; u_int32_t dlen, bytes; kore_debug("kore_task_channel_read: %p -> %p (%ld)", t, out, len); THREAD_FD_ASSIGN(t->thread->tid, fd, t->fds[1], t->fds[0]); task_channel_read(fd, &dlen, sizeof(dlen)); if (dlen > len) bytes = len; else bytes = dlen; task_channel_read(fd, out, bytes); return (dlen); } void kore_task_handle(struct kore_task *t, int finished) { kore_debug("kore_task_handle: %p, %d", t, finished); if (t->req != NULL) http_request_wakeup(t->req); if (finished) { kore_platform_disable_read(t->fds[0]); kore_task_set_state(t, KORE_TASK_STATE_FINISHED); if (t->req != NULL) { if (t->req->flags & HTTP_REQUEST_DELETE) kore_task_destroy(t); } } } int kore_task_state(struct kore_task *t) { int s; pthread_rwlock_rdlock(&(t->lock)); s = t->state; pthread_rwlock_unlock(&(t->lock)); return (s); } void kore_task_set_state(struct kore_task *t, int state) { pthread_rwlock_wrlock(&(t->lock)); t->state = state; pthread_rwlock_unlock(&(t->lock)); } int kore_task_result(struct kore_task *t) { int r; pthread_rwlock_rdlock(&(t->lock)); r = t->result; pthread_rwlock_unlock(&(t->lock)); return (r); } void kore_task_set_result(struct kore_task *t, int result) { pthread_rwlock_wrlock(&(t->lock)); t->result = result; pthread_rwlock_unlock(&(t->lock)); } static void task_channel_write(int fd, void *data, u_int32_t len) { ssize_t r; u_int8_t *d; u_int32_t offset; d = data; offset = 0; while (offset != len) { r = write(fd, d + offset, len - offset); if (r == -1 && errno == EINTR) continue; if (r == -1) fatal("task_channel_write: %s", errno_s); offset += r; } } static void task_channel_read(int fd, void *out, u_int32_t len) { ssize_t r; u_int8_t *d; u_int32_t offset; d = out; offset = 0; while (offset != len) { r = read(fd, d + offset, len - offset); if (r == -1 && errno == EINTR) continue; if (r == -1) fatal("task_channel_read: %s", errno_s); if (r == 0) fatal("task_channel_read: unexpected eof"); offset += r; } } static void task_thread_spawn(struct kore_task_thread **out) { struct kore_task_thread *tt; tt = kore_malloc(sizeof(*tt)); tt->idx = threads++; TAILQ_INIT(&(tt->tasks)); pthread_cond_init(&(tt->cond), NULL); pthread_mutex_init(&(tt->lock), NULL); if (pthread_create(&(tt->tid), NULL, task_thread, tt) != 0) fatal("pthread_create: %s", errno_s); *out = tt; } static void * task_thread(void *arg) { struct kore_task *t; struct kore_task_thread *tt = arg; kore_debug("task_thread: #%d starting", tt->idx); pthread_mutex_lock(&(tt->lock)); pthread_mutex_lock(&task_thread_lock); TAILQ_INSERT_TAIL(&task_threads, tt, list); pthread_mutex_unlock(&task_thread_lock); for (;;) { if (TAILQ_EMPTY(&(tt->tasks))) pthread_cond_wait(&(tt->cond), &(tt->lock)); kore_debug("task_thread#%d: woke up", tt->idx); t = TAILQ_FIRST(&(tt->tasks)); TAILQ_REMOVE(&(tt->tasks), t, list); pthread_mutex_unlock(&(tt->lock)); pthread_mutex_lock(&task_thread_lock); TAILQ_REMOVE(&task_threads, tt, list); pthread_mutex_unlock(&task_thread_lock); kore_debug("task_thread#%d: executing %p", tt->idx, t); kore_task_set_state(t, KORE_TASK_STATE_RUNNING); kore_task_set_result(t, t->entry(t)); kore_task_finish(t); pthread_mutex_lock(&task_thread_lock); TAILQ_INSERT_HEAD(&task_threads, tt, list); pthread_mutex_unlock(&task_thread_lock); pthread_mutex_lock(&(tt->lock)); } pthread_exit(NULL); /* NOTREACHED */ return (NULL); } kore/src/auth.c0000644000175000001440000000771512527355514013002 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "kore.h" #include "http.h" TAILQ_HEAD(, kore_auth) auth_list; static int kore_auth_cookie(struct http_request *, struct kore_auth *); static int kore_auth_header(struct http_request *, struct kore_auth *); static int kore_auth_request(struct http_request *, struct kore_auth *); void kore_auth_init(void) { TAILQ_INIT(&auth_list); } int kore_auth_new(const char *name) { struct kore_auth *auth; if ((auth = kore_auth_lookup(name)) != NULL) return (KORE_RESULT_ERROR); auth = kore_malloc(sizeof(*auth)); auth->type = 0; auth->value = NULL; auth->redirect = NULL; auth->validator = NULL; auth->name = kore_strdup(name); TAILQ_INSERT_TAIL(&auth_list, auth, list); return (KORE_RESULT_OK); } int kore_auth_run(struct http_request *req, struct kore_auth *auth) { int r; kore_debug("kore_auth(%p, %p)", req, auth); switch (auth->type) { case KORE_AUTH_TYPE_COOKIE: r = kore_auth_cookie(req, auth); break; case KORE_AUTH_TYPE_HEADER: r = kore_auth_header(req, auth); break; case KORE_AUTH_TYPE_REQUEST: r = kore_auth_request(req, auth); break; default: kore_log(LOG_NOTICE, "unknown auth type %d", auth->type); return (KORE_RESULT_ERROR); } switch (r) { case KORE_RESULT_OK: kore_debug("kore_auth_run() for %s successful", req->path); /* FALLTHROUGH */ case KORE_RESULT_RETRY: return (r); default: break; } /* Authentication types of "request" send their own HTTP responses. */ if (auth->type == KORE_AUTH_TYPE_REQUEST) return (r); kore_debug("kore_auth_run() for %s failed", req->path); if (auth->redirect == NULL) { http_response(req, 403, NULL, 0); return (KORE_RESULT_ERROR); } http_response_header(req, "location", auth->redirect); http_response(req, 302, NULL, 0); return (KORE_RESULT_ERROR); } static int kore_auth_cookie(struct http_request *req, struct kore_auth *auth) { int i, v; size_t len, slen; char *value, *c, *cookie, *cookies[HTTP_MAX_COOKIES]; if (!http_request_header(req, "cookie", &cookie)) return (KORE_RESULT_ERROR); slen = strlen(auth->value); v = kore_split_string(cookie, ";", cookies, HTTP_MAX_COOKIES); for (i = 0; i < v; i++) { for (c = cookies[i]; isspace(*c); c++) ; len = MIN(slen, strlen(cookies[i])); if (!strncmp(c, auth->value, len)) break; } if (i == v) { kore_mem_free(cookie); return (KORE_RESULT_ERROR); } c = cookies[i]; if ((value = strchr(c, '=')) == NULL) { kore_mem_free(cookie); return (KORE_RESULT_ERROR); } i = kore_validator_check(req, auth->validator, ++value); kore_mem_free(cookie); return (i); } static int kore_auth_header(struct http_request *req, struct kore_auth *auth) { int r; char *header; if (!http_request_header(req, auth->value, &header)) return (KORE_RESULT_ERROR); r = kore_validator_check(req, auth->validator, header); kore_mem_free(header); return (r); } static int kore_auth_request(struct http_request *req, struct kore_auth *auth) { return (kore_validator_check(req, auth->validator, req)); } struct kore_auth * kore_auth_lookup(const char *name) { struct kore_auth *auth; TAILQ_FOREACH(auth, &auth_list, list) { if (!strcmp(auth->name, name)) return (auth); } return (NULL); } kore/src/bsd.c0000644000175000001440000001312312527355514012577 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #if defined(__FreeBSD_version) #include #endif #include "kore.h" #if defined(KORE_USE_PGSQL) #include "pgsql.h" #endif #if defined(KORE_USE_TASKS) #include "tasks.h" #endif static int kfd = -1; static struct kevent *events; static u_int32_t event_count = 0; void kore_platform_init(void) { #if defined(__MACH__) || defined(__FreeBSD_version) long n; size_t len = sizeof(n); int mib[] = { CTL_HW, HW_NCPU }; if (sysctl(mib, 2, &n, &len, NULL, 0) == -1) { kore_debug("kore_platform_init(): sysctl %s", errno_s); cpu_count = 1; } else { cpu_count = (u_int16_t)n; } #else cpu_count = 0; #endif /* __MACH__ || __FreeBSD_version */ } void kore_platform_worker_setcpu(struct kore_worker *kw) { #if defined(__FreeBSD_version) cpuset_t cpuset; CPU_ZERO(&cpuset); CPU_SET(kw->cpu, &cpuset); if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset), &cpuset) == -1) { fatal("failed: %s", errno_s); } #endif /* __FreeBSD_version */ } void kore_platform_event_init(void) { struct listener *l; if ((kfd = kqueue()) == -1) fatal("kqueue(): %s", errno_s); event_count = (worker_max_connections * 2) + nlisteners; events = kore_calloc(event_count, sizeof(struct kevent)); LIST_FOREACH(l, &listeners, list) { kore_platform_event_schedule(l->fd, EVFILT_READ, EV_ADD | EV_DISABLE, l); } } int kore_platform_event_wait(u_int64_t timer) { u_int32_t r; struct listener *l; struct connection *c; u_int8_t type; struct timespec timeo; int n, i; timeo.tv_sec = timer / 1000; timeo.tv_nsec = (timer % 1000) * 1000000; n = kevent(kfd, NULL, 0, events, event_count, &timeo); if (n == -1) { if (errno == EINTR) return (0); fatal("kevent(): %s", errno_s); } if (n > 0) kore_debug("main(): %d sockets available", n); r = 0; for (i = 0; i < n; i++) { if (events[i].udata == NULL) fatal("events[%d].udata == NULL", i); type = *(u_int8_t *)events[i].udata; if (events[i].flags & EV_EOF || events[i].flags & EV_ERROR) { switch (type) { case KORE_TYPE_LISTENER: fatal("error on server socket"); /* NOTREACHED */ #if defined(KORE_USE_PGSQL) case KORE_TYPE_PGSQL_CONN: kore_pgsql_handle(events[i].udata, 1); break; #endif #if defined(KORE_USE_TASKS) case KORE_TYPE_TASK: kore_task_handle(events[i].udata, 1); break; #endif default: c = (struct connection *)events[i].udata; kore_connection_disconnect(c); break; } continue; } switch (type) { case KORE_TYPE_LISTENER: l = (struct listener *)events[i].udata; while (worker_active_connections < worker_max_connections) { if (worker_accept_threshold != 0 && r >= worker_accept_threshold) break; if (!kore_connection_accept(l, &c)) { r = 1; break; } if (c == NULL) break; r++; kore_platform_event_all(c->fd, c); } break; case KORE_TYPE_CONNECTION: c = (struct connection *)events[i].udata; if (events[i].filter == EVFILT_READ && !(c->flags & CONN_READ_BLOCK)) c->flags |= CONN_READ_POSSIBLE; if (events[i].filter == EVFILT_WRITE && !(c->flags & CONN_WRITE_BLOCK)) c->flags |= CONN_WRITE_POSSIBLE; if (!kore_connection_handle(c)) { kore_connection_disconnect(c); } else { if (!TAILQ_EMPTY(&(c->send_queue))) { kore_platform_event_schedule(c->fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, c); } } break; #if defined(KORE_USE_PGSQL) case KORE_TYPE_PGSQL_CONN: kore_pgsql_handle(events[i].udata, 0); break; #endif #if defined(KORE_USE_TASKS) case KORE_TYPE_TASK: kore_task_handle(events[i].udata, 0); break; #endif default: fatal("wrong type in event %d", type); } } return (r); } void kore_platform_event_all(int fd, void *c) { kore_platform_event_schedule(fd, EVFILT_READ, EV_ADD, c); kore_platform_event_schedule(fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, c); } void kore_platform_event_schedule(int fd, int type, int flags, void *data) { struct kevent event[1]; EV_SET(&event[0], fd, type, flags, 0, 0, data); if (kevent(kfd, event, 1, NULL, 0, NULL) == -1) fatal("kevent: %s", errno_s); } void kore_platform_enable_accept(void) { struct listener *l; LIST_FOREACH(l, &listeners, list) kore_platform_event_schedule(l->fd, EVFILT_READ, EV_ENABLE, l); } void kore_platform_disable_accept(void) { struct listener *l; LIST_FOREACH(l, &listeners, list) kore_platform_event_schedule(l->fd, EVFILT_READ, EV_DISABLE, l); } void kore_platform_schedule_read(int fd, void *data) { kore_platform_event_schedule(fd, EVFILT_READ, EV_ADD, data); } void kore_platform_disable_read(int fd) { kore_platform_event_schedule(fd, EVFILT_READ, EV_DELETE, NULL); } void kore_platform_proctitle(char *title) { #ifndef __MACH__ setproctitle("%s", title); #endif } kore/src/cli.c0000644000175000001440000005764112527355514012613 0ustar jorisusers/* * Copyright (c) 2014 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kore.h" #if defined(OpenBSD) || defined(__FreeBSD_version) #define PRI_TIME_T "d" #endif #if defined(linux) #if defined(__x86_64__) #define PRI_TIME_T PRIu64 #else #define PRI_TIME_T "ld" #endif #endif #if defined(__MACH__) #define PRI_TIME_T "ld" #endif #define LD_FLAGS_MAX 10 struct cmd { const char *name; const char *descr; void (*cb)(int, char **); }; struct filegen { void (*cb)(void); }; struct cfile { struct stat st; int build; int cpp; char *name; char *fpath; char *opath; TAILQ_ENTRY(cfile) list; }; TAILQ_HEAD(cfile_list, cfile); static void cli_fatal(const char *, ...) __attribute__((noreturn)); static void cli_file_close(int); static void cli_run_kore(void *); static void cli_generate_certs(void); static void cli_link_library(void *); static void cli_compile_cfile(void *); static void cli_mkdir(const char *, int); static int cli_dir_exists(const char *); static int cli_file_exists(const char *); static void cli_cleanup_files(const char *); static void cli_file_writef(int, const char *, ...); static void cli_file_open(const char *, int, int *); static void cli_file_remove(char *, struct dirent *); static void cli_build_asset(char *, struct dirent *); static void cli_file_write(int, const void *, size_t); static int cli_vasprintf(char **, const char *, ...); static void cli_spawn_proc(void (*cb)(void *), void *); static void cli_write_asset(const char *, const char *); static void cli_register_cfile(char *, struct dirent *); static void cli_file_create(const char *, const char *, size_t); static int cli_file_requires_build(struct stat *, const char *); static void cli_find_files(const char *, void (*cb)(char *, struct dirent *)); static void cli_add_cfile(char *, char *, char *, struct stat *, int, int); static void cli_run(int, char **); static void cli_help(int, char **); static void cli_build(int, char **); static void cli_clean(int, char **); static void cli_create(int, char **); static void file_create_src(void); static void file_create_config(void); static void file_create_gitignore(void); static struct cmd cmds[] = { { "help", "this help text", cli_help }, { "run", "run an application (-fnr implied)", cli_run }, { "build", "build an application", cli_build }, { "clean", "cleanup the build files", cli_clean }, { "create", "create a new application skeleton", cli_create }, { NULL, NULL, NULL } }; static struct filegen gen_files[] = { { file_create_src }, { file_create_config }, { file_create_gitignore }, { NULL } }; static const char *gen_dirs[] = { "src", #if !defined(KORE_BENCHMARK) "cert", #endif "conf", "assets", NULL }; static const char *src_data = "#include \n" "#include \n" "\n" "int\t\tpage(struct http_request *);\n" "\n" "int\n" "page(struct http_request *req)\n" "{\n" "\thttp_response(req, 200, NULL, 0);\n" "\treturn (KORE_RESULT_OK);\n" "}\n"; static const char *config_data = "# Placeholder configuration\n" "\n" "bind\t\t127.0.0.1 8888\n" "load\t\t./%s.so\n" #if !defined(KORE_BENCHMARK) "tls_dhparam\tdh2048.pem\n" #endif "\n" "domain 127.0.0.1 {\n" #if !defined(KORE_BENCHMARK) "\tcertfile\tcert/server.crt\n" "\tcertkey\t\tcert/server.key\n" #endif "\tstatic\t/\tpage\n" "}\n"; #if !defined(KORE_BENCHMARK) static const char *dh2048_data = "-----BEGIN DH PARAMETERS-----\n" "MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv\n" "VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY\n" "Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/\n" "PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV\n" "Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN\n" "xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg==\n" "-----END DH PARAMETERS-----"; #endif static const char *gitignore_data = "*.o\n.objs\n%s.so\nassets.h\ncert\n"; static int s_fd = -1; static char *appl = NULL; static char *rootdir = NULL; static char *compiler = "gcc"; static struct cfile_list source_files; static int cfiles_count; static struct cmd *command = NULL; void kore_cli_usage(int local) { int i; if (local) fprintf(stderr, "Usage: kore [command]\n"); fprintf(stderr, "\nAvailable commands:\n"); for (i = 0; cmds[i].name != NULL; i++) printf("\t%s\t%s\n", cmds[i].name, cmds[i].descr); fprintf(stderr, "\nThe commands mostly exist for your convenience\n"); fprintf(stderr, "when hacking on your Kore applications.\n"); fprintf(stderr, "\n"); fprintf(stderr, "Production servers should be started using "); fprintf(stderr, "the options.\n"); fprintf(stderr, "\nFind more information on https://kore.io\n"); exit(1); } int kore_cli_main(int argc, char **argv) { int i; if (argc < 1) kore_cli_usage(1); (void)umask(S_IWGRP|S_IWOTH); for (i = 0; cmds[i].name != NULL; i++) { if (!strcmp(argv[0], cmds[i].name)) { argc--; argv++; command = &cmds[i]; cmds[i].cb(argc, argv); break; } } if (cmds[i].name == NULL) { fprintf(stderr, "No such command: %s\n", argv[0]); kore_cli_usage(1); } return (0); } static void cli_help(int argc, char **argv) { kore_cli_usage(1); } static void cli_create(int argc, char **argv) { int i; char *fpath; if (argc != 1) cli_fatal("missing application name"); appl = argv[0]; cli_mkdir(appl, 0755); rootdir = appl; for (i = 0; gen_dirs[i] != NULL; i++) { (void)cli_vasprintf(&fpath, "%s/%s", appl, gen_dirs[i]); cli_mkdir(fpath, 0755); free(fpath); } for (i = 0; gen_files[i].cb != NULL; i++) gen_files[i].cb(); cli_generate_certs(); printf("%s created succesfully!\n", appl); #if !defined(KORE_BENCHMARK) printf("note: do NOT use the created DH parameters/certificates in production\n"); #endif } static void cli_build(int argc, char **argv) { struct cfile *cf; struct timeval times[2]; int requires_relink; char pwd[PATH_MAX], *src_path, *assets_header; char *assets_path, *p, *obj_path, *cpath, *config; if (argc == 0) { if (getcwd(pwd, sizeof(pwd)) == NULL) cli_fatal("could not get cwd: %s", errno_s); rootdir = "."; appl = basename(pwd); } else { appl = argv[0]; rootdir = appl; } if ((p = getenv("CC")) != NULL) compiler = p; cfiles_count = 0; TAILQ_INIT(&source_files); (void)cli_vasprintf(&src_path, "%s/src", rootdir); (void)cli_vasprintf(&assets_path, "%s/assets", rootdir); (void)cli_vasprintf(&config, "%s/conf/%s.conf", rootdir, appl); (void)cli_vasprintf(&assets_header, "%s/src/assets.h", rootdir); if (!cli_dir_exists(src_path) || !cli_file_exists(config)) cli_fatal("%s doesn't appear to be a kore app", appl); free(config); (void)cli_vasprintf(&obj_path, "%s/.objs", rootdir); if (!cli_dir_exists(obj_path)) cli_mkdir(obj_path, 0755); free(obj_path); (void)unlink(assets_header); /* Generate the assets. */ if (cli_dir_exists(assets_path)) { cli_file_open(assets_header, O_CREAT | O_TRUNC | O_WRONLY, &s_fd); cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n"); cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n"); cli_find_files(assets_path, cli_build_asset); cli_file_writef(s_fd, "\n#endif\n"); cli_file_close(s_fd); } free(assets_path); /* Build all source files. */ cli_find_files(src_path, cli_register_cfile); free(src_path); requires_relink = 0; TAILQ_FOREACH(cf, &source_files, list) { if (cf->build == 0) continue; printf("compiling %s\n", cf->name); cli_spawn_proc(cli_compile_cfile, cf); times[0].tv_usec = 0; times[0].tv_sec = cf->st.st_mtime; times[1] = times[0]; if (utimes(cf->opath, times) == -1) printf("utime(%s): %s\n", cf->opath, errno_s); requires_relink++; } (void)unlink(assets_header); free(assets_header); (void)cli_vasprintf(&cpath, "%s/cert", rootdir); if (!cli_dir_exists(cpath)) { cli_mkdir(cpath, 0700); cli_generate_certs(); } free(cpath); if (requires_relink) { cli_spawn_proc(cli_link_library, NULL); printf("%s built succesfully!\n", appl); } else { printf("nothing to be done\n"); } } static void cli_clean(int argc, char **argv) { char pwd[PATH_MAX], *sofile; if (cli_dir_exists(".objs")) cli_cleanup_files(".objs"); if (getcwd(pwd, sizeof(pwd)) == NULL) cli_fatal("could not get cwd: %s", errno_s); appl = basename(pwd); (void)cli_vasprintf(&sofile, "%s.so", appl); if (unlink(sofile) == -1 && errno != ENOENT) printf("couldn't unlink %s: %s", sofile, errno_s); free(sofile); } static void cli_run(int argc, char **argv) { cli_build(argc, argv); if (chdir(rootdir) == -1) cli_fatal("couldn't change directory to %s", rootdir); /* * We are exec()'ing kore again, while we could technically set * the right cli options manually and just continue running. */ cli_run_kore(NULL); } static void file_create_src(void) { char *name; (void)cli_vasprintf(&name, "src/%s.c", appl); cli_file_create(name, src_data, strlen(src_data)); free(name); } static void file_create_config(void) { int l; char *name, *data; (void)cli_vasprintf(&name, "conf/%s.conf", appl); l = cli_vasprintf(&data, config_data, appl); cli_file_create(name, data, l); free(name); free(data); } static void file_create_gitignore(void) { int l; char *data; l = cli_vasprintf(&data, gitignore_data, appl); cli_file_create(".gitignore", data, l); free(data); } static void cli_mkdir(const char *fpath, int mode) { if (mkdir(fpath, mode) == -1) cli_fatal("cli_mkdir(%s): %s", fpath, errno_s); } static int cli_file_exists(const char *fpath) { struct stat st; if (stat(fpath, &st) == -1) return (0); if (!S_ISREG(st.st_mode)) return (0); return (1); } static int cli_file_requires_build(struct stat *fst, const char *opath) { struct stat ost; if (stat(opath, &ost) == -1) { if (errno == ENOENT) return (1); cli_fatal("stat(%s): %s", opath, errno_s); } return (fst->st_mtime != ost.st_mtime); } static int cli_dir_exists(const char *fpath) { struct stat st; if (stat(fpath, &st) == -1) return (0); if (!S_ISDIR(st.st_mode)) return (0); return (1); } static void cli_file_open(const char *fpath, int flags, int *fd) { if ((*fd = open(fpath, flags, 0644)) == -1) cli_fatal("cli_file_open(%s): %s", fpath, errno_s); } static void cli_file_close(int fd) { if (close(fd) == -1) printf("warning: close() %s\n", errno_s); } static void cli_file_writef(int fd, const char *fmt, ...) { int l; char *buf; va_list args; va_start(args, fmt); l = vasprintf(&buf, fmt, args); va_end(args); if (l == -1) cli_fatal("cli_file_writef"); cli_file_write(fd, buf, l); free(buf); } static void cli_file_write(int fd, const void *buf, size_t len) { ssize_t r; const u_int8_t *d; size_t written; d = buf; written = 0; while (written != len) { r = write(fd, d + written, len - written); if (r == -1) { if (errno == EINTR) continue; cli_fatal("cli_file_write: %s", errno_s); } written += r; } } static void cli_file_create(const char *name, const char *data, size_t len) { int fd; char *fpath; (void)cli_vasprintf(&fpath, "%s/%s", rootdir, name); cli_file_open(fpath, O_CREAT | O_TRUNC | O_WRONLY, &fd); cli_file_write(fd, data, len); cli_file_close(fd); printf("created %s\n", fpath); free(fpath); } static void cli_write_asset(const char *n, const char *e) { cli_file_writef(s_fd, "extern u_int8_t asset_%s_%s[];\n", n, e); cli_file_writef(s_fd, "extern u_int32_t asset_len_%s_%s;\n", n, e); cli_file_writef(s_fd, "extern time_t asset_mtime_%s_%s;\n", n, e); } static void cli_build_asset(char *fpath, struct dirent *dp) { struct stat st; u_int8_t *d; off_t off; void *base; int in, out; char *cpath, *ext, *opath, *p, *name; name = kore_strdup(dp->d_name); /* Grab the extension as we're using it in the symbol name. */ if ((ext = strrchr(name, '.')) == NULL) cli_fatal("couldn't find ext in %s", name); /* Replace dots, spaces, etc etc with underscores. */ for (p = name; *p != '\0'; p++) { if (*p == '.' || isspace(*p) || *p == '-') *p = '_'; } /* Grab inode information. */ if (stat(fpath, &st) == -1) cli_fatal("stat: %s %s", fpath, errno_s); (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, name); (void)cli_vasprintf(&cpath, "%s/.objs/%s.c", rootdir, name); /* Check if the file needs to be built. */ if (!cli_file_requires_build(&st, opath)) { *(ext)++ = '\0'; cli_write_asset(name, ext); *ext = '_'; cli_add_cfile(name, cpath, opath, &st, 0, 0); kore_mem_free(name); return; } /* Open the file we're converting. */ cli_file_open(fpath, O_RDONLY, &in); /* mmap our in file. */ if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, in, 0)) == MAP_FAILED) cli_fatal("mmap: %s %s", fpath, errno_s); /* Create the c file where we will write too. */ cli_file_open(cpath, O_CREAT | O_TRUNC | O_WRONLY, &out); /* No longer need name so cut off the extension. */ printf("building asset %s\n", dp->d_name); *(ext)++ = '\0'; /* Start generating the file. */ cli_file_writef(out, "/* Auto generated */\n"); cli_file_writef(out, "#include \n\n"); /* Write the file data as a byte array. */ cli_file_writef(out, "u_int8_t asset_%s_%s[] = {\n", name, ext); d = base; for (off = 0; off < st.st_size; off++) cli_file_writef(out, "0x%02x,", *d++); /* * Always NUL-terminate the asset, even if this NUL is not included in * the actual length. This way assets can be cast to char * without * any additional thinking for the developer. */ cli_file_writef(out, "0x00"); /* Add the meta data. */ cli_file_writef(out, "};\n\n"); cli_file_writef(out, "u_int32_t asset_len_%s_%s = %" PRIu32 ";\n", name, ext, (u_int32_t)st.st_size); cli_file_writef(out, "time_t asset_mtime_%s_%s = %" PRI_TIME_T ";\n", name, ext, st.st_mtime); /* Write the file symbols into assets.h so they can be used. */ cli_write_asset(name, ext); /* Cleanup static file source. */ if (munmap(base, st.st_size) == -1) cli_fatal("munmap: %s %s", fpath, errno_s); /* Cleanup fds */ cli_file_close(in); cli_file_close(out); /* Restore the original name */ *--ext = '.'; /* Register the .c file now (cpath is free'd later). */ cli_add_cfile(name, cpath, opath, &st, 1, 0); kore_mem_free(name); } static void cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build, int cpp) { struct cfile *cf; cfiles_count++; cf = kore_malloc(sizeof(*cf)); cf->st = *st; cf->build = build; cf->cpp = cpp; cf->fpath = fpath; cf->opath = opath; cf->name = kore_strdup(name); TAILQ_INSERT_TAIL(&source_files, cf, list); } static void cli_register_cfile(char *fpath, struct dirent *dp) { struct stat st; char *ext, *opath; int cpp; if ((ext = strrchr(fpath, '.')) == NULL || (strcmp(ext, ".c") && strcmp(ext, ".cpp"))) return; if (!strcmp(ext, ".cpp")) cpp = 1; else cpp = 0; if (stat(fpath, &st) == -1) cli_fatal("stat(%s): %s", fpath, errno_s); (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name); if (!cli_file_requires_build(&st, opath)) { cli_add_cfile(dp->d_name, fpath, opath, &st, 0, cpp); return; } cli_add_cfile(dp->d_name, fpath, opath, &st, 1, cpp); } static void cli_file_remove(char *fpath, struct dirent *dp) { if (unlink(fpath) == -1) fprintf(stderr, "couldn't unlink %s: %s", fpath, errno_s); } static void cli_find_files(const char *path, void (*cb)(char *, struct dirent *)) { DIR *d; struct stat st; struct dirent *dp; char *fpath; if ((d = opendir(path)) == NULL) cli_fatal("cli_find_files: opendir(%s): %s", path, errno_s); while ((dp = readdir(d)) != NULL) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; (void)cli_vasprintf(&fpath, "%s/%s", path, dp->d_name); if (stat(fpath, &st) == -1) { fprintf(stderr, "stat(%s): %s\n", fpath, errno_s); free(fpath); continue; } if (S_ISDIR(st.st_mode)) { cli_find_files(fpath, cb); free(fpath); } else if (S_ISREG(st.st_mode)) { cb(fpath, dp); } else { fprintf(stderr, "ignoring %s\n", fpath); free(fpath); } } closedir(d); } static void cli_generate_certs(void) { #if !defined(KORE_BENCHMARK) BIGNUM *e; FILE *fp; time_t now; X509_NAME *name; EVP_PKEY *pkey; X509 *x509; RSA *kpair; char *fpath, issuer[64]; /* Write out DH parameters. */ cli_file_create("dh2048.pem", dh2048_data, strlen(dh2048_data)); /* Create new certificate. */ if ((x509 = X509_new()) == NULL) cli_fatal("X509_new(): %s", ssl_errno_s); /* Generate version 3. */ if (!X509_set_version(x509, 2)) cli_fatal("X509_set_version(): %s", ssl_errno_s); /* Generate RSA keys. */ if ((pkey = EVP_PKEY_new()) == NULL) cli_fatal("EVP_PKEY_new(): %s", ssl_errno_s); if ((kpair = RSA_new()) == NULL) cli_fatal("RSA_new(): %s", ssl_errno_s); if ((e = BN_new()) == NULL) cli_fatal("BN_new(): %s", ssl_errno_s); if (!BN_set_word(e, 65537)) cli_fatal("BN_set_word(): %s", ssl_errno_s); if (!RSA_generate_key_ex(kpair, 2048, e, NULL)) cli_fatal("RSA_generate_key_ex(): %s", ssl_errno_s); BN_free(e); if (!EVP_PKEY_assign_RSA(pkey, kpair)) cli_fatal("EVP_PKEY_assign_RSA(): %s", ssl_errno_s); /* Set serial number to current timestamp. */ time(&now); if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), now)) cli_fatal("ASN1_INTEGER_set(): %s", ssl_errno_s); /* Not before and not after dates. */ if (!X509_gmtime_adj(X509_get_notBefore(x509), 0)) cli_fatal("X509_gmtime_adj(): %s", ssl_errno_s); if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60 * 24 * 3000)) cli_fatal("X509_gmtime_adj(): %s", ssl_errno_s); /* Attach the pkey to the certificate. */ if (!X509_set_pubkey(x509, pkey)) cli_fatal("X509_set_pubkey(): %s", ssl_errno_s); /* Set certificate information. */ if ((name = X509_get_subject_name(x509)) == NULL) cli_fatal("X509_get_subject_name(): %s", ssl_errno_s); (void)snprintf(issuer, sizeof(issuer), "kore autogen: %s", appl); if (!X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char *)"SE", -1, -1, 0)) cli_fatal("X509_NAME_add_entry_by_txt(): C %s", ssl_errno_s); if (!X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (const unsigned char *)issuer, -1, -1, 0)) cli_fatal("X509_NAME_add_entry_by_txt(): O %s", ssl_errno_s); if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char *)"localhost", -1, -1, 0)) cli_fatal("X509_NAME_add_entry_by_txt(): CN %s", ssl_errno_s); if (!X509_set_issuer_name(x509, name)) cli_fatal("X509_set_issuer_name(): %s", ssl_errno_s); if (!X509_sign(x509, pkey, EVP_sha256())) cli_fatal("X509_sign(): %s", ssl_errno_s); (void)cli_vasprintf(&fpath, "%s/cert/server.key", rootdir); if ((fp = fopen(fpath, "w")) == NULL) cli_fatal("fopen(%s): %s", fpath, errno_s); free(fpath); if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) cli_fatal("PEM_write_PrivateKey(): %s", ssl_errno_s); fclose(fp); (void)cli_vasprintf(&fpath, "%s/cert/server.crt", rootdir); if ((fp = fopen(fpath, "w")) == NULL) cli_fatal("fopen(%s): %s", fpath, errno_s); free(fpath); if (!PEM_write_X509(fp, x509)) cli_fatal("PEM_write_X509(%s)", errno_s); fclose(fp); EVP_PKEY_free(pkey); X509_free(x509); #endif } static void cli_compile_cfile(void *arg) { int idx; struct cfile *cf = arg; char *args[24], *ipath[2], *p, *cppstandard; #if defined(KORE_USE_PGSQL) char *ppath; #endif (void)cli_vasprintf(&ipath[0], "-I%s/src", rootdir); (void)cli_vasprintf(&ipath[1], "-I%s/src/includes", rootdir); /* * These compiler options should be settable * somehow by the user if they so choose. */ idx = 0; args[idx++] = compiler; args[idx++] = ipath[0]; args[idx++] = ipath[1]; #if defined(PREFIX) (void)cli_vasprintf(&args[idx++], "-I%s/include", PREFIX); #else args[idx++] = "-I/usr/local/include"; #endif #if defined(KORE_USE_PGSQL) (void)cli_vasprintf(&ppath, "-I%s", PGSQL_INCLUDE_PATH); args[idx++] = ppath; #endif args[idx++] = "-Wall"; args[idx++] = "-Wmissing-declarations"; args[idx++] = "-Wshadow"; args[idx++] = "-Wpointer-arith"; args[idx++] = "-Wcast-qual"; args[idx++] = "-Wsign-compare"; args[idx++] = "-fPIC"; args[idx++] = "-g"; if (cf->cpp) { args[idx++] = "-Woverloaded-virtual"; args[idx++] = "-Wold-style-cast"; args[idx++] = "-Wnon-virtual-dtor"; if ((p = getenv("CXXSTD")) != NULL) { (void)cli_vasprintf(&cppstandard, "-std=%s", p); args[idx++] = cppstandard; } } else { args[idx++] = "-Wstrict-prototypes"; args[idx++] = "-Wmissing-prototypes"; } args[idx++] = "-c"; args[idx++] = cf->fpath; args[idx++] = "-o"; args[idx++] = cf->opath; args[idx] = NULL; execvp(compiler, args); } static void cli_link_library(void *arg) { struct cfile *cf; int idx, f, i, has_cpp; char *args[cfiles_count + 11 + LD_FLAGS_MAX]; char *p, *libname, *flags[LD_FLAGS_MAX], *cpplib; if ((p = getenv("LDFLAGS")) != NULL) f = kore_split_string(p, " ", flags, LD_FLAGS_MAX); else f = 0; (void)cli_vasprintf(&libname, "%s/%s.so", rootdir, appl); idx = 0; args[idx++] = compiler; #if defined(__MACH__) args[idx++] = "-dynamiclib"; args[idx++] = "-undefined"; args[idx++] = "suppress"; args[idx++] = "-flat_namespace"; #else args[idx++] = "-shared"; #endif has_cpp = 0; TAILQ_FOREACH(cf, &source_files, list) { if (cf->cpp) has_cpp = 1; args[idx++] = cf->opath; } if (has_cpp) { if ((p = getenv("CXXLIB")) != NULL) { (void)cli_vasprintf(&cpplib, "-l%s", p); args[idx++] = cpplib; } else { args[idx++] = "-lstdc++"; } } for (i = 0; i < f; i++) args[idx++] = flags[i]; args[idx++] = "-o"; args[idx++] = libname; args[idx] = NULL; execvp(compiler, args); } static void cli_run_kore(void *arg) { char *args[4], *cpath; (void)cli_vasprintf(&cpath, "conf/%s.conf", appl); args[0] = "kore"; args[1] = "-fnrc"; args[2] = cpath; args[3] = NULL; execvp("kore", args); } static void cli_spawn_proc(void (*cb)(void *), void *arg) { pid_t pid; int status; pid = fork(); switch (pid) { case -1: cli_fatal("cli_compile_cfile: fork() %s", errno_s); /* NOTREACHED */ case 0: cb(arg); cli_fatal("cli_spawn_proc: %s", errno_s); /* NOTREACHED */ default: break; } if (waitpid(pid, &status, 0) == -1) cli_fatal("couldn't wait for child %d", pid); if (WEXITSTATUS(status) || WTERMSIG(status) || WCOREDUMP(status)) cli_fatal("subprocess trouble, check output"); } static int cli_vasprintf(char **out, const char *fmt, ...) { int l; va_list args; va_start(args, fmt); l = vasprintf(out, fmt, args); va_end(args); if (l == -1) cli_fatal("cli_vasprintf"); return (l); } static void cli_cleanup_files(const char *spath) { cli_find_files(spath, cli_file_remove); if (rmdir(spath) == -1 && errno != ENOENT) printf("couldn't rmdir %s\n", spath); } static void cli_fatal(const char *fmt, ...) { va_list args; char buf[2048]; va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (command != NULL) printf("kore %s: %s\n", command->name, buf); else printf("kore: %s\n", buf); exit(1); } kore/src/accesslog.c0000644000175000001440000001176612527355514014005 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "kore.h" #include "http.h" static int accesslog_fd[2]; struct kore_log_packet { u_int8_t method; int status; u_int16_t time_req; u_int16_t worker_id; u_int16_t worker_cpu; u_int8_t addrtype; u_int8_t addr[sizeof(struct in6_addr)]; char host[KORE_DOMAINNAME_LEN]; char path[HTTP_URI_LEN]; char agent[HTTP_USERAGENT_LEN]; char cn[X509_CN_LENGTH]; }; void kore_accesslog_init(void) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, accesslog_fd) == -1) fatal("kore_accesslog_init(): socketpair() %s", errno_s); } void kore_accesslog_worker_init(void) { close(accesslog_fd[0]); kore_domain_closelogs(); } int kore_accesslog_wait(void) { ssize_t len; time_t now; struct kore_domain *dom; struct pollfd pfd[1]; int nfds, l; struct kore_log_packet logpacket; char addr[INET6_ADDRSTRLEN]; char *method, *buf, *tbuf, *cn; pfd[0].fd = accesslog_fd[0]; pfd[0].events = POLLIN; pfd[0].revents = 0; nfds = poll(pfd, 1, 1000); if (nfds == -1 || (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) { if (nfds == -1 && errno == EINTR) return (KORE_RESULT_OK); kore_log(LOG_WARNING, "poll(): %s", errno_s); return (KORE_RESULT_ERROR); } if (nfds == 0) return (KORE_RESULT_OK); len = recv(accesslog_fd[0], &logpacket, sizeof(logpacket), 0); if (len == -1) { kore_log(LOG_WARNING, "recv(): %s", errno_s); return (KORE_RESULT_ERROR); } if (len != sizeof(logpacket)) return (KORE_RESULT_ERROR); if ((dom = kore_domain_lookup(logpacket.host)) == NULL) { kore_log(LOG_WARNING, "got accesslog packet for unknown domain: %s", logpacket.host); return (KORE_RESULT_OK); } switch (logpacket.method) { case HTTP_METHOD_GET: method = "GET"; break; case HTTP_METHOD_POST: method = "POST"; break; case HTTP_METHOD_PUT: method = "PUT"; break; case HTTP_METHOD_DELETE: method = "DELETE"; break; case HTTP_METHOD_HEAD: method = "HEAD"; break; default: method = "UNKNOWN"; break; } if (logpacket.cn[0] != '\0') cn = logpacket.cn; else cn = "none"; if (inet_ntop(logpacket.addrtype, &(logpacket.addr), addr, sizeof(addr)) == NULL) kore_strlcpy(addr, "unknown", sizeof(addr)); time(&now); tbuf = kore_time_to_date(now); l = asprintf(&buf, "[%s] %s %d %s %s (w#%d) (%dms) (%s) (%s)\n", tbuf, addr, logpacket.status, method, logpacket.path, logpacket.worker_id, logpacket.time_req, cn, logpacket.agent); if (l == -1) { kore_log(LOG_WARNING, "kore_accesslog_wait(): asprintf() == -1"); return (KORE_RESULT_ERROR); } len = write(dom->accesslog, buf, l); if (len == -1) { free(buf); kore_log(LOG_WARNING, "kore_accesslog_wait(): write(): %s", errno_s); return (KORE_RESULT_ERROR); } if (len != l) kore_log(LOG_NOTICE, "accesslog: %s", buf); free(buf); return (KORE_RESULT_OK); } void kore_accesslog(struct http_request *req) { ssize_t len; struct kore_log_packet logpacket; logpacket.addrtype = req->owner->addrtype; if (logpacket.addrtype == AF_INET) { memcpy(logpacket.addr, &(req->owner->addr.ipv4.sin_addr), sizeof(req->owner->addr.ipv4.sin_addr)); } else { memcpy(logpacket.addr, &(req->owner->addr.ipv6.sin6_addr), sizeof(req->owner->addr.ipv6.sin6_addr)); } logpacket.status = req->status; logpacket.method = req->method; logpacket.worker_id = worker->id; logpacket.worker_cpu = worker->cpu; logpacket.time_req = req->total; kore_strlcpy(logpacket.host, req->host, sizeof(logpacket.host)); kore_strlcpy(logpacket.path, req->path, sizeof(logpacket.path)); if (req->agent != NULL) { kore_strlcpy(logpacket.agent, req->agent, sizeof(logpacket.agent)); } else { kore_strlcpy(logpacket.agent, "unknown", sizeof(logpacket.agent)); } memset(logpacket.cn, '\0', sizeof(logpacket.cn)); #if !defined(KORE_BENCHMARK) if (req->owner->cert != NULL) { if (X509_GET_CN(req->owner->cert, logpacket.cn, sizeof(logpacket.cn)) == -1) { kore_log(LOG_WARNING, "client cert without a CN?"); } } #endif len = send(accesslog_fd[1], &logpacket, sizeof(logpacket), 0); if (len == -1) { kore_log(LOG_WARNING, "kore_accesslog(): send(): %s", errno_s); } else if (len != sizeof(logpacket)) { kore_log(LOG_WARNING, "short accesslog packet sent"); } } kore/src/pool.c0000644000175000001440000000606512527355514013007 0ustar jorisusers/* * Copyright (c) 2013-2015 Joris Vink * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "kore.h" #define POOL_ELEMENT_BUSY 0 #define POOL_ELEMENT_FREE 1 static void pool_region_create(struct kore_pool *, u_int32_t); void kore_pool_init(struct kore_pool *pool, const char *name, u_int32_t len, u_int32_t elm) { kore_debug("kore_pool_init(%p, %s, %d, %d)", pool, name, len, elm); pool->elms = 0; pool->inuse = 0; pool->elen = len; pool->name = kore_strdup(name); pool->slen = pool->elen + sizeof(struct kore_pool_entry); LIST_INIT(&(pool->regions)); LIST_INIT(&(pool->freelist)); pool_region_create(pool, elm); } void * kore_pool_get(struct kore_pool *pool) { u_int8_t *ptr; struct kore_pool_entry *entry; if (LIST_EMPTY(&(pool->freelist))) { kore_log(LOG_NOTICE, "pool %s is exhausted (%d/%d)", pool->name, pool->inuse, pool->elms); pool_region_create(pool, pool->elms); } entry = LIST_FIRST(&(pool->freelist)); if (entry->state != POOL_ELEMENT_FREE) fatal("%s: element %p was not free", pool->name, entry); LIST_REMOVE(entry, list); entry->state = POOL_ELEMENT_BUSY; ptr = (u_int8_t *)entry + sizeof(struct kore_pool_entry); pool->inuse++; #if defined(KORE_PEDANTIC_MALLOC) explicit_bzero(ptr, pool->elen); #endif return (ptr); } void kore_pool_put(struct kore_pool *pool, void *ptr) { struct kore_pool_entry *entry; #if defined(KORE_PEDANTIC_MALLOC) explicit_bzero(ptr, pool->elen); #endif entry = (struct kore_pool_entry *) ((u_int8_t *)ptr - sizeof(struct kore_pool_entry)); if (entry->state != POOL_ELEMENT_BUSY) fatal("%s: element %p was not busy", pool->name, ptr); entry->state = POOL_ELEMENT_FREE; LIST_INSERT_HEAD(&(pool->freelist), entry, list); pool->inuse--; } static void pool_region_create(struct kore_pool *pool, u_int32_t elms) { u_int32_t i; u_int8_t *p; struct kore_pool_region *reg; struct kore_pool_entry *entry; kore_debug("pool_region_create(%p, %d)", pool, elms); reg = kore_malloc(sizeof(struct kore_pool_region)); LIST_INSERT_HEAD(&(pool->regions), reg, list); reg->start = kore_malloc(elms * pool->slen); p = (u_int8_t *)reg->start; for (i = 0; i < elms; i++) { entry = (struct kore_pool_entry *)p; entry->region = reg; entry->state = POOL_ELEMENT_FREE; LIST_INSERT_HEAD(&(pool->freelist), entry, list); p = p + pool->slen; } pool->elms += elms; } kore/docker/0000755000175000001440000000000012527355513012342 5ustar jorisuserskore/docker/build/0000755000175000001440000000000012527355513013441 5ustar jorisuserskore/docker/build/Dockerfile0000644000175000001440000000027112527355513015433 0ustar jorisusersFROM debian:jessie MAINTAINER Thordur I. Bjornsson RUN apt-get update -qq && \ apt-get -qqy install build-essential clang git libpq-dev libssl-dev libz-dev kore/docker/Makefile0000644000175000001440000000041512527355513014002 0ustar jorisusersall: build app build: docker build -t kore-build -f build/Dockerfile build/ docker tag kore-build kore/build app: docker build -t kore-app -f app/Dockerfile app/ docker tag kore-app kore/app clean: docker rmi -f kore-build kore-app .PHONY: all build app clean kore/docker/app/0000755000175000001440000000000012527355513013122 5ustar jorisuserskore/docker/app/Dockerfile0000644000175000001440000000067212527355513015121 0ustar jorisusersFROM kore/build MAINTAINER Thordur I. Bjornsson ENV KORE_VERSION 1.2.3 WORKDIR /kore ADD https://github.com/jorisvink/kore/archive/$KORE_VERSION-release.tar.gz /kore/ RUN tar -zxf $KORE_VERSION-release.tar.gz && cd kore-$KORE_VERSION-release/ && \ make clean && make && make install && \ rm -rf /kore/$KORE_VERSION-release.tar.gz /kore/kore-$KORE_VERSION-release EXPOSE 443 8888 ENTRYPOINT ["kore", "run"]