From cb357a0de48def43b4154c873d66e185209ca109 Mon Sep 17 00:00:00 2001
From: cketti
+ * Supported external intents:
+ *
+ *
+ * The differences mainly revolve around making this reporting as lightweight as
+ * possible. The report is streamed as the tests run, making it impossible to,
+ * e.g. include the case count in a <testsuite> element.
+ */
+public class JUnitReportListener implements TestListener {
+ private static final String LOG_TAG = "JUnitReportListener";
+
+ private static final String ENCODING_UTF_8 = "utf-8";
+
+ private static final String TAG_SUITES = "testsuites";
+ private static final String TAG_SUITE = "testsuite";
+ private static final String TAG_CASE = "testcase";
+ private static final String TAG_ERROR = "error";
+ private static final String TAG_FAILURE = "failure";
+
+ private static final String ATTRIBUTE_NAME = "name";
+ private static final String ATTRIBUTE_CLASS = "classname";
+ private static final String ATTRIBUTE_TYPE = "type";
+ private static final String ATTRIBUTE_MESSAGE = "message";
+ private static final String ATTRIBUTE_TIME = "time";
+
+ // With thanks to org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.
+ // Trimmed some entries, added others for Android.
+ private static final String[] DEFAULT_TRACE_FILTERS = new String[] {
+ "junit.framework.TestCase", "junit.framework.TestResult",
+ "junit.framework.TestSuite",
+ "junit.framework.Assert.", // don't filter AssertionFailure
+ "java.lang.reflect.Method.invoke(", "sun.reflect.",
+ // JUnit 4 support:
+ "org.junit.", "junit.framework.JUnit4TestAdapter", " more",
+ // Added for Android
+ "android.test.", "android.app.Instrumentation",
+ "java.lang.reflect.Method.invokeNative",
+ };
+
+ private Context mContext;
+ private Context mTargetContext;
+ private String mReportFile;
+ private String mReportDir;
+ private boolean mFilterTraces;
+ private boolean mMultiFile;
+ private FileOutputStream mOutputStream;
+ private XmlSerializer mSerializer;
+ private String mCurrentSuite;
+
+ // simple time tracking
+ private boolean mTimeAlreadyWritten = false;
+ private long mTestStartTime;
+
+ /**
+ * Creates a new listener.
+ *
+ * @param context context of the test application
+ * @param targetContext context of the application under test
+ * @param reportFile name of the report file(s) to create
+ * @param reportDir path of the directory under which to write files
+ * (may be null in which case files are written under
+ * the context using {@link Context#openFileOutput(String, int)}).
+ * @param filterTraces if true, stack traces will have common noise (e.g.
+ * framework methods) omitted for clarity
+ * @param multiFile if true, use a separate file for each test suite
+ */
+ public JUnitReportListener(Context context, Context targetContext, String reportFile, String reportDir, boolean filterTraces, boolean multiFile) {
+ this.mContext = context;
+ this.mTargetContext = targetContext;
+ this.mReportFile = reportFile;
+ this.mReportDir = reportDir;
+ this.mFilterTraces = filterTraces;
+ this.mMultiFile = multiFile;
+ }
+
+ @Override
+ public void startTest(Test test) {
+ try {
+ if (test instanceof TestCase) {
+ TestCase testCase = (TestCase) test;
+ checkForNewSuite(testCase);
+ mSerializer.startTag("", TAG_CASE);
+ mSerializer.attribute("", ATTRIBUTE_CLASS, mCurrentSuite);
+ mSerializer.attribute("", ATTRIBUTE_NAME, testCase.getName());
+
+ mTimeAlreadyWritten = false;
+ mTestStartTime = System.currentTimeMillis();
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, safeMessage(e));
+ }
+ }
+
+ private void checkForNewSuite(TestCase testCase) throws IOException {
+ String suiteName = testCase.getClass().getName();
+ if (mCurrentSuite == null || !mCurrentSuite.equals(suiteName)) {
+ if (mCurrentSuite != null) {
+ if (mMultiFile) {
+ close();
+ } else {
+ mSerializer.endTag("", TAG_SUITE);
+ }
+ }
+
+ openIfRequired(suiteName);
+
+ mSerializer.startTag("", TAG_SUITE);
+ mSerializer.attribute("", ATTRIBUTE_NAME, suiteName);
+ mCurrentSuite = suiteName;
+ }
+ }
+
+ private void openIfRequired(String suiteName) throws IOException {
+ if (mSerializer == null) {
+ String fileName = mReportFile;
+ if (mMultiFile) {
+ fileName = fileName.replace("$(suite)", suiteName);
+ }
+
+ if (mReportDir == null) {
+ if (mContext.getFilesDir() != null) {
+ mOutputStream = mContext.openFileOutput(fileName, 0);
+ } else {
+ mOutputStream = mTargetContext.openFileOutput(fileName, 0);
+ }
+ } else {
+ mOutputStream = new FileOutputStream(new File(mReportDir, fileName));
+ }
+
+ mSerializer = Xml.newSerializer();
+ mSerializer.setOutput(mOutputStream, ENCODING_UTF_8);
+ mSerializer.startDocument(ENCODING_UTF_8, true);
+ if (!mMultiFile) {
+ mSerializer.startTag("", TAG_SUITES);
+ }
+ }
+ }
+
+ @Override
+ public void addError(Test test, Throwable error) {
+ addProblem(TAG_ERROR, error);
+ }
+
+ @Override
+ public void addFailure(Test test, AssertionFailedError error) {
+ addProblem(TAG_FAILURE, error);
+ }
+
+ private void addProblem(String tag, Throwable error) {
+ try {
+ recordTestTime();
+
+ mSerializer.startTag("", tag);
+ mSerializer.attribute("", ATTRIBUTE_MESSAGE, safeMessage(error));
+ mSerializer.attribute("", ATTRIBUTE_TYPE, error.getClass().getName());
+ StringWriter w = new StringWriter();
+ error.printStackTrace(mFilterTraces ? new FilteringWriter(w) : new PrintWriter(w));
+ mSerializer.text(w.toString());
+ mSerializer.endTag("", tag);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, safeMessage(e));
+ }
+ }
+
+ private void recordTestTime() throws IOException {
+ if (!mTimeAlreadyWritten) {
+ mTimeAlreadyWritten = true;
+ mSerializer.attribute("", ATTRIBUTE_TIME, String.format(Locale.ENGLISH, "%.3f",
+ (System.currentTimeMillis() - mTestStartTime) / 1000.));
+ }
+ }
+
+ @Override
+ public void endTest(Test test) {
+ try {
+ if (test instanceof TestCase) {
+ recordTestTime();
+ mSerializer.endTag("", TAG_CASE);
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, safeMessage(e));
+ }
+ }
+
+ /**
+ * Releases all resources associated with this listener. Must be called
+ * when the listener is finished with.
+ */
+ public void close() {
+ if (mSerializer != null) {
+ try {
+ if (mCurrentSuite != null) {
+ mSerializer.endTag("", TAG_SUITE);
+ }
+
+ if (!mMultiFile) {
+ mSerializer.endTag("", TAG_SUITES);
+ }
+ mSerializer.endDocument();
+ mSerializer = null;
+ } catch (IOException e) {
+ Log.e(LOG_TAG, safeMessage(e));
+ }
+ }
+
+ if (mOutputStream != null) {
+ try {
+ mOutputStream.close();
+ mOutputStream = null;
+ } catch (IOException e) {
+ Log.e(LOG_TAG, safeMessage(e));
+ }
+ }
+ }
+
+ private String safeMessage(Throwable error) {
+ String message = error.getMessage();
+ return error.getClass().getName() + ": " + (message == null ? "
+ *
+ * These arguments may be specified as follows:
+ *
+ *
+ * {@code adb shell am instrument -w -e reportFile my-report-file.xml}
+ *
+ */
+public class JUnitReportTestRunner extends InstrumentationTestRunner {
+ /**
+ * Name of the report file(s) to write, may contain $(suite) in multiFile mode.
+ */
+ private static final String ARG_REPORT_FILE = "reportFile";
+ /**
+ * If specified, path of the directory to write report files to. If not set the files are
+ * written to the test application's data area.
+ */
+ private static final String ARG_REPORT_DIR = "reportDir";
+ /**
+ * If true, stack traces in the report will be filtered to remove common noise (e.g. framework
+ * methods).
+ */
+ private static final String ARG_FILTER_TRACES = "filterTraces";
+ /**
+ * If true, produce a separate file for each test suite. By default a single report is created
+ * for all suites.
+ */
+ private static final String ARG_MULTI_FILE = "multiFile";
+ /**
+ * Default name of the single report file.
+ */
+ private static final String DEFAULT_SINGLE_REPORT_FILE = "junit-report.xml";
+ /**
+ * Default name pattern for multiple report files.
+ */
+ private static final String DEFAULT_MULTI_REPORT_FILE = "junit-report-$(suite).xml";
+
+ private JUnitReportListener mListener;
+ private String mReportFile;
+ private String mReportDir;
+ private boolean mFilterTraces = true;
+ private boolean mMultiFile = false;
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ if (arguments != null) {
+ mReportFile = arguments.getString(ARG_REPORT_FILE);
+ mReportDir = arguments.getString(ARG_REPORT_DIR);
+ mFilterTraces = getBooleanArgument(arguments, ARG_FILTER_TRACES, true);
+ mMultiFile = getBooleanArgument(arguments, ARG_MULTI_FILE, false);
+ }
+
+ if (mReportFile == null) {
+ mReportFile = mMultiFile ? DEFAULT_MULTI_REPORT_FILE : DEFAULT_SINGLE_REPORT_FILE;
+ }
+
+ super.onCreate(arguments);
+ }
+
+ private boolean getBooleanArgument(Bundle arguments, String name, boolean defaultValue)
+ {
+ String value = arguments.getString(name);
+ if (value == null) {
+ return defaultValue;
+ } else {
+ return Boolean.parseBoolean(value);
+ }
+ }
+
+ /** you can subclass and override this if you want to use a different TestRunner */
+ protected AndroidTestRunner makeAndroidTestRunner() {
+ return new AndroidTestRunner();
+ }
+
+ @Override
+ protected AndroidTestRunner getAndroidTestRunner() {
+ AndroidTestRunner runner = makeAndroidTestRunner();
+ mListener = new JUnitReportListener(getContext(), getTargetContext(), mReportFile, mReportDir, mFilterTraces, mMultiFile);
+ runner.addTestListener(mListener);
+ return runner;
+ }
+
+ @Override
+ public void finish(int resultCode, Bundle results) {
+ if (mListener != null) {
+ mListener.close();
+ }
+
+ super.finish(resultCode, results);
+ }
+}
From 2674079fc0a035367cd24a677f8d3c14056511f0 Mon Sep 17 00:00:00 2001
From: ashley willis
+ *
+ *
+ * The contents of this string will be used instead of the body of a referenced message when
+ * replying to or forwarding a message.
+ * Right now this is only used when replying to a signed or encrypted message. It then contains
+ * the stripped/decrypted body of that message.
+ *
Note: + * When this field is not {@code null} we assume that the message we are composing right now + * should be encrypted. + *
+ */ private String mSourceMessageBody; /** @@ -208,6 +238,17 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private QuotedTextMode mQuotedTextMode = QuotedTextMode.NONE; + /** + * Contains the format of the quoted text (text vs. HTML). + */ + private SimpleMessageFormat mQuotedTextFormat; + + /** + * When this it {@code true} the message format setting is ignored and we're always sending + * a text/plain message. + */ + private boolean mForcePlainText = false; + private Button mChooseIdentityButton; private LinearLayout mCcWrapper; private LinearLayout mBccWrapper; @@ -243,7 +284,22 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private String mInReplyTo; private boolean mSourceProcessed = false; - private MessageFormat mMessageFormat; + + enum SimpleMessageFormat { + TEXT, + HTML + } + + /** + * The currently used message format. + * + *+ * Note: + * Don't modify this field directly. Use {@link #updateMessageFormat()}. + *
+ */ + private SimpleMessageFormat mMessageFormat; + private QuoteStyle mQuoteStyle; private boolean mDraftNeedsSaving = false; @@ -638,17 +694,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mSignatureView.setVisibility(View.GONE); } - mMessageFormat = mAccount.getMessageFormat(); - if (mMessageFormat == MessageFormat.AUTO) { - if (mAction == Action.COMPOSE) { - mMessageFormat = MessageFormat.TEXT; - } else if (mSourceMessageBody != null) { - // mSourceMessageBody is set to something when replying to and forwarding decrypted - // messages, so we set the format to plain text. - mMessageFormat = MessageFormat.TEXT; - } - } - mReadReceipt = mAccount.isMessageReadReceiptAlways(); mQuoteStyle = mAccount.getQuoteStyle(); @@ -710,6 +755,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mCryptoSignatureUserId = (TextView)findViewById(R.id.userId); mCryptoSignatureUserIdRest = (TextView)findViewById(R.id.userIdRest); mEncryptCheckbox = (CheckBox)findViewById(R.id.cb_encrypt); + mEncryptCheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + updateMessageFormat(); + } + }); + if (mSourceMessageBody != null) { // mSourceMessageBody is set to something when replying to and forwarding decrypted // messages, so the sender probably wants the message to be encrypted. @@ -764,6 +816,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mMessageContentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize); mQuotedText.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize); mSignatureView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize); + + updateMessageFormat(); } /** @@ -922,7 +976,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mCryptoSignatureUserId.setVisibility(View.INVISIBLE); mCryptoSignatureUserIdRest.setVisibility(View.INVISIBLE); } else { - mMessageFormat = MessageFormat.TEXT; // if a signature key is selected, then the checkbox itself has no text mCryptoSignatureCheckbox.setText(""); mCryptoSignatureCheckbox.setChecked(true); @@ -945,6 +998,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } } } + + updateMessageFormat(); } @Override @@ -994,9 +1049,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc outState.putString(STATE_IN_REPLY_TO, mInReplyTo); outState.putString(STATE_REFERENCES, mReferences); outState.putSerializable(STATE_KEY_HTML_QUOTE, mQuotedHtmlContent); - outState.putSerializable(STATE_KEY_MESSAGE_FORMAT, mMessageFormat); outState.putBoolean(STATE_KEY_READ_RECEIPT, mReadReceipt); outState.putBoolean(STATE_KEY_DRAFT_NEEDS_SAVING, mDraftNeedsSaving); + outState.putBoolean(STATE_KEY_FORCE_PLAIN_TEXT, mForcePlainText); + outState.putSerializable(STATE_KEY_QUOTED_TEXT_FORMAT, mQuotedTextFormat); } @Override @@ -1009,21 +1065,22 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc addAttachment(uri); } - mMessageFormat = (MessageFormat) savedInstanceState - .getSerializable(STATE_KEY_MESSAGE_FORMAT); mReadReceipt = savedInstanceState .getBoolean(STATE_KEY_READ_RECEIPT); mCcWrapper.setVisibility(savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN) ? View.VISIBLE : View.GONE); mBccWrapper.setVisibility(savedInstanceState .getBoolean(STATE_KEY_BCC_SHOWN) ? View.VISIBLE : View.GONE); - showOrHideQuotedText((QuotedTextMode)savedInstanceState.getSerializable(STATE_KEY_QUOTED_TEXT_MODE)); - if (mQuotedTextMode != QuotedTextMode.NONE && mMessageFormat == MessageFormat.HTML) { - mQuotedHtmlContent = (InsertableHtmlContent) savedInstanceState.getSerializable(STATE_KEY_HTML_QUOTE); - if (mQuotedHtmlContent != null && mQuotedHtmlContent.getQuotedContent() != null) { - mQuotedHTML.setText(mQuotedHtmlContent.getQuotedContent(), "text/html"); - } + + showOrHideQuotedText( + (QuotedTextMode) savedInstanceState.getSerializable(STATE_KEY_QUOTED_TEXT_MODE)); + + mQuotedHtmlContent = + (InsertableHtmlContent) savedInstanceState.getSerializable(STATE_KEY_HTML_QUOTE); + if (mQuotedHtmlContent != null && mQuotedHtmlContent.getQuotedContent() != null) { + mQuotedHTML.setText(mQuotedHtmlContent.getQuotedContent(), "text/html"); } + mDraftId = savedInstanceState.getLong(STATE_KEY_DRAFT_ID); mIdentity = (Identity)savedInstanceState.getSerializable(STATE_IDENTITY); mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED); @@ -1031,12 +1088,16 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mInReplyTo = savedInstanceState.getString(STATE_IN_REPLY_TO); mReferences = savedInstanceState.getString(STATE_REFERENCES); mDraftNeedsSaving = savedInstanceState.getBoolean(STATE_KEY_DRAFT_NEEDS_SAVING); + mForcePlainText = savedInstanceState.getBoolean(STATE_KEY_FORCE_PLAIN_TEXT); + mQuotedTextFormat = (SimpleMessageFormat) savedInstanceState.getSerializable( + STATE_KEY_QUOTED_TEXT_FORMAT); initializeCrypto(); updateFrom(); updateSignature(); updateEncryptLayout(); + updateMessageFormat(); } private void updateTitle() { @@ -1109,7 +1170,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc * @return {@link TextBody} instance that contains the entered text and possibly the quoted * original message. */ - private TextBody buildText(boolean isDraft, MessageFormat messageFormat) { + private TextBody buildText(boolean isDraft, SimpleMessageFormat messageFormat) { // The length of the formatted version of the user-supplied text/reply int composedMessageLength; @@ -1135,7 +1196,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc String text = mMessageContentView.getText().toString(); // Handle HTML separate from the rest of the text content - if (messageFormat == MessageFormat.HTML) { + if (messageFormat == SimpleMessageFormat.HTML) { // Do we have to modify an existing message to include our reply? if (includeQuotedText && mQuotedHtmlContent != null) { @@ -1293,14 +1354,14 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc final boolean hasAttachments = mAttachments.getChildCount() > 0; - if (mMessageFormat == MessageFormat.HTML) { + if (mMessageFormat == SimpleMessageFormat.HTML) { // HTML message (with alternative text part) // This is the compiled MIME part for an HTML message. MimeMultipart composedMimeMessage = new MimeMultipart(); composedMimeMessage.setSubType("alternative"); // Let the receiver select either the text or the HTML part. composedMimeMessage.addBodyPart(new MimeBodyPart(body, "text/html")); - bodyPlain = buildText(isDraft, MessageFormat.TEXT); + bodyPlain = buildText(isDraft, SimpleMessageFormat.TEXT); composedMimeMessage.addBodyPart(new MimeBodyPart(bodyPlain, "text/plain")); if (hasAttachments) { @@ -1316,7 +1377,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc // If no attachments, our multipart/alternative part is the only one we need. message.setBody(composedMimeMessage); } - } else { + } else if (mMessageFormat == SimpleMessageFormat.TEXT) { // Text-only message. if (hasAttachments) { MimeMultipart mp = new MimeMultipart(); @@ -1647,7 +1708,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } final CryptoProvider crypto = mAccount.getCryptoProvider(); if (mEncryptCheckbox.isChecked() && !mPgpData.hasEncryptionKeys()) { - mMessageFormat = MessageFormat.TEXT; // key selection before encryption StringBuilder emails = new StringBuilder(); for (Address address : getRecipientAddresses()) { @@ -1969,6 +2029,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mDraftNeedsSaving = true; updateFrom(); updateSignature(); + updateMessageFormat(); } private void updateFrom() { @@ -1998,14 +2059,16 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc break; case R.id.quoted_text_show: showOrHideQuotedText(QuotedTextMode.SHOW); + updateMessageFormat(); mDraftNeedsSaving = true; break; case R.id.quoted_text_delete: showOrHideQuotedText(QuotedTextMode.HIDE); + updateMessageFormat(); mDraftNeedsSaving = true; break; case R.id.quoted_text_edit: - mMessageFormat = MessageFormat.TEXT; + mForcePlainText = true; if (mMessageReference != null) { // shouldn't happen... // TODO - Should we check if mSourceMessageBody is already present and bypass the MessagingController call? MessagingController.getInstance(getApplication()).addListener(mListener); @@ -2021,37 +2084,43 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } } - /* - * Show or Hide the quoted text according to mQuotedTextMode. + /** + * Show or hide the quoted text. + * + * @param mode + * The value to set {@link #mQuotedTextMode} to. */ private void showOrHideQuotedText(QuotedTextMode mode) { mQuotedTextMode = mode; - if (mQuotedTextMode == QuotedTextMode.NONE) { - mQuotedTextShow.setVisibility(View.GONE); - mQuotedTextBar.setVisibility(View.GONE); - - mQuotedText.setVisibility(View.GONE); - mQuotedHTML.setVisibility(View.GONE); - mQuotedTextEdit.setVisibility(View.GONE); - } else if (mQuotedTextMode == QuotedTextMode.SHOW) { - mQuotedTextShow.setVisibility(View.GONE); - mQuotedTextBar.setVisibility(View.VISIBLE); - if (mMessageFormat == MessageFormat.HTML) { + switch (mode) { + case NONE: + case HIDE: { + if (mode == QuotedTextMode.NONE) { + mQuotedTextShow.setVisibility(View.GONE); + } else { + mQuotedTextShow.setVisibility(View.VISIBLE); + } + mQuotedTextBar.setVisibility(View.GONE); mQuotedText.setVisibility(View.GONE); - mQuotedHTML.setVisibility(View.VISIBLE); - mQuotedTextEdit.setVisibility(View.VISIBLE); - } else { - mQuotedText.setVisibility(View.VISIBLE); mQuotedHTML.setVisibility(View.GONE); mQuotedTextEdit.setVisibility(View.GONE); + break; } - } else if (mQuotedTextMode == QuotedTextMode.HIDE) { - mQuotedTextShow.setVisibility(View.VISIBLE); - mQuotedTextBar.setVisibility(View.GONE); + case SHOW: { + mQuotedTextShow.setVisibility(View.GONE); + mQuotedTextBar.setVisibility(View.VISIBLE); - mQuotedText.setVisibility(View.GONE); - mQuotedHTML.setVisibility(View.GONE); - mQuotedTextEdit.setVisibility(View.GONE); + if (mQuotedTextFormat == SimpleMessageFormat.HTML) { + mQuotedText.setVisibility(View.GONE); + mQuotedHTML.setVisibility(View.VISIBLE); + mQuotedTextEdit.setVisibility(View.VISIBLE); + } else { + mQuotedText.setVisibility(View.VISIBLE); + mQuotedHTML.setVisibility(View.GONE); + mQuotedTextEdit.setVisibility(View.GONE); + } + break; + } } } @@ -2319,6 +2388,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mSourceMessageProcessed = true; mDraftNeedsSaving = false; } + + updateMessageFormat(); } private void processMessageToReplyTo(Message message) throws MessagingException { @@ -2573,27 +2644,44 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc ? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE)) : mAccount.getQuoteStyle(); + + QuotedTextMode quotedMode; + try { + quotedMode = QuotedTextMode.valueOf(showQuotedTextMode); + } catch (Exception e) { + quotedMode = QuotedTextMode.NONE; + } + // Always respect the user's current composition format preference, even if the // draft was saved in a different format. // TODO - The current implementation doesn't allow a user in HTML mode to edit a draft that wasn't saved with K9mail. - String messageFormat = k9identity.get(IdentityField.MESSAGE_FORMAT); + String messageFormatString = k9identity.get(IdentityField.MESSAGE_FORMAT); + + MessageFormat messageFormat = null; + if (messageFormatString != null) { + try { + messageFormat = MessageFormat.valueOf(messageFormatString); + } catch (Exception e) { /* do nothing */ } + } + if (messageFormat == null) { // This message probably wasn't created by us. The exception is legacy // drafts created before the advent of HTML composition. In those cases, // we'll display the whole message (including the quoted part) in the // composition window. If that's the case, try and convert it to text to // match the behavior in text mode. - mMessageContentView.setText(getBodyTextFromMessage(message, MessageFormat.TEXT)); - mMessageFormat = MessageFormat.TEXT; - showOrHideQuotedText(QuotedTextMode.valueOf(showQuotedTextMode)); + mMessageContentView.setText(getBodyTextFromMessage(message, SimpleMessageFormat.TEXT)); + mForcePlainText = true; + + showOrHideQuotedText(quotedMode); return; } - mMessageFormat = MessageFormat.valueOf(messageFormat); - if (mMessageFormat == MessageFormat.HTML) { + if (messageFormat == MessageFormat.HTML) { Part part = MimeUtility.findFirstPartByMimeType(message, "text/html"); if (part != null) { // Shouldn't happen if we were the one who saved it. + mQuotedTextFormat = SimpleMessageFormat.HTML; String text = MimeUtility.getTextFromPart(part); if (K9.DEBUG) { Log.d(K9.LOG_TAG, "Loading message with offset " + bodyOffset + ", length " + bodyLength + ". Text length is " + text.length() + "."); @@ -2623,7 +2711,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc if (bodyPlainOffset != null && bodyPlainLength != null) { processSourceMessageText(message, bodyPlainOffset, bodyPlainLength, false); } - } else if (mMessageFormat == MessageFormat.TEXT) { + } else if (messageFormat == MessageFormat.TEXT) { + mQuotedTextFormat = SimpleMessageFormat.TEXT; processSourceMessageText(message, bodyOffset, bodyLength, true); } else { Log.e(K9.LOG_TAG, "Unhandled message format."); @@ -2636,7 +2725,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc Log.e(K9.LOG_TAG, "Could not set cursor position in MessageCompose; ignoring.", e); } - showOrHideQuotedText(QuotedTextMode.valueOf(showQuotedTextMode)); + showOrHideQuotedText(quotedMode); } /* @@ -2699,20 +2788,29 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc * @throws MessagingException */ private void populateUIWithQuotedMessage(boolean showQuotedText) throws MessagingException { - if (mMessageFormat == MessageFormat.AUTO) { - mMessageFormat = MimeUtility.findFirstPartByMimeType(mSourceMessage, "text/html") == null - ? MessageFormat.TEXT - : MessageFormat.HTML; + MessageFormat origMessageFormat = mAccount.getMessageFormat(); + if (mForcePlainText || origMessageFormat == MessageFormat.TEXT) { + // Use plain text for the quoted message + mQuotedTextFormat = SimpleMessageFormat.TEXT; + } else if (origMessageFormat == MessageFormat.AUTO) { + // Figure out which message format to use for the quoted text by looking if the source + // message contains a text/html part. If it does, we use that. + mQuotedTextFormat = + (MimeUtility.findFirstPartByMimeType(mSourceMessage, "text/html") == null) ? + SimpleMessageFormat.TEXT : SimpleMessageFormat.HTML; + } else { + mQuotedTextFormat = SimpleMessageFormat.HTML; } // TODO -- I am assuming that mSourceMessageBody will always be a text part. Is this a safe assumption? // Handle the original message in the reply // If we already have mSourceMessageBody, use that. It's pre-populated if we've got crypto going on. - String content = mSourceMessageBody != null - ? mSourceMessageBody - : getBodyTextFromMessage(mSourceMessage, mMessageFormat); - if (mMessageFormat == MessageFormat.HTML) { + String content = (mSourceMessageBody != null) ? + mSourceMessageBody : + getBodyTextFromMessage(mSourceMessage, mQuotedTextFormat); + + if (mQuotedTextFormat == SimpleMessageFormat.HTML) { // Strip signature. // closing tags such as , , , will be cut off. if (mAccount.isStripSignature() && @@ -2786,20 +2884,25 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc Log.e(K9.LOG_TAG, "Problem cleaning quoted message.", ioe); } } + // Add the HTML reply header to the top of the content. mQuotedHtmlContent = quoteOriginalHtmlMessage(mSourceMessage, content, mQuoteStyle); + // Load the message with the reply header. mQuotedHTML.setText(mQuotedHtmlContent.getQuotedContent(), "text/html"); - mQuotedText.setText(quoteOriginalTextMessage(mSourceMessage, - getBodyTextFromMessage(mSourceMessage, MessageFormat.TEXT), mQuoteStyle)); - } else if (mMessageFormat == MessageFormat.TEXT) { + // TODO: Also strip the signature from the text/plain part + mQuotedText.setText(quoteOriginalTextMessage(mSourceMessage, + getBodyTextFromMessage(mSourceMessage, SimpleMessageFormat.TEXT), mQuoteStyle)); + + } else if (mQuotedTextFormat == SimpleMessageFormat.TEXT) { if (mAccount.isStripSignature() && (mAction == Action.REPLY || mAction == Action.REPLY_ALL)) { if (DASH_SIGNATURE_PLAIN.matcher(content).find()) { content = DASH_SIGNATURE_PLAIN.matcher(content).replaceFirst("\r\n"); } } + mQuotedText.setText(quoteOriginalTextMessage(mSourceMessage, content, mQuoteStyle)); } @@ -2818,9 +2921,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc * @return Text in desired format. * @throws MessagingException */ - private String getBodyTextFromMessage(final Message message, final MessageFormat format) throws MessagingException { + private String getBodyTextFromMessage(final Message message, final SimpleMessageFormat format) + throws MessagingException { Part part; - if (format == MessageFormat.HTML) { + if (format == SimpleMessageFormat.HTML) { // HTML takes precedence, then text. part = MimeUtility.findFirstPartByMimeType(message, "text/html"); if (part != null) { @@ -2835,7 +2939,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc Log.d(K9.LOG_TAG, "getBodyTextFromMessage: HTML requested, text found."); return HtmlConverter.textToHtml(MimeUtility.getTextFromPart(part), true); } - } else if (format == MessageFormat.TEXT) { + } else if (format == SimpleMessageFormat.TEXT) { // Text takes precedence, then html. part = MimeUtility.findFirstPartByMimeType(message, "text/plain"); if (part != null) { @@ -3025,6 +3129,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc showOrHideQuotedText(QuotedTextMode.HIDE); Log.e(K9.LOG_TAG, "Could not re-process source message; deleting quoted text to be safe.", e); } + updateMessageFormat(); } else { processSourceMessage(message); mSourceProcessed = true; @@ -3436,4 +3541,47 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private static String getIdentityDescription(Identity identity) { return String.format("%s <%s>", identity.getName(), identity.getEmail()); } + + private void setMessageFormat(SimpleMessageFormat format) { + // This method will later be used to enable/disable the rich text editing mode. + + mMessageFormat = format; + } + + private void updateMessageFormat() { + MessageFormat origMessageFormat = mAccount.getMessageFormat(); + SimpleMessageFormat messageFormat; + if (origMessageFormat == MessageFormat.TEXT) { + // The user wants to send text/plain messages. We don't override that choice under + // any circumstances. + messageFormat = SimpleMessageFormat.TEXT; + } else if (mForcePlainText && includeQuotedText()) { + // Right now we send a text/plain-only message when the quoted text was edited, no + // matter what the user selected for the message format. + messageFormat = SimpleMessageFormat.TEXT; + } else if (mEncryptCheckbox.isChecked() || mCryptoSignatureCheckbox.isChecked()) { + // Right now we only support PGP inline which doesn't play well with HTML. So force + // plain text in those cases. + messageFormat = SimpleMessageFormat.TEXT; + } else if (origMessageFormat == MessageFormat.AUTO) { + if (mAction == Action.COMPOSE || mQuotedTextFormat == SimpleMessageFormat.TEXT || + !includeQuotedText()) { + // If the message format is set to "AUTO" we use text/plain whenever possible. That + // is, when composing new messages and replying to or forwarding text/plain + // messages. + messageFormat = SimpleMessageFormat.TEXT; + } else { + messageFormat = SimpleMessageFormat.HTML; + } + } else { + // In all other cases use HTML + messageFormat = SimpleMessageFormat.HTML; + } + + setMessageFormat(messageFormat); + } + + private boolean includeQuotedText() { + return (mQuotedTextMode == QuotedTextMode.SHOW); + } } From 982f78fcc9dcc9a5fecc2feab3b19381c2f77c49 Mon Sep 17 00:00:00 2001 From: ckettibM>?z?aHf3hBZSQ zo9c4PdE;yBuK%L>Mj_>BD1kKfT1?t3KUg|ClU(geiNlkyzqut>sJNgqGRlYf11kL3 zyE;HZEwTL044Rc!i?xaFZat) zhrD)j>?#1x?=}FR$No3<^_g73Ih-}9thYk73ii<=KGd;!dv||h4(qPM^UBVCA8Q?{ zqZ5X|0MS&_P%cH&EK}wQ-8l_Z8FTz5rIm@G_z2Ldl83T9S0IFm-+;su19L&NIE#Sr z_nFy3=nu;g7spdKCw~2Y_=o=X%v|`V#SkFK&VBq6`xlsgp~lqIuvggCW8DFqKI(|4 zp6WrYC5pIl(@m6}2r4H`-#P >6~?y(28qa!La`h)(vcWrwA9vo7SYfY z*bz^&kc@n`sHkXa3feR(wbm#WvverhF7b{ !BeALW)E^(Us8;oh*2vM@z!5+LTcYjo`;Mi2OYzilF#A9jhZWT78_~h}1e >4JHr3^*qD+_BTgWf?$Z9PlDM4-(mIlFEY+Zr zE( >v&Ouevd&cc|T2=R0!ao)v@KA9n zy7k4`l?}F?^6MezD))Zo>n-5x?K1mis88S-Nl0*((+K}c%8>t!_{x7i@K30iQSh zfZ<}zu?^sZGVfFefajsZH^FIyW+P1x6w((4$3Hx`vf)Y)s^YO45pLm%E-fe0pwHb* z%W{P31qemR<;M>3TrDvd04P?R`v9cpFZ}R`r=Imu0}&`((GlnmkpM|IzO??s=iYD= z=<1OkXxkw~HogL2M5yIN(qX6?_8en|`otsv_J?;aYDOBZJhv7~P)Ce32l9dQHiG&S zsy9n*f_Z`lnburtFF!^wKo2IA` +e&YEER6vaeY9UWo>ZM@)zL8? z5H;4WmiB!fbbySLVS9eXAYt^XPA|4>5}7n1jj@fVkV;qj^m-bv9zmznqyyX~qhm*e zod{KY46Yj5MTsWSjGD!rNEF(8;z@?L+W7PxGsEU&Fg-bR*2{Qm^p{xfkWP^)gS@Kz zqGL|IY9^nF$=(r5vo`{FjLf?I>IQvq #ecL#K+(~(Pjph$TFTeq7JyQ5Pt|NW{ca^28NBzua zaZuS!bGQZEJJuXZt<~vGTI1y}b2L 3gEBpeKwT#1H%fwkL`x`$cpU7 zi_EfHJ?@2F0oN0?>}9xN46eJRA3eQu1m2iiL0e6Uo6;G=KZF&>-)7&g+hkua2lz@b zeU$R8x?PJpH;RfjV6I;)$Aq{*cZ*d`9IM 2l !oGZEX#?JW|F&u#^)iJLi*q=>L|J2WMDt<9@%+nK@4&h z_#=mN9C+(PdU8&xBKx `6Ndy+Ge=KLvI+?Ag0A;O&PX(tJnzlB_cOlC=$wuEn4 z($h}Nr&9>FFR_hBV+p%L^T#)Ab=emBsXtnFdD_}i-F$wB{p=|;3I5nTH_OzRT2yZ4 zj%1Bwl5sUZ;DM|NeOO^(&pY|{sepa}(5qN~0s63Dy2OS;_=h4r{4~gtMq7|+S=hii z(>Sy{@OZ(B?pgqrCmtQWnJl?mwceS?{acOiG6$04$d3k?&6k1A-jrzC1DIZ2VH)(h z{b-u&)Ux?ohF+EA^zP^qs@k+)8t7;>Fg5$ ALuZ`Za~M{9(xpdnPlMWE;$UNI%A#PT#TU*`+3~aUvIlx}#5XxzB3}8XyTxJZL_l zTjw&ic*nMLI};~%Wl~#k;wopl<5lN5^GljxHF>k56^5$w16mzRpNn8q#8HnDi$OQ7 z@T?ja @AfT9u&R&XDeY6-j*~lg2AyAt)R2%(@!#aRuuug1n*TkDNOteh&j2 z)IBhLO2_Z-Jy5YPm@G? 9u* &5MXPI5FGXjJgc@;phoMtB9ttfY`_R>`HZX|)QArS3~?vbYvb zTg7D xVt46+N%I{?K%X!iXfXC}DH*_}4(YTB28YVIoYL(Zi;) 93@)hB1bVN!cyVUV(zE{)Z>y8?(w7HDBdnaipXeT(l<^;u+Qm zHjZwa@R-SSA%GZ})H8BmXBB?c2_CyO`WyaQ;)0V1(WZ-W!m=7z-^wk9|A|F5dikN< zyZ#VRC@ry3YkV!a1h@cKHR4GBCbP|c;dL~MsU>z>9Zj2j+j_|FR+`&BQlhv>YQI?B zYquN~{>Ityjc0eDEBIX>?E3ff_s?=8$KOx;t)C1^gqB>*Ubpw;H!^e0-T3&NHwA$B zn+AZQ*!FN98=T!vO1_6!^$RPlO+JCj#!C!9@isGjmp;Vi6v4Ip_446sol{e4`dVx2 zAbVkQqj^Ms&6mETByCb+06UNIZ$ZtT6PLy8psS MFhGt2of<5|eruJwX* z0R@Tbv6_In-^**ov?U=RSiwM}gI?nD1eQTyNbAICTefGrdE3(#y&KOIXd&liiQ Lw>Npr)Td841y6V)$)?N+1hzL~*==%8rKpM#|E*{561j|bW*4TigWtbU!i zkYLL)W1_83SBz)EeS}#w92Vi2AP5clY}5Rm*eWn5ta#0vw5yIY_hIbEC)a6Q!qx9M z(cSg9CB8DCZ0;;UZ3OPB$F0Ng(9R4$hw~(JZSG<3s1s2~aI2}sFAVKu`nGuzk`%bT zV2UP3m9DVzNO$ChIlk$p6zO3qAEZZfzxA-9b=kbmvz2efjv0MTs9XSl`jD}T3XKg% zghM=bz97c8G&p4D;RbpyMy)k0
7$%&q#@RV|$n9?|Ls z_ Pgrn9{u&Zkb#+u1nbDj>{T&8hukfn%V$Gy3 z%ep!>>}~eFTGF>V(~!`E(?pMa)dtt_=Z)Vx&Tm#S%}r|Sh?mR5S^jCc>fqVmr&rxo zJbOO)yy^?=TOAJI9$zl#PfY1MXPw9FWa iiy0n?*H7y3hf!p8*Vyo=^xix0&*0UI929EBQGO(y`7Ky;a9-wS zveiA48xFA|LlQLWGZ7`y@Zb;uwYLp1>`Npz d+%lg_6hz zV4-W0O$RHO#7QY$4`na8nMFw k5U*Z4a^$OM}!l!^=z}b|84^Qxzu| z_rv1pHK)M0_wl2@;uguxV#JM3^Vm;IaX)B4bQ8${X ufa9jCb}!aIv2(G{aDVI)NJqmP3ZRQ@poki}NtY?n90f1jLv zTS=>U{Odq4e`lcor8vjd%9z2^&bB1E%YKLnPW;Ii{Pzw@r>iqdDOEy&sJ~FdnQA00 z4p|6EfWf4@N}KGCM6&JeuFJk8dXoEXy;e}oc>$d;BR|J_a4)fCLh?ETl`m3WJ~;%e zPz1}i!p&)JK3$n7!JM*00qa^j14?E3s!nNXF&<)5&F@Ta(>SWIz3N`Li|!~KYCS!$ z$!bz4c;Uh@78CdOaoR8s)M#f@IBQK v6Sdzm~YF?|I>82u+>YbU%p7HzjhB^FC zO#Rg^*w&_C@!~Tt{mpskPuwS-7Tbul61k)Mk8wYS+daWjLNTASfI-`n`;>%CPd%o` z;Vk9UzE6<6f7$D=k^X~r^uM&%U;UB0ne%@TGm&P9QHlPYHZ%M^w*R^O^REo*pDRTj z?CkyymH&|dhba#zfHEWf1XTf3MMLAmVZ0b|zVA=8Bq1J%yxp&%J8U$y;@n|C5u6Dj z+?T{I!zIe6AfRCNb2y%vdbt1n@g0Q6akgLpm@ tu^JMTbRdlxb}s0{be=eb39LiolKvbP?e|< z7vE+imbH?bJ6DpW+o24R4pSqgpHr>KA;;xz7Hl3QQLTLjwUH}TDFioW&mJ=B{Rc{3 zs?0yxgwkM-3&-BRL89qptYV?AwrxC67(k*JFa`?;Qx7TB0mU~(zE0UHXB*@kmT(@; z{XBv t{t!dTkQ>*zsf3MR7st%@;D$_wfm{FkmvsHc0V+(Y| zeBb8mch-ZBcf?>V)We)tZ`ld>>&2M`=%`A)ynRX5$yCd%y=Zv0eGxu6Y?l37Ca(88 zJ}!LEA$5=qyTN&-x0;*Z47EtzfF$`)8%wplR14;_3`&PfZsk*DVXSI;NwI)A+Xd!y zNKH1c(TxeG@`ixAjd7k?@jU2ZW*b^H5MtP&(&rL D{(jV{(?P$V-Q_E~8E{40}?rlRb?`>@4U zC0->fQc++4TkKh!CGnahZzJG8^cE^WME*8ZKtQPe>gp-}o1?7eYGwP+i26fE5mgwA zU$m>sj@~2sATHZdCk#BO5IkFnq@hKLWbpg*ek)vk@kP=l+8@Y_=kLDEw?8fP=dlhE zZ$<)&bM>G`LWkwekF%Thj&dB#{Xah+zxQ)FGY==MBKb;hKHU<9E60u)8gI8z!11v$ zSsBU*>3FubzUvC1foWsvmetZp*66f^!@VqkzUEx6(@-MGl&*pg!d|7JSu$<_bnP!R zik}uMmm^(Mw=30j+W5Bi@`8+7Y}UZTWdN$?ep{wjmA|RxYM;&ZydxG_*HZMd&D@T( z6#R6&Up!=3EcvuHn-J)i+-HJa=9Q`@lUF}&Z}I3kRZ(|uCe9}Ph->I8jV{GlyWbz| z)Cj1y+%zSdK5W0<`x0`ctrs_xyW~`UjlxGmJ?QJJ6RFp9xM^|CP;+q6fYN7sML&Tu zC?C;Oxm%CTMkyKEuGo31by&XrjDFR_y0;l#03du{ax!Hy*;mFR^|U3z9iuxw@C-%> zx{@u1hI_A@0>u|LoN;!ab~aN~pXjK8rq}Adn(v)4)o#?3LuX90c9-s#vOk6mLt~Vm zGxIZg#+_5Y+fIxq0*@OcD(p_)pE(~wAMR*%UJK?x0Lq?hOAr5|X}3OOL>dc{#kAlD ziI|_^_CF6KAZvdtz|=S!F)UbOl(8*gjk->(#+W=Uh)rbLeF}JoYl5WzXg<;i6*MI| z6QECt%n_P8E$Xev6H>&2{%{-RdcCJb{sbfS13iS&=5U^lzNa#VPGl9(LV?^%31WUm ztVTyQWsNeDL(Uw9Q)C|V$}MY) =F2Rmm*bDgGJpS`^W*@n3 zAHyC}TVp={TPUbaf*w?pebBAPdKlJyJX4GU0&KhNR6oCWI5sv=3W8tm1N>i<_5V*h zNdFr@|0|_7v;W^WTK>U#Rc8tV!hiYh{qGp-zih(&lk@)h0MY;VIsYU+4LwKIBW(ZP zneZkpgit!NP_p^d{2f~oS^CeQ%|Qq<;teHGDyxr;3xcGP8SdX#8z7%LI+aoZ)t0b! z6`R)et7)q4Ka8xmoJN%$aumvXZbt!!aVBHfK1;Z~e!DL2>F`>{40k=(PoH0Y*SXzq zefJI^>w$Z3Ua@RM!48wR^xRkTj%9>@ux^12K^|{Nm|QfHgYjf=@R0AC!OX~nm~=-& z!a+|^?VD+LOXPm!@PkIw-GWWeK)*u%G|l9Ago$A(LI_>X#Y4LoJeU zSM+7OL|c&=UV1y&NZFPZtK(-Nc1M)bbA}xLc39A%EbJoTzBn#{a+V@IrVPnsT7$-d z3Ku0SE^1RX7*%@Mp*!8!rsKuhap^cXzD_;0%~zEny5bseG^pv@aohc~86mTn@<&H> z-3a%PoJ37jRQrSqeE2bZ2U%N(jef eY*Fl?U;LVt2(*~ZHTi(U zXMwkdzjfH@GqHa$kQ!fbbSWoN_SisIpytqfJO2 j@ rf;=DRxCT5o5Q{$XV%WS@}V$1-Bk`43rKfT8FFy#4&I}w){!DT3usGZ zQc0Fz(JYPH(75Fds|D{P3p2xHb+;KlA)Kpk!5hk*--g^}kNAZEMp?zb%!#;Wp~E0< zByL%YN6vG+#qN7*71K%2ZtR=}$Ys6w8J@V2WUkz O#?lpNT*eMf5FnOnx(HiRWIU4V#n=QXQTt{^wPNk=rJtn zY?!5zW1L>%0uV-ww+el(q7mQ`?4$lT)8kE++7{tixLDd}B*`h#zaBy6yL{t~yB{YI zn>cnvz&g(0zp{P))QWXp9C)F-YWZOmM()mGe~i_?O4>Rw(_7%~@M`0+giSo7*BE>G z%J|HEQMdDitUI8X2>)(x9Vq!o%N$>=3F$n=lOQ`Er0a_CE6auGDdT%b1>U%sxF+HV z`0A7ku7lNLPblpms}e95ln=N9z8uyCd!xXsz2()a1p9Dp1_uAomx4@J_N5~Y-}Sm4 zB+x%V#&Bea(l9nacFd#l){u -jrH;mk=w76#6zLdm0UzWz{Jz$Cx)T399X-N4|E9 z-Hbj@@Q5)#VB>>a<&Yihu@Cn^jTK^{w0D1kg^gcUuhG00Y#@Ye07L84U*rb!C%fBt z%8UckDQrIb$dZv2SC67di}pbx;?sGD4Fd=_d%#|8RAAwlJHi*wiTBL$_v#kZ0jck- zHDszJdzJd`P8$A@cCNDZ ^BerpPy>LyHTBPfP!hKGvaTf8NVIVMJ1{2;Q?p zCvC!#zc;BOoZeBXyW>M1%ocRAcAcNWI6g!8K4YYP0dHp?^>_P5D}j>BEPRz&PAQ3e zrJGQ^H^r ^qZhg0Z|7uRh`ydfG;ucPGKx+|%+qyo zTpBK#X!Vaf)ELz|)^8jd^zu7vvR&X;>c8)pSqV%dyt2X$HBZmZ4Ia)s!ob7NW;; zr_mIw*DWpq1L*8Oe_s9aDudSf3Y;ZbRYSCDkEAWDz!Jh$cM04kTOB-sOALn{{uH}1 zm #Tiq z3w^E|idxc?ZjK?mK@jdd{U9B*u1^^@nCI8DtBpAJX2>G-b{mRHwmici?vSoC7<=`W zdTq#Uimk_#ycHvVvdO>qMZA2*y?^1A{Y2zA_LK4J@BSQN{z^FfKz93-uZe$&6sTc4 z*Q~%`AseIJy5f2?tUI)Td<1g5R@Ba2&O+>b1^kQ7|G~x`-wA`{|4M~F|4M~f|L^Gh zA8h<@>hpgv@=pyP-ybXZU%3=B@(vELXfR+(lS)!Uq%4})!j5+IwVR+ta20Z`TfbW2 z$)4OfIh8mdcru6D6v~FURZB5A+!{BQqfuRx?QC5TPmcAkfV+%segbbMU$K63^4i8y zvcKYUTwG?apFa3!ubpNqzWCqx0%dO)(P`_);(O3NIct-L{y0Ck py!SDz+C-c){}XQ z%|RRo`g8lL2lM6cyChxYM?>BwL~nR%ju89q#!J%NQV~=QgCI-+BZC>AZ^Z=(>co%~ zpKpt!8Kob~(C|_hd#m?p{rPH)p&^dGVuOiaPO!m;U~<(Q<%Fcq7k1mNpq88MmOM^@ zq4tlVym-9!kJV^5k6NvyMB3o*%CwowGn&>ZY?s5RKzWJf2HT`czwn>YWq3O&aBEPi z?!Rw`d74IA>2>-&thQr$tHAjNUgg2;TaD3p3gQ~qN|W`%dz7zb+O0K}`5UC$4(|f& z7k)pCQgd#b<0x>g;Frdho2g7NykxRm;D_S_C=SBULbG?QigGs@Qf06e-Xg W?USwho9#xq#R zAsr&co7n)@z*c0#Mz!P;1PQ8eP_`1?+%DhZhp>xGDPN+J?NynYOV%)SE)a-YESQqj z2!D9VqT?kTZBm$IGO;;esh1I`z?1ByDalp-MteAO%2{X?aUh;Euu?L$-phoW?L@oX zJjIM-r?a aNQnwe*(JQP+}>U!WPi !*tMaar zGd*qNB`u#~wiiR4d3z8 ?o*ReL>!!o!!SYve=S@TPQeBv zM@P4gqkhN&KL@PB$sKb7r)296#ANq{Hz+HUWs(|_<*ESUK9>slO*~5Z^_A?WggYGa z;`GL(v-={Z+dK>S=kG`0=nure6%F$2q+DHbV8u4M4E`?k<}n*Sf9PcJx^ZJM&)h(U z7aXi|er^cQ+h>Ot9GL?%k4x9a@dvD-y^9Pn-gc^9Yry!|06CxO6{nr1GJ`qU-VypV zZXn?U{!ZrJu>*|kXp@X%Bk8BDekkJLd`9=(ezm}SGBEj7r 1UyM(^93RSL?Iky->_+SmSu6YGt)sl{te?d1fN%(>M%Dfb!67&zB`}rXQ5}%49BJ z7(F%S^hi|JGVXIjuX^+SYi@QXWOdai@ =Bo8^0yakJ{ sYb5*5PsD_S+FlwP;;scPXM-5lMK-*4f z mfYdHcn{yGnT1S)8;7t+8@74;(r ka79!^S-o zrZ)Abw$o6$vnx+>y@|k5-NIF#*VYzrYqUfCXj0_{dm)cAwGqSJoEyxNZh>vsj9d|b zNOMgY){b!-sh@;x;6SP}fulP!jcV!TN~=S%VQt_U>$jdX>WN2b(v;_>V}D?y!7$C& z*NbdJM}IaX$mNMHQ#pxa*nMlLFzu$gH8wfWyF9Qf1ur@HgTg34vCGb|i{YDZ+Dl z&3s$ycH0UF?I;V|%^gPSmOe03+Mw9PgcC*O3dDXdN8t)Oe+(;tqkuCp#)eSnbAn6e zISO$0e7;90Fu!EYz`KR$#+Hjp@xk$pVJYYTPDK(O`P>7KPC8z hd{ ziRPl#{VXvZzdzQ>_Y90oN37od(8I*27zGjHp+-_vNT&aXvU3d5rOVRxsZ*z_PT96? z>y&NVwr$(CZQHhO+xA!Q^i0ome;qMB|1zG4%pcF*nQN_mulri`y9xdPu2nnEpHDJa z!*aTvzjbIU5z_dHp^N0q6X+Gg@{jx4)?Jv##2%NWbU}v@-mRVcO~eN!)xACauVo5X zH5cp8l(ipeSFH4R&y9>X`@LIJc&x$g*GIKGA(<|_E!RWPt&x?k1}~aHqINVneBQ1R zu(sI`aU^$m+Czh`*{}{3K4GeMqqe)8<;Qz)X|bc^_V9IaGZDl}yZ|FZ6;Kc=hJ&FX zLL{6ckvPa*t;Gp$;3}LomsxnoH4)sNIaZ~}^@k0m`;>U-;T;i6NgL3yb0f(PEV+^8 zs$yr=N^Z!8kNVM2@{4ojvx7qNb2Xlm#mkh*8h5#t11~5B**+tF&GkxkGN+(Lh({Zm zn&m_Zyo%ByV;6oL%nKDDV>*|_yo=f;g~W(qcQs?NAFD9o)Ff?g5WWRBgJI_+85AvF z6z&Xt{#_IM{|{RT|F`VyZ%U2bKZ!juhYFhO-(nBt_qin7zx#;4y9)oO`ja91*I6aP zr=golF^*FhGlFwAq5qDLG2UQ5L+Y}5|L>iirj?6jDib57I=S7bZ#$*9`!&dOUbqo; zg@IhmGmTy4meXW9E0>qY7r^$9HOBbro!ywQAu1-+(kVW~?^mio@Gd-OeHL@1dOJY0 z6BEkaL^5EDc&fGtaE1$>Nc? h~T1}%jnp~|SJ0cS~TV^ZTxCmc(SU?>1z$ISiYK)`m+p_M$tIAFi5+XHEI z3}i#7hB<9H{BuV*eyxE|M`j=qKECTxelS$uTwswzQkd{B&XJ164;B|lFQfYwh;tb? zQ}hYwepmxi2=pa6nsE>%biE6%P8l&XFSn}@tW@q!s5ok6N^u9Sp79)Cvc8=!cW_89 z$~ENDv8a!8&b1}l2p{r2&!{0S*-d{wa-lZfHzh(95vwE$$=I0kb5FoG(NMn>4$$RZ ziVZuJpQg L%wW>N92^nA)8QW6}NlYZKIf!W4Lrf`VaCt68= zSerg1pv!wbMxB-^kFl toUm5aafAwkmImp;Yx<0XFPR32%N+_z$eLG#s!!lBpkNk;U@c0 z`diG~#oJNU52or^A*3;?%fpx++sN-8FgGePh=Etjvc@g*%lXwS(>FJ_wF$Pq&?^6% z-6t$1qUlloTD=Knemz(hMotv#g$g=xD-ps8vA~jr20-AV!Zu%>%_LC (=v1HGL-{UH;DYVcAN$7CoRj+KPF7CsAo!8-u zI_3)POEG^4Bo`8opopRRW?!^@L-Aq5%dZc){Lw#gvF)Txt&|{z3JvgjKo%OBAnY2^ zbHb_Rr|wae{p{yZ`gXNkAYL-^xFI6u$sBF6T-U*R?T23yu>^da2`}zNy&(2$5Gini zIQs6s(o6uT3{f&QgF7}tB>JUVAQHeSAp3Y{orV>r%%1Q+dZ++L>tj`>d1ppe@Qf`m zLuKd@QV6d=JHj{5UqP2?QBe_&8^Iwt2(IzRV-%9TtwHbZ>C^`k vc%rcX~K$3(B=2=|uf zek0HW;^oaH`fdof%SRXr&AxS!UPm8vH8f?l1#rG&i3((nWRn+8xgK7PnS-Pgq;r!p zJIZM^%$RBs_}+OU8knGL;=+JtpU(-K5zn@;On_$rUgpkeaj2nX03oGEi8=MhI!8md zzOHm{PJFedo`crUXL=*NE78Ps6E)58iMRrZ&xS&F0Wq@QG-7!f3z;wGp3rG9KSgQB zs+=_;#O&ovpiiWynh{%E+Jz`C2HEo#d8hALJ{(9X5c_y%7?YiRAbY`ms`^|DzagyP zvgHpTJHduYl+H&KN8s&P9Y0hC9b1@m(d%-!Ii41&)yg0%@}*k>7#;#@Vy``WIR1L+ zHq#{y$0wH?D%L0bjR3KoB7vn~*;L+ywAs!>$uy_uY}4VMJ|WYQiiBEXDptyLuvgp& zbAelhpCLNqzKMhhsfm#t!U#N@n7mDBxUS9<`LdBHl60XREyI~|ZXF$fw0hyNH2}HX zZJzg#i!MD3Gf^Muj8R!L%BRu*+C+Q5TC0?g?un)Y?h{bUdQplz>-5ucEwt}C6{oK^ zeao!;q)}2e)->Vki9xSM4u@1-*}VpM=+ZwcZd3x&B=O(7i1z=oi=_Y7f#mWR-Ac#A z^1r v?Wnc;@TiRi!F R}Lx0)s(BNhofcM2~h^gBsO;< zhZOos0#!=~0r(pGI+!$|FhmLa@B{5#8UzW8J{bjs$YewA9LuQg5v$x{g0F0=1{)ZT zSdu}l47#h8Wbo{L(SypS9}pXg(V1ad@$2_qE0C0yeC$d-*mL^c gig?#mtuV`^o(vmwD*(OvdY9KV=B z_-=yEb2kwzh41)rPuLZBtPV#&?(~%lsYiV?F-cYDQ$A@7QsWqHe&%iz&M~PN=9*P$ zOUbOlTmaQ}gN?+~if3*}^!^UjM-`++0%zg$G0Mks`w1vxjbG!80dI37(=W7Qc1A7y z(6m*UnjxGsKM{%;Ze&OoK@86``+@Tof>WR$ZO=7KyO9145F5o)n45a?Pk9XX4ZUjO z_iA%~uQunu8 Vr<8)R!J-xXBgn{Kq z6>~&=`WJy)woQEsYZXDNrH@#Ch_A>WTYPV_BiG)z8k%jo!x(Q8Jv54OqUjHF`b6!C0DKLF{KvqQNoCV_h>Rx57C846)0Ia~ZR(7GNo-)0@x+lL zeI-6bvFd96w4?Selp&1B{9q!Xyf01N(rfy*FRU?`?;P_VnUDP;49x{wztRS$d?Iu} zkZhrDhiT70?XUuGtUB)oBd&ST$VElAD!^OYBirenf)HIRDULs5a-&q|+zQ2=LW!jK z>)GsA3x~xUZy_FGMg)x;NPm{;%MFrTq<8+-Ln#`j@flg}{-AT_Km8ojCK0tHK$6m7 zqxuv4EUcm8#cNvq!L)GB4>iz9=19X%A7`R2{7VGdS00`xbOh&wCz`L6^%al++b=#h zHRbQQ@86P;aoOP`g>RjZ;hSj3@^3G=gXMpq>;6a6Qih^hJca_|24hs^W$Gx6h;TNb zpzhB}abdI}j%;Emh`11O6kg%M8UDOQ`=xRDS&a=vg(DwmY5x5Z9N%DS?%%+^AvBn{ zXnT4C1zhfL7fINk&9(0cPbH<5p80H`Djl!$Em3t>oky8&lOJzio9uwwNbfv-IAo*{ z+u6Z hr)#m %c8b>}W~H5_@;(%I(<(|RkJ_SSGg@M;um zw}Q>0U)}Y-l{K=N9F?i{=5|5_EP8BmgW}!g@$_JGfqEkB=jXSFl)C20^%B&3lZMSv z>LWx~s4^OJtj269>Ltny=j~}L3N=C&RusmuhM{XIV9X8NxV+7lslE*qN>=!YBQ&DYi;q}uPq`5-@Fl0I zt@sH4>7~+u!GKWS{;V&_2%Xjv`opU8*YzXLX1T0kFO?F9V6_QC(8qDiMRFsv$*SEZ zht-MWZlDLplQO$tCT?EY9`Xak6L%(Vq7FCc7-}Em2gzx~G{GcGe)KCNq>|2hC4$7z zb$RT>Or&k3+$h+pIhAS=5~A+jbYUFv(4E 9k&LFl9L z+G$&bci)SRg3vhnzV?-PwZ$<@d-GmH%&dN3O!OKa9<4KnB^B;JIeNnUz-RXB6uKS3 zN!PWZO7`z?Rdl*kBJx9KETfoAt%{3Xd_$7$m3vCdm3zs-YXw)3uvWXxp-tbI0;dxe zpExikjg^PF8}#;yJ +`xDzbt=n!(%n;2@~J|2 =HCdQ=OX{&vN<^s(o z;I}mvJgTDN`%$Po;YVhTOh}3KRFT-hIl&yfQZ*$%UalBuS3ZSxE`?IY^=h4(9C{|S z*%iv9(clSCbM4frE`Ux&mzwNczF5etYRp)xcPpZII^vhDoa?b)hhEIDTLtw-ntAOB z6&P$K0L)OCzI4ki-cYa^enm44M+mLR(Zyw_BG`vaqlm)NmWO$cze%a4#i|*E7IDU~ zvq7>^29Z1w-NEp8d{I3O%H6Ip38eVFLA&lAf%h(llToP|uy)R&QaGC(0Y=y`C$2Dy zCYZ2wTxiJoVI Q2Q2H{2Qe#67zV6&sfLV6>(lOFP7GcY-QQ8h zW8VuguHeTint- $4n0Z5s|V>XicH5SgLX z#$Tm7qjGQ9CURbC&a3VP >Lkba_>$QhfrKD@8 zbR#Muo;nYtN}G18dTCd|@NNkuMd)OI2~~C|xo1 K63{Zp(h?IiGzJc>^?khyIFUawp0e+pCxB+UOnLtEcN5?g8R;CsjJ0 z-~v1&k^wCxT2H+*_Q{%QB$=uMblTIUJa`MSH_%T@J4T7xz9@Cw@r`5@wS`P$jg? z*4@oInXjaMZM 1%?=Iz2^NY?LNW~fE;Qz8C5R=ao9_JK z=c?({_4Ke*wdJ<)deEii1)_~FX{sD03wEY0QYSUw38}Fotdbha&=}4tBG34aSP3TO z2c?yo8jb;T0x**zvWJ5ee`rO96}uC}Sl*A1hBcsv$4NB{Pxe{4i;cFJov*`~iEu(1 zlZkYKTEk8;0gE_Q%2K+^3Iw`kT_mB^6I$aj2!OA|bbhjqwbgKb!ULqb;80q4rdEh- zGVflNo<;-SxfdE}CYe%cg3SLNf@4oqJ7uWIr60+J)f%Y*<#+9M%M8>$nSe4n(1{T2 zA=w4wdTMFMn4A{L;tJU<#S Hf nw1KUZs&F@VZcn+2$(s~vpy@!}L6Nu8ihTLtiK zl0d?16&T!m%P%nP)=$!97{LhXkJu$w;89i<|74n1m#adugHf^7(J4%z)=9%}PZ$Ag z!VX3s> ukf+L;0lSZ=OA+3&H*DHNU- zvdA2;Ub*HFiTJGh0k!h^I;`r*PA5lG#yci=!|~>po~lM;)tKLYU#}Eirq9P#$tx*@ zT{%A!MUF`EZT!OQSkA^LpEzjd9Rg<&ToUu1(IV5FzmaP1-=LmvVbdIxVAG5_RDd{M z4yR<(?6X0vI&%hOK7B^sl&7g~7N5JZdKVf}Ly`VgA)J1_Yp5J@n(O?aqT`Zpugbpq zVu8ZM9?m7!e}NWw70!>k35i^bk*hY5QPAvZ0Ix+)y?0+C8BeKTk5kEaxLgmQ(X`C~ z=?xRn+d(5uOQ4xcwTf6H%CoiZNx4;pi$OiPE4_OpA0F7?xT&E6_M?32iCza0J9=&N z>+MSavuY`c+F)znMK}>nZ$wY2q-^&3*e`j#NQJst5os35Phzr`euFPmzgZ0_B~7}1 zOx4FoM#0)~cTQeOQk>s0S3JF!L_Hozv|0WgUEu{=h;orb%%;$4atJe6R3RwQbBUrr zjT-kD*^t=T`f^GPEjZLx%qnEjiK-K+`yQmNQCnwl83U+Cp-Sj_nAe_b34pdfx7)&B z%jM0PYn8Z(3Aby{lcZ}iil%WTj2_YLH$DhkrEqD9OS3>|l wj!WEU*^ zLjVgK(pT<;WBKkv&jTDtq=O^J2N+bczX8Q&33!KSTbsq%IO&g %EK4$RR zMn)oqZ}O+@{LoP-Uf_li`3|pILGBPS{OmDmx*-s;+W&ExQQu;L^&jE&p@x6n5zna~ zZUsq---6f{+Tt=JNVt(_A9x*wFMm%T9Tq=v7$##=QXkT Li7$M<~lwg=&$e! zU-Eq)mQ;RSMz9dN7Z% rV#?Q2$A`MA6bi_>_Jr;g|=y(2W#+%&`G-hx9n51b5kyBDzy0<(zGn zR{=Jqo+srLDZ|#Y;~jmnxN*V+B7I_bs0t`}Wfzv=`eYfx1!Mo^jw#Fz*nSrNBGr2tfCb=1_3+1<|WWep)#-D8g zCWJ%LTUqHam>-Qk?RaK>;R4TRp#q`_HSSTDubUu*d |IIO zufOAk|5ma7Dxvh>0Q&KR`5O}aZ%Zw52A2ANQTP5a3My{c!7CtqS)}U6RR_R<6?i+~ zYI8jc^OzIjh=K!|zUEK{{3QGCsM(0U4BSYQ<<|%HxbC^>K@|!@y{}=(qo>2K&@(zm zAAgp5&SJ@|OFImc#>B3Dx@FRkxXj zi!j|rFBEdmgk5i+2x4geDVK)CNJ5E6Y88&|M3NX%j81bXeYb)<9cYJu{_(wC$6#YW zxw;mkVGCK>+Cgv_09r{-$cVC*i0!;;GLr^M5mS1#H(6;~R>yN@6gd=RpU}~g7XNm( zp7LjD>)B1CqkPcbdfvWM`>^I+YoDoOo~4R`+fW$VIni#*4H<&X*cuSNks+i=pd0&a zBYhmht)QVIL4n1QdLcRM>9QRjJ|{6+&y>xBAf%)_cvmKJErkpU59?8kY^u1~=2L#Q z#h!3J8InL@cd_di(1NyxFMCyNlx~zFKq(n74Y@j-WpZQ5@3zupY|`P{!cYzc^KmK` z)Sac0mO_)r>WV-pdsAn~3pD%lf?Flm^4}Ao9cY$2{(*qP#@656!k(KKe7rolmV+KZ z^huOAA`fVE8cC&P?7NCR_WX*>1Wzn8g-v$U^>!GdcGem;qlt9}gi2OVLA4r15YGW@ zzK^m~pnVCg7N8!T+-amaZ2|6oj6%!7l>GRc0)I+=7k$>~VPK9*_81Ejv a6$_DPiLiWL>c)`EryniTpeUf`N0Gi34z6K$`S=yF zmWdwa+DBudrMs1ZQr1#^MaS~i?_cVOUkm5s@#L8J_+o}35#yq&Yoq0nQ*4hGU$%Q= zBVFu$ExR9eMtPt)lNmR}_Y~0WPGYEu7Af{tuk>s3Zd%`^BBW4jlEj}Xx4dcZi}Ls+ z7}qEM+(WD~FTxY_8EcVL*4Jqmn?!cX^iKBq8n9OO(@EPGq++!7G7Q4_k(J7B%~zC0 zo}RMbxZQUmS#v+8(wZ)*D?!>H0HA3r(uA`NQ!_R06Y~{v80Q;)9)uKmMrZ0sIsXVc zE_nfC3CFJ|)1UqDy{Y>BF01EWUwI>gL5>O{Ita BW5t_1{g-ttW-nwZ`tL^{o8K0D@!Qx|#O==7Qwj z{$kv{n$XtUat=QIratPW;QJM?+`0|il`#_!Nk3MUe%Yc~A$xoXl+$Nveq`p^Af^%R zt%9K~CFdR)8+xDJPEZv2nyU!T!JtpGxj#?SHU80$c-D7c14~^>oM!2N4N|Puy8s0` z?QcUV UuEWYQmA*W+tR+*(KAwLSvN|Rs3IN8Dj4^y7l1M@&;$=HiumO1Zb zkLUMh*vn7BdBzWxCBJtYkxY!u$ZuphB4qcz^Xwzz+{YC(3KJbY^ENV85f~#d>aQYS zP64CDmB9^jp+l;#4LI!}E4e096{+>rD6uw^wt{4S58Q~VaRId;eW2~FI8`N^Me_u9 zrO=y#<1IOkiV4j6eStc9l&VySzDcG%r{tQE2B7<^S fJbylEJ$VvY4~;OlN@X{9QU#8-kzz g;(GU}V7oS9{NyduL`}?JqWv-}<}-!!^ag9Rjs%yS{P9jNn@nL`26V zD&Ji{6k?xfVZ^I^1juMcC=buDsbK-hr2ialRZroR!-#b}>VeBk0{C75 xzQ?<=dt6V+ YR#!s}pSt}kw4XK(P|nwZj=7lIP1C((*NQJhcW0b2nB5m2hXKczr5a5*F{ z56!Q5l+cC7xQS|&<#Tf*LqHROwN=&g4h1zcvnzE~HBwQypR0=Tp4VZXH^g08Ssx@` zzFb*Pfx(e^fHOnN=g9!ut)2+I9Ey z?0=6v5!&R3oTa;lC@&KLfF2E}?%;OKiOluU0Spqy7z_>xy0)f7+6I~ZMd#Gt-EsSo z %gyl%=dBY?~wuIO1P2(&P39hLUC54;56F( z3y>;+NqzF10=(hmr%MIFKymW;E`B=wYH!+&E^6^GJAliKZ8@vm!m8Bj#!KuW-RFA= zI9VM>7Pz7=Dj}0kw&ynB8(1)-Iyqt_+u_%F24NltBr0z;d04ljfkuX&_R2uO)()W5 z2f4A*z9xrp>hz&m#5I(n-<0HN>k*liU}HiD3uTD9b9mW~Ug-NlN{n6D;eKrNR)F68 zS$$R{ngvCj #(qK1~p$TSfe z2o@Cb#OK7_H!4VYjF5hxod(89jVvrFOO`pQGZW*k)Y3O<{gFP4c1Q}X(NB(ofP8lx zHZwp~*5YJPZfH!fdGs!9EJ{9e<=kIRrOUr4W`PR2;ke}_=!n?I8*?Zeh1*(2@+-Db zq-MjDiL1f5rSs~AeFMjuE)-MlJy)D5D@Go;w^wsZq^(v)2B!{h00&;kn6$>Z7+L~t zp?CR I}X{QQn8SK3y+oq{G=+zGne`wXFeuwUZpM z$D*@Cu(?!i4ZH~3@|(an&M8nG6I=Ni^3VKDOu*J|d_a`VYVTG4lUsTY3q2ANpo48~ zOYW3LMKe+AJv(4{?TQSh9@3!AV(+iZdTYt_^daou$}ks)QP2L7zPfA^`Kr(Ijxo{h zYR?c}vo<}wSvI14YsggqXqM@`E=pejp~l9^AKc<66& zN;oWJ`by7gcn)4!19HC+N?W-prdj&YZqOUalM)e1Nq&VYrxv-=5WtM(R7xQv)g>pV zq`> IE>M)0?+u z6n8W=7dxz3Sd!{272S|)e5||!(Xvew(UYif<7@r-2hBuk81b}TC-$v_4fB@aVeg1a z-pcAMeqd&rxTSb<2OcVW;m854yN^c*{es5=Ikyx7{wEI5L7b-@HLj9_!R0W2X3v*b zH`h9e$q37T+L $PCFI$N5 )3w&`isCD?sEU$fKa!?*&K`-9uG~MGmZUiF|SRKzZ zPwQ>ix+Ppvr3de*O|KTClw*C*=ouH^9Co%3&eCZD7OGhE@_Vah^x z2!qIRkmwHy?ku8DPXs|Eu8k@kXCOLPpKk`3xBf3~Gu!W97y<|2m1RSabgSc0`kTcE zW`6ixP>uIl`rcS99}keZ2bEmtaXeYay^V4ohw7b^4H)Mka*BHZHJq9VaZekUAv8Ir z=!M-T8AYV|P@S24U?_^sS}N?=9u_wGXFOvNtHqARF_(?pDf1L=%qluyIlP^h+PIfg ztV%8~=oKdw_DF{BEHZ6WeorW2;v>{c5EWF5KwF;au9rYvef_1Vgd-Ui(@v>c)qogh zq4zT)?#wa5Vz6Vicu9AOKLb9Qn1`tZC(nX0>3})v!2C+j^UBB*^N>73?OCfDfNBw^ zZ;nOy6$=L(n$C#T(Chb;>=}TwI%W0Ip3X0p&}gd;ye+dn@c~@*{jIt#onJ}MT-RDG zzFvE;ufR Q&C5)#c<|OhKG*VxI?hq+KRj~Rd+xmAi!b!1 z@}t&nG#*WXnow@WXm`J)S(L1?y^P8|_? 9 z4(~|??;%#6C|KVx@;rRfJ#N6QA3u}pkXaHtv|5pjtl%cGx>B=12d4b5>q-@tm8m88 z%Bt&Bg J$ms9T zWIQrZJpn15;{who>Fz8HFEI@-HRw(`YY$jj+ Ml-O8@d-9vrvylD_e9C90SbBA6}jl6&z!0qaJ$G zj+aW2$F)RD7h+rW6%Ci_EV$+lt*%}ktqw4PRP@(Q!KRkgL}e)N%X*QJ%o z{_u?T1KyvH2Xb+LSJpi$2;HT5#Af4YF)KXHU_G}xgi&&R^v;4~eX ?J5}MIaX_}auG?f2Fvn_k1zrJLW48`OA )0gAj;0#>2^Y(g&=3U9Hb_j<5sD1t5$*zNymkWfJ^o$w?43 zPOjb9n)^`!&RKY?5eGTV+%G4}m9u#=l-mCH$L3xPD2uxL?f90@dhy6 W&1Wk-bJ zh5j-|(T~9{QfL9lNZ0enHG)-LBiPE7E=mHunrArn4Tl;WO@&k)J22*Bc>22HQ$G_U z#O{^*r Bp1}@DQLD{dWVA8p2Q0AL~{DQ X%&U&{c27y?xQI(%YzfN zNwBKNr7IJE7vn0*76{?li~KygKQ#)CxM$H*Z5N3eEFltnBCEw25Tf%<7SdPOR9ME2 zS~`s{uw)Lt#@kUO z7`(MwEFsbek_<_&BowGvjutzqq DtG=23E4DmE{{dNN4;4i(A{|sIi+_?ryRQ<^IwukUco&iMyd4nD zkdBW`k)0mdXYi6id(N%|M$Vub_oa;a06^LAPzSj;XH=^aXY{LLXJjup6c@AyKB`Ie z0w6d+C5KMk$r-nwonKvA@)!eeWS`+(#m_&mOP|UAz#VTvnijJJc9lG{Zz7|tk}FH6 zWMT12gJ&So6|+P}$-9sDeGec&{OZ*~{2C-C`}F%NeU2aNvnUV&cN~G+vCBYWyu#lI zNpJnyp+_WUxsG#I86-u_lH1B@Z_+Q6AL^iA&B^)51T#7jv;oo2-+*Dcs%KcFltSV0 zy>RpZRMz4UkT8=A=$7@_rREE~$8;P7QV}k#)+wPl*V g6=-}qq5Sn>8>HfUWIW9R4(VjP+5!7pW`OJN)C|9}0v*v*w zoh40~`!KkD!>vSh2;t_Q^F?C}+^F-HpliT1U=PJTn;1<0&{O5t$}s?1%Gy5?;2nhE zj1G?80#{;=N%bKm1Gt2sgn1l#N1{OJp9?V2DdQHQhHjO-qMr+Jv *mC0q1bfuIy?i4z*-^x53V4K^{03A%Z-udnC;E4!z zED7?#(iZPo2R0r62*y=<98}& <)` zJF5{bI(Xr0kw$uri1yYax%a}5h>whngN?jf#!uSVf6eHQNuy-0m`u(@F_WsPPD($a zpZGAo0rkf4iv43~6;j&Pse2Ow85ZHYgCA$9sYhiiblp=Fu5w4DSY*Eeud6X166nET zUq4IZSgjV`Bkp) u!Nee!mk7h-PTbXIUGcmQDN7nU7CIp#lBSPAK#Y}wn+G|#jLvxs?n0U&NoR7c} z5eTQXIFik bjg+9qA6)Cg0hpzv;`AK=6xip>2hhi)MC2z?3Cw;PI}?p%^TM& z)&XlGqeG3_-<{Jhwi}YWC})nXc5x_6zVC(*cchfVHsn$->IQEyTRGoDeaavW^bOjn zn; @oGvDYS#!CJPy%JP+s-fv(+XY<=?4~q^8pP zMwKq+k?a`@20_!ONdc)@Thb>kCdOazej$Zh4))%+7Nge9nT@IkNF9uqNWI(+UIejG zg{;gYbiT{3#uLd{ST?gg%2B5Z& t{4VdXQq5BToQ1Kw*;4AV`+u61yKq zMZ{@15GHzR0n;u#PvPhrhv6IR{xgo(H%hnk5w7&pw)8!$ID@P>rcf4sB3rW=0ynk` zObK5!bI2NfS2^fcqc-D!9pgZ4AYKcw#WU06jw(mk8A&B0!pwuSAHkpQi2LL&(5xLp zogqrzo{C&(OL#x)Hk3g2ew1}mqFpLlY$tHcvwp^AA@wN8Z=*9gR=;2kDs+fYjR=Pi z(hUO^63BHhi$CSAgE^v5wMM&NUVH=QE{S6ZbPU3fu@^?guHHFP*0#+J>4j9bM0$T* ztUqTgpb)9rTRtxbKH?7R=rVu_i)OUoE};p8X3jWfyr_+Gsy{O!_GSS@C!s`v3)?31 zj4t)7T)B&J{`!HeKDIWi0ZG!X8@iHgCPL_~f hxvjZpn9hbd9S1RJ$kUe4u7@>Fi)FP3{ud@kq3S}`oU z#H#==%L%Kgjo25BPY%P^(@2$PQ_Ro;#sZDT90X9H4=uEC?shX#bb6s7QdAT~+2p4- zm@0I&+ajyDd0&0h_KD;STM-xpR8}n=oz3}@Xi` {a2XD+2ppIO@$ ze9%RHJr+5h%Isa=?e6{{X|A`}BrG(REZ{ACK_c#s_n5O4V_=J3{R6k5hQ1( HCKWp=wawTM8>f_Jr69if9DO$%l>U^- zA=v@JCd}TVn%f?#E>*>wfA)5y1S6(YkxfRa2qR^r7%hxlcy1FsEwBn4z#x|H*r{tW z4_gsJy~l&m2P+v_&L2iY$_ec6MMnhtIZ~|qeiV+IL>nGN3lKDGCM-!0Bhc#U>x{Yp zTef1q#ci<7Y0Tmyn4Z73IbDFnBd`7_59g7zWy2O4djX0GI6~7WA)bK267lQLvTs7U zHmGYEPViPR+1!`P{;Z8k0kLp=PGydxE23&&Cf%bf0=b?Rs)H!%gPC!1VyptgA>G67 z72PAX-qbK!YSA|qxOTFm^vaq@ZqO$NOqtJ2-&q=ssMx`{zAn6POzI0w#q;%uz9N!t zwY0eD-TnjMkt(l(`SZuf; -m#FzqP_2N9WNyYAv*q)+ zd#-`GC9y8r-60#WtGjecnX_Me!LVLh0#`C5>?7eTrK0G1&f@v>=K0-0JFQ<@|M&$3 zrNFZ#{k91be}6^)H+INBd_n)49g+}dWi}^`FqpMgD1lzLps=xCYG+s0Sh7YL+_{pz zoFh$wSB~&VCsAcqf0(#$xW;_@(5+&fef1%|+hSr;6m0IFZugab$1XM5@$z!E=Jdm1 zo^n}vY!7&`!NnNY4-!6YHL1Zxf43$iG=QU&2m_um(43%G50-9T)km7cb!vm#g-$wW zYoYIkDXZD9|AGdE50wmfk)XE{``I)KSEIzy*huT~7hlc+$gahE33+eh8s@ZU4I!t~ zv<;uu6meMK=^HFym+MU eQpO&l1eeDs%By{ps z6v{_dE6a;2WnW3X)wq55mrxp2)XlNBFeYSH{h!)M1wQFIXR4HX%Adrp?MD2fP^g)T zl`c>sNAxka4?OD?>ZkT?*rV_sgX{}XizjTW_Cj*^(%^Bh4{_}Pg==DuNE46788J;6 zu*r4P$65FeiTqnc>`@FWWC!sfN86E+7(;rnV*4V1iPSZ+`*o5h(4h(Cwy&6{pgJ}f zjJU@!ih@cY EQajemHoj4zegIo1RG^B=w#LNqFsdT!f#d>3tKy*P+F|zpjQ!!Zd z6I01%8aQ6c=smACiQ0+6yq2=Y0sa7O1Q$RR%*LOw+f~&eA16lf$3vY#Zz7g1WIBwn zZ`*(8rvCq08S1~3y7Ud~OpGl5$wMSrkaB7Gt+n=kZ`yy&X#CIH_zkST+j8vwlQ s(wh!!TKP5KAw_$m6+A~k z9^;|YyWuB)hY9TFV<80jO3J}8e$HJR;*=;@(I-#I0#%Qd_7;}pc?dyflprdr7h42+ z3AO|*cs5(2+G&)>uhfVfnz0re;PnU_?x~_#J35kBUWG(c-`UinI05#!jY0HfdPFb? z)rS0*AVk%P5bwu@U-^2Jj7`E7)0V<^d(ViY;njjY+zGwVB5v`~Wbh86u?kEgxmKxk zX{2d#EB!l97YdiA)A2B>Cl#2*^}VKMzbUZHdLGn_jr?US#b^zwyTZq>77Ps+E*O z{`f(I{^Q5LHopITrT$vy|3U+TJ7X+3d{#X&sz&I$ML^a9Kx?DBJkUjA<9z?~D#|z` z!06%U+;poM8j$6V{g>s~9@4S1{;`cBX}?UHB-BV8R$F@lm4SaTiKwb)OBnOU5)l>< zSgaCAh^^gk1b!MBIyw@LF}?oTa68(xyW%|J`eJ=LC+G6KMDSiXeI$_FP5G56vE4#| zmz;R`LI9R5xg9_Nmu%VJ!9qA;Vxk#;XgBNr$A_9=W*7Wj=BHPB|Id}KAJir+_#auq zceM;v1f+MRzduVDyoe^gu`VKyU4=VSjP5FZN(}9l-^iEF!ksgTXK;6XA1l-6F#^S1 zNXRYG-Ky)t^v5NU_5iD~WA@p12{^B?E23*B(032GC2iHdr~I!@3Qwi)saNlQ?qAY< zT&B;&kXB<$T*NhKR>O>6xjR~E*ZA*gfnG`MpM0rb@rPXu?@h*^T(+}crq5iET!~js z%OnKxv7NXfxZji8<>hE41{f2j;|og!B?uW8@<}s@OAI9%gt?^T?o8@cvr7 iWjl%?>F8 zT=<@n-^MRP&5&DzCPpH_kR@Kt@ach$)(-x(#g`zA%XTR=-U$FT2;s_F--0DUBT_cC zrJpf{Sq_r661tVMpNTj?v$|lFBBqC*tU@_aqT7nTSjIJlt8G;7A&l0B*>?U2cn~j; zuMM@->Y+$Nl (V=N+(M~&%z9XNiP{--Ji;W|6>vg>F zK(bO-1{r0l #{J~&vvUDX-;=u6zvNjP8cA!7kQt$&2r0gYgXM%u6$ zYoG_aIlIWcu#{b1Z#;TG*7#AS;6%dzmR^1&-ew#jPc&FQOJ(<+iZ~*Wuj?e5zd#Y? zT{cUQSFt=bbi$%@KFKOEig@29qVu+PUYKW JA+6xQ^J0A;}=aYVz9m zitQ4XsgpK?QPO)zgr=^TXUUDPyoipB2F{VMQkDB=FT^$wRp>Sj!Wi6nMR$w4suK7* z1e85yLgPybH#bvXw~H$ejQ3n{=+CIb+}I{?QsbKy35H=6 WbAGsKeU8KQ!O2j?jGEsB6edIPO*Z~>G+E1*b5BHn@wDTSWPic=% zN5sI7WZ#w#U8w+}ThxyRMgwFvH)0_C6`)bz*ZEUTjIfBoJYg)eW@*yk9OFKnZzS fB%W^3n^I?SUq~j&T)4Q*z5zpu6a~39eWjj= zZr7RjLva!ruFruZTk+Vmpfy#+&@fjQc!}007fLAAW4UV2n*rno-UyVw?BrSG9l@a$ zhS7eZP%$RV*1K|+CBMwEK~xD7V@L1V05h&xN(j^dlZxzq2?ajE0LfvYq_x@RJe%LG zoZ~VcWg50^m`T+-)SW#y#iovbzD{yrOtMD3hjzpNbaBB{K)b3uhgO+H*`=?BNI0%;#C1;-tQ436;5MF=MOi|KsbOqB9G_ zY~55vl~kPkF)Oxh+xcVLHY>Jm+qP}nwprmx@9wk5=^o?s#kyQqYmM)FG3PU*&*m1@ z8) xNPi9VC+U+O>jWQ*VzjomXw`*{>`q zIDwSzsbi6$603(I27Rl;$Q1EGT1+WYk)X)ngrXd0XCn0G^=o~{lO>;l;)SfauP3~V z(+KEui^|M7<>?D7nQFJjm~0M$d|}!+-G76foWj+I#h`_S%D3uiV!1bNG+wNHpY@8C z*mWAI0qt_X!Et;-rhjb)yKXIc8RzzqR;N@mcF?yHV$&i!27o; zDYok-oQM;a)Q*f$b$2kAL2St{p3q(Wg%hOK-nbp(V x8-T>52sQdHL)Em&oLd4+Wyhk^4q9o^ww;$naDF zVvEa)2w>{~)l!qFjEpUNiLjBO+NyW7oOY>5tzm0bSXfO&Dv<1j#g*3XKB6yU&hrID zd5YNUX#qy}y+CMK^%*$f$F=J0MuYVW?)s98^yrc4teFTPsbEtI2 Ix?a5$HBrXOXmVXHC-RfRg=S)u9Wx|HG$Jzhy Gs`ZH zmNUilP$X-E`L2aYx5AwQoItNgDz5t@U3s4)5FfBz4qE%4CM4dVgN-Bi(75Z53=q17 zdN5tjq+iI6|6~}k ;h_EQOd=k0K z@}dJpx7-#S@X${Cq!EA7$LA^Es2P}``NP8;qNm0YiK51ujGL~hLtHp9J$ZZcj?BEX zNqa_cg5^jvIZ*4p0jh>=p;rIdF(~kPaDiRgMQc#4j?T;8bwFf!|BBv`hi6ij`(bKh zs}tvyfJsxj=Iw8js+!=6$|^FGwZ;`l9Xzvvd+521@*2E08npW=t Ioo- F*l!LZDR$)!i`?+ubn+KL)OeX3rBBoDjtym*I5@_3;xFq!@!9+ zR&&x-UG#2KWNlM?%t)+_N {v&wj&xX z5*1{sDTCw7yW=KG&}~OEWRjv7P4ACO$|1W9Zly8O-NdJe!F>R31*77|@%sz+_rK*a zFGLCMRBPT{_I!gD|ErnK3CHLTcz14`rg-SjI=VkcjD3V@T!M!E7!}CV%7-ps58|5? zlU8#V6|wDSzd{i%I)D&mV71*h%lL?o3YYU~bfZml2S5)Y6`@GhewtU%)w@Q1D{W z{uOv;>Aiw?wV0URj1%=z23!H*>H1kY!7fHYYKXG%^#&Tl?qtEH&W&kxhXU&Ab^K}F zA P@djmN<^ lISKhXv8D`q z6NrrI4egTM+p+ML)%zxzJ+vu`a6Ew`)n;gU@FJFGpSr(r$1}7f+L c!W4414@iyaPPhL zMPK!S>%9&75sQ#7I&${0^+7pe^`leXyMI|YVgz1EdK~&qOg=Z3SX#ysmgKIE%>NeT zZvyos_YV{t=4#?jmp7{=WZts;zQ3X%uKA?gm9OM36Y~=BI=vUd<*_*eV)DpNmZq49 zXC!9q&T9sI3D~A7z0u8m<^(cHT+%3pEQ1lm&;N*X^skUUiazoF`y{DQ7CWN(yWIoB z`)>LEw|-ve|Frf0;g|Uzf)OZJ4VA>t>WV`(@2R{2nS?@M21zUqY2J6Psm$CCiSyo& z^k#u{8anj!Tz#cbk`grmdB039pRa%~%a5_BRRX#70vavVwcHs!9B4*_6up#F7$cmd z)0)rYE>g9o!^85A)2_EG?q{kmwJW#iug6cwA6%k?el1Y>jcgJ07(BH7>=;+@x?I1y z>!1I^=)~;uW8gyX?BYvBV7dxr=`h_8yLq?5>GbA9;QrnN`JDZWLv*VG%SAI?jlo7Z zT@85?;Ohgu_YLp#wZV9CMxeaKiGADz`CRRJhT$TY+^+72zoCWrT 94p zKGb6a`(Ew4jq%dy%ZvVE0P=+ Y&NocY<$~Lq%6fRSBcNf zw5BY!my&ZDeGE q+Zv?b*?`sXf2g;OojCnz?l1Zy)%kSv$h`^RO89birs2ZBotssIOxM zCt*d$$0!OrmF)l#W35b=gO@x*H)U!#nxe9GbCHUiXsJq{ml`9ZL2woq>OgpFMkdXJ z>h1m#NFmdt=Sbl$IUaR5o{H*4i4ql&Vnc@H#_s|KyYiS(awbO;d(hf=!BW*N4snf# zI~FTv&0T>`3!}=H92`nRhSH7@$B{UU*~xD1R2kGNg%%nPPN8^Tb`Hq>Bf$Vi6%u{} zG-uNJr_VjP?9BGwGvpXSfg}#Y!??RE8u#D+qa6b0nyz6loyr`sb%PUYKicK)#@9^m zxiaLl>+e$+pxOzw#873(FCt{3D^4jV<8`kjOu_^GQ}t !mu_goa&`I~uvv7q$G9L$0O(?)J_;cL$BiERv cQ B x)0`Z`N$N9%bFR;14B zcBtf;-kJ)lbye+>!C8q_S7v9J2ld#fDm>#gGgq<`>OV<|mLyUo*>4t(qe<)4IOWII z-EoQvVF)$l^|XfLku7>(@DW4NEJI`X8eCLVl9Q%cWj$jAuW5>>j>IlVw?M(GXmXKK zGn5MZ{l)VHGswFM(#HobJ+nj{Z|6n<`+iK(w@l#(pp1F|sxikif#NP1%;Lq0NxzU# zm>}s65Lza^-06TwZ)DJ%n?S{|&QPMLRJN#uP&OozAims4MZ3 E6(%(|l(m|4|0gYc#SW+ZgVeL{I;m>3hRWM2Zm#mMft?xn< zck1UOhYYP^3^=jv4x)U4QjJ23itS4yk!Ej(N$ggnf0~dPVo82(3ym)-C^DCb1Ogb3 zTl*y1nYvxq@Z`_fV{(0h{-~V^-3MOQ{Z+Rvt5NSon!^+~`J>F X(NMXLE46 sp zI6;#BR2M(h`LG$%247y-t(=KcOWMOuh$vnr)7~q025F&DNptyt!8&Z_fn<5CXfigW zXoY_V#iz@gGO_qZhT4;&Z(6|L34r-4C(4!DDDGxN( cRWkAiYY;-O-Ue78VM#wUwlMASH0TaL z=ytZwZCAuKt4c@kKZE?d;|t(Jd}N4soz<+YGtKL$vM}#z 8$?J6La0jSHBQ3G)~Bu%xbi z2aL9me7G?cA7zp*a*_e#(x0KlO3(HTM-|%+B+i*2E?LbpQ{SIqf3rdpC8h^tqO(E^ zncYd6Tw8s9(%Msp-jY9bCB5x@NU0HYYj5NRroj193hfffv<64VR?VmKw76U)*MwJGPG?#c2`-yhtj?r>=tiO4&$?L~%^p!UDMt5k2-Gi|5ZFDe(ub~| z3G0k==zRdbcVafTTGGyMl+{QpnX+VB5!Wy8G{P|giiN$eA{uz085;s}Xt-gwi!6ZY z)yxYy+o*H}Lo+K!SRy_arm5N%mb2mGq75!ybuQ8tWSacl0!vL%28Xe6&&soUL{%7r z=C`}xRq%pn98m|#m*{`sZ_NU{@>LyN(Jj^jI!POriaV(`1kj-LR#=0a;4=%!f7_vL z`I4Z8$Ye?n%TK#%ih&AhYKf~ZAxEMAXpOsdV FdLcX zAswn?CVSfz?i|ofPLmB@3CqCr?P!NvCQG{(exoYZ7%OJwz~U0PU T>B;1|Ywu;$a`lU* zbjqE0$1E)9$2EigO=~l8wv}+7?w!u16{o948Q_8%o11I4wqJDG*y=}Jko~ V zeSqH+>4drCl&J6hD_CuL`UG@b<>^%i_zS-Ut>P=)8gqlbnn*8vV0>qqSbW&<<1ejz zrK9!csotHXj*y _(zvi- z)o(I5{;KB#81J7P cUpkhw?Y?vMMBafZC!b9%NO z`s}O_xz;oD# $>y`kqCUA%t*%jzS&rSw#<9Bc L-?S9t=-gin zE^~jEu*GQGH>xj1$824P M8n@ij<2MDzkuP0SlNxSD-2ty1k$|cs%&n+q2UNpG zufNO>)}yx5nS~RF6Qdi)ZZw6HF38d8 B5w|?z44@}Db zt>D?xYU%2YJnl9V?4(E0881vp!)}f1H^c11lHAF1+NJZy!82;D3O-KfWLo9o$anV4 zPp0Y>of@xq;w8F=rTt}?>+Kr1ck0ux9^~$Q;&%`2DxU>ooSgln`co9NS21AtGh>67 zr* 71XQPc4X-uBqA)5&J!{k>$$KySnMqw Cn8lbz|OEpZ+iDgAQca^ VDx13YN-xniZI}!qojT zjo8bj0HfwAV|-7|<4a*KYU{`O%5%+TYr8jMI}2HiN8F_fS@TowmxQWc3~x*(@td!y z3=mrGjnEN@m15!bYP(BuAVAcdvR`bRCdpMx(=&xWO&f(i*6PXL*+=wuF8{p=B#CKl zc>Jaa=^}qKJ^!~RP~6(V(cbC**cO$|9LyYT?EiEBSDE~#fxU<^+#MX4smB-zW Bt7}h`UTT*(6CrVYtcA(UFQ+pKayg7WQ$6r&y zy8fB~J?VXqZz`y=k_VFwZ;jMCa`uGPx(oIwDZ0w`i~u@{w@!d 8>)i+-Y6kaLd9EEH2I_W7b7>ii_DsKnzUDb{jX0NWhL8M?ckf(!L(H4KY8 zqq2Aoujd&I)MnkTS`@cgBGt5AD+@h!jgz*s;%V$c?ZS sNwN9IuXx9AK|~^5+ddYzZhb&bkrg zys8Zdi@}`(J@U9yGWlFY%92<-QZjerNrR__te@(}vbjC;RUBc^d_E^ugq&Tem>Il< zbY)xo0ct%qP>z;DR5g`*#`f x z8&!sCf*@~;g1(&?-;1P{AlaRGXz!d|>UTL^QLhv{ier0{%&U#Y2a{2^_Fpy=nC_$J zxO3m@S5;Kr*&D@osor(_BNvo+&0bojccgBGoAX6R6!cZ^au2ay8`t!+izYXDb?^39 z$xM<>r$=xzAC;Xbj`qWDkD$|of}OIU?OpCIKVX@g$x^{wJxr;GPCs);v7S8YveB)_ z2EyN V~?zN_C^PlJ46hOynOz5gb-Aqr ;h`QIol9+}yYo?h>y1jGiCJ57zwzS>Wgbkp=ff9#b9_*IN* zJ(i|15qE* p`hT7LNs-8DDz9jz(4`ouBC z!Z3dvt<;G$tkM?a+8nH+gaQQ%v6}QR$BX@LLVBi=f?;L<2@mhdg< uXU*V~)6SrvtS*a?#|It3ec)HQKb1>Ps1a?Vm#GMElRmArFp?nlB~;h2pey=~ z#$5IH 4pazZptym@$_TQq)N~Xh&H>?95V2yiHtR8 zuxCnisKoR_XJE;_&Z}T8TITh#aQH*>6nfRys18(Ym#&jlk=c(hBRBanU+m2g!;>Q5 zA_=oDNjesGuAe^+c6Pa+$b%^00$oIKG|GS~z)}NN?YwA2;lVb=knq7N!SEEJ&MxB@ z@f(v&P|T*fV3U`k;qZxGg5mI~MTQ}%z$l5pXdN3sz*z%!HA*^GdPXqGu=wPhX%rWh zAiaP&;zB;7G={nc&mglRW>Z`6Y4&f0TdI`6<04< no$lB z^RXws+lHApwQZI=Uj8n_;^f~JwO&(BZL Q$TSMiL|@KUmr57#6wq7s z_02_=LU*h7CDrvhJ66~ay&(@%Qwx~-Ey_x1y(Kua$Y8bWc;&*iwgy;Ga|;tJyaH~O z7m}vZO0Dn{Z_xFXGre=@JsXD(_cCqvM0IXp`WjL)p{C>4U-in(_N1o#!2VJ7-H-AB z2K)mtpwPk0kixN>3_S--gF%{!_1)|wJ }ZfUZRSZ^BejE? Hy#M_U4GZrK z4*b45lfR!o|JxlZW%JE7wbXNP;C!@M=7E5K0ELiohH!R pYP!fTF%YJv{j^Pl2NbOia`q*Ro80d&Q zc<0IqBKk;J*qeCZ^1_R8`}u4BJ-$vMUUCH;105p;o$qffxG5#*?~uVBXrff~mH$gZ z_)m^f^KAm9*f$O%^PB$rzsj`a^b9QYO#W{owuR!n90E7F6(}((8N6^p@U%eU4i>nZ ze;xqcjm P7J#-n$1QR$g@2X6hv$`+4h|T!v!2*510l$!#)i{d)eK zd<_Co6T^oLVPVJV%ZXk#Xp4hsr-DtmhYqAq;-iK*r;maH#P`XR&J0G+@1@Aw$qssf zpDjF0yx2R7^Ha3 @pcjr%xxcI&?G)*rTFRg}WJ7*2IxtbupfGF_jLbR!nMbsx61wbeSr` zvv2N1sntA!!)Ke8!nqt9B3GWCMS(Y|zhKSAUBMy~^Ao@OIesH%Quw|8rDe!|rAOlt z-J V|~{aVejdkn=0 zv3uq-G MDwq_2jb2HhjbfpX0uWwGtPp_ zVr+%%DVerYLo PDOmD=l)uSA_cOKkSzUMzuBwS@+_@ ze+%4t2|%583bXqIg!Vjy_7r%3WWW(4!6RWn6VHY7@cv^rClVqhF6WKCcne!AZZBE) zrQk}P78AN5Dp?`x#5Q=~lF3gi!Cz|?Z9vA*j2obd@4{XB-F;e>W>Yfl{ CWccinp(g;s^e=xPr*jMp1(&Sa?=QI*ibdqcHM6iq zXwq#+6m2-*i#uCv5PmH4n49yjSgc$jOg|x2ve $RT$56HUo1_wQf6*P*3q?!603Hhipz8$%M9}3*ao&X?p zi)D&Li_Y1IvxEy32@Hw|_iwPk1ltdZg%JCd+lh *W7wiK$ z>bwxEDQC6?wgq-3%Zs%Zi+pmqlT$u;r84jWv@<0VuhPDS=su=zNb!6qMnGM@!Mu-8 z3;+_jx2xw}5IOB3maj|s`j_fuiD(A+binK2jg`u9a2b}I$!NGIz){JvC5x%@VTI@? zCtCX0JW?i)N-baOQK#~C0#mG~@z2ibdSRWM2N#VTv9Q_ ${DP34e!lSIxGDNuS~0@Qg+
(cqry7w~OUuO` zW|CHgZA&N+?Odu{JA|YLX%MtjCc&q|2veB958ACHj`gPnBZf8;!U~7VtD&jimJKM_ zlEu~p;sd2zuEsIn4pJqy5B%l?``9RQSh!N7o;*YXRyF~qPOOKp_$P7&{K7=8RBZs) zAS{O}!6->miT&^&&0e58w6obyPpL9&?(oRy8fVdzH&FY!NDAncDg5z$f8<{#%Xa>B zeji!B>DfbzP|GinQJ))bEsKa3W}5M~l^89|8)LSPkfzag@O7AEbk+fVOqaNp8@vXp zdIIgz;a=N0z)_}j-v6QOoP$ 7;eb`7A>c&qPb^Fx7he ze(b|Lm966a{QeuHDrWk0WY+^=d&7#UJ->U;^T`r&UH ?-wmiNYeh-rWT@Zm6 zX3v8E-2j0XdXEPDR@VH*1n0{SuY6aB`9DOK%k;?GzxPPZKjE3*m0)@2=|OpyZy`Pv z`+ZK?qJMK7?V}~SB6q{=b^EuJAg^m+dKVgye=A3P9EEPW&)!*~@4irKx6NOCa42sq znBS|AY<@4`rzM=K5_jdiIFToVL< mM#qZ8Z+Wg6*4xgBT@8YU?u}X zyQ|9;DgG*j8-rn odsOk=2)Olj0ea=l=eu2~pWy<`{}6`+|f zsd?sSZzZ=xkz1wM|7hOA4||Ss=8h?b=~t&++eko$WNpH9z-qqyz#^D-y(HmYc46@oK ls_7d< zo(Pb-M;~K%W@s9naK3E7_ERE?GiGUDydcp5;tI`4ISn}@>6IxWb}Y%PPC5CF6B^Jp zdBXp*5o<;sKOo^WvYK>iR!h|~)|eYimq{7rHXc&m4wUYmH;OM`InlqUWpExwludb5 zo;zd0DIDfovS&%h=v^3*15n}?`2RuF<*Qa~#jUdNG0gtCSfNcB>o5{Vo7XjNnFU0X zXDM>GhilYL-6T@Cj%_6LQzMq>n7<0WtoL9kK^{coU#Grfo?le7abZYe_Au~hX1cV6 z|D}+0g0v82!bUtn!nl~_c&+4kGjAk !!Ie9mWs?E=ZZ <`}O-Y35 zqhx;XBVF8m@rEnZLrQ8z-Amovh^eINXbKi^%$`2E*ceStO>x(;8BB7hrO^!}!sVSi zf|=it>W@;E;At9Esluclrv;~(eUoFv&7Cf0yT<~6*X5L#atL2Qi?~9G6CmHBUM!A$ zFCj~kSyQ*FfD6WqY`hFCo7Bl46A45v%=$p?;hQ3b&!;ubqPq;0GgX3ly+FCtUez ?2y{;hlo>Z;K@Ogf8JBF6BqV%U6$@>tD}GRC$Eb4;WltqJ z!XU)IeYu*tYvD4(X);CG90%7n4HOxxrUYPu4%_ziWVVDuJ;ded?R2(ifPg;lctLCh zx?t4_Hz{;Ld@kKL$97M?UozQ(bwXV6Rg CMZ-O=9CVDeBRJqsWlSuqryUts4+uz^$9Zr<4E0VTpJ4P*pRjB;Yhk z#&pK26ICaxzgR3-)Fs}c4UypzwXm-zfIL7A+*OvgW*kUh>E)`Y&UEOL;gBL7Vbe>b zB=ZyX#AvLa=qZ0;VcaKU*HYW%$BmAg0kj76S{h 6vSszSfeM3A!IR3o^tp-@tVBAhD^3(%qnBu?)mwBj246`<9ta z75sxZp*btiZTPXMM5BRWJULOMXr~qGmLhH(FxNk(cn3K8>c2rB5JZ#LUczNPfXmp? z5OQnF4^iL+&6+6}+CrHs>KC1Bwe{f0kl@sVFkh){^H9}I063^oTDB!;(99FWBuY~| z^ckmbS_iI2*)CJeupWfW-DQSt#6bZdh!3>JlCI|hW*>0PW)DgTt`j?hHmIM`U2#7q zn32T~p%>p$yubc3RaId#9%yIG9PkL=wCK98d{n1IEf?939u%(c79`peo_;`R4@fGx zL4ov_T!6@4C&SO=qI; %forr+Lc7!(-gVc&0Quyn~&YkHtifKne0t;2BI|e@$5z z8$=SoQ%ZYp#K?}2o(h6*LEv^wVpve`+jbL>CI<87&G<<0SdHZ0rNo^w26-wUHj?*W z$%hOZ(JJmYUMdHtN|voSGcw|h*3HF`9*CpP@t&wj{_+1&UwN66sEd)#NfAbpc&`$* zuZ}gJYCTULikiJTg{iEiPQj(%G`{MEUT7BbROfzKLDBDtecv!QRn^QGAYHCv+jDVR ztHfWCDR+A}=e$XG^J6XFA2PF{S#UT!LKV4OG_TvF;dPIsee(Q?<@(4k4+G|Q?>+-O zmPy2;HCV*Ts{|`g9w(~!5FDH;83g_>!g>?Ec0q&H=1iCIHrq==&mtj%_KAr`NxAe{-IBf=Ry5-lQ2bp7aVxE+X%EL@18PZP|oFW zjf1n|&of|PuP|!!+2ihC$>p>zXZNPtW @>a~I(Rbt}qoNYn2>^u^} z92VRDM$bXDhnaa!3N>)qzaeAWBBI_A&@=3q#RpqKp+?Du-|}^|E4d5_s9d|{+4l_z zcmUM4PK;i9v0}vxK7_c+dmKLyMU5K4^L6A7N1UTtFwaSZ%*d#)2+p1(OYk=@8KI#l zdxF)9)s+k#tXBP=OoT8+Ym#5*fqCN-6%Gs8Lzu~|WbG^wz@$Wj^rlybNEtJvVCb`| zgM$|L^(A_VG0TCUY$N=(=$K h#NHJZ`wOTyX zFDLv+nT~8$6W8~BZ%+_g6$x)1l3Ng5Dls=4JrpIrQ3Yl(4HuVoc^OOpmY>3!KRjdF zfGs>s3{__Rc84M7QFgZ60q{D07I4hG*vsvq=O<(>36+4V=pC@>kn#(Y4Q3E_8DiOS zgI96QqslT_eSTi!h9?7(OOA4igkj5TLm6C$H@fQzChqX@<_80B3niQzl_4FvXj?o~ z%Sx?VY}6zI4qKnuosY6XO=NL5T*=qk2B6imp4!HCw3x-ncJSft-J0A#hmgC^Fs_o? zHSY>JTcDTfs#3ft749$atbTxBe2YZo7J+4u@?c|3(r_ZM{ND9ge4 ez@gK4rB^Vkm2Vu8x3Wh;|< z!R}k9YBm%eCttroAbN }!i%elk#gN@rnuV(f`R?V51)hyii4zu|?H z-9zrp-S49_VCD(+fvq!?y~~`@3qKpo+Twt#)1Us{Hu8@;W6);BTzT)D0d^Z-<@i9| zQ*mh*VEci$V~ooXG2Vt9x8IoW47D z_Wl{VS!t)l;S6}Q4mIbk=!*fz2f6n@_VOB6XjwGBQ^|tU{S7)(sIR2FWfs? O`T~%;QLQ+fjZv9v*U<{`;c9<7R>Gfe%d_TZhHU< zae%z8_MoL8y)hQ_gwEvsG^0E4fY+babym^|Eal^GlDDOKrPgflPz&$Dw1Gnh7v`U2 zR(izc7)}oF_}48Ycp*Vw9?Q$&rX>Uid3xRSeRbZZ=Abb_bv)+*e*)`kY$ Z7>96@~I7S|``_oIX-JwK%f*z8rp9A+~tKP&w#WQ +un^s zRWXi>RjC(7;%wRG56pAN*&Gk0i>?^a-;*UWp39TvUb|3A!WQPom1)btox`5?XP5W> zakRiVG4#Va1VA0Sq9J*a1U0cvD9|4KjIBC;QJ8Tl4^zizf-Jj?c1-75qCc2``yaSS zJi~st>*&5l)&ch+8QMslPt3CN9Y=J9^5uSB5Qa(jU2l5lg#&)H2A55NU9#=|Qu+Jh zr-`PyPJji~8BB`u+aK%k{*JPaqPC2x*``3OP_8wv>ApNp7=&~DIyqeg12VbARMBN| zDJbywv!1DaT`oBgcyLcQ>@h+$U<=Z+Qlc_O)0<%_Oes>s4_Zs}MVD6;Pk)Imsd>S@ z8^((9LkLa6#}@4+gJjF0A7*~U8nLm)T=<+fbfB+LtC7`XxJ5aro|5Xf2CLDm2Y=Ja z5(%8;G9gpmyJQ3t2>aKnwCR6f8UsEvC<{}53-4=^p^H{_`F7i8-V5}GEYH(V(;NLe zh1ecwhK@1@#0^c9Wfhq&Ub-1BO?gGQ^{^&On3w&tm#@Jff g$IX4PN`99GCuy=tn?j*~Jx^78X zJgbII=|123{Knq@_vvvC?YMmNH^EIC69k0fe;xMx=h{`=%GUBfXFY|gP_EcU7~Wro ztnH~%@N-27>L)XCah7$`fdaW^>T3yed`LOei*reJtC>WKEbZf0mZtKt 63RU$EROkjQ2R#E}z>^r7E~QzjRa8 zbM&~Mfcc=TBX` 9FvxI9}R@Oo?D@fPVo-`-zRF7TFb zpf;$AWz7pPl7?l?TEMfP_8Bp)2dyxzhjF|&N_Xp9CZpTmUowK)?V_nXyOyKhm^Pvz z1Fr79xyb57-q91U4KSbf33zc)S0O!Jg@|~|2>$xlagmIp8M 6hDzAe-HF9#2t2-eNsK*7JV5x94>9_1i5dp7zad zFm#p>7cS8BB8>D+Loig%wa4-jHhp% Sf_y%Y)7PuQ)WQ= z7xXb37E*C$DgBbE%#YU`bzEuMtF5GAXaAUWWh1IaL6uQ5RdkjJnE92=N2O*oNafMk z*J$KX+Tc*+G{O{<*2G|qa~o1hS3Vw=%6;0a&Dcu3fOVLzP7rPlOHA!H)$y