From 46c76ed0658d4c39718e463283983b2e9628ad70 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 20 Nov 2019 11:52:19 -0500 Subject: [PATCH] Start of Android implementation. --- .gitignore | 1 + PgpConnect.java | 286 ++++++++++++++++++++++++++++++++++++++++++++++++ impl_android.go | 86 ++++++++++++++- jni_android.c | 134 +++++++++++++++++++++++ jni_android.go | 186 +++++++++++++++++++++++++++++++ jni_android.h | 18 +++ main.go | 4 + openpgp-api.jar | Bin 0 -> 55335 bytes 8 files changed, 712 insertions(+), 3 deletions(-) create mode 100644 PgpConnect.java create mode 100644 jni_android.c create mode 100644 jni_android.go create mode 100644 jni_android.h create mode 100644 openpgp-api.jar diff --git a/.gitignore b/.gitignore index 2925ed9..6327216 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cmd/passgo/passgo cmd/passgo-gui/passgo-gui nohup.out *.apk +PgpConnect.jar diff --git a/PgpConnect.java b/PgpConnect.java new file mode 100644 index 0000000..dcd1c4c --- /dev/null +++ b/PgpConnect.java @@ -0,0 +1,286 @@ +package st.wow.git.passgo; + +import java.lang.Runnable; +import java.lang.String; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import android.os.Handler; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import org.openintents.openpgp.OpenPgpError; +import org.openintents.openpgp.OpenPgpSignatureResult; +import org.openintents.openpgp.util.OpenPgpApi; +import org.openintents.openpgp.util.OpenPgpServiceConnection; +import android.content.Context; +import android.content.ClipboardManager; +import android.content.ClipData; +import android.content.Intent; +import android.util.Log; +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.app.PendingIntent; +import android.content.IntentSender; +import android.content.IntentSender.OnFinished; +import android.content.IntentSender.SendIntentException; +import android.os.Bundle; + +public class PgpConnect extends Fragment { + Activity act; + Context ctx; + Handler handler; + OpenPgpServiceConnection mServiceConnection; + ClipboardManager cb; + + public PgpConnect(Activity act) { + Log.d("gio", "PgpConnect(Activity)"); + act = act; + ctx = act.getApplicationContext(); + this.handler = new Handler(ctx.getMainLooper()); + + final FragmentManager fm = act.getFragmentManager(); + final Fragment frag = this; + handler.post(new Runnable() { + public void run() { + Log.d("gio", "PgpConnect(): adding fragment"); + FragmentTransaction ft = fm.beginTransaction(); + ft.add(frag, "PgpConnect"); + ft.commitNow(); + } + }); + } + + @Override public void onAttach(Context ctx) { + super.onAttach(ctx); + Log.d("gio", "onAttach()"); + this.ctx = ctx; + this.handler = new Handler(ctx.getMainLooper()); + mServiceConnection = new OpenPgpServiceConnection(ctx, "org.sufficientlysecure.keychain"); + mServiceConnection.bindToService(); + cb = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); + installComplete(this); + } + + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d("gio", "onActivityResult(" + requestCode + "): " + resultCode); + super.onActivityResult(requestCode, resultCode, data); + //activityResult(requestCode, resultCode); + if (resultCode != Activity.RESULT_OK) { + Log.d("gio", "onActivityResult: not OK"); + stringResult(requestCode, null); + return; + } + Bundle bundle = data.getExtras(); + if (bundle != null) { + for (String k : bundle.keySet()) { + Log.d("gio", "data extra:" + k); + } + } + switch (data.getAction()) { + case OpenPgpApi.ACTION_DECRYPT_VERIFY: { + Log.d("gio", "action decrypt"); + _decrypt(data, requestCode); + break; + } + case OpenPgpApi.ACTION_ENCRYPT: { + Log.d("gio", "action encrypt"); + _encrypt(data, requestCode); + break; + } + case OpenPgpApi.ACTION_GET_KEY_IDS: + Log.d("gio", "action getid"); + String[] ids = data.getStringArrayExtra("user_ids"); + + if (ids != null && ids.length > 0) { + Log.d("gio", "got some IDs"); + stringResult(requestCode, ids[0]); + } else { + Log.d("gio", "no ids"); + stringResult(requestCode, null); + } + break; + default: { + Log.d("gio", "some other action"); + } + } + } + + public void Clip(byte []dat) { + ClipData clip = ClipData.newPlainText("PgpConnect", new String(dat)); + cb.setPrimaryClip(clip); + } + + public void GetId(int chint) { + if (handler == null) { + stringResult(chint, null); + return; + } + Log.d("gio", "GetId()"); + handler.post(new Runnable() { + public void run() { + Intent data = new Intent(); + data.setAction(OpenPgpApi.ACTION_GET_KEY_IDS); + //data.setAction(OpenPgpApi.ACTION_ENCRYPT); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{" "}); + _getid(data, chint); + } + }); + } + + public void Decrypt(byte []dat, int chint) { + if (handler == null) { + stringResult(chint, null); + return; + } + handler.post(new Runnable() { + public void run() { + Intent data = new Intent(); + data.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); + data.putExtra("DATA", dat); + _decrypt(data, chint); + } + }); + } + + private void _getid(Intent data, int chint) { + Log.d("gio","_getid"); + InputStream is = null; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(this.ctx, mServiceConnection.getService()); + Intent result = api.executeApi(data, is, os); + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + Log.d("gio","_getid: success"); + try { + String ret = os.toString("UTF-8"); + Log.d(OpenPgpApi.TAG, "output: " + ret); + stringResult(chint, ret); + } catch (UnsupportedEncodingException e) { + Log.e("gio", "UnsupportedEncodingException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + Log.d("gio","_getid: interaction required"); + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + startIntentSenderForResult(pi.getIntentSender(), chint, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e("gio", "SendIntentException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + Log.d("gio","_getid: error"); + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + stringResult(chint, null); + } + } + } + private void _decrypt(Intent data, int chint) { + Log.d("gio","_decrypt"); + byte []dat = data.getByteArrayExtra("DATA"); + InputStream is = new ByteArrayInputStream(dat); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(this.ctx, mServiceConnection.getService()); + Intent result = api.executeApi(data, is, os); + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + try { + String ret = os.toString("UTF-8"); + Log.d(OpenPgpApi.TAG, "output: " + ret); + stringResult(chint, ret); + } catch (UnsupportedEncodingException e) { + Log.e("gio", "UnsupportedEncodingException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + startIntentSenderForResult(pi.getIntentSender(), chint, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e("gio", "SendIntentException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + stringResult(chint, null); + } + } + } + + public void Encrypt(byte[] id, byte[] dat, int chint) { + if (handler == null) { + stringResult(chint, null); + return; + } + handler.post(new Runnable() { + public void run() { + Intent data = new Intent(); + data.setAction(OpenPgpApi.ACTION_ENCRYPT); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{new String(id)}); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); + data.putExtra("DATA", dat); + _encrypt(data, chint); + } + }); + } + + private void _encrypt(Intent data, int chint) { + Log.d("gio","_encrypt"); + byte []dat = data.getByteArrayExtra("DATA"); + InputStream is = new ByteArrayInputStream(dat); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(this.ctx, mServiceConnection.getService()); + Intent result = api.executeApi(data, is, os); + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + try { + String ret = os.toString("UTF-8"); + Log.d(OpenPgpApi.TAG, "output: " + ret); + stringResult(chint, ret); + } catch (UnsupportedEncodingException e) { + Log.e("gio", "UnsupportedEncodingException", e); + stringResult(chint, null); + } + + if (result.hasExtra(OpenPgpApi.RESULT_SIGNATURE)) { + OpenPgpSignatureResult sigResult + = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + IntentSender sender = pi.getIntentSender(); + Log.d("PgpConnect", "IntentSender:" + sender.toString()); + startIntentSenderForResult(sender, chint, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e("gio", "SendIntentException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + stringResult(chint, null); + break; + } + } + } + + static private native void installComplete(PgpConnect p); + static private native void activityResult(int requestCode, int resultCode); + static private native void stringResult(int requestCode, String result); +} diff --git a/impl_android.go b/impl_android.go index e6929bb..f1d1790 100644 --- a/impl_android.go +++ b/impl_android.go @@ -1,24 +1,104 @@ //+build android +//go:generate mkdir -p classes +//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar -classpath openpgp-api.jar -d classes PgpConnect.java +//go:generate jar cf PgpConnect.jar -C classes . +//go:generate rm -rf classes package passgo +/* +#import +#import "jni_android.h" +*/ +import "C" + import ( "fmt" + "io/ioutil" + "path" + "log" + "strings" + "sync" + + "gioui.org/app" + _ "gioui.org/app/permission/storage" ) +var ( + h *app.Handle + waitch chan struct{} + w *app.Window + pgp PGP + InitPgpOnce sync.Once +) + +func init() { + waitch = make(chan struct{}) +} + +//export installComplete +func installComplete(env *C.JNIEnv, class C.jclass, p C.jobject) { + log.Printf("InstallComplete()") + pgp = PGP(C.NewGlobalRef(env, p)) + close(waitch) +} + +func InitPgp(x *app.Window) { + InitPgpOnce.Do(func() { + log.Printf("InitPgp()") + w = x + h = app.PlatformHandle() + SetJVM(h.JVM, h.Context) + RunInJVM(func(env *JNIEnv) { + C.InitPgpConnect(env) + }) + w.RegisterDelegate("st/wow/git/passgo/PgpConnect") + }) +} + +func stopPgp() { + waitch = make(chan struct{}) + w = nil +} + +func connect() { + <-waitch +} + //Clip copies a string to the clipboard func Clip(x string) { fmt.Println("Clipboard not implemented for this platform") } func (s *Store) nativeDecrypt(name string) (string, error) { - return "", fmt.Errorf("NOT IMPLEMENTED") + connect() + log.Printf("Decrypt(): connected") + data, err := ioutil.ReadFile(path.Join(s.Dir, strings.Join([]string{name, ".gpg"}, ""))) + if err != nil { + return "", fmt.Errorf("Error reading file: %s", err) + } + ret, err := pgp.Decrypt(string(data)) + log.Printf("Decrypt(): got %s", ret) + return ret, err } func (s *Store) nativeEncrypt(pw string) ([]byte, error) { - return nil, fmt.Errorf("NOT IMPLEMENTED") + connect() + ret, err := Encrypt("", pw) + return []byte(ret), err +} + +func Encrypt(id, data string) (string, error) { + connect() + log.Printf("Encrypt(): connected") + return pgp.Encrypt(id, data) } func nativeIdentities() ([]string, error) { - return nil, fmt.Errorf("NOT IMPLEMENTED") + log.Printf("nativeIdentities()") + connect() + log.Printf("calling pgp.GetId()") + id, err := pgp.GetId() + log.Printf("pgp.GetId() returned") + return []string{id}, err } diff --git a/jni_android.c b/jni_android.c new file mode 100644 index 0000000..ecf7ee7 --- /dev/null +++ b/jni_android.c @@ -0,0 +1,134 @@ + +#include +#include +#include +#include +#include "jni_android.h" +#include "_cgo_export.h" + +static jobject gClassLoader; +static jmethodID gFindClassMethod; + +void +SetLoader(JNIEnv* env, jobject context) { + jclass cclass = (*env)->GetObjectClass(env, context); + jmethodID gcl_id = (*env)->GetMethodID(env, cclass, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jobject loader = (*env)->CallObjectMethod(env, context, gcl_id); + gClassLoader = (*env)->NewGlobalRef(env, loader); + jclass lclass = (*env)->GetObjectClass(env, loader); + gFindClassMethod = (*env)->GetMethodID(env, lclass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); +} + +jclass +FindClass(JNIEnv* env, char* name) { + jstring strClassName = (*env)->NewStringUTF(env, name); + return (*env)->CallObjectMethod(env, gClassLoader, gFindClassMethod, strClassName); +} + +jobject +CreateObject(JNIEnv* env, jclass cls) { + jmethodID init = (*env)->GetMethodID(env, cls, "", "()V"); + return (*env)->NewObject(env, cls, init); +} + +void +InitPgpConnect(JNIEnv* env) { + jclass cls = FindClass(env, "st/wow/git/passgo/PgpConnect"); + printf("class = %p", cls); + //jmethodID init = (*env)->GetMethodID(env, cls, "", "(Landroid/app/Activity;)V"); + //printf("init = %p", init); + //jobject ret = (*env)->NewObject(env, cls, init, act); + //printf("obj = %p", ret); + + static const JNINativeMethod actMethods[] = { + { + .name = "activityResult", + .signature = "(II)V", + .fnPtr = activityResult + }, + { + .name = "stringResult", + .signature = "(ILjava/lang/String;)V", + .fnPtr = stringResult + }, + { + .name = "installComplete", + .signature = "(Lst/wow/git/passgo/PgpConnect;)V", + .fnPtr = installComplete + }, + }; + + (*env)->RegisterNatives(env, cls, actMethods, sizeof(actMethods)/sizeof(actMethods[0])); + //return (*env)->NewGlobalRef(env, ret); +} + +void +GetId(JNIEnv* env, jobject p, int chint) { + jclass cls = (*env)->GetObjectClass(env, p); + printf("GetId(): cls = %p", cls); + jmethodID mid = (*env)->GetMethodID(env, cls, "GetId", "(I)V"); + printf("GetId(): mid = %p", mid); + (*env)->CallObjectMethod(env, p, mid, chint); +} + +void +Decrypt(JNIEnv* env, jobject p, char* cdata, int datalen, int chint) { + jbyteArray data = (*env)->NewByteArray(env, datalen); + (*env)->SetByteArrayRegion(env, data, 0, datalen, cdata); + jclass cls = (*env)->GetObjectClass(env, p); + jmethodID mid = (*env)->GetMethodID(env, cls, "Decrypt", "([BI)V"); + (*env)->CallObjectMethod(env, p, mid, data, chint); +} + +void stringResult(JNIEnv* env, jclass cls, jint requestCode, jobject response) { + if (response == 0) { + goStringResult(env, cls, requestCode, 0); + } else { + char* str = (*env)->GetStringUTFChars(env, response, NULL); + goStringResult(env, cls, requestCode, str); + } +} + +void +Encrypt(JNIEnv* env, jobject p, char* cid, int idlen, char* cdata, int datalen, int chint) { + jbyteArray id = (*env)->NewByteArray(env, idlen); + (*env)->SetByteArrayRegion(env, id, 0, idlen, cid); + jbyteArray data = (*env)->NewByteArray(env, datalen); + (*env)->SetByteArrayRegion(env, data, 0, datalen, cdata); + jclass cls = (*env)->GetObjectClass(env, p); + jmethodID mid = (*env)->GetMethodID(env, cls, "Encrypt", "([B[BI)V"); + (*env)->CallObjectMethod(env, p, mid, id, data, chint); +} + +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID) { + (*env)->CallVoidMethod(env, obj, methodID); +} + +void CallVoidMethod1(JNIEnv *env, jobject obj, jmethodID methodID, jobject arg) { + (*env)->CallVoidMethod(env, obj, methodID, arg); +} + +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID) { + return (*env)->CallIntMethod(env, obj, methodID); +} + +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + return (*env)->GetMethodID(env, clazz, name, sig); +} + +jint GetEnv(JavaVM *vm, JNIEnv **env, jint version) { + return (*vm)->GetEnv(vm, (void **)env, version); +} + +jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) { + return (*vm)->AttachCurrentThread(vm, p_env, thr_args); +} + +jint DetachCurrentThread(JavaVM *vm) { + return (*vm)->DetachCurrentThread(vm); +} + +jobject +NewGlobalRef(JNIEnv *env, jobject o) { + return (*env)->NewGlobalRef(env, o); +} diff --git a/jni_android.go b/jni_android.go new file mode 100644 index 0000000..44f7b14 --- /dev/null +++ b/jni_android.go @@ -0,0 +1,186 @@ +package passgo + +/* +#cgo LDFLAGS: -landroid + +#include +#include "jni_android.h" +*/ +import "C" + +import ( + "errors" + "fmt" + "log" + "runtime" + "unsafe" + "sync" +) + +var theJVM *C.JavaVM +type JNIEnv = C.JNIEnv + +func SetJVM(jvm, context uintptr) { + log.Print("set theJVM") + theJVM = (*C.JavaVM)(unsafe.Pointer(jvm)) + RunInJVM(func(env *C.JNIEnv) { + C.SetLoader(env, (C.jobject)(context)) + }) +} + +func FindClass(env *C.JNIEnv, name string) C.jclass { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + return C.FindClass((*C.JNIEnv)(env), cname) +} + +func JniCallVoidMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) { + C.CallVoidMethod(env, obj, methodID) +} + +func JniCallVoidMethod1(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID, arg uintptr) { + C.CallVoidMethod1(env, obj, methodID, C.jobject(unsafe.Pointer(arg))) +} + +func JniCallIntMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) int { + return (int)(C.CallIntMethod(env, obj, methodID)) +} + +func JniGetMethodID(env *C.JNIEnv, cls C.jclass, name, sig string) C.jmethodID { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + csig := C.CString(sig) + defer C.free(unsafe.Pointer(csig)) + return C.GetMethodID(env, cls, cname, csig) +} + +func CreateObject(env *C.JNIEnv, cls C.jclass) C.jobject { + return C.CreateObject(env, (C.jclass)(cls)) +} + +type PGP C.jobject + +func InitPgpConnect(env uintptr) { + C.InitPgpConnect((*C.JNIEnv)(unsafe.Pointer(env))) +} + +//func NewPgpConnect(env uintptr, act uintptr) PGP { +// return (PGP)(C.NewPgpConnect((*C.JNIEnv)(unsafe.Pointer(env)), (C.jobject)(unsafe.Pointer(act)))) +//} + +var ( + fragChans map[int]chan string + chmux sync.Mutex + chint int +) + +func (p PGP) GetId() (string, error) { + ch := make(chan string) + chmux.Lock() + if fragChans == nil { + fragChans = make(map[int]chan string) + } + fragChans[chint] = ch + curint := chint + chint++ + chmux.Unlock() + RunInJVM(func(env *JNIEnv) { + C.GetId(env, (C.jobject)(p), C.int(curint)) + }) + log.Printf("GetId(): waiting for response") + switch x := <-ch; { + case x == "": + log.Printf("GetId(): failed") + return "", fmt.Errorf("GetId failed") + default: + log.Printf("GetId(): got %s", x) + return x, nil + } +} + +func (p PGP) Decrypt(data string) (string, error) { + ch := make(chan string) + chmux.Lock() + if fragChans == nil { + fragChans = make(map[int]chan string) + } + fragChans[chint] = ch + curint := chint + chint++ + chmux.Unlock() + + cdata := C.CString(data) + defer C.free(unsafe.Pointer(cdata)) + RunInJVM(func(env *JNIEnv) { + C.Decrypt(env, (C.jobject)(p), (*C.char)(unsafe.Pointer(cdata)), (C.int)(len(data)), C.int(curint)) + }) + switch x := <-ch; { + case x == "": + return "", fmt.Errorf("Decryption failed") + default: + return x, nil + } +} + +func (p PGP) Encrypt(id, data string) (string, error) { + ch := make(chan string) + chmux.Lock() + if fragChans == nil { + fragChans = make(map[int]chan string) + } + fragChans[chint] = ch + curint := chint + chint++ + chmux.Unlock() + + cid := C.CString(id) + defer C.free(unsafe.Pointer(cid)) + cdata := C.CString(data) + defer C.free(unsafe.Pointer(cdata)) + RunInJVM(func(env *JNIEnv) { + C.Encrypt(env, (C.jobject)(p), (*C.char)(unsafe.Pointer(cid)), (C.int)(len(id)), (*C.char)(unsafe.Pointer(cdata)), (C.int)(len(data)), C.int(curint)) + }) + switch x := <-ch; { + case x == "": + return "", fmt.Errorf("Encryption failed") + default: + return x, nil + } +} + +func RunInJVM(f func(env *C.JNIEnv)) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + var env *C.JNIEnv + var detach bool + if res := C.GetEnv(theJVM, &env, C.JNI_VERSION_1_6); res != C.JNI_OK { + if res != C.JNI_EDETACHED { + panic(fmt.Errorf("JNI GetEnv failed with error %d", res)) + } + if C.AttachCurrentThread(theJVM, &env, nil) != C.JNI_OK { + panic(errors.New("runInJVM: AttachCurrentThread failed")) + } + detach = true + } + + if detach { + defer func() { + C.DetachCurrentThread(theJVM) + }() + } + f(env) +} + +//export activityResult +func activityResult(env *C.JNIEnv, class C.jclass, request, result C.jint) { + log.Printf("activityResult (%d): %d", request, result) +} + +//export goStringResult +func goStringResult(env *C.JNIEnv, class C.jclass, request C.jint, str *C.char) { + fragChans[int(request)] <- C.GoString(str) + C.free(unsafe.Pointer(str)) + chmux.Lock() + delete(fragChans, int(request)) + chmux.Unlock() +} diff --git a/jni_android.h b/jni_android.h new file mode 100644 index 0000000..a7d68b1 --- /dev/null +++ b/jni_android.h @@ -0,0 +1,18 @@ +#include + +void SetLoader(JNIEnv* env, jobject context); +jclass FindClass(JNIEnv* env, char* name); +jobject CreateObject(JNIEnv* env, jclass cls); +void InitPgpConnect(JNIEnv* env); +void GetId(JNIEnv* env, jobject p, int chint); +void Decrypt(JNIEnv* env, jobject p, char* cdata, int datalen, int chint); +void Encrypt(JNIEnv* env, jobject p, char* cid, int idlen, char* cdata, int datalen, int chint); +void stringResult(JNIEnv* env, jclass cls, jint requestCode, jobject response); +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID); +void CallVoidMethod1(JNIEnv *env, jobject obj, jmethodID methodID, jobject arg); +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID); +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); +jint GetEnv(JavaVM *vm, JNIEnv **env, jint version); +jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args); +jint DetachCurrentThread(JavaVM *vm); +jobject NewGlobalRef(JNIEnv *env, jobject o); diff --git a/main.go b/main.go index f4531a7..673c910 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/ioutil" + "log" "os" "os/user" "path" @@ -134,6 +135,8 @@ func (s *Store) list(level int, p string) ([]Pass, error) { fd, err := os.Open(dir) defer fd.Close() if err != nil { + log.Printf("password store directory = %s", dir) + log.Printf("error is %s", err) return nil, fmt.Errorf("Cannot open password store") } files, err := fd.Readdir(0) @@ -262,6 +265,7 @@ func (s *Store) Decrypt(name string, prompts ...func() []byte) (string, error) { } func Identities() ([]string, error) { + log.Printf("Identities()") getKeyring() if useNative { return nativeIdentities() diff --git a/openpgp-api.jar b/openpgp-api.jar new file mode 100644 index 0000000000000000000000000000000000000000..0ff1dc0db47374e1f1320a150b53f4efc29b2ed1 GIT binary patch literal 55335 zcmb4rQ*>or*JdiVZQHhO+qTV$PHfw%m=)W$ZL8v>lCJmb?$KBE{{8JS&KUdZTx zgSno$6lFj_QGp;KA%TE^i2nTk-@^ig2ISyu!QkL%W^ZNhYG&{1@}GA{3r7YaH&+J} zXD>%rMKd#JHAhn;S2I#3dJ|hC7Z){EI3S4s_b)&|pW{G4DXJIpC_<>8rM4bMTGt*0 z`jt(pnuuaGa)@MB$|;~^OrJ(p6lPKx)r}j}!_T*Dw+N)zen14{p62WM$-}F1=Esv6 zH@+v#7EdR&wE{r2#5M!s>%*|j*6j{P%YZB8P<==0YcL}6IvfO} zi8!jQw_<~0sMc-DKU%YvC@Dviq?-oXeD$cjkre2wm>w`lDZF&RM|g5+Z9*im?lO%O$wUAJ=%%phF%z>0pdb@W59&?&W-S*1q(!-m_ohuKA^yce z^_iyWb}S+CeLD`)XE}_t#m;9x?J{u+;LTLC@V(e(=zIzfyLmbHL&K-bbkZuo8f;b= zpcsBg7dE!2c7aG+d{IA87f?$z7&UCG18X_k-ki&Yc&<27X5e#`pjg98SNBy>LTGFDpeFgCTNM{9z0cE zT9L965S_n#gHx1&fK(kRJMIDo0wMti0#f{I$p`=;{Z}QU=xk>zjjyp8>e%{`pXyuxODQi3P=zB7#lY^R|7fDB;e3(kfxPz~hS zaYqn!0o*v@g>D^FsBFg!Hh_m(E!fQY+aJ;gSjgcS!yh>hPF z=k!idyhLI~lU||S1Zt?#APoqSG25{*QA~D5mA#vC-mMW(nqlgG?M$7iBE1M&T8N%t z?=hi+{03DK0=?pxPp2gh`1a3cMycaZQTVf&A3^_ZGc)~noB40sSKUqpMFZ8Joq;w4 z3<*wp$-1(dNQp$T89h=M7Cj~&xG>y7#u*C6h+~VE@@c61nd1TDrDUPPE>u3}OhVv6 zp!und!v;3q3BV2OG1KLvpX)O1a(#Rg@bv*B$lxE|+v^IN(>f<=B~H(AejJ*_7j=A(IPkGT0KDMV)!nuzT@zx$8-tgM~X@d?Q;jLLojZ&Spu{B*W#t#$x9% zPD>v}$TG)z8fE+#be4e)%p$Ug-hl9~*OVdpL|%deVvwZ!XJo z!>!JLmYk%uFcneArGqNr3x>@urwO+4kg8XR>(}i5<&O9SH|r(RW2UqH9bju~Zs`K0 zPqI@(1y_)qL~)FVHGy6?^XSbu2$n!;Nj*7wI^WYSK7^lAEE^X`G6RoTxFvELB~=LNP&o4!X>!S*EYIF}QuG zB@-m7M{O038shN^CL&T#KQ=eosa2B;W}?R-sq&+QgZU@la&tB%%%WUntj`YrKJ5rC}8+gca8wTTskfRO02?22HD*KuMwpI30!_R zS+^9nGiCrhb{7xiW}ni_%n&RX{5sIhW^0uVq2s1?Msdo z4np5+$ZECii0>wSycoXPSzB*K_sH`Xp@8v%K~XYute&D?Cu!M5VmpEQ;YuJV-fmOZ zvMFYf$=cn6qc<;KrZh`_CIlJ}s)|N}5KANAUb+C>Ha#t3ae=EjsT0MMjWPw=ddulo zs@*v2M1P0k0kp$i)EX3=1L5Qshg1ALk^c>_?*jdpM4R5d0-ux+KaUwlg@^1Jo&<}= zJ%ED3OZkv~@Z|c18~APz1@vGfmk?Fp6LfE6yfDiK;^3R!Vsuf&w)UAFhTr2YtA71S zZP+sqnG|kjB5C6HMAFp!NZ;|e4;H_12R8?@du(h|NB&2G`d?JoWmN3dB=?X+a>Q>S zQ}G10&Tu;4@_Ux!7youXL%!TAP*zyf}#m+v3y#w4NdjA-2vv^nZp17>-Dinpk~Ufz5(oY4!;*t(4g^VkoZu3N z;mY*ptq;IkKagYF(qQTGX6uZN`+dtjtma82$2dkfpgWX&^HJvw!YUv(^1%J{0qBZT zQ_%<4EF5P;d*G%4*4GpQXRG`2r6>c2_P|g$fRp?B4=+5blPi~l0RaWV{u?h){R=M$ zyII+qia6MtTUq>t4`LEWRfe^a|h$g|k67)sC&5!d+f4}(pKsbg}<05NL8dCC7T^_Oy-4$nXjLIOm(VQy*lel6S)yHr zI%BD{Tw!QjB|N-3H)EkytkL+fISCtuF#OTH4_3*p*JBgXiY_D z^Si9&L8tI)+!4B#L|5m9`jEha*;A3PzvbvPcF(OuojacURP3f^flb=)X!|bpd7SGw zB1?bgW|RfZdc?S1xYY<>C7s;%vk1NN%U;<*U|e1>-OPxHoc03}3d^8f`Jt6+hr`QJ zb9Lk!IN~;Gj2CHwaX_XO5Y{m*cmUT3FX{pBFUM$!bP1-XiGxX$`WMn3O5NxySfA+d zz{PEvQ!?p{nBn}<>H4Vv3de%bQxRHmEg6Gvxe_!aN4w@u?ar8DIVFPu>eL! z8QKorQ7Q|ugKA51(Heo}=Ey=#ms;|LBMQWj%t;SShoGC;%c^h=)1bC9#8s~1wkXyAU_8M<$ z*u*k|#OI(};OVR5P**5$NEO0rZUmiWw$lEvt%%=~*Pc0)Le6M{;}fXlDcz+J9?Ig- zTUXYn8ptQ3i{dHr+H&KP0$GUd>g;!Pop*PJ>KLV4xNkjbOQb)Jj5tI^T4*zl-kOtn`pbj;fctMtGi&^x}T*eDNp_ufAd%1@8LkKPfI>x6^T5b2`WccXeubN;cpb zW7KJkxnnL#WRpJR1?R9I1c+)a-eayA1>K%!46DR;4a^KIAd0e~K4weT%rB@g@Pv!v z9C3V^D@!eKvso@>hS|IwkN69D>WR|vJH!1`cv zS_*a_UXU~9!S7UCBC_hZPRFnP(^cpiEqR)TA=|}fZ?>{Gks`86Ol<1Pm8+O99Mjw9z9AKgC_D&Q&fY4o9`h8x`_VvI!IQa z5h2_oe@QmRUq~)_UBtKfMdJG#M4-1vJ{v(vJ8Q4(5m`%D98zPJjIM+oUxb6O0wiSo z)CEyNoe?Dw0{HjNK)_FEjO6}GWN{iARYS~NVTB>ja^uT5$_=?jw$jfZXGFYmxET!s zP<4T(7Xn0#RpDfaYQ*E5Cz_FJR6GON)`LL3M6dz5?y_uV?M2kyA zQ!IM}5cYtkB|va2AEMNB#6~!sT0N!H~+Gu{wboIhHTIelv=S#!wK*>o%*EjdfgF0 zzA=F&*afzqZM+m&eSyU1FI`Z$rLs@V(|G~T+mkuFL+>Vk!zsMkbUXN+e=y`RPv8})HyfK9wv`wi=>xNJ%c0CUK-u{=I_JonVS|*u^;rD|ZBj8Id3`!VUA?>V}xZc%49F zu!j^tK^d|z8VDis1^f>#x_A{F7yL0pQc(Yfi_HHeF8&n}|FbERxn~B+h!NqPVz3YZM9Hn&ka&101CUZ_$C>EnRbm)n^_zKn)KKtYet4J zl?~^L?AB>o{oIIpbvDtw)}pI67gp9{Ri{bTYq6fZxqOEDwxc+B?h@tI>s2UOAl}rZ zqE%+9;Iqm2+ZD5smc~MD_JXv&BDHH^zIqKl#wr$$r9Hc?4wppZc;+=U>@agoIo8x% z%)TUwlKC!i6jv=*=m0RE+jn~(CUO>htO}u6$jcpDlYUxk6LBq%$wV6-oYf-W^G=gw z8nO1GQ+>3Q&SUG#@8tfs$tKB>m*uHLh3bY#1F!9JXkPBLSt(sLL4f`Pnsy~;Irr2^ zvFk?nQ1fC6*>{vj%v8BCz*=@QBz(RC;T`W5v19n{9{7tR9RCL>ZxArOgrRYT_pw$D zBIg_L^n*{WBETusD>r_PM!k4V?UE!YGKIamr{u(o^|+?|K=Yj9VH52E_p$(rKFEmKK{moYEx zSwj-V4S5D(d>`0qdjs^H;ai8#w^?Hlq4!;@8ap>-qNCsXoAVM;c&Q{w?%r>Q4syn^ zwf!IB8JzsS`8%k+9IZ#f<0g+%9SuDE%in zAA)b7+e100Y#$PCHCGa0O6=Qy<)b5T?xCOvX16w`usqPUr}9TAdI(j=PDQb{_l@wU z-;L2;&RJI8xLo`byqL~1qWU!%sof*RGU6*bkH4_a{x|*GJ)(7$Kpx0&)m;I-5rDmp z^rNe_ir(x3*uk8jY7F?wYz8!3wUH0&17wa!)m*HlWMYm7BJRCQRIj-D#}hhVg|$Ot zHPXop8kMeM8qPKGk3BW5!6O26J z1H(UXp59mFuK&l!%s~GeoYVdP!}(v3JVr@Q280RGufk?!`N!kMzLuiUWM7d)WgTHt zYY*X6tju_32&vB72JZ{VhmvuFFjbHxVMeEy1Afxj$jJuJcOBf5)fuOFlk9_dA{r4M z3rsZaqz;FW=R+)K?F3s8rjQAW0vZd|p^~{k*IhA;>t(NlS6NP}sUmAjVSR41V5b0> z8vjOfO#Uj;wfyKOu2|yScsEk9eCnY2raAgHrfgId8E^HC#7$+XcCGLd!&b(cV{+yn zjSpK}%c)=SEYT|8971YdUAqafFy%S88I%>S#YoQ{1>|OW!n|9Ie#zF7&%UYofdlk6 zb?#I&(J5kc!Xc2%n0N;1=g*B6b9_!mIHP5ae>V1E{PWo>UAV7c{oe;meNd*odI z|DT=tf3_Dn>K863YN%g!4OwyvP08Jagv8pUb_?QtZ<6)R$?C)<)pmzwXg|ji>E%3F zvgl9=IEz@y2RILK!jSMrBrHC@_gbO}e9!yX-2vUd*)F!SEXrqD^O@m$&fdv&@qgZ& z$_x1Ij@L_n==Kmc8*O1d8xlzP6v7zZWsHeD;7FG{#7{&vbgK(@Ue|+8!kKTPYB?-y zIp`UFeupjn?#5edB0N$Yn+)t{-=FQmt0MF(+{i+AWPC73n73`Dfu(e#lCW;0fv#4e z4`9g_{1gnmC`2Lh-HjyGE_QlGF3WyAeOhUObH6xdQ)r-hu)SEd3#+o%YCbDZ9Z`P0 z`sjX3Nw@Hcv zsaj{8+!8esiP|!zMMI&Q&Bj}*zhfk(scnU}SdZq0>%p>g1nQs|X$H%ko&T&YHK)W+ zWStFe1~=>Z{?~SE%8AW-;TTWv2posqF`!x(44?1Oq(&=!#tXV-E7*-t;nGw*Fws;j z)(mz=akgn$DIJ+J&!q31oR5Uhr+0LM`oc5tQYLdu!P1h*?wD_)9)=s93EQPlb|#9t zM4eNPr(yQ4INSRM+gxnBQWwqkkiYSh_D9iOYf?*e}sjBp+&TW4Fg#ca{ zBm2H1X7y@5q4dl(^vrdl#j~}-GHo;oC-!huI`jcqXVrlwW^FH|iFR*E0@Q%0dKlU; z)Fkz)cN%eM0!pk)o!9D*G||4AFQ<7gbdBkg)dwh+D>Rla3PP}p70_vrmZ0=ZryP|b z`z=)?txl@(FsVQR>UDu#Ss%cVnM{*3L;SB&m71fBBY7FF#?mJJ4HIDcR@d!|*|#qA}{5>O$!j0<*HZ2o^M{Q)4=V5!Y46x81>6L2FxK$-!Cv3!lNBEyNE_2k+(qm>Mun%7v%6iS+#T;iWy%;OJdO@_tt%M?enCbs1OqKjo^ zHbUOs8%dVdsS%3IkUXrI8FA6_HBqZ{Z-NuW5r$hg*H73lv>M;l$$EVM*pUL_DD25y z{u=G5<<%g&@5%V2)He*gAuY(}x;3w*v3a{ax&Ro-qpA=n3^-{<=$3=ML>G;*wVm=B zcQ$(qpnaEx+M*}g2?3ik*R)xF zZeLCPhE4s;P5c#nfoEWFTa;kC@J0)E50CVYzH7!f=w4`C;x>2Efxz_vxe*U<5L?hr z%2@yChe81g({ar{qf>{OEY)&XmcPV!cie0P$~oP`nP+lO*6rDy;>8K;0d ziqUm`7(BHR!O1VsT-uaJ?g{L}X|Yt+f=HpL@`i?-fPAV#<#`^G9|2Go=t?ADeCpc~ zQeq-r6ovLwb3)1C>cpglP~wA<(%Ln~exfu^^XZV1^1#N8{Dso$*eGw~%!NDQpr8yy z>aVyUd|}T=x`$?&Wq2>&rFxPduQh%7UZW&9N^Ka zE^7!6l+Rx=*BM!ZK%Ff?(8B)o`d{Rud&5=s_iPa^>G8*T^^O;;#WyrKk>s z<3-&()2FwK5MJfnD&TIoo_$z&7Pxu7y97?)i#OS&L`_2ZO(#4jJUus`IS#Lnc?AC8 zbvPVc;vkj-m?NzS6u^!qh2XGKv8W?sK)&g)yLQ>g6IS)vNa-Gf*HxO^N1PafD5W2k zy|37o>Bo}q5iYqTBz4~3?Mp)vuwrS0Db7&KuogqC&fR&-(4f5o`*`eieraFWF7IZ^m0n_ogfK_-4X zD{NB1YsEx^SHf~}Q3(Uy$~`k}EDS7vbsg>WEGn#;22R~%a&-n6-4&x~P=xeit9jX@ zZUCA(u`58DzhrGK2iA9d8D~Ceb0Yp+?1+eb2kQ=QSjf8Cc2hSI_OT=&!FQkc&?bPl#=GQ;*1mCQ8;pzhyAAw!MK8U9oA{4$Ns3+EkUMD7v+C znJCqv!8>A?WrU3K%MF7HEl;mZ8xlVN&$P(5Gg_;WPElwncZ4O!LtKzjm{lKsoQ01! z2FLUAGqFFE)rm!#YQl7C@D~fg-5_BOnemZCBi`m>auaK8Lfnzy00Dt% zbcqcein^E)yn=Rz{4W@{V%LETpO8CN%qIq{+Rg z#DE-8o4H86Q?kmA5(xSuByCQ8lHrS06=!m3RnBv0hSUKiQVSh1%o=4(*-2>bgkl?l zPDsQXqpq@5lDW&sc8cQfnA2E;t>SB-$euDkU9DUN@jRDP z*76$oPVlI)QcH=XCk!1kj?mqd){wWPr8+zGB2x_Gu{E4TBz_dV+B?upc$}P_(FLyv zYw+eVD1j?qZ86xyY<0vRy8kj*I&&D+;LFkYVEp#e2o8%8b9TK*0b4W~2Un4!kiIYz z(HZi9UwA>{iWYYu-db2Q>PDi7;GcDf^R`vT`D4m1{?(Xq{L4E0pHm-Ev;QQOtQ_o> z&0O4UUH_W-%Td)+L6tz|gZot<9UOIPj2O-&v<2oyL`=PljZUg1ROn|V5D#f$igGPz4VpnzQ%Ew{H=gr^k>+@u$=UZ!J2Y&3H zOWbBQ`3h@>htpPY432i|S>Heqc@%xB?xwSoPOlbp5o0Cf1BOf-SXBzABJk@YqcQ^b zh7R?swtaIsmVO*g!=om7L8^~5jSqS$us>a-YQub@)elO2y|^TEF8fN#Xl69CioJ~~ z_gA8o7;_&rw!|%W^x-*@6nE{l!^^^6MG_@u6&tC}E}|rWHB=SaiWw@Y6K3*3)8-O= zYHXyuEkz8ED>|naWd8S#qQvAU;6if8PP+&00q>Vc`Cu#ZBwG^sfk{lRh(5I2^qQxR zGIy{y_R2wo_OQzQ&+BD*V#fDxP6*2^Yo1O9EplCQE8UJx>Vy~-H>pXY$RFDE>gyjs zwlr*GF__OM&Jw9Q%+{#{_Iw&}T>*Eu`vk^ZiU?T=liW~yn`m1@>961ratOfZP2@iG zG7|EI{R3U?R#)2PCr%#*w6&*-oJ$^s;!$?dna^rZwD7*L`lq?)snEr$;uQP}z z9V^xCSryxaT0@EWd%E>4T3c1;BZPTBY#;d;q89pN`U~z1!QbHam3-rEKdb0Vc-xpY z3Yt|M2>po{!ibbdC=GT&D|Xm=8RebO+C%g#63X1aw?i!WoOYB*g%$^F&tG=(+5ZNL zt9m4%t>5irXz%I$EH#YdF1p6yglRhqV!LxixVF4zLwc7(#ejWdSBOX#l->Ht%hTso zoGudPa)PcFa6rqF zSM&kJmG&~?2%kqBHWTg%zifbti;+Y>4dXwX_SsK>NxFm^cM$(b?UQ7aN58pRTW4@n zdHGC!oKVxZ!?Y2-2Rk^+Y*gya$kH^YKE1e#@BHqxeHFhjRN(P#0isjuCGcx+DpQwP zU4s+bJEyN|?!2CBEMQetIe^Ps-Ej@e6Xu^PZazO!Rs;b8I{()QBHMpo#eV_S6g9m+ z$t_HO`GzrJU4BqtZP9vVID^u1F&cC^;id#hMj`6L{X|+LGW+>0Ii831ucEZBJK-`k z9=G9b*K=8i_WMlBKO(`Z<(ott0$H@~`1E_c2@Ke2ng7D+G#Yw)f#lc(&~4%JZC z>rjOtJ%}}jIjFD2>ww*XzjNB^u_;8fywMg$zJ`7WXUG6Xl!H zPSmNOZ8^b8(9BI zUl+EwqU(wuucf6gISF!jrIs*&J@hwFxcj!PXp_3*;}Nk5e(tQZM2@k z*#Hh)Di(AYqg>x$TcJeLZdp|2&(R!LN^Qtq1zfA!1)^weQLm{rqSkWXiEYtiqxp3i zN54RrgRaAvug!0@+d&=*_`XTESf?Et@+7l9Y8y1emA7 z_iM;bxLSZEYnr=e=>5PvVg>{JcQ|fLB*a+p3xu z=S@IpyQRUFS!P{;R}PuTh2PjMu%-Tha{~i6erLa9xKGfdfZC?k!7j1WQ9lvuY5f^}wMXGL zf~U^`sP-;lwzao~B~UybC_T86k;tN!g^Q~vL;M1N2)C(o)Dl5sgWDmVHoaUT z(c+*X3zpp=iGlI*(hP=^V6Oqd+BdKY%)gH&12BiR@H)1gFXCc|lkoU%KcQg#ZuRHs zQ@3E)NnBPOl{}`Td5t#S*lEahtCm|_e9sqGt(gy&Zub06X+dh`S^lGuW7^Sd^jc{HHn%-RMqT1?(!fdeze`$r-h7+2LPlOxJ3VkHUX2lM?|6gQafc`{ z4`0%KgO~1GG8g#j?6VNUmEjmBTCy{34JWt4x_FicBZ3Rxo z^=iOYpJTd0FmZeXd(%Aw^KFw)a)(ei{Qa{9Q9~)O22V+a8JMQMd~*4E>@g10z84|I zr9Iq--W(}_T1_w*E=&yKl#kCS1|{8q3lton3DfZHr73=4X2p||`ymU(4LX(EmO;A4 zl1{t$2NuXBO^em&-j7DJZL*GKKaY(jB$MsN6f+8GkH-r;IAKOcMhOp*eS)kE!ri6% zR7ZUyV(s^hnD7^MVh|=|eWC$Y$Py0i8p4W;TISq!LDKEo$D!~$fX9aTx<3e5hi&@i z+zeJc0Fm(o1QJ#w^2~BEhLYf+4re*mY+EOSu^aByWlsEZKau{2L z)L|{vz!0)z{vB3%ZVnFMxz-SaK@sy~ulsO`TT6UgK4#^)%_hQcgYs1(btFI4cEd5s z?b-|6PQ`45jjhaTHT4Ro%Zok0>f+H)F8j4}F2(5Q7CmQ~4b=uOnVYLM~tb@TBVcjlgM#2gX_ zINGRtr&wv@rS7c#gG7W}O}girL;gMpn>;ApF(e&odn5HB(waH8M-Dqy+qAX#`YFa= z2IA#EYg`J`;U5#PAZh{Rl1ptfU-0p`u!>R?sUapq9uZ)GdexJy=BmNsO-A0htUjCz zC){V)fC~c8h~v=QbI+OndQk*lMAq|%0LTT2ss;OW));m2stlL9+G1G45K~e{eB_Bu-utTj@9F zgbVgU(#jCkVBnlc9}z6s$$dzy&LL)OA-u|J-7D@8_RtH}2x0vNNkna2mvkaJ(L1Qk zUb(j^CML8i?-fft#4gz{L5XkG<~v|gz_yl2hSyC-siP8}V$2H`iu4Dr ziRe~)iVviTdUK*M5pBIT-zp5{R0jH~6L8BMLTs%S?ULY!~sQ*8!=`Z3bM%Bh;Llm{kX2Sh4{CJL=jLr%Mt{SC`$xfJ(l&v)~Gn_j$ z9=B}oh`OHfyfslm*$}WZ2*Ew;S~_`~g5{6u=w7`_&Xlvt(&6*mJe9`7ER({(gZ1Nxa)V`&#nki^M!ezJOFrNAlF?OId_jCj zbMrlurV^rDQ+?Zv6%+=`W!O!1+HXuC$^icOY2OWbum z8MdtT(xKYK=$cbNLDu6|rukBWg+wDQTut1PpAiw$IH%Aqgf>jsi9F`I9mJ7Z-kQK_ zN$gd#j5=zoz7L-DkSdMa)@1xxXm34Wz!a7;cg=Y;0mp*Ew%g-&kv(*@PjU&UAiSW#AM?MZ}7HM>J>}b*< z2cl2WrN`{`xnCd@<-dA6(Z6P|SucB!oPDXpb~-E%s(+P$+<;xtlJQ;%@A(q7((xE3 z+wdfK3voeh`t_m}%S_H@g2Gh*+UPCy}mJoonLLVIGi6M%3y zpZmx8iKoF>_%zTfN;<}3>fshxB)`>|{6vz6-^#-sK-e06O8p_f1sZVZvB??*2i*!$a^ReOJCH+5z9)=Qv?B12$dOD=R6U6`OWA+c)^C~ z7)x#&cOE1=L<5#rCDz<3h}XdCuw9L65Sl$ z-N#nx5oa$y?JEge9|*0!pH#$9Nm?>)NTxVqP!?z!ZOSRIAEEH}Y1se-ba31G< zh@?v7!lm$W{5`SU9f$O->}nE8;?_Vr@MLBFvq*w%>B*)-DnvL>;X_B=bqVETh2TTp zJJG`a{ih_hdVJxDZtPtN7+6`v=J%OkBEmENcvoFEklAJ=!Ni_y;QKX6LV|C*R)j-e zj0+$QPy~+w-yP?@_T%28X@>-n#}-^|5eg(9lzfFR>QC}4?Xf$QlVhpWcuQT|(xVk@ zloMDc$@F)b%wFvDt*c8ST}D{dC(Byt8IDvGh~T9)OP#8~rRx;s@mw0B#IKEx^9hFE`0s0b*?iRv)3|KD`qv>6E~?{<8vEHA^ z+WDWs&A%VEGyKmeCTHeq^k;t4=&!OMMNLTqM-257VB27%2i+8kO@&S;4YV<6~!Er4dLC^QF&q}A}L8Zfbuyc(b({3)j5QzY1g90B= zXFAA+F+pF`p@}p~TdqhZ7O3j)t~V zBmEYO6` zh67D)kpvuWFk*4c8?|zf`|-*;P@~O1KXLT@XJvz#RfB23xH**R!0uk+va`ajZa3@i zDH=oW`YF3b0AGAZ!)&}!S6#~^VL3T(-ubi^#>{8rk1*!7xe%8$xL2f$4xhzG%6uw| z29$fz*+?kH7^b?ye_&@tXf1)uNXY*Es2|#e)HJlrN3o6ayZmjR#$EAcx`sa z6TTg|acD`h{HS>UK|SS$Gj0f(`CGEG9onquw^ZwrUB$t7DR^c504k9%lCd1FEQ3cGlewK?)%z+bzYd3a94H&-TvY5uZ@ z$y3L~Eu#D zcG-QPHjj$KI*ZDKx7{)5eMVH;m?>`vgJex}6us(vW+^4pzIP?v}0n%`=Lu zPq5PmBDkNnELe6tyfdUzofL$CRLEcY5azM`!!#@`EpaAcPWqQ(r7;7iOxZlha>Nim z;pQbL)hoF4tB=HAThU7elXo83Eks#%sc&$o%)kG4Hr2zDb<^ih+Xwv5Q1#yn{ole& z|EGETe+&I@isjFs-k+fUpFus+5W9j|RH>bEFdRs`DnF$_<3ME?IEK*h7S#K3UQ<`@{P zmW|l(ay;%+EVd3ylnz-&#PC+(4w_~Q?9}8SE;_>|Bs%Pu%I-rhbRDeXK0`m!Ul}T! zMxe6*IxKu}dT3>qcA8)Vjkr7xQg!SSgt0a$v>TMQng$VH5BHO%{!U!rGVC>0p0SmC zuG4i%oGkm(9J*S;yw92g4Q?D{wG*m9E zD>C(p^{LfPBITt;QP+=aa z4K$nH5QulmMadCxGsbd9zKU!3nEtHI*?U05S(n<_m*JDUHT8CYwL3_)^FkT-Q5(?o z4&ZuMI6i*LlX{r_Ry5>6>bL7Wq^Cn+7HM9+t9?N(RZfg*ZFGe3C${2M#;*g{b@m&D zAS;Cxsnl?Z@0&Z^Tug(Kv2xciKOGmFjQ7|jY3Bvob66!D^b!vCbGEnD;DIfRpKqt) z(?+JIQ_C4$G?9)rbq8VBoD;aiIVX)VqQe;{g|T2u5#bLP2wN3c9d7)Bs-hq%Ja$|> zHQ$gxQ+M;Y^5#Kwoq%YZ4=qKMX5w z+4X=__WoPb2YOLnqHEAc&g0|vS}FRH8LBOcDf7+nNS>LSU;xaha`zO<9JZV53xcIW z@`TtpyBlY?2jycsh=5jF1)DAuEPOLK0vNc#P)E$JA_?b*j?C?A@9r~jFiCYE21xJ@ zLI|E+s2>?)I>I7C_adY}prtHk7nBW>vEL^MCHfu8UkKCb++T_@do7Tiw;_1;HUlpt zEKbY=5$ihYig10>FLD9mfTR`RF1yRfFNjd%(vW02klgMNbeplzqoCdoFIOExK-7$E z95xkHJ>d(vX|pFa;+i;jP3&Ei{Ia%2 zocVs$JpmE#o~;_Mkfb|yoU1D-VSmZ;_>lfVR{2O;JaH~;lU)YSY$fphas%Z4mWbPk zFakJ$A(D3D&}5yknuBYHPW}wZzG#wM)iG`-mfT|*yIOMqPF_`|GRxE;TY1-q8A0%iHfzhOU%#5IDu-1yo1>-3(n20wx}BKHoXqc#9wh*S{fc6Td2^CkBf4) z<8$gN4fc_s>9I?4N&-g5QZP8(2R#EjjfVuI5d>@TdAD%>{(*2iZ*-?-CiXO$!(;hf zX#wi5KzK8A6Er(7czy~?t65Fu^Je;b?Sc*8wsaqVVro&S6P21os(O-d@Y4n6S-IVh2pa%eaa zQ+I1qQiExRo%>JB-z1-Z24NxlFbRBb|6C#qI0`~0(%_il{Y{K*LS2FnAQUZ25Y z?335+_}a51i{^t&?9UU>noW*mZP#4@thx{+zOAP`rt|tV`tN+>cQtxlBqyX$YrSgK zE4xIVl=B)LBzaYs7a9EJPD-}M{#gU)R+PKyUV(L|AmnFE_60GCWRM-Y4S&m(W||E4 zu?TI1-`H!+u+6(BjImyb?cIikV1Vr(^AjKLTL`9$DB|*nS1$!PREn3JhNH~{Vr9EG z%fY=~GmLrkrrS+3`JvSLN@jkixI8T<;gMZk0i!baz71|&+Jqf7qg21)v^?_?srAD2 zDUw5_*ksi=ric`}r}W%#bZTt#MQwJQU_;s+Rg!tBJIi@b<^l~`3=2kjgF?$Ro9aTu z0B29a@u(B%>UGw8==M68!;pFw9dI(g*L7(?Y+%O%mZOYz*SYk7@KRxjl@;Q-XQ_D- zes%0XSKBwwexfARb}$^yHTJBsS(9^PT48ZGKQuD-&B_U+al%mxTzOlWC7CMoxPd=K zpff$pRnZ(_y`gD-WBg8(D68IX^pViSJvMepWo+X-zOY!IuP5k}lVfNR&M?wQqJ4iw z^>FtxhW1;|>?vb%hN=d}*(CzXR}6Y5dBXRf8#rpjnZ)G}TElQKDgGB{?--n0+iZ=l z*tWA`+qP}nwr$(Ctrgq0v7(h^#mOD(WbgNURpe$1-*XWn&J*VWxuj~+c5 z9YxXzOB`ZPU_4RzX`w0A-lFxAot5q_H0|d0>Y!>h-6W!dV!}xEQU_iFE{0p zN6BmLzd7C0Vl{5P->41WzoIr0|8tl5-=u8*<3|5*L#qA8NB>)iW3^V7(ik=);5ST> zO~EwOb6Y5^1Cb+xk)zbR%AeM>6t^=j%hRZr+n^ z@3;H4HG&`L3K4>XIZ<8h#!EO5-+uF^sV!`Z~d8xW{)19tY8gX-YeMmLuX1v-z zdu&%-r(9tB&Tid;&gdlXVfSknallQTh4*weG`$B9d08&XC=|TbvZ3!>Tua|OOPFiQ znRzEEYdfwvhXgj9p4ILR;=Q>?^JMjp0(_4_hPGTh_c&OZ+V(Rvcb;g*rp>*Sc{Sav z!*p4Bq){(b(r^z0V73TUEz7{B8sAOBR4|lqGO0x02xzlBFLHid%4lJx2+dr9s?!gr z<@^yW#Mq%h;Z=3d){Eu;B|@Oy1u+-Bi9I^JfxmKtDR07Ks`23ujZK!g#t^EF4bE6& zC=!u^sLnt)Od%%C{ z&MwFwAmJ#J03i|Y;v!{{g~|GZWOU>LQaU2CS0I^;MO2H&3g!Yv$Q;t2Y?wiiiOPmX z?lZZ4^;TbmB0?c~@q&`bJR!vYH0jG#%i5NHyMLx%Zi$qV=?Jk5Bf2Hi{1UjaK3 zFdwgs>y!s$m>gW!Ty*P=K+}k+MAC>>>GH%Vr<$-}xeK`iJV_&sd;gU&@VyV=E%^s-vT?KETvQt*>fr1+^(rKf+XD z4u_!@I!1>*4%D=lTCaxEL?e8tq9t2xw%m5`SDkIcV8@h6DyNzJ$>U~rpUvEv`cHR2 zgz5*>J+zSr4KdAOWDp^GN8}r0jRM0gbJ{!R;b$em;Wqz0@$iRp-fd95-lPP>_{e*< zk0JLQ;xerFoCAxxJI;e_@os|-IIHzmSaKV{Yo~&_#96f*xq20Lt3`Ln?c7MWdf5o< z&YqfereBO`H}F*_U*Zi3THjmj-nLzFn@Wa&t~y>5BG)EFo1g*8Nx z>rD_#SH8>&jG(EhuJ(JQ3}dP=56yD25!q4NCuB1UznZ+j?Ki46MLbE6FEeBe-S;T& zf3bYoZ)2u$>BqIlMV|K-OtBzWf_0t4+ z?RSWtXYu@`kZq_x*j~cTO>wLmiY0a>r~v;>I^!7$6D|4nl;wZ*6qf(7r~E@wSkdtG&{0L> zcW+~7_LXgRNs`N2v<%FcE`g)fXrN4_QO;nK6>77y$~4nk44jb3AZ1alCTcHeyMh@n zO9c*U5m*#T6-7ne*hX{|6cq(i(a|ue>~r3mnl|~f5WoHz_;R=7p8h@S{>JHk<$w9e z9dT-+ct}Q%=dx7kk`2?m<;gKT#P0cwj^KXdK#t&k>+mbPSN7@V1`oe?YN&^2`=ki^ z6(3>Gyy%G<01}Gtu%zQPFRBVi5JKoWLwYR~;y1b>xW7Tc_nRCl=6R0^AH#e*iFx9n z_b;5M-*MsD`BS2Q`?SWxGcaVI1JEY_h%1-pI(xEv1^G}cEYAUuv(uLHGiUa-pILg1 z%FZq7qrGNl%Pow&cL~i=0uThzXfs`m7&!T|u2x%2;?pLF7lW1+cgHAp z^PUG?!v5@!0va$s7wYLLoMnC)CaNfd{MF}--Nq{J|JN_?aEJ^KZpZxJB4`$ zT?H>>;f1ri2H8IYg%gM^PpAFz*zltSWUULz7ED}7a&WKZEhTrUuQ}Lx(CuPE4~JrV z&P-VNwn-!=#+BFmiwVpZ7c`8enXvG$Bgz&793I5N4;#J@wu(J?b5({N^Nkb)%59;A zlSni`URN=XiP2eGoQQKf19RnI!9y#$T-k|_i)V8^)c)zl;?WQ9FvLjT(r8gx!FK@( zZkLe>8vSnF7NMNA-*f2YD&oB8?3Pk)(|j^A(z;n{%PWZ1SC<$1BN;=IHb;&GjP?R@ zjCewXWidm7)h#?ZSc|5cwJg`*$B)|!V&R&spWchmajFX*EITx(XPpX-xvLqQ+dlWF zwJGlY)ts8&#xl8mYLTkpm7kggG&Ho9iv5 zzeM-*$Y)dr+6m9yI!j)-l^xl+yOz-6V~LeBPX!f@T}DU6;r@t>;IQRb681Xwe^G;| zub@FlD@VxVR*HaAuR1e=0z1h_mlZ{FTmbJv%xPobr$&j*sGRCkl#hE1X?anRYn=a8 zbmUoQq*fg0d^Jw$krM3l_G-)1R<}>9-wBvLUg~@gu{k>5ESg!9oJS*EQA;V#UDvI~ zKpO8IP1qsnkn7u)s4qpLWzC4OTM^Kx0?)S0QEl$p#yoAHW9GcB`g=W^=0XS`w(DBQm?!6Y(DDFi8A|3 zFUvf!ZJz|{pt9)Y^yfn6Xv66xMi_4R&!32a@-y%7pI-FuYIaUsKmXxSh7~Z?TC56qse?{j0MPo3Toj3ay+>KgosQOwd8C& zC$2)JQJ&1!ZDXf#Qo1?ax=#fIa*VlHNe^?QhBQwT7jCqzs2O_8Ce4KXEJ{3MHuTy< zD9(ItSiKLe0KcgyYJzH5Q+gVDewA^|=J$>D&~Vlu`|Y*CI`z=9`c)0xpk`3eS-F|= zo@3CzM}#&xlTqJmc9-ls2^CFuG!e;OQ;>l8&0as)2cQZwwI*0{=2j}xB)8CP$sZVE zAxt5)GnWH<*I>tB#Zp%xMs#|cs_Nq%``Pw#{!vPkErraT8w!!qb?KDiU9MJQ&#hG= zc&Kg(43BM*ES&+sr|wE#3vH;M?X?J(o}7WD>XqbD^@w0p0tmb`OVv+RQ}v9Wt52;2 zX~lC%6qm|Q@Xa0>=!7zq&lkcAi9)DofUjpunTgAwvm2@hfn*^?IaK$N?Nq0M?Fl)w zOV7{Ft0)4EhH(QS+*J*sEN4WF6VU3;R`ZLgeXA(YOnFkOTcX{F+P9bROR0SuYPLLr z{{BW|=+*8uQh!BdR7b;Cq_l9nYEqyng9|sNo!Fm-EP=KoSQdNGGaNDCxRNGZc@@ez(JkvFr@$BuQKOvk)4&AvnZj*f<)vPh~`8RXqj6>1|sn}Os5GQR4i zv@K{(f1WQlz3SK?tG#6i+=I|@Zx_O86kX!T(w599;H%{FTI0%Du_$U4$n9lZCGJ{? z2b7EJ{*rHq1>jgNiSzQ~jm3m)^uA=UbV&K1Y|hp_9i^;GXyT!2m7y`_m<_w%Oy<55b;6^0EqN79nB^a5h~HD zKpiozJaIYq4bsF)Umjj5MHu57*aVj6IeLxu{i?0Tuanwf zjrv*b{KyAQ&vV38>$_F!#w&_;d)?hm6x>2RL%rD*DL=)|BaBcO2M}aC-c=mvRSI)t zcr;l*#pRm^C#uOoI3-ds63!UmbMB|{6NpDYeUEQkR|Q-m*U z0`QX0$Ec;wFX`&jv&q=MHDQ~yj$%rGO=3;irZcCl|1_tmCNd{RB`?ou-2R@0pV&$1 z?_Mleg@BV?&_KZMWD_f;n;qMk55)uq-D_9>OT-}ATmbL0{Lq~-V>R##G^?`lvJhEs zIxy%_h#q(k`wd^~6k%JYlwEm4kg6}5O2d>Zr78W-b0dEt2sLXQ?@_Y5j-Y9{#g$l@ zPXLeiM3`~9;F4>$?hrZ2DsW%j7%Gy}XVnGB3Y^kf!^0*H-VCfA*qIqYuMiKs6E!IE1zemCA{j{RxO4>qN% z0Ur;(y+?eL9w$p*#O;LTPG17H zi|EF$;>xUZf^PAyMqw&cRjP@>i=)+bRxD<588*q;vK{b+X{NT_5zH5t38#I+H08tS|5aL8AZ0C)sxr;#6k{=}wn^#p>wlkpw2m>Tv zQ;?9{hm1LL=_}iGB&}LMq?D@YOEL0lGd!^gWCxqjbocDvOFX9GZ5V(NcQ zoJ*TbdZF%(S>W^1)$>ZLMUgg5CgePfTYHYGjuM&cnA$kC4OFm8o1{99W38c+))&zv zqM1Vb^%x@IXiDjb1^8hb`G)aXYn0*}-RfgC+Ye+*ePY!_cUO1X^B}^BDKi625>r%hibgKBA1#4>{K+-DE3Zyag9Cb~oxXq&Fbn zzd2OM@kfjW9gI7)!A|bf%o9B2iB|ia$zz7o^mG2lTsx|}9+|p6+jF~)lPj2zoVkDU zfcRzNGvc&JzliMI@s3V*Plp;CtOv{O;qJ}Q)UE0LtT5rUm7YOI)P>PrP(Pk}a*v_D z!N6V4l&Um_ClK8Y5k)uXr=HmT1GLqh^&MNEocO9-Qgc0_B_!uo@UkJ08Q3C3xYz6e zrjG%S6WJgvwNwMj>ZebX}9+gmg$|OkS*o8|J7Y-l)Ee_B~waq~S_v1(T&wm3j{*ABT z>SAd_|9|%~1syE^k*^RNBMUvqfGE~y!P*M_2uTO(XpAUNSoB+n$|FcaSO!YcLJ8qy z5X6ImaV1pSJVPJ<`lXZqM-4+s0V+t)g-LcNDt9T^K)b^rZmBkRYsGWy*xYK$rkClF zU`Tb3f(fXzwzL^>l?)=;^W0U5v8+PY2ksK-fQ5Zb1$&k^J&)k7RpuYDrURWwCdBE_ zmSYq|mz!8SnPF-{`dQGA^(75W6A753Go1fIb@Y@;f0uu^0WQ9ue@1oq{-sv^KaKLg z^x1?BZETDTjjjKoYK@KUvHDiw3o-v7){GKf?1CG%a}v!8pf+ZJ1crxd=bs4Ycvf#(D+^}bePGI?Ju?KUHw$lfQt%| z_|T+t0eKd0>r=?KNin#zO8H5(GkNw)3g0w_a)0PmY5lSAO=YKElid zJ9+9rz@wL6mf7rhO>DKbN?Tl=IOa&n=3WXd@aA={H$nij00$c>46~J`zkLsBQBBz; z4^uK_``c*W;!X5avg6+dB>vawrvHf%|JNaN_OvrrF?9YXBd(~)I-`gq`WDCQN@Lpq zjS41!CSxY3u~{2SK)U4+Zj3@hGcg`ZQ-!y-l+r}#uK1OV^QL|!X;(DKkcO+wa-KYu zEb?lFB$lR3(^e_T&$-N<=lSt=y{+;0eE}Ju#W!b+YK0AZp))_{w8Ek5H#{eee9%x; z{JFtrbG2#wYKtR^M{v0~t$-@gQnP^4snNEZddf-L0Bp~@2{)I8u?B{qKdj{B5-f%UAp|(Gj0o&6213`u+_NT)*%n3MIC!hMe9`DUuJ7A ze}T+#*wLkjXxGz_ttcVhu7e9Pd_3>N9l`aJ)$$foaU#8W5}H`lGYwkLZlfu0Y})#my*In}pzf3@J(f6($3051(q9Y(Yrv77z3XJb*Lh43Vf$ zG9a4qw-sy#WBr&3&02XNuoxX8KRVS z`o*u&3C(D=jKPBnENc-00TG&RsQ_X6N)B08C-DS7J*0VGfdpCE5j2TcO_$J-=`WCVC z)#J%*zsqW`_PL6X_rZl^d-CS9EKW}iSmU!QO5d_X>LK#`6np;;%IZEP^LwpJdrSNj zfcQ(m9DpABqnhwD`}xJ4z&HPMD7^9OtoW;GtlGw?pEju9R&TwgOOg*qjHc} z#*a3g`BGt(0)2)^S-r;K&%t4+fg@GA9M*_2G(Cvw{rFGfY+jp^ct+OppkSGuh2l}i zVt(tR(YIvMt;yJHv%j#%&Lc^Q)UntbO;BehB#c#|M4fCoQLyCzTPlbQt{_KQf>@Fy zEt`zUR&!S=KX3^tgyOg1UAFv-K+C#uC~+m>GL&~t zs?3^4&bR{wBf5NLcU4t8W(h?2km?_+vQ+&0ehCuBG6-=c#_)1-<$+}hrDIlA(Ltni zuq6xcF%>=ST(2xv(9ppF6@}yT2IhE9Oh?tVC-G4i+M2ruhxlRV2@PvqRsZ<9JGh%H z@hueCOM=Mi?mWv-aqLLr)`$`}9%RW1AL1n;Od6zRYaJ{H%ScGJY?-qG6Nx2&fe{6G zqTYU~gcC_tRV!6ZLPSM3koUtnS`}YOXwZUS>RZ7t?gvQV$(<>&)5}Gwtu4^xu(D^FGn-@gSpZ7VaSLk6h<=8Yd^Tx?fmYp!)1IeOSAVr8NsUDh)1BEfC! zrXq9QA$*)mLEdzxx~qD-k-%01XX$QumQ4+xRiac@Pku6j31A*OdC z9x|-Jg$*C+rrHaG^UOgS)AWL^%$RRrH&4s(W5~c<4NDaKrLI;XYdQw77c7{abZOQ< zCR}=GhR2NgX>+j4VbKDyuaQ4O6<$SGbtP}Q?inavm&UqoZ#uGh(@p_0IIh)V^w9&U zXg{9whF2q|Y@yGPi0ar}pF~|jrRZxS0%NbLnJqa&=?am|mC15>sD?eJq0eF;|8(Mr zsMV2_NsX5KH0V+2|LOt=v)iIQa)3;mP9{a|u1K6(_oQCRpXCnvz=s*~Np`F@u*wu< z9&1_PEuJK$rVcBcYNHjyDSa4u?CFQk6Ddn(T z0sAA#tV@@PxevgVvCr=ynDM-DyEHxyggHijg2 z^rF+4`B|}=s*I7!_y^?>KD%^Xymow-Y<~S;^)g|8=ybb`EgYLw4q|l9Og0!H)id)E562<7?2R6^RoLv27F#qaPw!uYZwsl#Q0g32HwhMt znP_5j#xp$wV#&Q%Gq2Fc6GB$NLrkr3?b1V#{=1ozw6qNYFlcdt9GUdOP=z2)_1L)D z!z_NUOk;_Q_jJO3uSC8R^7;kLeqK>|W}U~eqeU980fSKdux^XCgw>mfG&wmO4A!{#+6hg}o%IiihZrh5|szSfJDV zwp*eVM&{57RG%~Qn|aPoaQCP$tf_SX&ff!pe6!?;4t{);7h9@38W%T;%y5@%)9gxZ zy>S&;p0byrr|6O{(d3<_pP(jx^Q|iq(MR``{E0=mmj#4e_+_$jX0)B}O*WSed}M!3 zwDb-*)SKIP_q|3_FU^7@H}9F@T(>_)ZD};WdebY_1d8mKV$N*wfKsu?iIF{k7vI`3 z%=a`iTv{;Lt-`cPv>R#gVD(tUp2R3^pzo|&n!}Il|*XC@ft5A2d4IfU-`PV*6P!vj(=s$cRH6mrMAV99hf zT15u{Em}(A)EEs6Yz<9ue0kw`(D*pftmJ%{*` zLzUQQselkej8IRX1D*LPQ|e|_@Ct`&901XspoZ<3!+lPzXeDReyw{O@`%_TeYgkBS zhdRs3-evBS>i*XQFoXR>?X0fhhK?_^kCLx+*i&?M^*8lMX&4KX>J>?tPAOF@&-G5#LCKehGg zVf@lZc4`(qk=THc8T!=ZY14Cfo3^KUv_CA&mMx25Av7}yB1g5@lVq;8hq=$VkE|5= zx{KXHsLzSgsmX-cnSG8a`B7_zhfYqILTHqOMSHu;u!|#>rL?TC;jKg7OxqwX!>C`9ivK8)9`H zqs=AP!@ylmr>=!=I6kRqG|O`o~tC%J7jYmv04*`ND9n;coc9M(hpQNfE^TOwW~C`5odBioRd*lt_1&_V3eZ{UCD zwp0h%gZGLa^g((2Xx|v>I#atn%h`?TV~gp8oBOdtC)o|gL9x%<{}U=akQjLvhKFL` zw?8Z7`o}K)KE+K!NO+(zavTUjf&(xIG@lnp` z06*1!JdnT6U_7wD&|p5OpUhx9h`-ced7!`IU_Q8?(4ai<_s98QpE)7?@q6W`mgLcW z0_Hbcq`heS8$pcvW%a+GXy!qk^xjcc?|ScteK9I5FL+q@yHn9`;I*c?Df_!lc|5GQHBYf#tD65fd7)P~-MayKvFv}OpIUoFspgZR zxrSQ2fhmo?ve|9oTI}DKz_<8CZgz3u7mEUQyWX&m`^Rx1@CoJys$u9jD^x7eR5DBH z`e4u=c2%Y$EU>NOx!O6G*H<*>_R7t1{o ztheP8r-nZ;JqFWaT}8Fv6|bIK%5rW&9|kIQlUm7CaxGJtg>6}L@`YbJaoEZy4psZT zt|7j&?up>G8@x)zzx(vIo^W; zP%hwyd<_@y#{`HA_{Yd|OQx_LF@p{`yuH03?IIR zxKlMcbRxr)Q#U$nMu(b_9Nz2YB z;&|$e!q#}o4tm{DD2lm1ABsS5#y@XWJHvb)VBaCqsLw)vOWQ%R?Zw!>4fF&dZm;|5 zs)tA5<6BtomfG}6SikiOMTDKZQ+ilx7x|>FvMva~Bwb;38WzYRvfCjaJ6azCiriKKq`B1!OV-G&d}+IR3JN=e--8|a-R_WlI1KfjR1KP@hpZ-k)y?M2ax-9HHb zK%U5gpm^-X(F=KQ?!NpK_GnhX?juLh!cHa0Q0i2b_Ja`L zO>^_vJc#s@$-=2v=Tj$L zc-LiStK^Ev&qdDN&nUM24mh$c3UHT7%;pHT;AXJ7&o;M=Yj1!&$tOh9wPVtzVrlOj zn36x_f5C+@cgqL$2tR%Vko_Cx`fn<=|2s6`@Si1argq=kF#c%;Vvm}(@|GCtC%Or> z+VUt6EJuovQaK~MAP0+OG-YK6sT{6QU=mvov^A1+Y>8A;VEShu-(!3Wb7k_GFnN6L zXNBAxv@o8Lg(1^JjJo-ppZ6noI`87QH0>jI0MrH9d@v;(r4LECB^rTy6Fk5oW1uFA z6D~Ppts$U`>dJCnVX@$#R|ywf*6T(<7z=@w=0Fix`dOp{q@%z{b0jKCHO!-(GH9A( zNMz%|cIcsq@!$hJml zK06F`YD(D-nR?J|y5Wy9!)5VJ(RH@B=oCQcs&5t1irQ|b{s!!)bB5h7cNwyTD7W28 z6-t4)kA(2-y3zw>JnLs2ar*CC>@YG8_ggP8Na``*!%0j76-e-u-qk0x9_uv@DkRSS zrWRUxjEf2urhZHu54}AOZk>zmr;5$lGrTI=78hB(z6Q^TX^$3H5P#xx7 zd7EVVw5tWxxwTw|>RMi9B$a1L5S65@946Do5EUcu9EDn?!P9Lf8JQKA@rJTn<*?x+ zCS9-6X37rSzJ^lH2DPG_cXR3ElO!`W8oq)(e)->C|FlQ0MIrhqt7a(IUy95wN;gEMd} zg!1&Qj9X6wT%qyx-;qD67Ck<*DGVVB(HqP{zWOqAY~l6Zh?acmbZNq)jG z4&LOB^S+>CF$iTTu18qBzJxjy5SCFWsK43v3miT1BZOfA5=m^DByfjLCft$K9^sEt zl)_2KlIpi~xh}CLJ&}D;NQ(>`YuP%V1szgzBisF_vF4{aDvMI;HG$7C70Hb*G*74( zoU?E&2_8U~oU_cM*z;YxZb#)H}_G3$pD&2usEqBgG&444N;XGnN zT5hmFMjPWet_Kj0ME9phd47N$Qt@!U=pvkuyGT-?;~ia~=aFQ2LMeh{a<7=NiS&?n z3$fg$_Cn>aTR*^i00ZGA3A9Ic2{p-+!54X-QZoxxdoa=QF{9NpY~+9RTU#yMD!spF zh5!7ke#rm7kjL~7$Y`zVeWRA+K7EQNU$f zen&+5;j%iywgn2J)M74y8#Qj8@nPT7_XHWvD zZajkQOVT6jp^lyx;I5}ibUv~`F&`6RfHF(*ph|hfVU`}Al#mxQh9zf`%|7iJO8ogq zGB~A>l9y4ZjR^#oMl@le&L61%f^#plk%0WmAn%41KyjU}@#gN}J~eqFKmNStS}u z$4E_`c@JZ7_=Y;p zIesX39ZMq3ype(!qtpFP3Y|G^nvd-cox)^iFx-c(W0H9%*hGhJH{0im0w<%DG29%4 zwbN*i)C}8oRkAh2aMNxNq^B4hhU?S9A$5Xaf#Ns-H+t8rUFOnG6in6^tA;vwxO&U9TXdE48O0cFq+}y zM+u)hY#*@}H&Zq1RW?c2Eo|*&HN#=m6lbCi!eUWdbK39+O8&ZFpBsW;9m!Lhk_!2A zWG*I&RG+@gxvotsVR13ZFnJS9>~`(76zgSuUAnKuem<`*E&*ML)s0GfbgxCN)4f>Q z5WCV9%n5A9W)Ombru_Lky4ABnMo}&Suq}&=N-INdH{e?-?P47DJxEsV>qLR1KRS;f z>rBX9=?U*)tChu5629W;V(A7JmQc3WEfVLCrWx)JUInI5tNrFSCiAGsjG-VF#g2(V z9&&duCAY}F9-%+GM>V?#M7v|pOsnI*=BEr19!CMrr==_{3897;V}ecDWG!$Pb4t>=qwyL~NJ#5ntw{ktLboO5Utd(XJ$q!`w){c<>lV}b{2-wH-QXbk z*YSV3|IeM{|K}}6-cH2Q(8k_e*v8)3)I`S8`Fr=Xsnb9Bd8+)B6|f*;4O?gRd2kN! zE-y(s>`#3{a79G7p9yd6XRyRW(+tgj4xMg5?i3Gd*aZqz<>^SZq?q1m? zB0=J{2=4$mIwM`@xvybG2Z3wJ#t3n8{=17TtN5HZ{M|+7{?{(D%>O@w{%2>}_nI^} z%kNe_EH;`YoKfq=3l#3$7#uQ9)tgI=;&G8IpqUjH8$WWDy8AgB;mwPM|}+D{v6JbSiWzlZ^X0RGspb*B_S|;!2a(48!8hsl4Q~ z;Py7@;JOgmEcb4@)O8*ni-_k`z9nqoc!(~Zv{!#}%Mx!U!;Hrm}8l zeqen$4j{0ody@0S@HSFC{GB;+)tjfKi7B!%6v4qcM5l?-%m}ES!9rQKbY);>mdTm! zURlS$?`a;X+RZKfGV6DJ?N2!+HYq3wFRv&_HOV6}$pa*?pNT68*prF^9mCxz&oYMP zY@kEW>cC8A+7CSE6p~HkjUo208Z@}ZG+;DrfRkzBDZBh>x#bAAB#dU^pCaNF{22{^ z9f|QQ8|oJSmNnkW%+2N>ZD2NTQQ+Bcapm0#nrLGj)icwXvK2|6x^mjkrR$n9HIIVh z>Wh%ZQ%mozBXH^s@co+vcTVD+o2YRa#5N%UmF`FiVe<~<_lomu1>qB$Cqv)9PVfwF z_a^}6Bhdah$eZOP;H*1oW2;?2Pro6OQ!D6B{=Z^Nyw0Uw!1n~jzY9(Nn_TQaR!IL4 zL|V0=d{9qZ{pGthH*~=fg>a34qzMHuv>eBf(@8*U5<`e4APp}b8n~0d)w-tefj1%# znZt8ABI#ixvrAm1H#=!Z3HRqq>=rj`y*cgTI>k53B(vM(wg3_+M&X}((-&5xwE};{ zOY_Zo4}GtDdtc5T^8L@KMOp&qJSw7l>EhXYT*yB! zf0L%YYL$BgC=l(1+6e_WuTN}IOGz|&&j{u+;DLP$RZEu-$n zq)j}NqF28$+BZ!dtOi@a4yE4FA>~nnS!1=UbG_F}_`}8iwxe@>?Aon2Z=>K*JeZw< zeieVk)FNS1K#DB=cb|Wo<@;q|Yf{Kx7 zDz_HzP3ukTkqwM1C|8#DE$gv`3GEl&N*JrZNHqL&mogMF*Zeq37b&`IS&PNr0CdT7 z!kyja*7{a*%+piL%TuV`T{K8GcGp9|1r&}<^j3=n2NLt(rveT1qta)<3-Byawn;;A zWe@B6atA~Uch@5U&NYZ5Hneq z%MdJnCL@#?_&wSM=;2Fe38BGjrbLBxK1AS4o$brfy2#)J*y(7;RwQoDwv;+WF=`$8 zGOc9nG-${OYKt#Y_Grtqs^J+pwG9vUv;3Ng_=|T|NbFT4&W*em zZlxfI-LL(gDG0%ogb`%rvzBck9XOhxuxsoXX4+gmgG8%5ba-vG$$@70 z8+ekI=K>_D*CD9OkcjI&Qv@00D-RmWk{FGYNRXSTcGDDiTS%`vve-h8;XIDm1Oe4) zP-bP*W0`hXNSG+Xt0bNV2K3OXLoK0SIc=P_B7`l2+CNO?`v=+=TRgV+P!~`rVR{F{ z7)h1mOyE=WG4SWLG@{Evy)4mRLy++2mHlqF$gD8}qLaO>{6C*<>bpIGsF0^K6Cef| z1do3@?=)>Rz?YU1JBaXwbg$+Hoo%*yjE*I5GU&xgaWdk_u!|1mdJ$QI?+5X$GVU+l zHh`bVAi!BB1*V#q9fguLO-WN#JI(%rwTiU+@Ysxt4-J478G4=g_`s^S&Ca9nnFXq5 zxa`rK5Ziwms2va~i;^*5(`Eo2tV6ppapRyz-zhG4JNv*!wXV0#!Y+a0J-fz=JU3)k zAB=UTxZrm}J%dBlFsAC-RWyMXPBBfoLZ2CEN@}Q~QuDN+GGkQPZvZO*)}>0DxAkD< z3A{h>v6-2vDDxZ!*Up_|cyVE4$B!;2c0kM+XgZ^rj~5Ml5NP2~liz$!=(ENJrcm*i zXGBtN+gDp%o@AgK(o+ps8PrHoPQR$?^iYs?8!nnbYWEfyB;97hWEL{}%*ePXH08!z zl^1G$@QSeu$5G9?T&+E=CdmRfCP(xXYog>sOpqf+PK@YQ0~S~CYDN5JHZQNO75nT7 zcv(zuu?xU}k)Mw(*jMP!ExQw+np->vC7&abX$vEDDR_4opNUB9*+w`?-y7DU&`^<5 zlq@=ORVgJItiO1MB-SobjeuID$T45`az_5}=ny;>+pW4|+pW8SPjz=n9-N{2bwjry z$lbo*gQ8u2W9MNudZmkoWJ{73=2AB;fVao|n*>ZuBV(g@@#GAKUBsy;XRo?Q=vU?T zEFKk{qDm?G8D(l7+9hu!#Px|<>g>F^%GJ?R^)@L^{zwYlyl84yhxqZ<%a6O_$sQkt zV?Mr;J3JqaV{XT!>w|(p_i71kaTWLl(Q%FqG!^*fIwyVtH4la3VnD&<*sxiNgUE5k zv~i40FN44GOpBS>AkHb_56yHCO>^N@Fq;ZHUdEVqjGc(-F|1f2rDN1`q*j@!db|TF zgnOt^`6>XSPm1_6e(LoxLdCmauRJNp?l=Lm?;}b{Z~l@|AcTrv0)f)AVJg8sLiIb+ zXT>0a@;6ZG5Y$woQ+;Rr?pWq}y|FFxE8=3p#lH`U$$^Y1X<4{kY#DD!TqrmT3C)bJ z@b2(kQo5LV0cEmHpy*+R=mXr!Ew{FSixwV}M@oo_VrMZ;eLyf_I*jw*?L zMY!_N{F=(44z<@3oYt;Ngxd^F?Vwd8%Qyxn_btRiZNCr5VYZSZYx~-u<5=RdO_{y8 zfz#c-)8)H!lc$R)5>0YiYP}L&0+l9|U&!*%6=0d*rKvs@(DNDzXsq}0;sD7(^5}u| zIU*uA4Tf?7>KZ=jYIq3R=)W)vRPdU0~%HiaJva zYo?s$<2~v}V31caU1|`iy z_6L5aMeagt^nS8-m&!>=qp6^=q>mF1Zp$~vh(tU5pb}}J77kH#ppQ3DTFOvIn#48o z%NlC}+=2NX`KGRBUi2)>q(IE9Fe;WTsw zjx(>hAEdKRI)k22Fz0zs#-UK?3!^js0KrxLAC9zU{IR`T$$QWnMA}iUBqfhB#^^+l zK9S=U)>h-Aie8!7UPh{JiMm@u!3RuA`YemETOEl|54Pm!wnd&zG3m}PlZjNi2?Yd4r3W0D>-$Gn7%Ya(6qz*9x4HZ3v) zMQ^qy;*C@>sVe$}>DNr2uU2bmTw~+hQq5$>S4A)L?FPFRxf4cog%GEL$@|D1(^>PR z00uF5X8@#cMh@9d{JP6ESbAs~xVR)<>Bf|prChLb1|q(dl`a0C$2exjF%h=_v!NVQ z7l!aeof%$}EL|~#t(cT0@qrwW6Q&rBGh={bcA|K}kAW`HY1hoC*Q(Isg9D=li2+Pn zi~7piQN$`ek4*FjAe&o?)W=nZ_{F5%3GiN+aaO9(^5-+nO__3M*lyCPKj^QZyzt;s zmYlvxe5TmXOMsA>MYritM|Ia3(L33;L36>A4&1lSCJo&(`Qq!8IVQF`6t+6mm0m`z zzudCUBHug)9^)2R;l1jT$#YY!S&|Z5vPx0`F#uS?D=AgcNnuCxQ8B#|*oPMUnX2Yu z^{J&7IElRBMM+Rn$GSiIptcMk0~nc>0gY4YSI*Cq=r*OP(Ma?|iUs=x8U~{L7^%}D zNtssotzo&$n;PH~tk)RXpBB+)D5;IIW!)HMI)+P{oEu8%H}AF_E7t*6>OXJRoIvkQ z!R|NURSEYRZH#m?B6(N-W+_%#)YsvaswVFMR4Hy)CGH?NAJv;RRB@_d`sOn2CIK)2 zPMj}rZC!lrxF~1MBRc29c<1GV#zge-a$cMP<%~!w_9&S6#lMf6>6UOqxM-LvOg%z* zajoeU&=>0YY?t~CZYfrJ9NrJKV=$V|8dhE)RL@+sW$gR&dj$`G%NhYb%u|eg0(fS4 z<|5k`QEpSGQ;+cftG2fQiYtrScJbh@!4e!2+}+*XT^sk{!QI_mgS!WJ3l`knC0GdZ z_snPE`)?*QbMNh{u7c{Se$Lwa?6Y?-dDk*5cgKAw=$sY)Wm_gbx%rna;1@e3A*(jO=W z9-3XeGIZ!}wXbjor47p0{I@i*v!LqKDxoG@@)uRUEQV|L#7!vJoxD?;lW)gd9x>c; zfu|PbAil4DSbGI_TSPZC!S{p@vEQmBtt##Osag|Ce`4W#Guen50?`>xT=i=XSy~@@ z&TLPIDmTyzv+6t7r7mX~=PKs!c$PGQPjiD2s*laJsvV>-H(ceo1=o9I9JpA~QTTO< z8FiW3bs;P4;|&x?mYlT@r=xq8%BoV|B2A`byOy>C>w0fBmaU_c1c#+A`t4MXIUF-t za!}Q;W!LkGBBpj%N9qbH@4nKTo7IBgTHxi?)vr{y-zc{b3fLH$+a_{YF$)H{_)7cX8nkLx^Eu($DX;%e;*JbfLB+Y1Ia?~#3anxY~X$c*kE4sEgH z7gQ~yr3VN)f;RRTo^cij)D?MW)mdJh*TKVzDWGF9Oy<_1Zi4_)!%$dx2Oc<9Warb?4yqgNV&b~p zFsy3`stL6OP3Lw;{%lz%b>(d-G+XZlhpEuBX?v92JD*jNT@cZU-`S|USI&c~309Ok zvSLtOwZeKT=Ty=!rz6iA!#=KJ9QyZk2ufBtLq;G>pP9m)iExg!e2NjU&Whi6c_p-v z5=X@dGwgSGof@&h-a1{*2)^zO!6$83$tLN<0*wqNY}@P??pww-5j*{!X#65|{6kEV z9~082i|WKU)T7ZzrMr@P*~!dghmLm4B+S5=Qe*qBXg zm>5aN0c?D)5a*>v|0FXk1Fb6nb4&WP$Lv;W6(VUvW@1;Q#lA}T>(0)sl(KfvkI^!{ zVUe|AzBEWf9nj_^&#Y#T=nH3}8@5sU9|$~?J_kiQ@T@+I6?owC_WaPgL~;hV)I05R z50-dF`orf!(<&zTgbeh#Q2c)pm6kMi{Tor~45cHPKSaR-RT61R%axIp>dayk{C7?v zNqnHB4IxpXd-stVm#X0_7{`t=udAh)kfl992!~yq)oJMUByJfT##7kWyxeKN{g{Z- z1u48>f<$vgTft^H?-T+PBs@G zfYO5UB4Is5XvKk^&>=Q%Uv(MkD6;@+s?%um$ezLpgzClUS9}S49>f%^$v01btBn#{ z$-=AByz2OgK)nWIhhsG{Pq=uX-$)D?jFB928glT+isNv2GynZ+ zr1}TcoO}0~XJmt($5h1i_p=jdxyu6cQ8a7E17f$)HlCWE&TIDtB%U+Ykrmy}VQ zTJfYYP3Q;cmL;T;Ui;>7s@O{&8Rw2i-RV|N--)v?(3MYD$t0K0Is z`T(WUCN#Q2w{#Vh7_A52bvVa6Z>goW(Unr9k;*m^VxtDo*%fZJEEid)W_xK^6}_c0 zH6@`68=chH){%D#444+KLotKBdiY44#;M^6%L(xEXJB4Zxr!Ea`7DR#Ys{d}J~@Wi#~ttG|m1H&&&_jZh6?Ey>l`}XkWCJ~l%`=AO-&ztRn zu;c6`uWW;CQJZkTZ_|l6#L6uE*ndkY$$}P?1c@7$QSzsDv9{2gGAE#eG3zfSS_J;4 zul?oCF75i8(zgN?t3Nshds$C8Pdnz2&Isg4^g;s!#5K3;y%Xh(mg-8RDOI{!#1kFg z9tVy=Y49rvL1awIKOl|XMc}}MkF$B)kbmd*JSA&*11Op?x>2hL(by5-?M1jJ`rCye6&g zTcGzB2#saeTD$|S`J|c*fo>X{L_l-kP9k@U5(Oz$g}PLJbMpK6{_sBWfhIk+zy!uX z3a^T}`c)jC!c@i+%4r5Ns-)UL#&XlJWtf8Fbe;4`e8q~RH0dc_pY=Nf z1zOBnx6@efPwI&qBw=pNmgmQJBkri`Dg)VI4a~+(7z3#D1kwj8tJPy3M5gYGsHv<7 z;&W-VIAI!@e37ts*Xi%R)b~~-NrY^qTj(&a2p^(fc{=o0T{2(91f&Cd-lvg4saCy7 zK_H*v3q157jT`4SwTulfR4#56-Gd*f#`n>F*DWtiEkrxEC3h1+2*SBic%n+mPLrD4fqfN4pu8LOU0b;&W*Ix?T6&7= zMsDsVRRz5tvnLg1)u5P486rm3dJCUvo`$j=c-E(;kO_1TnlH~aed1?_p#DMR%#gap zY~Gq+G4)D0otPnxxy70RLj6wr7a^hQ`IM`fB{8EZGgn#+p7uu8M&?x9P9$ZUlFKR= z7^lT|8i=oKRoC~Qo1ek(M`-eEu@GF#k;>`yQOad_^G<+S1pUc1uPXDr7F=^LY3eZG zRpVT3@m0)KnXYx;ELbg^Dc2NOmR7;8nb9t(%T4Tr+p{ywuXT*?@=&$IPA=zh$Q9@IZDW+-2=#e`%;G<(vq~ zusyq=9*9`2_EU)$Zw+>s-6^peARqyW ziY4<+Y8L;@C^g7L;ZVb*8Gk6#|_){+yLTa^>B;r)PoI!CMH=3^mH zD4jn?#~s))!8nnfq@SE?EDDugHpBGdWferSbs?I;aVt23X&L8<4sCEz&>RrV=*V%u zp>GIiP@NR4R%KVdSVTL1llS~qn=4Q~y~hNK+>a|j8V@UY(TT{xPk(tkX@}Z=r5|w9 zLBHGuzo+gYSklTC<=)h3E9D`o_IdC5)kAO=m#vIoP9zJwf?rgrv<8nNC8u8%KXt(l;52z@deK zjIrb%ei4V7%<+sm{rbA6KcmVHZ!6ldfe+=_ziikj^sgSwiu%sRMt|tc{W?vqAl}Lb zl^=QFd1M+xC~PJd-NKV^#P4SDZrHn5!g30o8m2JhVixS(%5F=LyQuV|(tV*c(>>^e zT>rvWE&_7i2F(Xf&fBcDQU(G`Q&yYNmoe^{&p5V+8kPw@AT}kM5O5eiJa;Cm6><7fTY zmOP^(b({u@8|^RDCYHWx;6#_8(xq5~JKoSUi}E;_|G@-63UuGBEAQjX2{;VdB-FAi z?TUv3x5q83`4YrEHyV1}y+qrs15RxgIdc6>qo+IVF&1d&99|piIU9UBE?xn$j zz(iPs9XPY6shnq`(S?uVESh>VI1xHeM=OkfBXEs37iWI1a2I6F8$qIgNx(3(=L+NJ z8ZUx4H$7+&l0&ciL;hA8bFv$%=TH}JsOowRAWb}azgkC`WJ=aUW@QXFlU6sk?V*W-v_sboYGsS-P!xmaI?vWOU)!Lv&=tPdJ0=PSAk8?GS$jUDY8B%9WgTm znx)qdXD_9-35S_Tqr1EN53bfm^2h7j zvyWg+5hetX%fq$K(E=++gVh&>jBqYO33!!RO4Kd%nBcHJ{~4|B#01rq z-#vit@Dq2@5&47x#*m7G(~pC^jB+b93x<&RIRCZ}4W|&+=x!DG{mwlh8p9u)J?p=G zSm$dloI^~{$E7dN;yKYS36fvJ^wNngeiKr^3ixnrz4`q{CF(BFZ8~@+GgRq|0vutD zP6Em*~4r%x53&i;P!Z!OuM9LO(?R#^+ z+&D}|-yyb2`Pf=RQ&-$f#3U7GRGGe!LNe5yzS71Z_sDhsJZ)m2M689q`Tp3c<$KeT zynF|B;d4(+ba~x_*Ny^ddu0hsrK>_fiayM0bVao-j;fT0>4y8vd#UyG04GbeM`0zi0zHQFEzzG;dlhlSn9lflE>mx;#}i3 z1p(-qJ_`kxC}t%d!HgYkf)eppoJRLkcgi-I)BKDe1u<{I4UKZe)U|T(Dh`?PVZSvM z!i*Y#X3-;yo8Exl;?T{4w>d)8wq0SC2pS2SAjY5psvcO^Dd4H-*43f#Ogmu^*yiAv zLDZ(abEyqNh{Y;)cpMY<1inOTeIrD^G$^2yDPfBaw8NY2bn+OYuW15pB|J*K0Tp@b z91J5?>(EyMi$yephUA!_VPzg<=vN6DGB3mSoZ`(s2zwi3W>>Y0=WdfH=(Q zFJGwv3Tbr(kP&e!01n3w&I`m$I_o~0o*R>)3bcpvb;30z5GWUX$i3i5=R$45ko;}P zj~^LpMI+0tme*|7+FZZ2pZ)l__hZ#_V#SNx+aW=NkjteJp7qWaWmR!#!QI#;3+pUt z$1j1+AL-7Pn1`YkX{a&HgDo6sWG-s(TweW0G8Q4$r?hsqO+Uh{^Bl~qc-pMkg`##g z4IfR9J9r*VAHz#7nxn@1FWwWbc4n3gJ5T5q18a3&P5hBOhxLsspttqVIei6AI zKO|3FcH29|p3bsa=nLn*H58+l4iC>*o^}w= zEE`VZn^K2@z>#ihNz&?CEqT?hL6*82GZp7+EU(Z(l~**yeGx3j;4oc>IkN|S(TA^s0jroa0@eEFNzB(pYt2x zd$Sb)6-&DK5x856!?g^gHA-1_;T+xdXDLfHSw!<5dF?V3B#X%mjj8Alrjr?~reDhT zGGm_Ug9{rU>~@)=b7@+-H}mzu%BOIKZK=u5vYzgSJ!lm8wT+mkpbIU%$*T zR+$;jSVBA%U9f%QTLjd{w9z*I8g;rGO-iEPwjYtkEiVYBjGf6_Izo;aj9}NH;w9ii_d4Q-P)c&T#$bO~#g4^L37L{8M(Q=2yi)8TT6t3w9cDnw z*dPmc3WEZC;CDL*hgA>6o$rjw5{D)0>uLf~j^uHRYNo~WJC8l83_Z|NIfbT=mF2xA z$taKBq;7n8die-2PLhtE-!fCug~u-C)A&eR9l1(4uZ9U|gbTB8C!nlAjVI0Dz6BPhy0{yN5CLu*^@;tV&~)GR_eP-(EQcCucatGEgEhq6$1smogd zDmUAZP?|EuFLsNu${tuqt{0vdyuGA4TxFXm4`O{$0XuG5$9=L&59qv#7YJ7F&kvEc3F9{AsC2xoF*>@8VO25=%H_X^3^x!Bvjo*h*GAV{ zt+KH(AuleI7j4T07v7bJu5H{(!BKV!iU{=)o;QW^Zp!*@PQbRv=!OYkz2(Z3yCBI_ zxlrZG+qAiB4K3}he(vN|evo|6?ahxdvAL$hRkX?b9w{`p$>j#?lYq@Ko_qoWiBcQv zTydx-WfoeMzzuBGTq#|(j51e~nsQq>Sb=~t6-L%4C79tOvFzfezyTQ=?m8i&WJzT* zfHiwe67qX%G4mqA04_q)a+sU%%W<5ixM88oSKw=ux%*b3i21=CA0UADMm(mD#9Ybvf>QcfaRSY1Ho+=e`)^nQ!ArpIgEO^;k^7S`INwp)d zjTH5{S=r8xKiz5hMtCsjme-FJZ>39P4Nz<02;pqQa?^g9;_#{Id{AcIvL$RZqfKx+ zvWUI}D;D8&`|h0B4z4*#o@6tAUmfvabVFphCnJpLCE6{y(eRlXX*uw67#A^zB|6|% zMaf9s6=L=#EQ)qOOi6|0ii>I81D10F_0yshUJmEoZMQPvr2+X)b*V$Xwu$&FOnHr2 znBrIR7!)J9_s~>e);v*r0e2yAE<7G;Bd%Bh<+P}E#bVL8G#&d@xbAqAX%u~ZMYLZS zWI)l9Syv2JD2fQF4!}3mZ4~#YcYAiOP;8`{h$bA`d!~uGEMOlzz8;cYE@}0S#O>{L zh2iVac18ERGiwLmsq_6|mYFc1v8<49(%d7GlU9er_qxd67a>2&{az9TrvYp%!gdv3 zHM={umVqv0ab@%9{ce~A*~Xf5D|Is83LB=qu|DQCqaNEZ|B`ys}c7Z-CW;?!C=-#{slRlN_Z zg`GMoA+Cx-F+m>k0Ml^N8C+%$k68DoNo(fyq@cJ|1a>P#oOkE#%CWupeOj)H`H zY~yY0{21iwm8TQ}i^-yk`^9G>sFb2=gD5Jq_E2$c-#HfV=9$_)V7Zo4O_ad`jLOcG zv5jY125-#qZ0A2G+JITQZt=T~PwF$zvimN6ZRKOuV1Y=KwaYCZ;$C*4#a#Ew_4F1X ztn+`>v^aQX*sH6e)N6FZ(6&rzS=spxrl*7zPARetiQOBK!_Aq_Si_z2Io*%KhMgs( zVTBqE+S&>uc*`uwbe0YHE1ctVVZEH-Gv3<=?4e!S}{f9wNGC#KM z(9~HW)S1|Uu7Q;|=4j{oO(0TcdsOI8#=W6TX6jsrw5hVU%7_}k!IMSqixYalBJv6i z&gu_nb93HIA==h<-E!VQK)l2d9!z2PqS1+B<;Ye{{C3bKQUVzy?+|!I2ls;=&9*rz z5kDifa2QtU-MbA{l^hxMjN6JkUh;-jNFUNAF7Kv8k`2X@$iOBT*vJ3HlGQC-9*soW|HK&|&)7oBRDgsM}{lJeo$n6##I_ zmB?xH4yQs@jg}bhET)BDA0)`z03_9yJwawk z5d%(5soLKdglLivah ziw(v#CTw^GA2&8|FJ_^2rFF_Ue?{Lt5PaNnPhauaD<=AlchW{qfbH_G>2qvw^n0{j z#EteGxKEqkGtN<3y&ReXmIx~GPW9rsRd zjjXkRjgz&}FMg(G$W}{$^CNqrZI!d<71mWtqQGg(mG$-`zeQ$ytM`#T$gqdL^>_uc zV~mJ!T{NWi)$8|DMxiMKqwb70pFi_9f}GmrL{p`s#3z_84Rdao)Kq<*`C5$)P)lv; zsc>}5ggn=1A^j0Sd3SnoU#>Xb)|hF_u3q*{x}sD|g8K)>JafN8Oz{QR5{dMt3tWF4Is?op}!>!Uzl_Vxi#>)5{+=$}D)dMqY@!W^29d>nO)+MwW(JBl{ z4FX9Pnv*{=lgXv&Fsx{g&_U+f4M_K=hXXVTRKIeX#-_}Vf+2+sg->uuHIEz!&n?uW z7Pc1SF1bym&rSD24>VqBb0@Z3k;rTMJ=qR zqiLLe@IfFHNm@f%C%R~K3r(g5C0gwez`zSpi4@L6Wn%cO$H!$SA=r(u?0uLzDr_yQ zEaK|G7nCjEuOQ9xG@xq)&{N*h?7l-#4v#};F&!4>^d$JP#<)2Jl=)lX`XtV%N|F6p zY{FGSth&YvLsi)AD};a~I|pl#>BD)zS8C4cWAybQVO)WQhi~CUeA(?J5Z`fmJ*E&q z`Ca&f6LYJ$Rv1UavCMAL`KBYOucceZ0iwk%`pFBHx9jUwol!AxyBEjw?5cNQ?tb<- z9Lx@8(edqJsp{(A)ip1fwCZ~9o=+&yAe@F4><}ClV<8>NQFpyZTLRPezn+7(FfI3c z-t6=};Ky#lAP{aOLZRWluGnY^#J!W#5rWVd!OHJEsijCCR0Bh?M?|+nyh{f^3*`GG zWj+rPut+ruhM+mW3r(qbAD;5wjgWe3dMC9Re~txB8`q7>V)aY3fQBD}s36oDOt=<> zi3emlm9E;_rJMaj`>?d$RX1cm=WlEX)%gQcE?2(N46}DqQf$rfU3=Oq3RBMbjg7@ypHem>U4K1C0#p2 z<2Pn|MJRF+-p5#(U^N)+8Rc6i$Fer2rgoKn(T~0LL9&!ya>{lc1l$73SJ++31fP)P z&`!Ah?Y$Sx)<6$++%M%T%4Z6O;h-gu6)EI z)GkSDc2XDRt{^+NpIFBIi$-Qw5T>JfFIMJNfS|%1b^JPyuQG3(oH7K1CIspw|LJb6 z!n4ruT8}5;nGNrHVDAsK+JRzSgrG=U%2i2;mA9{TY%3Fxn7ag-B6J^Nat!@dd&WeY z9tL>sH``Ecxc!9AaO)tdq8hl$<*iZg5H!GDq!VCITskXP+v@Ye-(|;{XNL$jfa8|= zOKVuhOuXG=aa9O+e?4)>g@iQ`)5qZqhht`d&;16gh;p+3JbD9<)Cn(&>p6nxSy^c< zL+QMU^2=x|dBB@+xB52@vZ@6|L1vs|?T5yf?z@jcxlQ-3Hf04)aXjPLkFjkMbstW$ znHn=PT`V#KgyU&(A+xHKAbm0!eiV=r4fmwS560W{72O@bzg8AWzGYnH2rFIg;c}{q z;jlPt1KT^({o~Y^GH@Tf53KYC2P!T9T2T0}8Vmkhx}^+MTy`K)b}+UV|J9b2ps*wX z6cXlM`r6+xsZoCIMR}KffjUVp??DMIP%SWfYt`CIJyb|ig7oCm7#%LBEtwjqC#_Pj=joiF^qvDUju_0P&8Eb?33x^LM@%;XJs8Mgx?W zF#>@e3$CCJEU(1aHNo>UPCywZdW+;pG;>-y@iW?rUL(bS52obO_f<1Zmc1VF=GREV z$xl#(0-P{y02FHl7P338va7tsw|V|Nx^Q@ftpox$)(qhB<=0dHcLlcpocdpEs2QqZ zx{7o7&pKjFZ?y;tr6SnigPGrofi#YTfuj(Mpcz3N*HN|lFCmYW4ngMB*Ppbsl#jQ! z9;~jUyEjQ!3u-i;S~Z@2XSIA5QN889UFD0eTDaJ77(ZM7#@(@Y_K-<#)A6G}4a9ki zP{vWe0TqMoNCaHGr02w*LB>KysJUJ3PrxcxcE+5{qQN9 zW~6CT2<@}V(8iI$T_E_HmDme;lK;$mrVHweLxnjh_d*d@hLSqgY8PEDU2?z<+P zsr1#<8V+zJVJchHq!!~NfvMk`T;CTmd+r_VoL94TOjhuX@sV>e)}BlgBfsK-+0j{( zhiT{@_2eRH76Wk^-q_#&lLUaZ*w>G$k_s+7uK{I9(p{&{>u$mWs7>h){Y^ zqD4lJ5o{dJ2?^E5Rdjn7so0p@jBGI1Gg(*2Ok$}64vT|EZ!a?vG$m_9GJ~Q0CVen$ zETYtkCyRQ%{fNi%>^10ulAh9tX>4uk`s(zYq0y!j3~q4pto^;d6%P}0B75-|3>MyH zLQVB!I0!ull6(^Lp7RH3GMDCIfYmtH+b!}sL!LCL{eWe5x#4Cc0%~e9LKG&A(D7=m z;ZDg?%CU1nD&ypN>*KIuNxF}~qu2K%NXs7_MHm^IlbzqZ1=ACxzjf{s=;DE=xHvT#jCM z*Hbzg zBAHpOi?kz&cN(R1!MCAE?)CTOybB1|rE)<-WAG|ipSwfIlkc**;DqcLAjAfSf=*!@ zY$)g7gb=&7gz+zl9gw8wfh-zRrd7St)OEM$_>gqB zgoOu-;I4MYtrElX*?uY6ujj|y@%KedI1#laee?&6k8#MfU2DgXqHFirjvr$~K(V@1mVx zZdjb29ogvjXZ0$LEryQ@^L(zWl(f7_|o!b7J$!m=i z;+E4z0^|CGXd5fq7_{$tRHYNObf45k7~gGF#P+$iyY(96o5Chm+$O#cVScyPjpI`~ zC0s<2{^{M6gd>Z5mtT+IhTPSMkN$J#*ECQ)Gp$$@J?PhL)L zDA_Uw_Lg2kOW-wlppRbE9s{E~3Ubbr0<;Qbnlg%EU`^NhBr23wG%eAhkj2RB`p@kU zNnaMdbzDC@VRa;Sev{Yg!s5E)`w&*hKTN$COn=su=V9g?MyrV|;_zCs8(sH_Jo1k+|Q z5i-7>CYP%XBrTcPDy&L3u>GNBjl^AKz)elgv@!fX3ynwIC%4 zgMph&7f)nf&h;G;cHs=i%ocPBLpXM7!XvIV4&g?JUup!AIWQ4q4>IWF!y7^e<<&q& zslHDSJ7ID}R+V`g-57%n7F7vweU^a+%>6OeY=Bue4JYB46YL%~Q*sRM&;g2kg8Dm( zNcotp#E?jK>Ctxfv}=ZJ0Wgw{J?N_a%?F6)kt-tQrPe68uaCH7X}d@% z95i|bSx+4XR*60^Z5YZSM35!n@QU^eERFZO&1C6z_d{B0^qOoSe8|{Rwxon!7I?BM z3?Hm_e>QKeKE}mT_Z~HGUX-!}z1M4@~ zXn-3g10oow))U7Bs`HBP*sQg@aYZL8hqZob>2z}A3X@lLWp8`X!A!RhV(n`1>pWZ- zHa{fn5HcKLS5~U$KRpXFG80%)Kq(Xxl)pOsNc_&TAg6C{XlyA0urwAjb}+OD*gD$S z|8Wu`QL@*!b}%uvS26>}3VwAKE>~LnBeVF)+Br_TM?g@bR5@C>R2t0;y=<{gSaPv@ zm`pm&mk8gqVJMb{tktd-bSLVfeqvP22v2m)^Cs(@_uQx2>qDILzSMTt#oOD=ZyAJZ z?0cEVXCI#*-g#RTlgW#{jkq14i$vPCWA5A1fF(3|8xVC~9nUjaMS-!}N0Jz;CZi8I z$Lvw4ugnKX%k0d*{^DhXrPZP5mZ75t2R>j;3sZbDrb9vJWLbD$!(DysX6>S_$HU3c zv)|O*I;wSv8`;^k<0exux9Z@F?_McPV))&u)oBhwt`G{?qTE+bU>r%OTzn1AmTg~y*>GD_Bd(LglTzuZg5UfjL^;8cXx@_9hdxboJU@^lTEO&jjy zp4GS&?K($4F$zUGvq5R>teQYQvNPagsg;gBv{dqJtesLJeX-&Ii3G*PH*8?l& zm;~0=zc2we*z8<=MZJ?}7gQg|8UB%*)Bs|$O^9t?g0kUlTQuTyxPhA70Nf*vjntDm z<1O=>cQDf7YU;0FEo?3PVBMWRZkB&1Rco2z_G?g~Q2{{1r4##r?fo86kb zk4$9m&hTu?5*Mb{D<}d+&$5 zammR?X1rsxkHI!5m#d^icBH8a-ru-Xaq7nbHgsQ!WCNs(8I*_Wr5mWdVk|~o!fKgP z=7>xK2#hn8FRkNT;coY9!|k0i<29c^q{%cSEn2)p`aoIi|F>ZRgxbH<93{GuTsUnFD^zb1;Gg3?wQ6cm z!Ryjss+E+&8C!jan|o(-YQ86KqMuF0lH!Z_G>@ zaFspRtMGcnrN7Dx4Hg@737zBiQ^j`bJ3*ahg(4}*j<0uGNbdk;xk>sthWBG5OHNhw z?iU&sCi`J-ha9Uh+U#5#%7^Qn-(8E-&!ht{SnNymm1A@7WE?H+zYCDR0>;ogG7eHx z0G{)jHe&c+FsR7o1_g9K-ebL*PV?{QajP9-sL}3&nrBVzwN2|6+Q#GOjW{3!0mmju z6Mz!*pX$njF^wL3;w#e%ov=y>Z$4q{MG7^gLoCGIH-B@1zdJMMu;~s=omHHN&~8vC z`sgjcJ@}16Ld6o*0QYwRBF&>Z)GW9YYr=rM24D9X3I{Idh2i(x_mp>CoITSh_k z(TpTW5(xQbP9fzbr3!9D^Gst_x#X;x)))_VJ-8WIjP8^v;w3_$cBEE^A@9 zuxZ1XHWE)-gFqqDp>g8tKf8DJB9c?p104%~e=ZkLFmw=f5NK%Nh70l*L}{RCw;lKy zG4L}+5TN7f#mmOtl-35Qe+94xs)#u{{Q0-7sVyzPlcSBHy{oOGoUyUJvaQjJyl_Ym zVEhFH7D&4WdbxN(fbCuW`^5-c&i{n=9~E-K)_-2be=XSmB>!*f zwF;R+F)*vx2Ob23{sk2TX!Sp!{)S^wi6;GLbOdN2g z`yE_!c5{FuCk`Aqwin<39XN5n`u_iFD)ygIU=l?~Cj%0onwiUgtC;;_*pj>QoOOW1 zHUSJoGrYi|p#3x4Z|o{{;5dN;I=?1>Z|WDIb?mNFo=pt_UO$lM2Q0>5e8Ho8^ACByu`J5XQUw<{a!0^7%?pwl+21Gq22y{xqaX)d zqJOB0vA%$ulm8m>pRL%0jQ?Dvz{CRuV+SWo$Nxz`_{E(^`}u}B5IA^Wfs@7jg4Xcv zAJcwg83;e8+ZJ%a!UHXP|AJLT|67)@y}gb7Z_VL*ZMmxrT(^h7M=sS1#1qrsL;S{u z4`xiu?!eiB0zP%A`)^ZzW67vU zne%7hZ14bQgXM)KK7zkxC<08a^&Oq;jsNCthR@w$?E-}P0gV!S0jm@F$FLV$;(uJg zZ*1l23lz==;%9(((HHny@qdh0G`0qcQ~pt*<>c_U=s&mgWO_kgk@~0f-x&IHqs*7L zr=!NNQ9sABUUUro#Y5xgPLez?3<}Zw`;`CME&q2N@-Lu2x2k&y9oPE%&|kHz`~~!9 z5&V}6aZ~SaLw_@8KdVl^+%F$(|1RTaS=#>=*Z+l0KTG1i|k6oV5D#R{EIvFTlT{{haK_{bGc-Oa311FVbRvF{?kPzzM!!zApc_%>R{C z_zUvSsUe&%$SxKClKh+T{W&Ay